]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
Merge tag 'v2.0.26' into master.
authorPeter Powell <petpow@saberuk.com>
Sat, 21 Apr 2018 11:04:43 +0000 (12:04 +0100)
committerPeter Powell <petpow@saberuk.com>
Sun, 22 Apr 2018 12:02:19 +0000 (13:02 +0100)
14 files changed:
1  2 
docs/conf/helpop-full.conf.example
docs/conf/helpop.conf.example
docs/conf/inspircd.conf.example
docs/conf/modules.conf.example
include/modules.h
modulemanager
src/modules.cpp
src/modules/extra/m_geoip.cpp
src/modules/m_banredirect.cpp
src/modules/m_shun.cpp
src/modules/m_swhois.cpp
src/modules/m_xline_db.cpp
src/users.cpp
src/xline.cpp

index aa63b6ebb3d53ea7c0b8fcd25fb5a36be06525e4,72ec2a7d4919c5dd7ee00b0229e567e26388c8eb..20e03d64a27000cdcc1e3077ffc5d31ceec3eff2
@@@ -402,9 -412,10 +404,10 @@@ Returns the ip and nickname of the give
  
  This command returns the number of local and global clients matched,
  and the percentage of clients matched, plus how they were matched
- (by IP address or by hostname).">
+ (by IP address or by hostname). Mask should be given as either a
+ nick!user@host or user@IP (wildcards acceptable).">
  
 -<helpop key="lockserv" value="/LOCKSERV
 +<helpop key="lockserv" value="/LOCKSERV :[<message>]
  
  Locks out all new connections notifying connecting users that the
  service is temporarily closed and to try again later.">
@@@ -740,7 -755,7 +743,7 @@@ Sends a message to all +w users."
  
  <helpop key="rline" value="/RLINE <regex> [<duration> :<reason>]
  
- Sets or removes an r-line (regex line) on a n!u@h\\srealname mask. You
 -Sets or removes an r-line (regex line) on a n!u@h\sgecos mask. You
++Sets or removes an r-line (regex line) on a n!u@h\srealname mask. You
  must specify all three parameters to add an rline, and one parameter
  to remove an rline (just the regex).
  
@@@ -799,18 -808,16 +802,18 @@@ using their cloak when they quit."
   s <mask>     Receives server notices specified by <mask>
                (IRCop only).
   r            Marks as a having a registered nickname
-               (requires services account module).
+               (requires the services account module).
   w            Receives wallops messages.
-  x            Gives a cloaked hostname (requires cloaking module).
-  z            Only allow private messages from SSL users (requires
+  x            Gives a cloaked hostname (requires the cloaking module).
++ z            Only allow private messages from SSL users (requires the
 +              sslmode module).
-  B            Marks as a bot (requires botmode module).
+  B            Marks as a bot (requires the botmode module).
   G            Censors messages sent to the user based on filters
-               configured for the network (requires censor module).
-  H            Hides an oper's oper status from WHOIS (requires
+               configured for the network (requires the censor module).
+  H            Hides an oper's oper status from WHOIS (requires the
                hideoper module).
   I            Hides a user's entire channel list in WHOIS from
-               non-IRCops (requires hidechans module).
+               non-IRCops (requires the hidechans module).
   L            Stops redirections done by m_redirect (mode must be
                enabled in the config).
   R            Blocks private messages from unregistered users
  
   A                  Allows anyone to invite users to the channel
                      (normally only chanops can invite, requires
-                     allowinvite module).
+                     the allowinvite module).
   B                  Blocks messages with too many capital letters,
                      as determined by the network configuration
-                     (requires blockcaps module).
-  C                  Blocks any CTCPs to the channel (requires noctcp
-                     module).
-  D                  Delays join messages from users until they
-                     message the channel (requires delayjoin module).
+                     (requires the blockcaps module).
+  C                  Blocks any CTCPs to the channel (requires the
+                     noctcp module).
+  D                  Delays join messages from users until they message
+                     the channel (requires the delayjoin module).
 + E [~*][lines]:[sec]{[:difference]}{[:backlog]} Allows blocking of similar messages.
 +                    Kicks as default, blocks with ~ and bans with *
 +                    The last two parameters are optional.
   F <changes>:<sec>  Blocks nick changes when they equal or exceed the
-                     specified rate (requires nickflood module).
+                     specified rate (requires the nickflood module).
   G                  Censors messages to the channel based on the
-                     network configuration (requires censor module).
+                     network configuration (requires the censor module).
   H <num>:<duration> Displays the last <num> lines of chat to joining
                      users. <duration> is the maximum time to keep
-                     lines in the history buffer (requires chanhistory
-                     module).
+                     lines in the history buffer (requires the
+                     chanhistory module).
   J <seconds>        Prevents rejoin after kick for the specified
                      number of seconds. This prevents auto-rejoin
-                     (requires kicknorejoin module).
+                     (requires the kicknorejoin module).
   K                  Blocks /KNOCK on the channel.
   L <channel>        If the channel reaches its limit set by +l,
-                     redirect users to <channel> (requires redirect
-                     module).
+                     redirect users to <channel> (requires the
+                     redirect module).
   M                  Blocks unregistered users from speaking (requires
-                     services account module).
+                     the services account module).
   N                  Prevents users on the channel from changing nick
-                     (requires nonicks module).
+                     (requires the nonicks module).
   O                  Channel is IRCops only (can only be set by IRCops,
-                     requires operchans module).
+                     requires the operchans module).
   P                  Makes the channel permanent; Bans, invites, the
                      topic, modes, and such will not be lost when it
                      empties (can only be set by IRCops, requires
@@@ -1039,21 -1056,19 +1055,21 @@@ setting +I <extban>
  Matching extbans:
  
   j:<channel>   Matches anyone in the given channel. Does not support
-                wildcards (requires channelban module).
-  n:<class>     Matches users in a matching connect class (requires
+                wildcards (requires the channelban module).
 - r:<realname>  Matches users with a matching realname (requires the
++ n:<class>     Matches users in a matching connect class (requires the
 +               classban module).
-  r:<realname>  Matches users with a matching real name (requires
++ r:<realname>  Matches users with a matching real name (requires the
                 gecosban module).
-  s:<server>    Matches users on a matching server (requires serverban
-                module).
-  z:<certfp>    Matches users with a matching SSL certificate fingerprint
-                (requires sslmodes module)
+  s:<server>    Matches users on a matching server (requires the
+                serverban module).
+  z:<certfp>    Matches users having the given SSL certificate
+                fingerprint (requires the sslmodes module).
   O:<opertype>  Matches IRCops of a matching type, mostly useful as an
-                an invite exception (requires operchans module).
+                an invite exception (requires the operchans module).
   R:<account>   Matches users logged into a matching account (requires
-                services account module).
+                the services account module).
   U:<banmask>   Matches unregistered users matching the given banmask.
-                (requires services account module).
+                (requires the services account module).
  
  Acting extbans:
  
index b38e4130e3ff0afaddf88b1ce7a35ba671e63b95,bdd3c4605862113cf2ea94f0fc209c0c42e5c84f..25253c1399726dbb59b4831850a0e5541acf6adf
@@@ -91,18 -93,16 +91,18 @@@ LOCKSERV       UNLOCKSERV"
   s <mask>     Receives server notices specified by <mask>
                (IRCop only).
   r            Marks as a having a registered nickname
-               (requires services account module).
+               (requires the services account module).
   w            Receives wallops messages.
-  x            Gives a cloaked hostname (requires cloaking module).
-  z            Only allow private messages from SSL users (requires
+  x            Gives a cloaked hostname (requires the cloaking module).
++ z            Only allow private messages from SSL users (requires the
 +              sslmode module).
-  B            Marks as a bot (requires botmode module).
+  B            Marks as a bot (requires the botmode module).
   G            Censors messages sent to the user based on filters
-               configured for the network (requires censor module).
-  H            Hides an oper's oper status from WHOIS (requires
+               configured for the network (requires the censor module).
+  H            Hides an oper's oper status from WHOIS (requires the
                hideoper module).
   I            Hides a user's entire channel list in WHOIS from
-               non-IRCops (requires hidechans module).
+               non-IRCops (requires the hidechans module).
   L            Stops redirections done by m_redirect (mode must be
                enabled in the config).
   R            Blocks private messages from unregistered users
  
   A                  Allows anyone to invite users to the channel
                      (normally only chanops can invite, requires
-                     allowinvite module).
+                     the allowinvite module).
   B                  Blocks messages with too many capital letters,
                      as determined by the network configuration
-                     (requires blockcaps module).
-  C                  Blocks any CTCPs to the channel (requires noctcp
-                     module).
-  D                  Delays join messages from users until they
-                     message the channel (requires delayjoin module).
+                     (requires the blockcaps module).
+  C                  Blocks any CTCPs to the channel (requires the
+                     noctcp module).
+  D                  Delays join messages from users until they message
+                     the channel (requires the delayjoin module).
 + E [~*][lines]:[sec]{[:difference]}{[:backlog]} Allows blocking of similar messages.
 +                    Kicks as default, blocks with ~ and bans with *
 +                    The last two parameters are optional.
++
   F <changes>:<sec>  Blocks nick changes when they equal or exceed the
-                     specified rate (requires nickflood module).
+                     specified rate (requires the nickflood module).
   G                  Censors messages to the channel based on the
-                     network configuration (requires censor module).
+                     network configuration (requires the censor module).
   H <num>:<duration> Displays the last <num> lines of chat to joining
                      users. <duration> is the maximum time to keep
-                     lines in the history buffer (requires chanhistory
-                     module).
+                     lines in the history buffer (requires the
+                     chanhistory module).
   J <seconds>        Prevents rejoin after kick for the specified
                      number of seconds. This prevents auto-rejoin
-                     (requires kicknorejoin module).
+                     (requires the kicknorejoin module).
   K                  Blocks /KNOCK on the channel.
   L <channel>        If the channel reaches its limit set by +l,
-                     redirect users to <channel> (requires redirect
-                     module).
+                     redirect users to <channel> (requires the
+                     redirect module).
   M                  Blocks unregistered users from speaking (requires
-                     services account module).
+                     the services account module).
   N                  Prevents users on the channel from changing nick
-                     (requires nonicks module).
+                     (requires the nonicks module).
   O                  Channel is IRCops only (can only be set by IRCops,
-                     requires operchans module).
+                     requires the operchans module).
   P                  Makes the channel permanent; Bans, invites, the
                      topic, modes, and such will not be lost when it
                      empties (can only be set by IRCops, requires
@@@ -280,21 -272,19 +276,21 @@@ setting +I <extban>
  Matching extbans:
  
   j:<channel>   Matches anyone in the given channel. Does not support
-                wildcards (requires channelban module).
+                wildcards (requires the channelban module).
 - r:<realname>  Matches users with a matching realname (requires the
 + n:<class>     Matches users in a matching connect class (requires
-                classban module).
-  r:<realname>  Matches users with a matching real name (requires
++               the classban module).
++ r:<realname>  Matches users with a matching real name (requires the
                 gecosban module).
-  s:<server>    Matches users on a matching server (requires serverban
-                module).
+  s:<server>    Matches users on a matching server (requires the
+                serverban module).
   z:<certfp>    Matches users having the given SSL certificate
-                fingerprint (requires sslmodes module).
+                fingerprint (requires the sslmodes module).
   O:<opertype>  Matches IRCops of a matching type, mostly useful as an
-                an invite exception (requires operchans module).
+                an invite exception (requires the operchans module).
   R:<account>   Matches users logged into a matching account (requires
-                services account module).
+                the services account module).
   U:<banmask>   Matches unregistered users matching the given banmask.
-                (requires services account module).
+                (requires the services account module).
  
  Acting extbans:
  
index abb8830a96043d3e5e483e7e65c24ac077b997da,d54cdc916923854e1b18b2357a8ca3bebfffc12c..6a9b960e09c9b48990ad0c2b9292946de5f5b665
           # you only want to adjust sendq and a password
           parent="main"
  
-          # allow: What IP addresses/hosts to allow for this block.
+          # allow: The IP address or hostname of clients that can use this
+          # class. You can specify either an exact match, a glob match, or
+          # a CIDR range here.
           allow="203.0.113.*"
  
 -         # hash: what hash this password is hashed with. requires the module
 -         # for selected hash (m_md5.so, m_sha256.so or m_ripemd160.so) be
 -         # loaded and the password hashing module (m_password_hash.so)
 -         # loaded. Options here are: "md5", "sha256" and "ripemd160".
 -         # Optional, but recommended. Create hashed passwords with:
 -         # /mkpasswd <hash> <password>
 -         #hash="sha256"
 +         # hash: the hash function this password is hashed with. Requires the
 +         # module for the selected function (bcrypt, md5, sha1, sha256, or
 +         # ripemd160) and the password hashing module (password_hash) to be
 +         # loaded.
 +         # You may also use any of the above other than bcrypt prefixed with
 +         # either "hmac-" or "pbkdf2-hmac-" (requires the pbkdf2 module).
 +         # Create hashed passwords with: /mkpasswd <hash> <password>
 +         #hash="bcrypt"
  
           # password: Password to use for this block/user(s)
           password="secret"
  
  # Example of an executable file include. Note this will be read on rehash,
  # not when the command is run.
- #<execfiles motd="wget -O - http://www.example.com/motd.txt">
 -#<execfiles rules="wget -O - https://www.example.com/rules.txt">
 -
 -#-#-#-#-#-#-#-#-#-#-#-# MAXIMUM CHANNELS -#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
 -#                                                                     #
 -
 -<channels
 -          # users: Maximum number of channels a user can be in at once.
 -          users="20"
 -
 -          # opers: Maximum number of channels an oper can be in at once.
 -          opers="60">
++#<execfiles motd="wget -O - https://www.example.com/motd.txt">
  
  #-#-#-#-#-#-#-#-#-#-#-#-#-#-# DNS SERVER -#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
  # If these values are not defined, InspIRCd uses the default DNS resolver
  
           # defaultmodes: What modes are set on a empty channel when a user
           # joins it and it is unregistered.
 -         defaultmodes="nt"
 +         defaultmodes="not"
  
 -         # moronbanner: This is the text that is sent to a user when they are
 +         # xlinemessage: This is the text that is sent to a user when they are
           # banned from the server.
 -         moronbanner="You're banned! Email abuse@example.com with the ERROR line below for help."
 +         xlinemessage="You're banned! Email irc@example.com with the ERROR line below for help."
 +
 +         # allowzerolimit: If enabled then allow a limit of 0 to be set on channels.
 +         # This is non-standard behaviour and should only be enabled if you need to
 +         # link with servers running 2.0. Defaults to yes.
 +         allowzerolimit="no"
  
-          # exemptchanops: exemptions for channel access restrictions based on prefix.
-          exemptchanops="nonick:v flood:o"
+          # exemptchanops: Allows users with with a status mode to be exempt
+          # from various channel restrictions. Possible restrictions are:
+          #  - auditorium-see  Permission required to see the full user list of
+          #                    a +u channel (requires the auditorium module).
+          #  - auditorium-vis  Permission required to be visible in a +u channel
+          #                    (requires the auditorium module).
+          #  - blockcaps       Channel mode +B - blocks messages with too many capital
+          #                    letters (requires the blockcaps module).
+          #  - blockcolor      Channel mode +c - blocks messages with formatting codes
+          #                    (requires the blockcolor module).
+          #  - censor          Channel mode +G - censors messages based on the network
+          #                    configuration (requires the censor module).
+          #  - filter          Channel mode +g - blocks messages containing the given
+          #                    glob mask (requires the chanfilter module).
+          #  - flood           Channel mode +f - kicks (and bans) on text flood of a
+          #                    specified rate (requires the messageflood module).
+          #  - nickflood       Channel mode +F - blocks nick changes after a specified
+          #                    rate (requires the nickflood module).
+          #  - noctcp          Channel mode +C - blocks any CTCPs to the channel
+          #                    (requires the noctcp module).
+          #  - nonick          Channel mode +N - prevents users on the channel from
+          #                    changing nicks (requires the nonicks module).
+          #  - nonotice        Channel mode +T - blocks /NOTICEs to the channel
+          #                    (requires the nonotice module).
+          #  - regmoderated    Channel mode +M - blocks unregistered users from
+          #                    speaking (requires the services account module).
+          #  - stripcolor      Channel mode +S - strips formatting codes from
+          #                    messages (requires the stripcolor module).
+          #  - topiclock       Channel mode +t - limits changing the topic to (half)ops
+          # You can also configure this on a per-channel basis with a channel mode.
+          # See m_exemptchanops in modules.conf.example for more details.
+          exemptchanops="censor:o filter:o nickflood:o nonick:v regmoderated:o"
  
           # invitebypassmodes: This allows /invite to bypass other channel modes.
           # (Such as +k, +j, +l, etc.)
index da72775e915435b343fd25f49a34c152c32d31d3,c3f074b94b82bb069bfc6c89844e29c1c3d5249f..6955b2d74f7f397db1711f8d2d5d217ddc83bd79
  # characters in the channel name such as bold, colorcodes, etc. which
  # can be quite annoying and allow users to on occasion have a channel
  # that looks like the name of another channel on the network.
 -#<module name="m_channames.so">
 +#<module name="channames">
  
- <channames
#<channames
        # denyrange: characters or range of characters to deny in channel
        # names.
-       denyrange="2,3"
+       #denyrange="2,3"
  
        # allowrange: characters or range of characters to specifically allow
        # in channel names.
  
  #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
  # Exempt channel operators module: Provides support for allowing      #
- # channel operators to be exempt from some channel modes.  Supported  #
- # modes are blockcaps, noctcp, blockcolor, nickflood, flood, censor,  #
- # filter, regmoderated, nonick, nonotice, and stripcolor.             #
+ # users of a specified channel status to be exempt from some channel  #
+ # restriction modes. Supported restrictions are                       #
+ # blockcaps, blockcolor, censor, filter, flood, nickflood, noctcp,    #
+ # nonick, nonotice, regmoderated, stripcolor, and topiclock.          #
+ # See <options:exemptchanops> in inspircd.conf.example for a more     #
+ # detailed list of the restriction modes that can be exempted.        #
+ # These are settable using /mode #chan +X <restriction>:<status>      #
 -#<module name="m_exemptchanops.so">                                   #
 +#<module name="exemptchanops">                                        #
  
  #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
  # Filter module: Provides message filtering, similar to SPAMFILTER.   #
  #
  #-#-#-#-#-#-#-#-#-#-#-#-  HELPOP  CONFIGURATION  -#-#-#-#-#-#-#-#-#-#-#
  #                                                                     #
 -# If you specify to use the m_helpop.so module, then specify below    #
 -# the path to the helpop.conf file.                                   #
 -#<include file="conf/examples/helpop-full.conf.example">
 +# If you specify to use the helpop module, then specify below the     #
 +# path to the helpop.conf file.                                       #
 +#                                                                     #
- #<include file="examples/inspircd.helpop-full.example">
++#<include file="examples/helpop-full.conf.example">
  
  #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
  # Hide chans module: Allows users to hide their channels list from non-
index 11bf6d55a8fdc692c9efc5b453251a0cae456818,b16dcc49aa626f56c8c04190b0a5b5e1aea45a37..082079cd98512213070159f912047932b3f00987
@@@ -211,23 -322,23 +211,23 @@@ enum Priority { PRIORITY_FIRST, PRIORIT
   */
  enum Implementation
  {
 -      I_BEGIN,
 -      I_OnUserConnect, I_OnUserQuit, I_OnUserDisconnect, I_OnUserJoin, I_OnUserPart, I_OnRehash,
 -      I_OnSendSnotice, I_OnUserPreJoin, I_OnUserPreKick, I_OnUserKick, I_OnOper, I_OnInfo, I_OnWhois,
 -      I_OnUserPreInvite, I_OnUserInvite, I_OnUserPreMessage, I_OnUserPreNotice, I_OnUserPreNick,
 -      I_OnUserMessage, I_OnUserNotice, I_OnMode, I_OnGetServerDescription, I_OnSyncUser,
 -      I_OnSyncChannel, I_OnDecodeMetaData, I_OnWallops, I_OnAcceptConnection, I_OnUserInit,
 +      I_OnUserConnect, I_OnUserQuit, I_OnUserDisconnect, I_OnUserJoin, I_OnUserPart,
 +      I_OnSendSnotice, I_OnUserPreJoin, I_OnUserPreKick, I_OnUserKick, I_OnOper, I_OnInfo,
 +      I_OnUserPreInvite, I_OnUserInvite, I_OnUserPreMessage, I_OnUserPreNick,
 +      I_OnUserPostMessage, I_OnUserMessageBlocked, I_OnMode,
 +      I_OnDecodeMetaData, I_OnAcceptConnection, I_OnUserInit,
        I_OnChangeHost, I_OnChangeName, I_OnAddLine, I_OnDelLine, I_OnExpireLine,
 -      I_OnUserPostNick, I_OnPreMode, I_On005Numeric, I_OnKill, I_OnRemoteKill, I_OnLoadModule,
 +      I_OnUserPostNick, I_OnPreMode, I_On005Numeric, I_OnKill, I_OnLoadModule,
        I_OnUnloadModule, I_OnBackgroundTimer, I_OnPreCommand, I_OnCheckReady, I_OnCheckInvite,
        I_OnRawMode, I_OnCheckKey, I_OnCheckLimit, I_OnCheckBan, I_OnCheckChannelBan, I_OnExtBanCheck,
 -      I_OnStats, I_OnChangeLocalUserHost, I_OnPreTopicChange, I_OnPostDeoper,
 -      I_OnPostTopicChange, I_OnEvent, I_OnGlobalOper, I_OnPostConnect, I_OnAddBan,
 -      I_OnDelBan, I_OnChangeLocalUserGECOS, I_OnUserRegister, I_OnChannelPreDelete, I_OnChannelDelete,
 -      I_OnPostOper, I_OnSyncNetwork, I_OnSetAway, I_OnPostCommand, I_OnPostJoin,
 -      I_OnWhoisLine, I_OnBuildNeighborList, I_OnGarbageCollect, I_OnSetConnectClass,
 -      I_OnText, I_OnPassCompare, I_OnRunTestSuite, I_OnNamesListItem, I_OnNumeric, I_OnHookIO,
 +      I_OnChangeLocalUserHost, I_OnPreTopicChange,
-       I_OnPostTopicChange, I_OnPostConnect,
++      I_OnPostTopicChange, I_OnPostConnect, I_OnPostDeoper,
 +      I_OnChangeLocalUserGECOS, I_OnUserRegister, I_OnChannelPreDelete, I_OnChannelDelete,
 +      I_OnPostOper, I_OnSetAway, I_OnPostCommand, I_OnPostJoin,
 +      I_OnBuildNeighborList, I_OnGarbageCollect, I_OnSetConnectClass,
 +      I_OnUserMessage, I_OnPassCompare, I_OnNamesListItem, I_OnNumeric,
        I_OnPreRehash, I_OnModuleRehash, I_OnSendWhoLine, I_OnChangeIdent, I_OnSetUserIP,
 +      I_OnServiceAdd, I_OnServiceDel,
        I_END
  };
  
diff --cc modulemanager
Simple merge
diff --cc src/modules.cpp
index 9359cac3755934c8db5b582d0fa2e3e10048c3bc,7df7579bf84172afbce39afc41206bc0d9000e36..ab10d6ae13ead59f48d3f638f30a1ba29ada72e1
@@@ -63,100 -85,101 +63,101 @@@ Module::~Module(
  {
  }
  
 -ModResult     Module::OnSendSnotice(char &snomask, std::string &type, const std::string &message) { return MOD_RES_PASSTHRU; }
 -void          Module::OnUserConnect(LocalUser*) { }
 -void          Module::OnUserQuit(User*, const std::string&, const std::string&) { }
 -void          Module::OnUserDisconnect(LocalUser*) { }
 -void          Module::OnUserJoin(Membership*, bool, bool, CUList&) { }
 -void          Module::OnPostJoin(Membership*) { }
 -void          Module::OnUserPart(Membership*, std::string&, CUList&) { }
 -void          Module::OnPreRehash(User*, const std::string&) { }
 -void          Module::OnModuleRehash(User*, const std::string&) { }
 -void          Module::OnRehash(User*) { }
 -ModResult     Module::OnUserPreJoin(User*, Channel*, const char*, std::string&, const std::string&) { return MOD_RES_PASSTHRU; }
 -void          Module::OnMode(User*, void*, int, const std::vector<std::string>&, const std::vector<TranslateType>&) { }
 -void          Module::OnOper(User*, const std::string&) { }
 -void          Module::OnPostOper(User*, const std::string&, const std::string &) { }
 -void          Module::OnPostDeoper(User*) { }
 -void          Module::OnInfo(User*) { }
 -void          Module::OnWhois(User*, User*) { }
 -ModResult     Module::OnUserPreInvite(User*, User*, Channel*, time_t) { return MOD_RES_PASSTHRU; }
 -ModResult     Module::OnUserPreMessage(User*, void*, int, std::string&, char, CUList&) { return MOD_RES_PASSTHRU; }
 -ModResult     Module::OnUserPreNotice(User*, void*, int, std::string&, char, CUList&) { return MOD_RES_PASSTHRU; }
 -ModResult     Module::OnUserPreNick(User*, const std::string&) { return MOD_RES_PASSTHRU; }
 -void          Module::OnUserPostNick(User*, const std::string&) { }
 -ModResult     Module::OnPreMode(User*, User*, Channel*, const std::vector<std::string>&) { return MOD_RES_PASSTHRU; }
 -void          Module::On005Numeric(std::string&) { }
 -ModResult     Module::OnKill(User*, User*, const std::string&) { return MOD_RES_PASSTHRU; }
 -void          Module::OnLoadModule(Module*) { }
 -void          Module::OnUnloadModule(Module*) { }
 -void          Module::OnBackgroundTimer(time_t) { }
 -ModResult     Module::OnPreCommand(std::string&, std::vector<std::string>&, LocalUser*, bool, const std::string&) { return MOD_RES_PASSTHRU; }
 -void          Module::OnPostCommand(const std::string&, const std::vector<std::string>&, LocalUser*, CmdResult, const std::string&) { }
 -void          Module::OnUserInit(LocalUser*) { }
 -ModResult     Module::OnCheckReady(LocalUser*) { return MOD_RES_PASSTHRU; }
 -ModResult     Module::OnUserRegister(LocalUser*) { return MOD_RES_PASSTHRU; }
 -ModResult     Module::OnUserPreKick(User*, Membership*, const std::string&) { return MOD_RES_PASSTHRU; }
 -void          Module::OnUserKick(User*, Membership*, const std::string&, CUList&) { }
 -ModResult     Module::OnRawMode(User*, Channel*, const char, const std::string &, bool, int) { return MOD_RES_PASSTHRU; }
 -ModResult     Module::OnCheckInvite(User*, Channel*) { return MOD_RES_PASSTHRU; }
 -ModResult     Module::OnCheckKey(User*, Channel*, const std::string&) { return MOD_RES_PASSTHRU; }
 -ModResult     Module::OnCheckLimit(User*, Channel*) { return MOD_RES_PASSTHRU; }
 -ModResult     Module::OnCheckChannelBan(User*, Channel*) { return MOD_RES_PASSTHRU; }
 -ModResult     Module::OnCheckBan(User*, Channel*, const std::string&) { return MOD_RES_PASSTHRU; }
 -ModResult     Module::OnExtBanCheck(User*, Channel*, char) { return MOD_RES_PASSTHRU; }
 -ModResult     Module::OnStats(char, User*, string_list&) { return MOD_RES_PASSTHRU; }
 -ModResult     Module::OnChangeLocalUserHost(LocalUser*, const std::string&) { return MOD_RES_PASSTHRU; }
 -ModResult     Module::OnChangeLocalUserGECOS(LocalUser*, const std::string&) { return MOD_RES_PASSTHRU; }
 -ModResult     Module::OnPreTopicChange(User*, Channel*, const std::string&) { return MOD_RES_PASSTHRU; }
 -void          Module::OnEvent(Event&) { }
 -void          Module::OnRequest(Request&) { }
 -ModResult     Module::OnPassCompare(Extensible* ex, const std::string &password, const std::string &input, const std::string& hashtype) { return MOD_RES_PASSTHRU; }
 -void          Module::OnGlobalOper(User*) { }
 -void          Module::OnPostConnect(User*) { }
 -ModResult     Module::OnAddBan(User*, Channel*, const std::string &) { return MOD_RES_PASSTHRU; }
 -ModResult     Module::OnDelBan(User*, Channel*, const std::string &) { return MOD_RES_PASSTHRU; }
 -void          Module::OnStreamSocketAccept(StreamSocket*, irc::sockets::sockaddrs*, irc::sockets::sockaddrs*) { }
 -int           Module::OnStreamSocketWrite(StreamSocket*, std::string&) { return -1; }
 -void          Module::OnStreamSocketClose(StreamSocket*) { }
 -void          Module::OnStreamSocketConnect(StreamSocket*) { }
 -int           Module::OnStreamSocketRead(StreamSocket*, std::string&) { return -1; }
 -void          Module::OnUserMessage(User*, void*, int, const std::string&, char, const CUList&) { }
 -void          Module::OnUserNotice(User*, void*, int, const std::string&, char, const CUList&) { }
 -void          Module::OnRemoteKill(User*, User*, const std::string&, const std::string&) { }
 -void          Module::OnUserInvite(User*, User*, Channel*, time_t) { }
 -void          Module::OnPostTopicChange(User*, Channel*, const std::string&) { }
 -void          Module::OnGetServerDescription(const std::string&, std::string&) { }
 -void          Module::OnSyncUser(User*, Module*, void*) { }
 -void          Module::OnSyncChannel(Channel*, Module*, void*) { }
 -void          Module::OnSyncNetwork(Module*, void*) { }
 -void          Module::ProtoSendMode(void*, TargetTypeFlags, void*, const std::vector<std::string>&, const std::vector<TranslateType>&) { }
 -void          Module::OnDecodeMetaData(Extensible*, const std::string&, const std::string&) { }
 -void          Module::ProtoSendMetaData(void*, Extensible*, const std::string&, const std::string&) { }
 -void          Module::OnWallops(User*, const std::string&) { }
 -void          Module::OnChangeHost(User*, const std::string&) { }
 -void          Module::OnChangeName(User*, const std::string&) { }
 -void          Module::OnChangeIdent(User*, const std::string&) { }
 -void          Module::OnAddLine(User*, XLine*) { }
 -void          Module::OnDelLine(User*, XLine*) { }
 -void          Module::OnExpireLine(XLine*) { }
 -void          Module::OnCleanup(int, void*) { }
 -ModResult     Module::OnChannelPreDelete(Channel*) { return MOD_RES_PASSTHRU; }
 -void          Module::OnChannelDelete(Channel*) { }
 -ModResult     Module::OnSetAway(User*, const std::string &) { return MOD_RES_PASSTHRU; }
 -ModResult     Module::OnWhoisLine(User*, User*, int&, std::string&) { return MOD_RES_PASSTHRU; }
 -void          Module::OnBuildNeighborList(User*, UserChanList&, std::map<User*,bool>&) { }
 -void          Module::OnGarbageCollect() { }
 -ModResult     Module::OnSetConnectClass(LocalUser* user, ConnectClass* myclass) { return MOD_RES_PASSTHRU; }
 -void          Module::OnText(User*, void*, int, const std::string&, char, CUList&) { }
 +void Module::DetachEvent(Implementation i)
 +{
 +      ServerInstance->Modules->Detach(i, this);
 +}
 +
 +void          Module::ReadConfig(ConfigStatus& status) { }
 +ModResult     Module::OnSendSnotice(char &snomask, std::string &type, const std::string &message) { DetachEvent(I_OnSendSnotice); return MOD_RES_PASSTHRU; }
 +void          Module::OnUserConnect(LocalUser*) { DetachEvent(I_OnUserConnect); }
 +void          Module::OnUserQuit(User*, const std::string&, const std::string&) { DetachEvent(I_OnUserQuit); }
 +void          Module::OnUserDisconnect(LocalUser*) { DetachEvent(I_OnUserDisconnect); }
 +void          Module::OnUserJoin(Membership*, bool, bool, CUList&) { DetachEvent(I_OnUserJoin); }
 +void          Module::OnPostJoin(Membership*) { DetachEvent(I_OnPostJoin); }
 +void          Module::OnUserPart(Membership*, std::string&, CUList&) { DetachEvent(I_OnUserPart); }
 +void          Module::OnPreRehash(User*, const std::string&) { DetachEvent(I_OnPreRehash); }
 +void          Module::OnModuleRehash(User*, const std::string&) { DetachEvent(I_OnModuleRehash); }
 +ModResult     Module::OnUserPreJoin(LocalUser*, Channel*, const std::string&, std::string&, const std::string&) { DetachEvent(I_OnUserPreJoin); return MOD_RES_PASSTHRU; }
 +void          Module::OnMode(User*, User*, Channel*, const Modes::ChangeList&, ModeParser::ModeProcessFlag, const std::string&) { DetachEvent(I_OnMode); }
 +void          Module::OnOper(User*, const std::string&) { DetachEvent(I_OnOper); }
 +void          Module::OnPostOper(User*, const std::string&, const std::string &) { DetachEvent(I_OnPostOper); }
++void          Module::OnPostDeoper(User*) { DetachEvent(I_OnPostDeoper); }
 +void          Module::OnInfo(User*) { DetachEvent(I_OnInfo); }
 +ModResult     Module::OnUserPreInvite(User*, User*, Channel*, time_t) { DetachEvent(I_OnUserPreInvite); return MOD_RES_PASSTHRU; }
 +ModResult     Module::OnUserPreMessage(User*, const MessageTarget&, MessageDetails&) { DetachEvent(I_OnUserPreMessage); return MOD_RES_PASSTHRU; }
 +ModResult     Module::OnUserPreNick(LocalUser*, const std::string&) { DetachEvent(I_OnUserPreNick); return MOD_RES_PASSTHRU; }
 +void          Module::OnUserPostNick(User*, const std::string&) { DetachEvent(I_OnUserPostNick); }
 +ModResult     Module::OnPreMode(User*, User*, Channel*, Modes::ChangeList&) { DetachEvent(I_OnPreMode); return MOD_RES_PASSTHRU; }
 +void          Module::On005Numeric(std::map<std::string, std::string>&) { DetachEvent(I_On005Numeric); }
 +ModResult     Module::OnKill(User*, User*, const std::string&) { DetachEvent(I_OnKill); return MOD_RES_PASSTHRU; }
 +void          Module::OnLoadModule(Module*) { DetachEvent(I_OnLoadModule); }
 +void          Module::OnUnloadModule(Module*) { DetachEvent(I_OnUnloadModule); }
 +void          Module::OnBackgroundTimer(time_t) { DetachEvent(I_OnBackgroundTimer); }
 +ModResult     Module::OnPreCommand(std::string&, std::vector<std::string>&, LocalUser*, bool, const std::string&) { DetachEvent(I_OnPreCommand); return MOD_RES_PASSTHRU; }
 +void          Module::OnPostCommand(Command*, const std::vector<std::string>&, LocalUser*, CmdResult, const std::string&) { DetachEvent(I_OnPostCommand); }
 +void          Module::OnUserInit(LocalUser*) { DetachEvent(I_OnUserInit); }
 +ModResult     Module::OnCheckReady(LocalUser*) { DetachEvent(I_OnCheckReady); return MOD_RES_PASSTHRU; }
 +ModResult     Module::OnUserRegister(LocalUser*) { DetachEvent(I_OnUserRegister); return MOD_RES_PASSTHRU; }
 +ModResult     Module::OnUserPreKick(User*, Membership*, const std::string&) { DetachEvent(I_OnUserPreKick); return MOD_RES_PASSTHRU; }
 +void          Module::OnUserKick(User*, Membership*, const std::string&, CUList&) { DetachEvent(I_OnUserKick); }
 +ModResult     Module::OnRawMode(User*, Channel*, ModeHandler*, const std::string&, bool) { DetachEvent(I_OnRawMode); return MOD_RES_PASSTHRU; }
 +ModResult     Module::OnCheckInvite(User*, Channel*) { DetachEvent(I_OnCheckInvite); return MOD_RES_PASSTHRU; }
 +ModResult     Module::OnCheckKey(User*, Channel*, const std::string&) { DetachEvent(I_OnCheckKey); return MOD_RES_PASSTHRU; }
 +ModResult     Module::OnCheckLimit(User*, Channel*) { DetachEvent(I_OnCheckLimit); return MOD_RES_PASSTHRU; }
 +ModResult     Module::OnCheckChannelBan(User*, Channel*) { DetachEvent(I_OnCheckChannelBan); return MOD_RES_PASSTHRU; }
 +ModResult     Module::OnCheckBan(User*, Channel*, const std::string&) { DetachEvent(I_OnCheckBan); return MOD_RES_PASSTHRU; }
 +ModResult     Module::OnExtBanCheck(User*, Channel*, char) { DetachEvent(I_OnExtBanCheck); return MOD_RES_PASSTHRU; }
 +ModResult     Module::OnChangeLocalUserHost(LocalUser*, const std::string&) { DetachEvent(I_OnChangeLocalUserHost); return MOD_RES_PASSTHRU; }
 +ModResult     Module::OnChangeLocalUserGECOS(LocalUser*, const std::string&) { DetachEvent(I_OnChangeLocalUserGECOS); return MOD_RES_PASSTHRU; }
 +ModResult     Module::OnPreTopicChange(User*, Channel*, const std::string&) { DetachEvent(I_OnPreTopicChange); return MOD_RES_PASSTHRU; }
 +ModResult     Module::OnPassCompare(Extensible* ex, const std::string &password, const std::string &input, const std::string& hashtype) { DetachEvent(I_OnPassCompare); return MOD_RES_PASSTHRU; }
 +void          Module::OnPostConnect(User*) { DetachEvent(I_OnPostConnect); }
 +void          Module::OnUserPostMessage(User*, const MessageTarget&, const MessageDetails&) { DetachEvent(I_OnUserPostMessage); }
 +void          Module::OnUserMessageBlocked(User*, const MessageTarget&, const MessageDetails&) { DetachEvent(I_OnUserMessageBlocked); }
 +void          Module::OnUserInvite(User*, User*, Channel*, time_t, unsigned int, CUList&) { DetachEvent(I_OnUserInvite); }
 +void          Module::OnPostTopicChange(User*, Channel*, const std::string&) { DetachEvent(I_OnPostTopicChange); }
 +void          Module::OnDecodeMetaData(Extensible*, const std::string&, const std::string&) { DetachEvent(I_OnDecodeMetaData); }
 +void          Module::OnChangeHost(User*, const std::string&) { DetachEvent(I_OnChangeHost); }
 +void          Module::OnChangeName(User*, const std::string&) { DetachEvent(I_OnChangeName); }
 +void          Module::OnChangeIdent(User*, const std::string&) { DetachEvent(I_OnChangeIdent); }
 +void          Module::OnAddLine(User*, XLine*) { DetachEvent(I_OnAddLine); }
 +void          Module::OnDelLine(User*, XLine*) { DetachEvent(I_OnDelLine); }
 +void          Module::OnExpireLine(XLine*) { DetachEvent(I_OnExpireLine); }
 +void          Module::OnCleanup(ExtensionItem::ExtensibleType, Extensible*) { }
 +ModResult     Module::OnChannelPreDelete(Channel*) { DetachEvent(I_OnChannelPreDelete); return MOD_RES_PASSTHRU; }
 +void          Module::OnChannelDelete(Channel*) { DetachEvent(I_OnChannelDelete); }
 +ModResult     Module::OnSetAway(User*, const std::string &) { DetachEvent(I_OnSetAway); return MOD_RES_PASSTHRU; }
 +void          Module::OnBuildNeighborList(User*, IncludeChanList&, std::map<User*,bool>&) { DetachEvent(I_OnBuildNeighborList); }
 +void          Module::OnGarbageCollect() { DetachEvent(I_OnGarbageCollect); }
 +ModResult     Module::OnSetConnectClass(LocalUser* user, ConnectClass* myclass) { DetachEvent(I_OnSetConnectClass); return MOD_RES_PASSTHRU; }
 +void          Module::OnUserMessage(User*, const MessageTarget&, const MessageDetails&) { DetachEvent(I_OnUserMessage); }
 +ModResult     Module::OnNamesListItem(User*, Membership*, std::string&, std::string&) { DetachEvent(I_OnNamesListItem); return MOD_RES_PASSTHRU; }
 +ModResult     Module::OnNumeric(User*, const Numeric::Numeric&) { DetachEvent(I_OnNumeric); return MOD_RES_PASSTHRU; }
 +ModResult   Module::OnAcceptConnection(int, ListenSocket*, irc::sockets::sockaddrs*, irc::sockets::sockaddrs*) { DetachEvent(I_OnAcceptConnection); return MOD_RES_PASSTHRU; }
 +ModResult     Module::OnSendWhoLine(User*, const std::vector<std::string>&, User*, Membership*, Numeric::Numeric&) { DetachEvent(I_OnSendWhoLine); return MOD_RES_PASSTHRU; }
 +void          Module::OnSetUserIP(LocalUser*) { DetachEvent(I_OnSetUserIP); }
 +void          Module::OnServiceAdd(ServiceProvider&) { DetachEvent(I_OnServiceAdd); }
 +void          Module::OnServiceDel(ServiceProvider&) { DetachEvent(I_OnServiceDel); }
 +
 +#ifdef INSPIRCD_ENABLE_TESTSUITE
  void          Module::OnRunTestSuite() { }
 -void          Module::OnNamesListItem(User*, Membership*, std::string&, std::string&) { }
 -ModResult     Module::OnNumeric(User*, unsigned int, const std::string&) { return MOD_RES_PASSTHRU; }
 -void          Module::OnHookIO(StreamSocket*, ListenSocket*) { }
 -ModResult   Module::OnAcceptConnection(int, ListenSocket*, irc::sockets::sockaddrs*, irc::sockets::sockaddrs*) { return MOD_RES_PASSTHRU; }
 -void          Module::OnSendWhoLine(User*, const std::vector<std::string>&, User*, std::string&) { }
 -void          Module::OnSetUserIP(LocalUser*) { }
 +#endif
 +
 +ServiceProvider::ServiceProvider(Module* Creator, const std::string& Name, ServiceType Type)
 +      : creator(Creator), name(Name), service(Type)
 +{
 +      if ((ServerInstance) && (ServerInstance->Modules->NewServices))
 +              ServerInstance->Modules->NewServices->push_back(this);
 +}
  
 -ModuleManager::ModuleManager() : ModCount(0)
 +void ServiceProvider::DisableAutoRegister()
 +{
 +      if ((ServerInstance) && (ServerInstance->Modules->NewServices))
 +              stdalgo::erase(*ServerInstance->Modules->NewServices, this);
 +}
 +
 +ModuleManager::ModuleManager()
  {
  }
  
index 7083be6acba44fb7b317142791a50a33202633ad,03b7a55f75c95895315bff75492ec0115b31e999..0d7c2eb70636a17a327f061365197d5efe6e83ed
@@@ -146,22 -99,16 +146,29 @@@ class ModuleGeoIP : public Module, publ
                return MOD_RES_DENY;
        }
  
 -      void OnSetUserIP(LocalUser* user)
++      void OnSetUserIP(LocalUser* user) CXX11_OVERRIDE
+       {
+               // If user has sent NICK/USER, re-set the ExtItem as this is likely CGI:IRC changing the IP
+               if (user->registered == REG_NICKUSER)
+                       SetExt(user);
+       }
 -      ModResult OnStats(char symbol, User* user, string_list &out)
 +      void OnWhois(Whois::Context& whois) CXX11_OVERRIDE
 +      {
 +              // If the extban is disabled we don't expose users location.
 +              if (!extban)
 +                      return;
 +
 +              std::string* cc = ext.get(whois.GetTarget());
 +              if (!cc)
 +                      cc = SetExt(whois.GetTarget());
 +
 +              whois.SendLine(RPL_WHOISCOUNTRY, *cc, "is located in this country");
 +      }
 +
 +      ModResult OnStats(Stats::Context& stats) CXX11_OVERRIDE
        {
 -              if (symbol != 'G')
 +              if (stats.GetSymbol() != 'G')
                        return MOD_RES_PASSTHRU;
  
                unsigned int unknown = 0;
index 4a4188757c23f31c5f59c59c065214ba88de984d,1d35c293454dbb9bbebbbac32541e7415e8bb68e..5ec75f13ce12d016f942f3bfdc650071bf806a4b
@@@ -182,6 -178,21 +182,21 @@@ class BanRedirect : public ModeWatche
                                                redirects = new BanRedirectList;
                                                extItem.set(channel, redirects);
                                        }
 -                                                      if ((irc::string(redir->targetchan.c_str()) == irc::string(mask[CHAN].c_str())) && (irc::string(redir->banmask.c_str()) == irc::string(param.c_str())))
+                                       else
+                                       {
+                                               for (BanRedirectList::iterator redir = redirects->begin(); redir != redirects->end(); ++redir)
+                                               {
+                                                       // Mimic the functionality used when removing the mode
++                                                      if (irc::equals(redir->targetchan, mask[CHAN]) && irc::equals(redir->banmask, param))
+                                                       {
+                                                               // Make sure the +b handler will still set the right ban
+                                                               param.append(mask[CHAN]);
+                                                               // Silently ignore the duplicate and don't set metadata
+                                                               // This still allows channel ops to set/unset a redirect ban to clear "ghost" redirects
+                                                               return true;
+                                                       }
+                                               }
+                                       }
  
                                        /* Here 'param' doesn't have the channel on it yet */
                                        redirects->push_back(BanRedirectEntry(mask[CHAN], param));
Simple merge
index c7c14e30cd7cecfb9d0821ec3a505971ea961aa3,b29d268d14d1f6973136f08251087cf4b7793927..d42649909babf9d48c0c6d612d00c14c664f37ab
@@@ -37,16 -32,18 +37,18 @@@ enu
  class CommandSwhois : public Command
  {
   public:
+       LocalIntExt operblock;
        StringExtItem swhois;
        CommandSwhois(Module* Creator)
 -              : Command(Creator,"SWHOIS", 2,2)
 -              , operblock("swhois_operblock", Creator)
 -              , swhois("swhois", Creator)
 +              : Command(Creator, "SWHOIS", 2, 2)
++              , operblock("swhois_operblock", ExtensionItem::EXT_USER, Creator)
 +              , swhois("swhois", ExtensionItem::EXT_USER, Creator)
        {
                flags_needed = 'o'; syntax = "<nick> :<swhois>";
 -              TRANSLATE3(TR_NICK, TR_TEXT, TR_END);
 +              TRANSLATE2(TR_NICK, TR_TEXT);
        }
  
 -      CmdResult Handle(const std::vector<std::string> &parameters, User* user)
 +      CmdResult Handle(const std::vector<std::string>& parameters, User* user) CXX11_OVERRIDE
        {
                User* dest = ServerInstance->FindNick(parameters[0]);
  
@@@ -131,7 -136,34 +135,28 @@@ class ModuleSWhois : public Module, pub
                ServerInstance->PI->SendMetaData(user, "swhois", swhois);
        }
  
 -      void OnPostDeoper(User* user)
++      void OnPostDeoper(User* user) CXX11_OVERRIDE
+       {
+               std::string* swhois = cmd.swhois.get(user);
+               if (!swhois)
+                       return;
+               if (!cmd.operblock.get(user))
+                       return;
+               cmd.operblock.set(user, 0);
+               cmd.swhois.unset(user);
+               ServerInstance->PI->SendMetaData(user, "swhois", "");
+       }
 -      void OnDecodeMetaData(Extensible* target, const std::string& extname, const std::string&)
++      void OnDecodeMetaData(Extensible* target, const std::string& extname, const std::string&) CXX11_OVERRIDE
+       {
 -              // XXX: We use a dynamic_cast in m_services_account so I used one
 -              // here but do we actually need it or is static_cast okay?
 -              User* dest = dynamic_cast<User*>(target);
++              User* dest = static_cast<User*>(target);
+               if (dest && (extname == "swhois"))
+                       cmd.operblock.set(dest, 0);
+       }
 -      ~ModuleSWhois()
 -      {
 -      }
 -
 -      Version GetVersion()
 +      Version GetVersion() CXX11_OVERRIDE
        {
                return Version("Provides the SWHOIS command which allows setting of arbitrary WHOIS lines", VF_OPTCOMMON | VF_VENDOR);
        }
index d220027fef5fdb5fe7cbf87e27ecfac92c6e7c02,fb2a6f65a1325ecdeebad5b7f2d0948eee991b28..fb0c81d2fb4186169c30cd78b4aa634aaf5b5ea8
@@@ -113,9 -129,8 +113,9 @@@ class ModuleXLineDB : public Modul
                        for (LookupIter i = lookup->begin(); i != lookup->end(); ++i)
                        {
                                XLine* line = i->second;
 -                              fprintf(f, "LINE %s %s %s %lu %lu :%s\n", line->type.c_str(), line->Displayable(),
 -                                      line->source.c_str(), (unsigned long)line->set_time, (unsigned long)line->duration, line->reason.c_str());
 +                              stream << "LINE " << line->type << " " << line->Displayable() << " "
-                                       << ServerInstance->Config->ServerName << " " << line->set_time << " "
++                                      << line->source << " " << line->set_time << " "
 +                                      << line->duration << " :" << line->reason << std::endl;
                        }
                }
  
diff --cc src/users.cpp
index 5f31ff299e87d1fa0fd651141471c261efb9a7f0,ac87f1187992cc943d1dab44cc9de778473ffcdb..1e2554107b1905c1d1a9bb1f30918e2c85330ebb
@@@ -442,22 -672,39 +442,23 @@@ void User::UnOper(
  
  
        /* Remove all oper only modes from the user when the deoper - Bug #466*/
 -      std::string moderemove("-");
 -
 -      for (unsigned char letter = 'A'; letter <= 'z'; letter++)
 +      Modes::ChangeList changelist;
 +      const ModeParser::ModeHandlerMap& usermodes = ServerInstance->Modes->GetModes(MODETYPE_USER);
 +      for (ModeParser::ModeHandlerMap::const_iterator i = usermodes.begin(); i != usermodes.end(); ++i)
        {
 -              ModeHandler* mh = ServerInstance->Modes->FindMode(letter, MODETYPE_USER);
 -              if (mh && mh->NeedsOper())
 -                      moderemove += letter;
 +              ModeHandler* mh = i->second;
 +              if (mh->NeedsOper())
 +                      changelist.push_remove(mh);
        }
  
 +      ServerInstance->Modes->Process(this, NULL, this, changelist);
  
 -      std::vector<std::string> parameters;
 -      parameters.push_back(this->nick);
 -      parameters.push_back(moderemove);
 -
 -      ServerInstance->Parser->CallHandler("MODE", parameters, this);
 -
 -      /* remove the user from the oper list. Will remove multiple entries as a safeguard against bug #404 */
 -      ServerInstance->Users->all_opers.remove(this);
 +      // Remove the user from the oper list
 +      stdalgo::vector::swaperase(ServerInstance->Users->all_opers, this);
  
 -      this->modes[UM_OPERATOR] = 0;
 -      FOREACH_MOD(I_OnPostDeoper, OnPostDeoper(this));
 -}
 -
 -/* adds or updates an entry in the whowas list */
 -void User::AddToWhoWas()
 -{
 -      Module* whowas = ServerInstance->Modules->Find("cmd_whowas.so");
 -      if (whowas)
 -      {
 -              WhowasRequest req(NULL, whowas, WhowasRequest::WHOWAS_ADD);
 -              req.user = this;
 -              req.Send();
 -      }
 +      ModeHandler* opermh = ServerInstance->Modes->FindMode('o', MODETYPE_USER);
 +      this->SetMode(opermh, false);
++      FOREACH_MOD(OnPostDeoper, (this));
  }
  
  /*
diff --cc src/xline.cpp
index dfd7e290301040afb1d8aa3f5ab203d017aefc51,586c7342ac2197094cdb947316627adc5a11875e..cb4f011c0fffa76f8c8caa90d01c474a2a93b34f
@@@ -589,13 -593,9 +589,9 @@@ void GLine::Apply(User* u
  
  bool ELine::Matches(User *u)
  {
-       LocalUser* lu = IS_LOCAL(u);
-       if (lu && lu->exempt)
-               return false;
        if (InspIRCd::Match(u->ident, this->identmask, ascii_case_insensitive_map))
        {
 -              if (InspIRCd::MatchCIDR(u->host, this->hostmask, ascii_case_insensitive_map) ||
 +              if (InspIRCd::MatchCIDR(u->GetRealHost(), this->hostmask, ascii_case_insensitive_map) ||
                    InspIRCd::MatchCIDR(u->GetIPString(), this->hostmask, ascii_case_insensitive_map))
                {
                        return true;