1
0
mirror of https://github.com/anope/anope.git synced 2026-06-14 09:54:47 +02:00

Compare commits

...

173 Commits

Author SHA1 Message Date
Adam a762391446 Anope 2.0.2 Release 2015-03-22 15:34:50 -04:00
Adam c070a00114 Fix m_ldap_oper to build 2015-03-22 15:34:49 -04:00
Adam e7c3090a70 Fix new version stuff with empty version extra 2015-03-22 14:38:29 -04:00
Adam 5dd6326eff Merge pull request #115 from aFreshMelon/aFreshMelon-patch-1
XML-RPC responses also don't have a methodName tag
2015-03-22 13:56:07 -04:00
Adam 535ad6fd70 Merge pull request #112 from attilamolnar/2.0+inspircdmlock
InspIRCd 2.0: Ensure ircd-side mlock and topic lock state is always what we think it should be
2015-03-22 13:56:01 -04:00
Robby- 5df4ac9a98 Make the signed kick/ban message format configurable. 2015-03-22 13:44:08 -04:00
Adam 4c54a3939f Change git version name back to what it was, which the core uses 2015-03-22 10:26:53 -04:00
Adam 3d09748d1c Fix typo in Changes 2015-03-22 10:26:26 -04:00
Sebastian Barfurth 36a4be7623 XML-RPC responses also don't have a methodName tag
Following http://xmlrpc.scripting.com/spec.html
2015-03-18 19:06:08 +01:00
Adam 5fc72660e4 Merge pull request #113 from attilamolnar/2.0+openssl
m_ssl_openssl: SSL context option changes
2015-03-12 17:53:52 -04:00
Adam 303e652a35 Only apply keepmodes on channel sync
Not sure why this was this way originally, it interfears with the
chanserv +r check to determine how new the channel is because it
restores +r. This seems to still work okay, though.
2015-03-12 17:52:38 -04:00
Adam e5447a8024 Update Changes.conf and Changes 2015-03-12 17:52:38 -04:00
Attila Molnar 1bee18fcf4 m_ssl_openssl: Allow disabling SSLv3 via the config 2015-03-12 19:35:07 +01:00
Attila Molnar a57e41304f m_ssl_openssl: Set sane default context options 2015-03-12 19:35:07 +01:00
Adam e0e8147ee0 Merge pull request #114 from anope/revert-99-extemp_protected
Revert "Added kickcheck override for users with protected privs"
2015-03-12 13:30:12 -04:00
Adam 41a24afa4f Revert "Added kickcheck override for users with protected privs" 2015-03-12 13:29:50 -04:00
Adam 4266d17e8c Update cmake version parsing code to deal with recent build version changes
Update Config.cs to no longer hardcode VS generators, it seems no longer necessary.
Fix new version system, cannot return C++ types from extern C functions
2015-03-12 11:20:18 -04:00
Adam 8d3fa47ab2 Merge pull request #99 from H7-25/extemp_protected
Added kickcheck override for users with protected privs
2015-03-12 08:15:59 -04:00
Adam 64781817ac Merge pull request #105 from miwob/master+use-uid-for-svsnick
- Change SendForceNickChange() to use UIDs
2015-03-12 08:15:49 -04:00
Adam 69c18f131f Merge pull request #106 from miwob/master+SendClientIntroduction
- Update SendClientIntroduction() to use * for account names instead of ...
2015-03-12 08:15:44 -04:00
Adam e030771cbc Merge pull request #107 from miwob/master+misc-hybrid-changes
- Misc updates to the hybrid protocol modules:
2015-03-12 08:15:38 -04:00
Adam 03f05d3948 Merge pull request #111 from aFreshMelon/fix-xmlrpc-response
Correct wrong XML response tag
2015-03-12 08:15:31 -04:00
Adam 32c4908c8c Document that m_ldap_authentication:disable_register_reason blocks grouping 2015-03-12 08:01:27 -04:00
Adam c5ff7c6868 Show passlen in PASSWORD_TOO_LONG 2015-03-12 08:00:12 -04:00
Attila Molnar 89257d9bce InspIRCd 2.0: Re-set server-side topiclock when an incoming METADATA topiclock from a bursting server changes it 2015-03-11 23:46:00 +01:00
Attila Molnar e47aacad0e InspIRCd 2.0: Re-set server-side mlock when an incoming METADATA mlock from a bursting server changes it 2015-03-11 23:46:00 +01:00
Attila Molnar 72ade225a7 InspIRCd 2.0: Pass use_server_side_topiclock and use_server_side_mlock references to METADATA handler 2015-03-11 23:46:00 +01:00
Attila Molnar a52af0d260 InspIRCd 2.0: Add METADATA handler, pass everything to inspircd12/metadata 2015-03-11 23:46:00 +01:00
Adam 92920f5a1c Only matches sqlines against channels if they begin with a # 2015-03-11 14:49:03 -04:00
Peter Tseng bf727285bc SendConfirmMail: Replace %E with new email
The old mailer message said the user is changing email "to %e", which is
changing TO the OLD email. But instead, the user is actually changing
the email to the new email.

We could change %e to be the new email, but maybe some users of Anope
have already configured their messages to assume %e is the old email. So
instead, add a new %E that is replaced with the new email.
2015-03-11 14:44:38 -04:00
Adam 310e95a92e Allow cs clone to clone levels too 2015-03-11 14:36:56 -04:00
Adam 78bff86dab Make cs_clone behave closer to how the help describes it 2015-03-11 14:24:42 -04:00
Adam 3f093d708f Normalize masks given to cs_kick, use entry to match them against users 2015-03-11 12:13:08 -04:00
Adam c3cc5804c3 Normalize masks given to cs_ban, use entry to match them against users 2015-03-11 11:26:12 -04:00
Adam dc58239c8a Remove cloak prior to applying vhost in insp20 fhost handler 2015-03-11 10:48:25 -04:00
Adam b67963353f Hide set desc because set description exists 2015-03-11 09:30:02 -04:00
Adam a899c04ec2 Strip color codes when looking up fantasy commands. 2015-03-11 09:16:32 -04:00
Adam fb17bc85ea Redesign m_ldap to no longer rely on undefined behavior
Accessing the same LDAP* from multiple threads at once is always
undefined, even if one thread is just polling ldap_result.

Instead keep one thread per connection and issue blocking queries on the
thread.
2015-03-11 08:48:08 -04:00
Sebastian Barfurth 474cd7a99b Correct wrong XML response tag 2015-03-07 19:05:41 +01:00
Adam 7de4b86b7f Move GIT_VERSION define to build.h, otherwise version.h is bumped per commit which forces a rebuild 2015-02-23 20:43:22 -05:00
miwob 76337bc04a - Misc updates to the hybrid protocol modules:
- best supported version is 8.2.x
  - fixed UID message handler to cope with account names being '*'
  - minium required TS version is TS6 now
2015-02-15 21:47:55 +01:00
miwob abe232601b - Update SendClientIntroduction() to use * for account names instead of 0 2015-02-15 21:33:22 +01:00
miwob 6ada3ec871 - Change SendForceNickChange() to use UIDs 2015-02-15 21:27:01 +01:00
H7-25 61a8dd57f7 Added kickcheck override for users with protected privs 2015-02-11 08:11:25 +01:00
Adam 94427b234c Merge pull request #102 from miwob/master+protocol-missing-modes
- Added some missing user modes to the ircd-hybrid protocol module
2015-02-10 19:18:46 -05:00
Adam fb3c819bee Merge pull request #103 from miwob/master+hybrid-misc-changes
Misc changes to the ircd-hybrid protocol module:
2015-02-10 19:18:40 -05:00
Adam f0c23e80a2 Merge pull request #104 from miwob/master+anope.de_DE.po-minor-update
- Minor update to anope.de_DE.po; removed double space + proper translat...
2015-02-10 19:18:30 -05:00
miwob 1e86c46000 - Minor update to anope.de_DE.po; removed double space + proper translation 2015-02-10 22:48:22 +01:00
miwob 2f49065500 Misc changes to the ircd-hybrid protocol module:
- Increase MaxModes to 6
  - SendLogout(): send "+d *" instead of "+d 0"
  - Update copyright year
  - Removed user mode +z from supported modes
2015-02-08 12:29:16 +01:00
miwob 41ae2dbefb - Added some missing user modes to the ircd-hybrid protocol module 2015-02-07 19:08:55 +01:00
Adam f44280a9c9 Merge pull request #101 from miwob/master+hybrid-protocol-no-globops-override
- Removed SendGlobopsInternal() override as it's basically a duplicate o...
2015-02-06 17:21:33 -05:00
Adam d147db9023 Merge pull request #100 from miwob/master+hybrid-protocol-cmode-ctcp
- Update ircd-hybrid protocol module to support channel mode 'C' (no CTC...
2015-02-06 17:21:30 -05:00
miwob f484a68dee - Removed SendGlobopsInternal() override as it's basically a duplicate of SendGlobopsInternal() in protocol.c 2015-02-06 20:28:30 +01:00
miwob 8550e22167 - Update ircd-hybrid protocol module to support channel mode 'C' (no CTCPs) 2015-02-06 19:39:31 +01:00
Adam 9834518b28 Fix os_mode to handle channels going away due to mode changes, and maybe cs_mode 2015-02-05 20:16:43 -05:00
Adam 64ca357b13 Make module version system work 2015-02-03 19:38:23 -05:00
Adam dc5039e994 Properly unescape xmlrpc 2015-02-03 18:42:35 -05:00
Adam 845ca576b4 More properly track topic change sources and allow users with access to change topics through topiclock 2015-01-28 22:57:15 -05:00
Adam 2264a206d2 Check virtual mode bases better 2015-01-26 15:10:18 -05:00
Adam d324e91520 Fix negatively locking param modes in default mlock 2015-01-26 13:16:25 -05:00
Adam 9ac1b4ba01 Merge pull request #98 from flotwig/patch-1
cs_entrymsg to use SET permission, not isFounder
2015-01-11 19:38:35 -05:00
Zach Bloomquist 7e0cb6d8ef cs_entrymsg to use SET permission, not isFounder
Correcting syntax error

(i don't actually know c++)
2015-01-11 19:29:33 -05:00
Adam 3055b7272b Fix m_xmlrpc server configuration option 2015-01-10 15:37:49 -05:00
Adam 969cd5dd6c Always use source name when logging server kicks 2015-01-10 15:29:19 -05:00
Adam 1f02278a1c Log user away messages 2015-01-10 15:24:48 -05:00
Adam 32007f81cf Add networkinfo:nick_chars option to allow configuring additional characters allowed in nicknames 2015-01-10 15:19:40 -05:00
Adam 609f87d39f Include botserv/* in default Services Administrator opertype to behave like 1.8 2015-01-10 15:19:40 -05:00
Adam e88925e587 Merge pull request #94 from webczat/2.0
Fix issue 1627.
2014-12-28 20:30:36 -05:00
Adam c46ec39e50 Only disable CMP0026 if it exists 2014-12-28 20:01:11 -05:00
Adam 9b2202dfee Merge pull request #93 from alexbarton/ngircd-fix-servertoken
ngIRCd protocol module: fix servertoken
2014-12-28 18:12:38 -05:00
Adam 03f6e26550 Merge pull request #95 from webczat/2.0x
fix chanserv.cpp using Get for bool extensible items
2014-12-28 18:11:37 -05:00
Adam c554e85063 Merge pull request #96 from webczat/termfork
Anope will now fork even when not started from a tty, like init scripts.
2014-12-28 18:10:40 -05:00
Adam 2892c9580f Replace spaces in opertypes with underscores in stats o 2014-12-28 18:09:37 -05:00
Adam 3c0994a89e Fix crash when non-users register channels 2014-12-28 18:08:58 -05:00
Adam e800afcfac Fix adding regmoderated mode twice in plexus 2014-12-28 18:08:39 -05:00
Adam 2ad697898f Disable CMP0026 warnings on cmake 3 2014-12-19 18:55:50 -05:00
Michał Zegan e4068249dd Anope will now fork even when not started from a tty, like init scrpits.
It is useful for init systems or startup scripts, because it allows easily waiting until services connect to the uplink, without them forking it wouldn't be possible to tell if they finished initialization or not unless they would communicate directly with init systems like systemd.
2014-12-12 19:53:30 +01:00
Michał Zegan d45cb5451e Fix issue 1627.
It required that the FHost message was rewritten for the insp20 protocol module instead of relying on inspircd12's version.
The insp20 version internally removes +x mode on host change.
2014-12-12 03:56:38 +01:00
Michał Zegan d9c9f2a407 Changed calls to Get() for bool extensible items to HasExt in the chanserv module, remove duplication of code. 2014-12-12 03:48:00 +01:00
Adam 7213413f8b Remove os exception move 2014-12-11 19:33:06 -05:00
Adam 516211c88a Add SAVE support to inspircd20 2014-12-07 19:32:21 -05:00
Robby- d576137f28 Update the dutch language file. 2014-12-07 17:42:00 +01:00
Adam e1f5e030bc Change webpanel access add to just add via the commands, split Command::Run into two so I can do this as I need to run named commands for it 2014-12-05 20:24:27 -05:00
Adam afffeb0a1d Update Kill() calls to pass source pointer instead of name 2014-12-05 17:27:08 -05:00
Adam 4fc71bb22f Link m_ldap against ldap_r not ldap 2014-12-02 15:49:14 -05:00
Alexander Barton d4732faf41 Correctly assign nicks to their respective host servers
Use the "server token" parameter of NICK commands to find the host server and
correctly assign the nick name to this server.

This allows Anope to correctly free all nick names again when (remote) servers
leave the network, which fixes arbitrary "KILL attacks" when such nick names
reconnect later on.

Initial debugging and patch by DukePyrolator, thanks a lot!
2014-11-30 21:50:11 +01:00
Alexander Barton 95684187b6 Fix server token assignment of servers in the network
1. the directly linked server, our upstream, always has token "1", and
2. for remote servers in the network, the token and description filds
   were interchanged during registration,

therefore up to now no server could be found by Server::Find() using its
assigned server token.
2014-11-30 21:49:34 +01:00
Adam 4f33b17f96 Move automatically identified for log message to users 2014-11-25 09:00:15 -05:00
Adam 0cdab86978 Set require_oper in /os oper 2014-11-24 22:10:12 -05:00
Adam 4f76bee273 Fix sid generator generating invalid sids after sid 999 2014-11-24 22:00:30 -05:00
Adam 8557a4161a Allow 0 ttb in flood kicker 2014-11-15 08:50:37 -05:00
Adam c9008cdafa Fix access dup check to account for accounts 2014-11-15 02:13:10 -05:00
Adam 8a7793da0c Fix bahamut mode handler 2014-11-08 04:31:56 -05:00
Adam 64b332730e Fix not removing zones from server->zones 2014-11-08 04:30:27 -05:00
Adam 36837330ae Fix typo in botserv.example.conf 2014-11-06 05:40:51 -05:00
Adam 8b64e46ef1 Show access denied if /os kick can't kick the target 2014-11-04 23:54:16 -05:00
Adam c4460784c2 Allow mlock to be enforced when unsetting defcon modes 2014-11-04 01:36:27 -05:00
Adam 408ec02406 Move chan register event prior to applying final mode changes, so cs_mode can set mlock on register. #1620 2014-11-04 00:09:00 -05:00
Adam 67fc8c3416 enc_bcrypt is no longer extra because it doesn't depend on external dependencies anymore 2014-11-03 23:50:40 -05:00
Adam fb2fd9e9d3 Fix log message when enabling botserv kickers 2014-11-03 23:45:22 -05:00
Adam 527e04275f Merge pull request #91 from Alef-Burzmali/2.0+fix-addakiller
Keep the akiller's name when updating the reason.
2014-11-03 23:43:50 -05:00
Adam c895bd2e59 Merge pull request #92 from Alef-Burzmali/2.0+update-fr
Update the French translation
2014-11-03 23:37:08 -05:00
Thomas Fargeix 94b2d1ac12 Update French language file. 2014-10-29 00:08:21 +01:00
Thomas Fargeix a76e074f6d Update the French install instructions. 2014-10-28 22:59:26 +01:00
Thomas Fargeix 2f004c2aab Keep the akiller's name when updating the reason.
The name of the oper issuing an akill or a sxline could be removed by updating the reason,
even though addkiller was enabled.
2014-10-24 23:49:02 +02:00
Adam b940077553 Validate credentials sent via sasl more 2014-10-16 21:38:46 -04:00
Adam c8ded08b43 Show extended strftime output for suspend info 2014-10-14 21:17:47 -04:00
Adam 62a01dcc87 Set access masks to the case of the nick they match, if any 2014-10-14 21:09:41 -04:00
Adam 0cd3bfa24f Fix module event prioritization which was broken with the newer
auto-attach event stuff.

Also remove logically dead code from os_defcon, and make os_defcon akill
similar masks to os_session when enforcing session akills.

Fixes #1618 which relies on os_session to be prioritized before
os_defcon.
2014-10-14 18:58:55 -04:00
Adam e46bcff324 Move nick register event to make it easier for modules to determine if a newly registered nick is confirmed or not. Add confirm event. 2014-10-12 19:25:39 -04:00
Adam 67719e8db1 Add exempts and optionally allow authenticated users past m_dnsbl 2014-10-12 15:03:51 -04:00
Adam 48be41cf7b Squit uplink when I receive an squit for myself 2014-10-12 14:34:15 -04:00
Adam 5ceee5df38 Hide dumb user notice if we are quitting 2014-10-12 14:32:17 -04:00
Thomas Fargeix 1c12976958 Add an operserv/oper/modify privilege.
The operserv/oper command privilege allows to add operators
with fewer or the same privileges as ourself.
This new privilege allows to have operators who can use operserv/oper
to see the list of operators and their privileges, but cannot add new
operators.
2014-10-12 10:54:11 -04:00
Thomas Fargeix 96583892c6 Add a chanserv/access/list privilege
Replace the existing chanserv/access/list command access,
only used in cs_xop, by a privilege with the same name.

It which allows read-only access to cs_access, cs_flags, cs_xop
and cs_akick, while the already-existing chanserv/access/modify
privilege allows to modify them.
2014-10-12 10:52:48 -04:00
Robby- 0991d4e199 operserv.example.conf: Add missing permission definition to os_defcon's command. Fixes bug #1617. 2014-10-09 23:35:38 +02:00
Adam 58233fb8bc Log when memos are sent 2014-10-06 14:06:36 -04:00
Adam be928b5bbc Clean up collide timers on identify, otherwise you can login and logout before the timer tick which will still enforce the collide 2014-10-06 14:06:36 -04:00
Adam 31bc1d6b82 Don't add duplicate akills in os_session 2014-10-06 14:06:36 -04:00
Adam 829ef1b7bd Clear pending collided state on release, fixes colliding users using recover into enforcers 2014-10-06 14:06:36 -04:00
Adam b068874f40 Add a confirmation reply to ns recover on an unidentified user with svsnick 2014-10-06 14:06:36 -04:00
Adam 18b3c572f4 ngircd doesn't allow sourceless messages 2014-10-06 14:06:36 -04:00
Adam af034928cb Remove auto cmake downloader Config stuff, which randomally doesn't work on some systems for no reason 2014-10-06 14:06:36 -04:00
Adam 8d40a750cc Update INSTALL to reflect cmake requirement 2014-10-06 14:06:36 -04:00
DukePyrolator 6a3f7c01b1 changed the engine of the chanstats table from InnoDB back to MyISAM to avoid increasing the auto_increment counter on each INSERT IGNORE. For existing tables please manually run 'ALTER TABLE anope_chanstats ENGINE=MyISAM'. 2014-09-14 11:36:05 +02:00
DukePyrolator 4c2bf72cb6 fixed typo in the last commit 2014-09-14 11:12:54 +02:00
DukePyrolator 8e7b742ec7 added missing support for operonly and silentoperonly in os_defcon 2014-09-14 11:11:22 +02:00
DukePyrolator 19b47c7bae fixed a possible crashbug in the german language file 2014-09-13 13:06:56 +02:00
Adam 3bdc81348a Fix unserializing badwords to not add dupes when unserializing an existing bw object 2014-09-01 13:11:21 -04:00
Adam bf8f62c32d Change Channel::GetModeList to return a copy of the mode list, not a
pair of lower/upper bound iterators.

Sometimes when iterating the list, like in cs_mode, we can modify the
contents of it, which combined with mlock always agressively trying to
readd modes to it can do bad things.
2014-08-24 16:39:04 -04:00
Robby- d417241a5b cs_set: Fix logging for SET SUCCESSOR to correctly log overrides. 2014-08-11 20:16:42 +02:00
Adam e5cb2018e5 List opertypes in /os oper info 2014-08-03 19:15:08 -04:00
Adam df6095fed2 Make botserv fantasy override its own privilege 2014-08-03 19:10:15 -04:00
Adam 8210e82a5e Fix some botserv help entries from showing when they shouldn't 2014-08-03 19:08:12 -04:00
Adam d6d72cd803 Add cs_mode:max config option 2014-08-03 18:57:00 -04:00
Adam 063d9bf5f6 Allow "modify" in flags to be optional 2014-08-03 18:33:56 -04:00
Adam 830e8617e6 Allow "set" in topic set to be optional 2014-08-03 18:28:54 -04:00
Adam cf89e10a4c Add ms_ignore:max config option 2014-08-03 18:22:03 -04:00
Adam 6842ad36f7 Do not allow unconfirmed users to send memos or request vhosts 2014-08-03 18:05:41 -04:00
Adam 24f17de4aa Fix stats u on Windows 2014-08-03 18:03:07 -04:00
Adam bbb04d4662 Fuzzy italian signkick help 2014-08-01 16:12:41 -04:00
Robby- 20052247c3 Regenerate anope.en_US.po 2014-07-27 08:05:54 +02:00
Robby- 8b61a529a2 Update the dutch language file. 2014-07-27 07:48:50 +02:00
Robby- 1137c50095 Fix a few help messages. 2014-07-27 07:34:02 +02:00
Adam 52d422d020 Merge pull request #81 from miwob/master+invite_ts
hybrid.cpp: add our own SendInvite() which sends the channel's timestamp...
2014-07-26 13:41:47 -04:00
Adam 43c460e593 Merge pull request #85 from attilamolnar/2.0+help
Correct the help text of options:useprivmsg ("defmsg" -> "msg")
2014-07-26 13:40:58 -04:00
Adam 17ba13bc95 Use ts version of services stamp when the account is unconfirmed on Unreal as 3.2.10.4 has changed thie behavior 2014-07-26 13:28:43 -04:00
Adam 60229b15d2 When object unserialization fails (due to not having dependency objects) bump the ts to try again later. 2014-07-26 13:24:52 -04:00
Adam 3c88f3b8cf Check modetimes in CheckModes before enabling bouncy modes 2014-07-15 17:02:14 -04:00
Adam 93cb5d06db Fix channelcount with clone 2014-07-11 01:02:02 -04:00
Adam 7a64d95f7c Fix Log() calls in m_ldap_oper 2014-07-11 00:22:32 -04:00
Attila Molnar ff66e15f38 Correct the help text of options:useprivmsg ("defmsg" -> "msg") 2014-07-04 04:39:12 +02:00
Adam 07902c03fd Check that the list of items isn't NULL when destructing types 2014-06-28 23:15:59 -04:00
Adam d9949320c7 Don't try to setuid down until after we signal the parent to exit, unless we're not forking. Also don't issue the run as root warning if we're going to setuid later. 2014-06-28 23:15:59 -04:00
Robby- b0ec178e85 Merge pull request #84 from Zantox/2.0
Minor cs_unban Lang Update @Robby-
Updated HostServ Command English Language
Updated ChanServ Command English Language
Updated BotServ Command English Language
2014-06-26 22:17:51 +02:00
Zantox f753a925ad Minor cs_unban Lang Update @Robby- 2014-06-26 22:14:10 +02:00
Zantox 74dbfe0699 Updated HostServ Command English Language 2014-06-25 02:16:09 -04:00
Zantox 3bea089793 Updated ChanServ Command English Language 2014-06-25 02:09:43 -04:00
Adam ff93355af8 Hold a reference to the type in Serialize::Checker in the event it goes away, and invalidate the type pointer of objects when the type goes away 2014-06-23 15:44:06 -04:00
Zantox 8fecad3039 Updated BotServ Command English Language 2014-06-23 07:47:26 -04:00
miwob 37bd2c238e hybrid.cpp: add our own SendInvite() which sends the channel's timestamp along the INVITE command. INVITE with channel TS will be mandatory in some future release of ircd-hybrid 2014-06-19 16:27:05 +02:00
Adam 9a947fa435 Correct some language strings 2014-06-17 08:37:19 -04:00
Adam 4f7868b125 Log more when unable to backup databases in db_flatfile 2014-06-15 04:50:26 -04:00
Adam 8066378471 Fix WindowsGetLanguage() 2014-06-10 22:00:26 -04:00
Adam ab27b792b0 Track SVSKILL on unreal 2014-06-09 17:18:21 -04:00
Adam f1c3bdd55e Correct wording of log message when ldap services are created 2014-06-09 17:16:55 -04:00
Adam 08edb15bea Fix help log output example 2014-06-09 16:44:15 -04:00
Adam 56c6ef4449 Fix information leak in cs_updown 2014-06-09 16:36:49 -04:00
Adam 6526d2d8b3 Fix Windows release build with gettext 2014-06-01 13:53:32 -04:00
Adam 76ab5c2c38 Update WIN32.txt reflecting new Windows stuff 2014-05-31 23:54:50 -04:00
Adam 54e98f017c Always log when the uplink socket errors, and give possibly helpful advise 2014-05-31 21:17:46 -04:00
Adam bb7706d0f7 Anope 2.0.2-git 2014-05-31 19:09:23 -04:00
Adam 16e0b72d2d Update FindGettext.cmake for new Windows stuff and fix language.cpp
compile
2014-05-31 18:30:50 -04:00
141 changed files with 4848 additions and 4202 deletions
+16 -12
View File
@@ -2,6 +2,12 @@
cmake_minimum_required(VERSION 2.4 FATAL_ERROR)
if(COMMAND cmake_policy)
cmake_policy(SET CMP0003 NEW)
if(POLICY CMP0026)
cmake_policy(SET CMP0026 OLD)
endif(POLICY CMP0026)
if(POLICY CMP0007)
cmake_policy(SET CMP0007 OLD)
endif(POLICY CMP0007)
endif(COMMAND cmake_policy)
# If the Source dir and the Binary dir are the same, we are building in-source, which we will disallow due to Autotools being there (but only on non-Windows)
@@ -80,7 +86,7 @@ set(DEFAULT_LIBRARY_DIRS)
set(DEFAULT_INCLUDE_DIRS)
# If we are using a GNU compiler (have to use CXX because it seems to fail on C), we will be able to determine it's default paths for libraries and includes
if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
if(CMAKE_COMPILER_IS_GNUCXX OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
# First look for the compiler's default library directories
execute_process(COMMAND ${CMAKE_C_COMPILER} -print-search-dirs OUTPUT_VARIABLE LINES OUTPUT_STRIP_TRAILING_WHITESPACE)
# Find only the part after "libraries: "
@@ -146,7 +152,7 @@ if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
if(DEFAULT_INCLUDE_DIRS)
remove_list_duplicates(DEFAULT_INCLUDE_DIRS)
endif(DEFAULT_INCLUDE_DIRS)
endif(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
endif(CMAKE_COMPILER_IS_GNUCXX OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
# If we are using Visual Studio, locate the path of the Windows Server 2008 SDK or Windows Server 2003 Platform SDK, depending on which is installed
if(MSVC)
@@ -408,16 +414,14 @@ endif(NOT LOGS_DIR)
read_from_file(${Anope_SOURCE_DIR}/src/version.sh "^VERSION_" VERSIONS)
# Iterate through the strings found
foreach(VERSION_STR ${VERSIONS})
# Get the length of the string
string(LENGTH ${VERSION_STR} VERSION_LEN)
# Subtract 16 from the string's length (8 for VERSION_, 5 more for the type, 2 for the space and leading quote, 1 for the trailing quote)
math(EXPR VERSION_NUM_LEN "${VERSION_LEN} - 16")
# Extract the type from the string
string(SUBSTRING ${VERSION_STR} 8 5 VERSION_TYPE)
# Extract the actual value from the string
string(SUBSTRING ${VERSION_STR} 15 ${VERSION_NUM_LEN} VERSION)
# Set the version type to the value extract from above
set(VERSION_${VERSION_TYPE} ${VERSION})
string(REGEX REPLACE "^VERSION_([A-Z]+)=\"?([^\"]*)\"?$" "\\1;\\2" VERSION_OUT ${VERSION_STR})
# Depends on CMP0007 OLD
list(LENGTH VERSION_OUT VERSION_LEN)
list(GET VERSION_OUT 0 VERSION_TYPE)
if(${VERSION_LEN} GREATER 1)
list(GET VERSION_OUT 1 VERSION_DATA)
set(VERSION_${VERSION_TYPE} ${VERSION_DATA})
endif(${VERSION_LEN} GREATER 1)
endforeach(VERSION_STR ${VERSIONS})
# Default build version to 0
+3 -36
View File
@@ -176,42 +176,9 @@ done
which cmake > /dev/null
if [ $? -ne 0 ] ; then
clear
if exists "cmake-bin" ; then :
else
echo "Anope requires CMake 2.4 or newer, which can be downloaded at http://cmake.org"
echo "If you have installed CMake already, ensure it is in your PATH environment variable."
if [ `uname` = "Linux" ] ; then
echo ""
echo "Config can attempt to install CMake for you now, which"
echo "will take approximately 50 MB of disk space."
echo "Would you like to install CMake now?"
echo2 "[y] "
read YN
if [ "$YN" = "n" ] ; then
exit 0
fi
echo "Downloading CMake... this may take a minute or two."
wget -q http://anope.org/cmake/linux-i386.php -O cmake-bin.tar.gz
if [ $? -ne 0 ] ; then
rm -f cmake-bin.tar.gz
echo "Unable to download CMake"
exit 0
fi
mkdir -p cmake-bin
tar zxf cmake-bin.tar.gz -C cmake-bin
rm -f cmake-bin.tar.gz
echo "Done!"
else
exit 0
fi
fi
CMAKE_BIN=`find cmake-bin -name cmake`
CMAKE_BIN="`pwd`/`dirname $CMAKE_BIN`"
PATH="$PATH:$CMAKE_BIN"
echo "Anope requires CMake 2.4 or newer, which can be downloaded at http://cmake.org or through your system's package manager."
echo "If you have installed CMake already, ensure it is in your PATH environment variable."
exit 0
fi
###########################################################################
BIN
View File
Binary file not shown.
+6 -14
View File
@@ -2,33 +2,25 @@
if(NOT WIN32)
find_path(GETTEXT_INCLUDE libintl.h /usr/include /usr/local/include ${EXTRA_INCLUDE})
find_library(GETTEXT_LIBRARY intl PATHS /usr/lib /usr/lib64 ${EXTRA_LIBS})
find_library(ICONV_LIBRARY iconv PATHS /usr/lib /usr/lib64 ${EXTRA_LIBS})
find_program(GETTEXT_MSGFMT msgfmt PATHS /usr/bin/ /usr/local/bin ${EXTRA_INCLUDE})
if(GETTEXT_INCLUDE AND GETTEXT_MSGFMT)
set(GETTEXT_FOUND TRUE)
if(GETTEXT_LIBRARY)
set(GETTEXT_LIBRARIES ${GETTEXT_LIBRARY})
endif(GETTEXT_LIBRARY)
endif(GETTEXT_INCLUDE AND GETTEXT_MSGFMT)
else(NOT WIN32)
find_path(GETTEXT_INCLUDE libintl.h ${DEFAULT_INCLUDE_DIRS} ${WSDK_PATH}/include $ENV{VCINSTALLDIR}/include gettext/include ${EXTRA_INCLUDE})
find_library(GETTEXT_LIBRARY libintl PATHS ${DEFAULT_LIBRARY_DIRS} ${WSDK_PATH}/lib $ENV{VCINSTALLDIR}/lib gettext/lib ${EXTRA_LIBS})
find_library(ICONV_LIBRARY libiconv PATHS ${DEFAULT_LIBRARY_DIRS} ${WSDK_PATH}/lib $ENV{VCINSTALLDIR}/lib gettext/lib ${EXTRA_LIBS})
find_library(MINGWEX_LIBRARY libmingwex PATHS ${DEFAULT_LIBRARY_DIRS} ${WSDK_PATH}/lib $ENV{VCINSTALLDIR}/lib gettext/lib ${EXTRA_LIBS})
find_library(GCC_LIBRARY libgcc PATHS ${DEFAULT_LIBRARY_DIRS} ${WSDK_PATH}/lib $ENV{VCINSTALLDIR}/lib gettext/lib ${EXTRA_LIBS})
find_program(GETTEXT_MSGFMT msgfmt PATHS ${DEFAULT_INCLUDE_DIRS} ${WSDK_PATH}/bin $ENV{VCINSTALLDIR}/bin gettext/bin ${EXTRA_INCLUDE})
if(GETTEXT_INCLUDE AND GETTEXT_MSGFMT AND ICONV_LIBRARY AND MINGWEX_LIBRARY AND GCC_LIBRARY)
if(GETTEXT_INCLUDE AND GETTEXT_LIBRARY AND GETTEXT_MSGFMT)
set(GETTEXT_FOUND TRUE)
endif(GETTEXT_INCLUDE AND GETTEXT_MSGFMT AND ICONV_LIBRARY AND MINGWEX_LIBRARY AND GCC_LIBRARY)
set(GETTEXT_LIBRARIES ${GETTEXT_LIBRARY})
endif(GETTEXT_INCLUDE AND GETTEXT_LIBRARY AND GETTEXT_MSGFMT)
endif(NOT WIN32)
# If we found everything we need set variables correctly for lang/CMakeLists.txt to use
if(GETTEXT_FOUND)
include_directories("${GETTEXT_INCLUDE}")
set(GETTEXT_MSGFMT_EXECUTABLE ${GETTEXT_MSGFMT})
if(WIN32)
set(GETTEXT_LIBRARIES libiconv libintl libmingwex libgcc)
else(WIN32)
if(GETTEXT_LIBRARY)
set(GETTEXT_LIBRARIES ${GETTEXT_LIBRARY} ${ICONV_LIBRARY})
endif(GETTEXT_LIBRARY)
endif(WIN32)
endif(GETTEXT_FOUND)
+2 -2
View File
@@ -10,7 +10,7 @@
* client, the client becomes no different from a normal service bot, so you will have to use botserv/bot
* to manually delete the client.
*
* You may then waant to map some of the below commands to other services, like placing botserv/bot on
* You may then want to map some of the below commands to other services, like placing botserv/bot on
* OperServ so you can delete the below client, and mapping assign and unassign to ChanServ so users are
* able to control whether or not ChanServ is in the channel. You may also want to map botserv/set/nobot
* to OperServ so you can restrict who can assign the other core service clients.
@@ -202,7 +202,7 @@ command { service = "BotServ"; name = "BADWORDS"; command = "botserv/badwords";
* Used for administrating BotServ bots.
*/
module { name = "bs_bot" }
command { service = "BotServ"; name = "BOT"; command = "botserv/bot"; }
command { service = "BotServ"; name = "BOT"; command = "botserv/bot"; permission = "botserv/bot"; }
/*
* bs_botlist
+15 -1
View File
@@ -151,6 +151,13 @@ module
*/
reasonmax = 200
/*
* The message formatting to use for signed kick messages.
* %n is the nick of the kicker
* %m is the message specified
*/
signkickformat = "%m (%n)"
/*
* If set, prevents channel access entries from containing hostmasks.
*/
@@ -1061,6 +1068,13 @@ module
* If not set, the default is +nt.
*/
mlock = "+nt"
/*
* The maximum number of entries that may be on a mode lock list.
*
* This directive is optional.
*/
max = 32
}
command { service = "ChanServ"; name = "MODE"; command = "chanserv/mode"; group = "chanserv/management"; }
@@ -1161,7 +1175,7 @@ command { service = "ChanServ"; name = "SET"; command = "chanserv/set"; group =
command { service = "ChanServ"; name = "SET AUTOOP"; command = "chanserv/set/autoop"; }
command { service = "ChanServ"; name = "SET BANTYPE"; command = "chanserv/set/bantype"; }
command { service = "ChanServ"; name = "SET DESCRIPTION"; command = "chanserv/set/description"; }
command { service = "ChanServ"; name = "SET DESC"; command = "chanserv/set/description"; }
command { service = "ChanServ"; name = "SET DESC"; command = "chanserv/set/description"; hide = yes; }
command { service = "ChanServ"; name = "SET FOUNDER"; command = "chanserv/set/founder"; }
command { service = "ChanServ"; name = "SET KEEPMODES"; command = "chanserv/set/keepmodes"; }
command { service = "ChanServ"; name = "SET PEACE"; command = "chanserv/set/peace"; }
+18 -5
View File
@@ -319,6 +319,16 @@ networkinfo
*/
modelistsize = 100
/*
* Characters allowed in nicknames. This always includes the characters described
* in RFC1459, and so does not need to be set for normal behavior. Changing this to
* include characters your IRCd doesn't support will cause your IRCd and/or Services
* to break. Multibyte characters are not supported, nor are escape sequences.
*
* It is recommended you DON'T change this.
*/
#nick_chars = ""
/*
* The characters allowed in hostnames. This is used for validating hostnames given
* to services, such as BotServ bot hostnames and user vhosts. Changing this is not
@@ -462,7 +472,7 @@ options
/*
* If set, this will allow users to let Services send PRIVMSGs to them
* instead of NOTICEs. Also see the defmsg option of nickserv:defaults,
* instead of NOTICEs. Also see the "msg" option of nickserv:defaults,
* which also toggles the default communication (PRIVMSG or NOTICE) to
* use for unregistered users.
*
@@ -703,7 +713,7 @@ log
* create, destroy, join, part, kick, leave, mode
*
* Valid user options are:
* connect, disconnect, quit, nick, ident, host, mode, maxusers, oper
* connect, disconnect, quit, nick, ident, host, mode, maxusers, oper, away
*
* Rawio and debug are simple yes/no answers, there are no types for them.
*
@@ -747,7 +757,9 @@ log
*
* Available privileges:
* botserv/administration - Can view and assign private BotServ bots
* botserv/fantasy - Can use fantasy commands without the FANTASIA privilege
* chanserv/administration - Can modify the settings of any channel (including changing of the owner!)
* chanserv/access/list - Can view channel access and akick lists, but not modify them
* chanserv/access/modify - Can modify channel access and akick lists, and use /chanserv enforce
* chanserv/auspex - Can see any information with /chanserv info
* chanserv/no-register-limit - May register an unlimited number of channels and nicknames
@@ -761,13 +773,14 @@ log
* nickserv/confirm - Can confirm other users nicknames
* nickserv/drop - Can drop other users nicks
* operserv/config - Can modify services's configuration
* operserv/oper/modify - Can add and remove operators with at most the same privileges
* protected - Can not be kicked from channels by Services
*
* Available commands:
* botserv/bot/del botserv/bot/add botserv/bot/change botserv/set/private
* botserv/set/nobot
*
* chanserv/access/list chanserv/drop chanserv/getkey chanserv/invite
* chanserv/drop chanserv/getkey chanserv/invite
* chanserv/list chanserv/suspend chanserv/topic
*
* chanserv/saset/bantype chanserv/saset/description chanserv/saset/email chanserv/saset/keepmodes
@@ -848,7 +861,7 @@ opertype
inherits = "Services Operator"
commands = "chanserv/access/list chanserv/drop chanserv/getkey chanserv/saset/noexpire memoserv/sendall nickserv/saset/* nickserv/getemail operserv/news operserv/jupe operserv/svs operserv/stats operserv/oline operserv/noop operserv/forbid global/*"
commands = "botserv/* chanserv/access/list chanserv/drop chanserv/getkey chanserv/saset/noexpire memoserv/sendall nickserv/saset/* nickserv/getemail operserv/news operserv/jupe operserv/svs operserv/stats operserv/oline operserv/noop operserv/forbid global/*"
privs = "*"
}
@@ -1005,7 +1018,7 @@ mail
emailchange_subject = "Email confirmation"
emailchange_message = "Hi,
You have requested to change your email address to %e.
You have requested to change your email address from %e to %E.
Please type \" /msg NickServ CONFIRM %c \" to confirm this change.
If you don't know why this mail was sent to you, please ignore it silently.
+11 -1
View File
@@ -137,7 +137,17 @@ command { service = "MemoServ"; name = "DEL"; command = "memoserv/del"; }
*
* Used to ignore memos from specific users.
*/
module { name = "ms_ignore" }
module
{
name = "ms_ignore"
/*
* The maximum number of entries that may be on a memo ignore list.
*
* This directive is optional.
*/
max = 32
}
command { service = "MemoServ"; name = "IGNORE"; command = "memoserv/ignore"; }
/*
+52 -10
View File
@@ -124,26 +124,58 @@ module { name = "help" }
* %g is the realname of the user
* %h is the hostname of the user
* %i is the IP of the user
* %r is the reason (configured below). Will be nothing if not configured.
* %r is the reply reason (configured below). Will be nothing if not configured.
* %N is the network name set in networkinfo:networkname
*/
reason = "You are listed in the efnet RBL, visit http://rbl.efnetrbl.org/?i=%i for info"
/* Replies to ban and their reason. If this is totally omitted all replies get banned. */
1 = "Open Proxy"
/* Don't ban for result 2 or 3 */
#2 = "spamtrap666"
#3 = "spamtrap50"
4 = "TOR"
5 = "Drones / Flooding"
/* Replies to ban and their reason. If no relies are configured, all replies get banned. */
reply
{
code = 1
reason = "Open Proxy"
}
#reply
{
code = 2
reason = "spamtrap666"
}
#reply
{
code = 3
reason = "spamtrap50"
}
reply
{
code = 4
reason = "TOR"
/*
* If set, users identified to services at the time the result comes back
* will not be banned.
*/
#allow_account = yes
}
reply
{
code = 5
reason = "Drones / Flooding"
}
}
blacklist
#blacklist
{
name = "dnsbl.dronebl.org"
time = 4h
reason = "You have a host listed in the DroneBL. For more information, visit http://dronebl.org/lookup_branded?ip=%i&network=%N"
}
/* Exempt localhost from DNSBL checks */
exempt { ip = "127.0.0.1" }
}
/*
@@ -267,7 +299,9 @@ module { name = "help" }
password_attribute = "userPassword"
/*
* If set, the reason to give the users who try to "/msg NickServ REGISTER".
* If set, the reason to give the users who try to register with nickserv,
* including nick registration from grouping.
*
* If not set, then registration is not blocked.
*/
#disable_register_reason = "To register on this network visit http://some.misconfigured.site/register"
@@ -588,6 +622,14 @@ module { name = "help" }
*/
cert = "data/anope.crt"
key = "data/anope.key"
/*
* As of 2014 SSL 3.0 is considered insecure, but it might be enabled
* on some systems by default for compatibility reasons.
* You can use the following option to enable or disable it explicitly.
* Leaving this option not set defaults to the default system behavior.
*/
#sslv3 = no
}
/*
+1 -1
View File
@@ -260,7 +260,7 @@ command { service = "OperServ"; name = "CHANKILL"; command = "operserv/chankill"
*/
#akillreason = "This network is currently not accepting connections, please try again later."
}
#command { service = "OperServ"; name = "DEFCON"; command = "operserv/defcon"; }
#command { service = "OperServ"; name = "DEFCON"; command = "operserv/defcon"; permission = "operserv/defcon"; }
/*
* os_dns
+23
View File
@@ -1,3 +1,26 @@
Anope Version 2.0.2
-------------------
Fix keepmodes preventing the first user of a channel from being deopped
Fix SQlines that don't begin with # from matching channels
Made cs_clone behave like the help describes, copying many settings and lists by default
Allow cs_clone to clone levels, too
Update Hybrid protocol module for 8.2
Fix not unescaping all characters sent over XMLRPC
Fix crash when os_mode is used to destroy channels, like when unsetting permanent channel mode from an empty channel
Allow users with topic change privilege to change the topic instead of requiring them to use ChanServ's topic command
Fix negatively locking param modes in default mlock
Change entrymsg to check for the SET privilege, not real founder
Allow configuring characters allowed in nicknames
Fix crash when non users register channels externally (like XMLRPC)
Remove operserv/exception MOVE, it did not function correctly. Instead reorder the list by deleting/adding entries.
Allow flood ttb to be 0.
Enforce mlock when disabling defcon modes
Fix cs_mode not being able to apply mlock on register
Add log message when users send memos
Fix old collide timers from staying around after successful identify. Fixes being able to identify and logout and still being hit by the old timers.
Fix undefined behavior in cs_mode which usually crashes when clearing large list modes
Show all opertypes in operserv/info, even if no opers use them
Anope Version 2.0.1
-------------------
Fix access entries on accounts sometimes not updating when a user's display name changes
+11
View File
@@ -1,3 +1,14 @@
Anope Version 2.0.2
-------------------
Add an operserv/oper/modify privilege, required to use oper add and oper del
Add a chanserv/access/list privilege, which allow readonly access to ChanServ access and akick lists
Changed m_dnsbl's result configuration to be more extensible
Add 'max' setting to cs_mode
Add 'nickchars' setting to networkinfo
Add 'botserv/fantasy', 'chanserv/access/list', and 'operserv/oper/modify' oper privileges
Fix 'emailchange_message' to include the proper email address
Set a default permission on operserv/defcon
Anope Version 2.0.1
-------------------
Add MUTE command to BotServ fantasy configuration
+4 -19
View File
@@ -21,26 +21,19 @@ Note: You should also read the README and FAQ files!
http://www.anope.org/
Anope can be built one of two ways. The recommended way is to use CMake.
You can check if CMake is already installed on your system using the
command:
Anope requires cmake to build. You can check if CMake is already
installed on your system using the command:
cmake --version
If it's installed, you will get a line that says something similar to
"cmake version 2.6-patch 1". If the version is less than 2.4 or you get
"cmake version 2.8.12.2". If the version is less than 2.4 or you get
an error saying the command was not found, you will not be able to use
CMake unless you install it yourself into your home directory. CMake
can be downloaded from:
http://www.cmake.org/cmake/resources/software.html
If you are unable to install CMake yourself (either due to lack of space
or restrictions by your hosting provider), you still have the alternative
to use the provided configure script. This option is not recommended and
will eventually be phased out, but is provided for compatibility for those
lacking CMake.
Next, unpack the package in your home directory, and go into the created
directory.
@@ -51,16 +44,8 @@ Note: You should also read the README and FAQ files!
Now type ./Config to start the configuration script. It will ask you a
few questions, and figure out how to compile Anope on your system. If
you are unsure about the answer to a question, use the default value.
The question to using configure or cmake depends on your decision from
above. If you have CMake and wish to use it, answer with cmake, otherwise
answer with configure.
You can now type make to compile Anope. If there are errors in the
Makefile, *try to use gmake* instead. If it still doesn't work, you (or
the system administrator if it's a shell) must install GNU make. You may
find it at ftp://prep.ai.mit.edu/pub/gnu/.
Now type make install (or gmake install; see above). This will install
Now cd build and type make and make install. This will install
all the needed files in the paths you specified with the configure
script, and setup file permissions. You should ensure that the data
directory is not accessible by other users, as malicious users may
+90 -99
View File
@@ -1,5 +1,5 @@
Instructions d'installation d'Anope
------------------------------------
-----------------------------------
1) Installation d'Anope
2) Mettre à jour Anope
@@ -11,148 +11,139 @@ Note : Vous devrez également lire les fichiers README et FAQ !
1) Installation d'Anope
NOTE IMPORTANTE : il n'est pas recommandé d'utiliser (et même d'installer)
Anope en tant que root. Utilisez un utilisateur non
privilégié. Celui que vous utilisez pour l'IRCd ou un
utilisateur dédié suffira.
NOTE IMPORTANTE : il est déconseillé d'utiliser (et même d'installer)
Anope en tant que root. Utilisez un utilisateur non
privilégié. Celui que vous utilisez pour l'IRCd ou
un utilisateur dédié suffira.
La première chose que vous devez faire est d'obtenir le package Anope (si ce
n'est déjà fait). Vous pouvez le trouver ici :
La première chose que vous devez faire est d'obtenir le package Anope
(si ce n'est déjà fait). Vous pouvez le trouver ici :
http://www.anope.org/
http://www.anope.org/
Anope peut être installé de deux façons. La méthode recommandée est
d'utiliser CMake. Vous pouvez vérifier si CMake est déjà installé
sur votre système en utilisant la commande :
Anope nécessite cmake pour être compilé. Vous pouvez vérifier si CMake
est déjà installé sur votre système avec la commande :
cmake --version
Si CMake est installé, vous aurez une ligne qui dit quelque chose similaire
à "cmake version 2.6 cmake-patch 1". Si la version est inférieure à 2.4 ou
si vous obtenez une erreur disant que la commande n'a pas été trouvée,
vous ne serez pas en mesure d'utiliser CMake, sauf si vous l'installez
vous-même dans votre répertoire home. CMake peut être téléchargé ici :
Si CMake est installé, vous aurez une ligne qui dit quelque chose comme
"cmake version 2.8.12.2". Si la version est inférieure à 2.4 ou si vous
obtenez une erreur disant que la commande n'a pas été trouvée, vous ne
pourrez pas utiliser CMake à moins de l'installer vous-même dans votre
répertoire home. CMake peut être téléchargé ici :
http://www.cmake.org/cmake/resources/software.html
Si vous n'arrivez pas à l'installer (soit en raison du manque d'espace
ou de restrictions par votre fournisseur d'hébergement), vous pouvez encore
utiliser le script de configuration fourni. Cette option n'est pas
recommandée et finira par être retirée, mais est fournie pour la
compatibilité de ceux à qui il manque CMake.
Ensuite, décompressez le package dans votre répertoire home, et allez
dans le répértoire qui vient d'être créé.
Ensuite, décompressez le package dans votre répertoire home, et allez dans
le répértoire qui vient d'être créé.
Si il y a des modules facultatifs que vous voulez activer comme m_mysql,
exécuter le script 'extras' pour les activer. Si vous ne savez pas, vous
pouvez les activer plus tard.
Maintenant, tapez ./Config pour lancer le script de configuration. Il va
vous poser quelques questions, et compiler Anope sur votre système. Si vous
ne savez pas répondre à une question, utilisez la valeur par défaut. La
question d'utiliser CMake ou configure dépend de la décision que vous avez
prise précedemment. Si vous avez CMake et que vous souhaitez l'utiliser,
répondez avec cmake, sinon répondez avec configure.
Maintenant, tapez ./Config pour lancer le script de configuration. Il
va vous poser quelques questions, et déterminer comment compiler Anope
sur votre système. Si vous ne savez pas comment répondre à une question,
utilisez la valeur par défaut.
Vous pouvez maintenant taper make pour compiler Anope. S'il y'a des erreurs
dans le Makefile, *essayez d'utiliser* gmake à la place. Si cela ne
fonctionne toujours pas, vous (ou votre administrateur système) devriez
installer GNU make.
Vous pouvez le trouver ici : ftp://prep.ai.mit.edu/pub/gnu/.
Allez dans le dossier build (cd build) et tapez make et make install.
Ceci va installer tous les fichiers nécessaires dans les dossiers que
vous avez indiqués avec le script Config et régler les permissions des
fichiers. Vous devez vous assurer que le répertoire data n'est pas
accessible par les autres utilisateurs, car des utilisateurs
malveillants pourraient causer des problèmes sur votre réseau, si les
mots de passe ne sont pas chiffrés, ou lire les mémos de tous les
utilisateurs.
Maintenant, tapez make install (ou gmake install ; voir ci-dessus). Cela
permet d'installer tous les fichiers nécessaires dans les chemins que vous
avez spécifié au script configure, et de régler les permissions des fichiers.
Vous devez vous assurer que le répertoire data n'est pas accessible par les
autres utilisateurs, des utilisateurs malveillants pourraient causer des
problèmes sur votre réseau, si les mots de passe ne sont pas chiffrés,
ou lire les mémos de tout utilisateur.
Allez maintenant dans le répertoire conf (par défaut, ~/services/conf).
Copiez l'exemple de fichier de configuration (example.conf) en
services.conf et ouvrez ce dernier avec votre éditeur de texte favori.
Il contient toutes les directives de configuration qu'Anope va utiliser
en démarrant. Lisez attentivement les instructions contenues dans le
fichier. L'utilisation des valeurs par défaut n'est pas toujours
recommandée, et Anope ne fonctionnera probablement pas !
Si vous voyez des erreurs lors de ce processus, merci de nous envoyer un
e-mail avec la sortie d'erreur *complète* et n'oubliez pas de mentionner
les versions de votre système, compilateur et bibliothèque C++.
Allez maintenant dans le répertoire de données (par défaut, ~/services/data).
Copiez l'exemple de fichier de configuration (example.conf) en services.conf
et ouvrez ce dernier avec votre éditeur de texte favori. Il contient toute
les directives de configuration. Anope va l'utiliser au démarrage.
Lisez attentivement les instructions contenues dans le fichier.
L'utilisation des valeurs par défaut n'est pas recommendé et Anope ne
fonctionnera probablement pas.
Si vous avez besoin d'aide, abonnez-vous à la liste de diffusion Anope
et envoyez-y vos e-mails pour obtenir de l'aide de la part des autres
utilisateurs. Voir le fichier README pour plus d'informations.
Si vous avez besoin d'aide, vous pouvez aller sur le site
http://forum.anope.org/ ou le canal #anope sur irc.anope.org.
Fournissez *l'essemble* des erreurs qui apparaîssent, en plus de
toutes informations utiles, comme les versions de votre OS, du
compilateur utilisé et de la librairie C++. Lisez le fichier README
pour plus d'informations.
2) Mettre à jour Anope
Pour mettre à jour Anope, suivez simplement les instructions d'installation
décrites dans la section 1. Il y a cependant une ligne de conduite
spécifique :
Pour mettre à jour Anope, suivez simplement les instructions
d'installation décrites dans la section 1. Prenez garde cependant :
* IMPORTANT : Sauvegardez vos anciennes bases de données !
* Si vous mettez à jour vers une nouvelle version majeure, toujours
redémarrer avec un fichier de configuration neuf depuis example.conf.
* Si vous mettez à jour vers une nouvelle version majeure,
recommencez *toujours* toute votre configuration à partir du
fichier example.conf.
3) Configuration de l'IRCd
Les Services agissent comme un serveur IRC avec des pseudo-clients.
Pour les relier à votre réseau, vous aurez besoin de configurer votre IRCd
pour permettre aux services de linker.
Pour les relier à votre réseau, vous aurez besoin de configurer votre
IRCd pour permettre aux services de se connecter.
La configuration varie selon les IRCd, mais vous aurez probablement besoin
d'un block link (aussi appelé connect block, ou C line), un U line (aussi
appelé shared block) et assurez-vous que l'IRCd écoute sur le port donné
dans le block link.
La configuration dépend de l'IRCd utilisé, mais vous aurez probablement
besoin d'un bloc link (aussi appelé connect block, ou C:line) et un
U:line (aussi appelé shared block). Assurez-vous que l'IRCd écoute
sur le port donné dans le bloc link.
Des exemples de configurations de link peuvent être trouvés dans le fichier
example.conf pour certains des IRCd les plus populaires.
Des exemples de configurations de bloc link peuvent être trouvés dans
le fichier example.conf pour certains des IRCd les plus populaires.
Souvenez-vous de /rehash votre IRCd pour appliquer les changements.
Vous pouvez également essayer notre créateur de link interactif situé ici :
Vous pouvez également essayer notre créateur de bloc link interactif
situé ici :
http://anope.org/ilm.php
4) Mettre en route Anope
Allez dans le répertoire où les fichiers binaires ont été installés (par
défaut, ~/services/bin). Tapez ./services pour lancer Anope.
Allez dans le répertoire où les fichiers binaires ont été installés
(par défaut, ~/services/bin). Tapez ./services pour lancer Anope.
S'il ya des erreurs de syntaxe dans le fichier de configuration, elles
seront affichées sur l'écran. Corrigez-les jusqu'à ce qu'il n'y en ait plus.
Un démarrage réussi ne générera pas de message.
S'il y a des erreurs de syntaxe dans le fichier de configuration, elles
seront affichées à l'écran. Corrigez-les jusqu'à ce qu'il n'y en ait
plus. Un démarrage réussi ne générera pas de message.
Donnez aux services au moins une minute pour se connecter à votre réseau.
Certains IRCds sur certains systèmes peuvent être très lents pour le
processus de liaison. Si rien n'arrive après environ une minute, il y a
probablement un problème de configuration. Essayez de lancer Anope en mode
debug ./services -debug -nofork pour voir toutes les erreurs rencontrées
et essayez de les corriger.
Donnez aux services au moins une minute pour se connecter à votre
réseau, car certains IRCds sur certains systèmes peuvent être très
lents pour le processus de liaison. Si rien ne se passe après environ
une minute, il y a probablement un problème de configuration. Essayez
de lancer Anope en mode debug avec ./services -debug -nofork pour voir
toutes les erreurs rencontrées et essayez de les corriger.
Si vous avez besoin d'aide pour résoudre des erreurs, n'hésitez pas à vous
abonner à la liste de diffusion Anope et d'y poser vos question.
Si vous avez besoin d'aide pour résoudre des erreurs, n'hésitez pas à
vous abonner à la liste de diffusion Anope et d'y poser vos question.
Voir le fichier README pour plus de détails.
5) Mettre en place un crontab
Une entrée crontab vous permettra de vérifier périodiquement si Anope est
toujours en cours d'exécution et de le redémarrer s'il n'est pas.
Une entrée crontab vous permettra de vérifier périodiquement si Anope
est toujours en cours d'exécution et de le redémarrer s'il n'est pas.
D'abord renommez le script example.chk qui est dans le chemin d'Anope
(par défaut, ~/services/data) en services.chk et modifiez-le. Vous aurez
besoin de modifier la partie CONFIGURATION du fichier. Assurez-vous ensuite
que le fichier est marqué comme exécutable en tapant chmod +x services.chk
et essayez de lancer le script pour voir si cela fonctionne (Anope ne doit
pas être en marche lorsque vous faites cela ;))
D'abord renommez le script example.chk qui est dans les dossiers
d'Anope (par défaut, ~/services/conf) en services.chk et modifiez-le.
Vous aurez besoin de modifier la partie CONFIGURATION du fichier.
Assurez-vous ensuite que le fichier est marqué comme exécutable en
tapant chmod +x services.chk et essayez de lancer le script pour voir
si cela fonctionne (Anope ne doit pas être en marche lorsque vous
testez cela ;))
Lorsque c'est fait, vous devrez ajouter l'entrée crontab. Tapez crontab -e.
Cela va ouvrir l'éditeur de texte par défaut avec le fichier crontab.
Entrez la ligne suivante (avec le chemin correct) :
Lorsque c'est fait, vous devrez ajouter l'entrée crontab. Entrez
crontab -e. Cela va ouvrir l'éditeur de texte par défaut avec le
fichier crontab. Entrez la ligne suivante (avec le chemin correct) :
*/5 * * * * /home/ircd/services/data/services.chk > /dev/null 2>&1
*/5 * * * * /home/ircd/services/conf/services.chk > /dev/null 2>&1
Le */5 au début signifie "vérifier toutes les 5 minutes". Vous pouvez
remplacer le 5 par un autre numéro si vous voulez (mais moins de 60).
Consultez pages de manuel de votre système pour plus de détails sur la
syntaxe du fichier crontab. Les pages de manuel intéressantes sont
remplacer le 5 par un autre numéro si vous voulez (mais moins de 60).
Consultez les pages de manuel de votre système pour plus de détails sur
la syntaxe du fichier crontab. Les pages de manuel intéressantes sont
crontab(5), crontab(1) et cron(8).
Sauvegardez, quittez et c'est installé.
Sauvegardez, quittez, et c'est installé !
+3 -11
View File
@@ -73,18 +73,10 @@ Anope for Windows
Some Anope modules require third party libraries, such as m_mysql and
the SSL modules. If these libraries are installed in nonstandard
locations, cmake will probably not find them and should be told where
they are by passing additional search paths to the last question in
Config, such as:
they are by passing their location to Config.
-DEXTRA_INCLUDE:STRING=c:/openssl/include;c:/mysql/include
-DEXTRA_LIBS:STRING=c:/openssl/lib;c:/mysql/lib
Building Anope with gettext requires libintl, libiconv, libgcc and
libmingex. We have precompiled these libraries for you that you may
use if you want. They are avaiable at http://anope.org/downloads/anope-extra.zip
The OpenSSL, MySQL, and OpenLDAP header files and libraries are also included in
this package. Once downloaded and extracted, you should run install.bat
then give Config the path to the new 'installed' directory.
The libraries used to build the 'extra' modules are available at
https://github.com/Adam-/windows-scripts.
5) You are now ready to compile. If you said you wanted to use NMake in step 4,
at the prompt type:
+2 -2
View File
@@ -3,8 +3,8 @@ This allows external applications, such as websites, to execute remote procedure
Currently there are 5 supported XMLRPC calls, provided by m_xmlrpc_main:
checkAuthetication - Takes two parameters, an account name and a password. Checks if the account name is valid and the password
is correct for the account name, useful for making login pages on websites.
checkAuthentication - Takes two parameters, an account name and a password. Checks if the account name is valid and the password
is correct for the account name, useful for making login pages on websites.
command - Takes three parameters, a service name (BotServ, ChanServ, NickServ), a user name (whether online or not), and the command
to execute. This will execute a the given command to Anope using the given service name. If the user given is online, the
+2 -1
View File
@@ -7,7 +7,7 @@ get_target_property(version_BINARY version LOCATION)
# Modify version.h from the above executable, with dependencies to version.cpp
# and all of the source files in the main build
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/version_build
COMMAND ${version_BINARY} ${Anope_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/version.h
COMMAND ${version_BINARY} ${Anope_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/version.h ${CMAKE_CURRENT_BINARY_DIR}/build.h
DEPENDS version ${SRC_SRCS}
)
# Add version to list of files for CPack to ignore
@@ -15,6 +15,7 @@ get_filename_component(version_BINARY ${version_BINARY} NAME)
add_to_cpack_ignored_files("${version_BINARY}$" TRUE)
if(NOT WIN32)
add_to_cpack_ignored_files("version.h$" TRUE)
add_to_cpack_ignored_files("build.h$" TRUE)
endif(NOT WIN32)
set(PCH_SOURCES_GCH "")
+3 -3
View File
@@ -242,9 +242,9 @@ class CoreExport Channel : public Base, public Extensible
/** Get a list of modes on a channel
* @param name A mode name to get the list of
* @return a pair of iterators for the beginning and end of the list
* @return a vector of the list mode entries
*/
std::pair<ModeList::iterator, ModeList::iterator> GetModeList(const Anope::string &name);
std::vector<Anope::string> GetModeList(const Anope::string &name);
/** Get a string of the modes set on this channel
* @param complete Include mode parameters
@@ -258,7 +258,7 @@ class CoreExport Channel : public Base, public Extensible
* @param newtopic The new topic
* @param ts The time the new topic is being set
*/
void ChangeTopicInternal(const Anope::string &user, const Anope::string &newtopic, time_t ts = Anope::CurTime);
void ChangeTopicInternal(User *u, const Anope::string &user, const Anope::string &newtopic, time_t ts = Anope::CurTime);
/** Update the topic of the channel, and reset it if topiclock etc says to
* @param user The user setting the topic
+2
View File
@@ -170,6 +170,8 @@ class CoreExport Command : public Service
*/
static void Run(CommandSource &source, const Anope::string &message);
void Run(CommandSource &source, const Anope::string &, const CommandInfo &, std::vector<Anope::string> &params);
/** Looks up a command name from the service name.
* Note that if the same command exists multiple places this will return the first one encountered
* @param command_service The command service to lookup, eg, nickserv/register
+2
View File
@@ -103,6 +103,8 @@ namespace Configuration
time_t TimeoutCheck;
/* options:usestrictprivmsg */
bool UseStrictPrivmsg;
/* networkinfo:nickchars */
Anope::string NickChars;
/* either "/msg " or "/" */
Anope::string StrictPrivmsg;
+1 -1
View File
@@ -74,7 +74,7 @@ namespace Language
#define MORE_OBSCURE_PASSWORD _("Please try again with a more obscure password. Passwords should be at least\n" \
"five characters long, should not be something easily guessed\n" \
"(e.g. your real name or your nick), and cannot contain the space or tab characters.")
#define PASSWORD_TOO_LONG _("Your password is too long. Please try again with a shorter password.")
#define PASSWORD_TOO_LONG _("Your password is too long. It must not exceed %u characters.")
#define NICK_NOT_REGISTERED _("Your nick isn't registered.")
#define NICK_X_NOT_REGISTERED _("Nick \002%s\002 isn't registered.")
#define NICK_X_NOT_IN_USE _("Nick \002%s\002 isn't currently in use.")
+4
View File
@@ -107,6 +107,8 @@ class CoreExport ChannelMode : public Mode
bool CanSet(User *u) const anope_override;
virtual void Check() { }
/** 'wrap' this channel mode and param to the underlying mode and param
*/
virtual ChannelMode *Wrap(Anope::string &param);
@@ -215,6 +217,8 @@ class CoreExport ChannelModeVirtual : public T
~ChannelModeVirtual();
void Check() anope_override;
ChannelMode *Wrap(Anope::string &param) anope_override;
ChannelMode *Unwrap(ChannelMode *cm, Anope::string &param) = 0;
+39 -14
View File
@@ -20,6 +20,7 @@
#include "timers.h"
#include "logger.h"
#include "extensible.h"
#include "version.h"
/** This definition is used as shorthand for the various classes
* and functions needed to make a module loadable by the OS.
@@ -40,6 +41,14 @@
extern "C" void AnopeFini(x *m) \
{ \
delete m; \
} \
extern "C" DllExport ModuleVersionC AnopeVersion() \
{ \
ModuleVersionC ver; \
ver.version_major = VERSION_MAJOR; \
ver.version_minor = VERSION_MINOR; \
ver.version_patch = VERSION_PATCH; \
return ver; \
}
#else
# define MODULE_INIT(x) \
@@ -50,6 +59,14 @@
extern "C" DllExport void AnopeFini(x *m) \
{ \
delete m; \
} \
extern "C" DllExport ModuleVersionC AnopeVersion() \
{ \
ModuleVersionC ver; \
ver.version_major = VERSION_MAJOR; \
ver.version_minor = VERSION_MINOR; \
ver.version_patch = VERSION_PATCH; \
return ver; \
}
#endif
@@ -173,6 +190,11 @@ enum
};
typedef unsigned short ModType;
struct ModuleVersionC
{
int version_major, version_minor, version_patch;
};
/** Returned by Module::GetVersion, used to see what version of Anope
* a module is compiled against.
*/
@@ -184,12 +206,7 @@ class ModuleVersion
int version_patch;
public:
/** Constructor
* @param major The major version number
* @param minor The minor version number
* @param patch The patch version number
*/
ModuleVersion(int major, int minor, int patch);
ModuleVersion(const ModuleVersionC &);
/** Get the major version of Anope this was built against
* @return The major version
@@ -279,11 +296,7 @@ class CoreExport Module : public Extensible
*/
void SetAuthor(const Anope::string &author);
/** Get the version of Anope this module was
* compiled against
* @return The version
*/
ModuleVersion GetVersion() const;
virtual void Prioritize();
/* Everything below here are events. Modules must ModuleManager::Attach to these events
* before they will be called.
@@ -472,11 +485,12 @@ class CoreExport Module : public Extensible
virtual void OnJoinChannel(User *u, Channel *c) { throw NotImplementedException(); }
/** Called when a new topic is set
* @param source The user changing the topic, if any
* @param c The channel
* @param setter The user who set the new topic
* @param setter The user who set the new topic, if there is no source
* @param topic The new topic
*/
virtual void OnTopicUpdated(Channel *c, const Anope::string &user, const Anope::string &topic) { throw NotImplementedException(); }
virtual void OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic) { throw NotImplementedException(); }
/** Called before a channel expires
* @param ci The channel
@@ -747,6 +761,12 @@ class CoreExport Module : public Extensible
*/
virtual void OnNickRegister(User *user, NickAlias *na, const Anope::string &pass) { throw NotImplementedException(); }
/** Called when a nick is confirmed. This will never be called if registration confirmation is not enabled.
* @param user The user confirming the nick
* @param The account being confirmed
*/
virtual void OnNickConfirm(User *user, NickCore *) { throw NotImplementedException(); }
/** Called when a nick is suspended
* @param na The nick alias
*/
@@ -1091,7 +1111,7 @@ enum Implementation
I_OnAccessClear, I_OnLevelChange, I_OnChanDrop, I_OnChanRegistered, I_OnChanSuspend, I_OnChanUnsuspend,
I_OnCreateChan, I_OnDelChan, I_OnChannelCreate, I_OnChannelDelete, I_OnAkickAdd, I_OnAkickDel, I_OnCheckKick,
I_OnChanInfo, I_OnCheckPriv, I_OnGroupCheckPriv, I_OnNickDrop, I_OnNickGroup, I_OnNickIdentify,
I_OnUserLogin, I_OnNickLogout, I_OnNickRegister, I_OnNickSuspend, I_OnNickUnsuspended, I_OnDelNick, I_OnNickCoreCreate,
I_OnUserLogin, I_OnNickLogout, I_OnNickRegister, I_OnNickConfirm, I_OnNickSuspend, I_OnNickUnsuspended, I_OnDelNick, I_OnNickCoreCreate,
I_OnDelCore, I_OnChangeCoreDisplay, I_OnNickClearAccess, I_OnNickAddAccess, I_OnNickEraseAccess, I_OnNickClearCert,
I_OnNickAddCert, I_OnNickEraseCert, I_OnNickInfo, I_OnBotInfo, I_OnCheckAuthentication, I_OnNickUpdate,
I_OnFingerprint, I_OnUserAway, I_OnInvite, I_OnDeleteVhost, I_OnSetVhost, I_OnSetDisplayedHost, I_OnMemoSend, I_OnMemoDel,
@@ -1197,6 +1217,11 @@ class CoreExport ModuleManager
* @return MOD_ERR_OK on success, anything else on fail
*/
static ModuleReturn DeleteModule(Module *m);
/** Get the version of Anope the module was compiled against
* @return The version
*/
static ModuleVersion GetVersion(void *handle);
};
#endif // MODULES_H
+16 -26
View File
@@ -1,8 +1,6 @@
#ifndef ANOPE_LDAP_H
#define ANOPE_LDAP_H
typedef int LDAPQuery;
class LDAPException : public ModuleException
{
public:
@@ -59,28 +57,26 @@ struct LDAPAttributes : public std::map<Anope::string, std::vector<Anope::string
}
};
enum QueryType
{
QUERY_UNKNOWN,
QUERY_BIND,
QUERY_SEARCH,
QUERY_ADD,
QUERY_DELETE,
QUERY_MODIFY
};
struct LDAPResult
{
std::vector<LDAPAttributes> messages;
Anope::string error;
enum QueryType
{
QUERY_UNKNOWN,
QUERY_BIND,
QUERY_SEARCH,
QUERY_ADD,
QUERY_DELETE,
QUERY_MODIFY
};
QueryType type;
LDAPQuery id;
LDAPResult()
{
this->type = QUERY_UNKNOWN;
this->id = -1;
}
size_t size() const
@@ -126,48 +122,42 @@ class LDAPProvider : public Service
/** Attempt to bind to the LDAP server as an admin
* @param i The LDAPInterface the result is sent to
* @return The query ID
*/
virtual LDAPQuery BindAsAdmin(LDAPInterface *i) = 0;
virtual void BindAsAdmin(LDAPInterface *i) = 0;
/** Bind to LDAP
* @param i The LDAPInterface the result is sent to
* @param who The binddn
* @param pass The password
* @return The query ID
*/
virtual LDAPQuery Bind(LDAPInterface *i, const Anope::string &who, const Anope::string &pass) = 0;
virtual void Bind(LDAPInterface *i, const Anope::string &who, const Anope::string &pass) = 0;
/** Search ldap for the specified filter
* @param i The LDAPInterface the result is sent to
* @param base The base DN to search
* @param filter The filter to apply
* @return The query ID
*/
virtual LDAPQuery Search(LDAPInterface *i, const Anope::string &base, const Anope::string &filter) = 0;
virtual void Search(LDAPInterface *i, const Anope::string &base, const Anope::string &filter) = 0;
/** Add an entry to LDAP
* @param i The LDAPInterface the result is sent to
* @param dn The dn of the entry to add
* @param attributes The attributes
* @return The query ID
*/
virtual LDAPQuery Add(LDAPInterface *i, const Anope::string &dn, LDAPMods &attributes) = 0;
virtual void Add(LDAPInterface *i, const Anope::string &dn, LDAPMods &attributes) = 0;
/** Delete an entry from LDAP
* @param i The LDAPInterface the result is sent to
* @param dn The dn of the entry to delete
* @return The query ID
*/
virtual LDAPQuery Del(LDAPInterface *i, const Anope::string &dn) = 0;
virtual void Del(LDAPInterface *i, const Anope::string &dn) = 0;
/** Modify an existing entry in LDAP
* @param i The LDAPInterface the result is sent to
* @param base The base DN to modify
* @param attributes The attributes to modify
* @return The query ID
*/
virtual LDAPQuery Modify(LDAPInterface *i, const Anope::string &base, LDAPMods &attributes) = 0;
virtual void Modify(LDAPInterface *i, const Anope::string &base, LDAPMods &attributes) = 0;
};
#endif // ANOPE_LDAP_H
+5
View File
@@ -198,6 +198,11 @@ class CoreExport ChannelInfo : public Serializable, public Extensible
*/
void ClearAkick();
/** Get the level entries for the channel.
* @return The levels for the channel.
*/
const Anope::map<int16_t> &GetLevelEntries();
/** Get the level for a privilege
* @param priv The privilege name
* @return the level
+3 -3
View File
@@ -60,9 +60,9 @@ class CoreExport Serializable : public virtual Base
* constructed before other objects are if it isn't.
*/
static std::list<Serializable *> *SerializableItems;
friend class Serialize::Type;
/* The type of item this object is */
Serialize::Type *s_type;
private:
/* Iterator into serializable_items */
std::list<Serializable *>::iterator s_iter;
/* The hash of the last serialized form of this object commited to the database */
@@ -109,7 +109,7 @@ class CoreExport Serializable : public virtual Base
* of class that inherits from Serialiable. Used for unserializing objects
* of this type, as it requires a function pointer to a static member function.
*/
class CoreExport Serialize::Type
class CoreExport Serialize::Type : public Base
{
typedef Serializable* (*unserialize_func)(Serializable *obj, Serialize::Data &);
@@ -188,7 +188,7 @@ class Serialize::Checker
{
Anope::string name;
T obj;
mutable Serialize::Type *type;
mutable ::Reference<Serialize::Type> type;
inline void Check() const
{
+1
View File
@@ -25,6 +25,7 @@ namespace Uplink
class UplinkSocket : public ConnectionSocket, public BufferedSocket
{
public:
bool error;
UplinkSocket();
~UplinkSocket();
bool ProcessRead() anope_override;
+87 -35
View File
@@ -13,7 +13,7 @@
#include <iostream>
#include <fstream>
#include <sstream>
#include <list>
#include <map>
static std::string get_git_hash(const std::string &git_dir)
{
@@ -45,29 +45,16 @@ static std::string get_git_hash(const std::string &git_dir)
return "g" + filebuf.substr(0, 7);
}
int main(int argc, char *argv[])
static bool read_version_sh(const std::string &version_sh, std::map<std::string, std::string> &versions)
{
if (argc < 3)
{
std::cerr << "Syntax: " << argv[0] << " <base> <version.h>" << std::endl;
return 1;
}
std::string version_sh = std::string(argv[1]) + "/src/version.sh";
std::string git_dir = std::string(argv[1]) + "/.git";
std::fstream fd;
fd.clear();
fd.open(version_sh.c_str(), std::ios::in);
std::fstream fd(version_sh.c_str(), std::ios::in);
if (!fd.is_open())
{
std::cerr << "Error: Unable to open src/version.sh for reading: " << version_sh << std::endl;
return 1;
return false;
}
std::string filebuf;
std::list<std::pair<std::string, std::string> > versions;
while (getline(fd, filebuf))
{
if (!filebuf.find("VERSION_"))
@@ -75,24 +62,25 @@ int main(int argc, char *argv[])
size_t eq = filebuf.find('=');
std::string type = filebuf.substr(0, eq);
std::string value = filebuf.substr(eq + 2, filebuf.length() - eq - 3);
versions.push_back(std::make_pair(type, value));
std::string value = filebuf.substr(eq + 1);
versions[type] = value;
}
}
fd.close();
std::string git_version = get_git_hash(git_dir);
if (!git_version.empty())
versions.push_back(std::make_pair("VERSION_GIT", git_version));
return true;
}
fd.clear();
fd.open(argv[2], std::ios::in);
static bool write_build_h(const std::string &buildh, const std::string &git_version)
{
std::fstream fd(buildh.c_str(), std::ios::in);
std::string build = "#define BUILD 1";
if (fd.is_open())
{
while (getline(fd, filebuf))
for (std::string filebuf; getline(fd, filebuf);)
{
if (!filebuf.find("#define BUILD"))
{
@@ -110,27 +98,91 @@ int main(int argc, char *argv[])
}
fd.clear();
fd.open(argv[2], std::ios::out);
fd.open(buildh.c_str(), std::ios::out);
if (!fd.is_open())
{
std::cerr << "Error: Unable to include/version.h for writing: " << argv[2] << std::endl;
return 1;
std::cerr << "Error: Unable to open build.h for writing: " << buildh << std::endl;
return false;
}
fd << "/* This file is automatically generated by version.cpp - do not edit it! */" << std::endl;
fd << build << std::endl;
if (!git_version.empty())
fd << "#define VERSION_GIT \"" << git_version << "\"" << std::endl;
fd.close();
for (std::list<std::pair<std::string, std::string> >::iterator it = versions.begin(), it_end = versions.end(); it != it_end; ++it)
return true;
}
static void read_version_h(const std::string &versionh, std::map<std::string, std::string> &versions)
{
std::fstream fd(versionh.c_str(), std::ios::in);
if (!fd.is_open())
return;
for (std::string filebuf; getline(fd, filebuf);)
{
if (it->first == "VERSION_EXTRA" || it->first == "VERSION_GIT")
fd << "#define " << it->first << " \"" << it->second << "\"" << std::endl;
else
fd << "#define " << it->first << " " << it->second << std::endl;
if (!filebuf.find("#define VERSION_"))
{
size_t space = filebuf.substr(8).find(' ');
std::string name = filebuf.substr(8).substr(0, space),
version = filebuf.substr(8).substr(space + 1);
versions[name] = version;
}
}
fd << build << std::endl;
fd.close();
}
static bool write_version_h(const std::string &versionh, const std::map<std::string, std::string> &versions)
{
std::fstream fd(versionh.c_str(), std::ios::out);
if (!fd.is_open())
return false;
for (std::map<std::string, std::string>::const_iterator it = versions.begin(); it != versions.end(); ++it)
{
fd << "#define " << it->first << " " << it->second << std::endl;
}
fd.close();
return true;
}
int main(int argc, char *argv[])
{
if (argc < 4)
{
std::cerr << "Syntax: " << argv[0] << " <base> <version.h> <build.h>" << std::endl;
return 1;
}
std::string version_sh = std::string(argv[1]) + "/src/version.sh";
std::string git_dir = std::string(argv[1]) + "/.git";
std::string versionh = argv[2];
std::string buildh = argv[3];
std::map<std::string, std::string> versions, old_versions;
if (!read_version_sh(version_sh, versions))
return -1;
std::string git_version = get_git_hash(git_dir);
if (!write_build_h(buildh, git_version))
return -1;
read_version_h(versionh, old_versions);
if (versions == old_versions)
return 0;
if (!write_version_h(versionh, versions))
return -1;
return 0;
}
+1 -3
View File
@@ -11003,9 +11003,7 @@ msgstr "You are now an IRC Operator."
#: modules/commands/ns_resetpass.cpp:108
#, fuzzy
msgid "You are now identified for your nick. Change your password now."
msgstr ""
"You are now identified for your nick. Change your password using \"/msg %s "
"SET PASSWORD newpassword\" now."
msgstr "You are now identified for your nick. Change your password now."
#: modules/commands/ns_group.cpp:50
#, c-format
+2 -4
View File
@@ -6389,7 +6389,7 @@ msgstr "%s ist ein services operator vom Typ %s."
#: modules/commands/ns_info.cpp:34
#, c-format
msgid "Nick %s is part of this Network's Services."
msgstr "Der Nickname %s ist ein teil der Network Services."
msgstr "Der Nickname %s ist ein Teil der Netzwerkdienste."
#: include/language.h:80
#, fuzzy, c-format
@@ -10693,9 +10693,7 @@ msgstr "Du bist jetzt ein IRC Operator."
#: modules/commands/ns_resetpass.cpp:108
msgid "You are now identified for your nick. Change your password now."
msgstr ""
"Du bist jetzt für deinen Nick angemeldet. Ändere jetzt dein Passwort mit \"/"
"msg %s SET PASSWORD newpassword\" ."
msgstr "Du bist jetzt für Deinen Nick angemeldet. Bitte ändere jetzt das Passwort."
#: modules/commands/ns_group.cpp:50
#, c-format
+1 -1
View File
@@ -10917,7 +10917,7 @@ msgstr "Τώρα είστε IRC Operator."
msgid "You are now identified for your nick. Change your password now."
msgstr ""
"Έχετε γίνει identify για το nick σας. Αλλάξτε τον κωδικό σας με την εντολή "
"\"/msg %s SET PASSWORD #newpassword#\" τώρα."
"\"/msg SET PASSWORD #newpassword#\" τώρα."
#: modules/commands/ns_group.cpp:50
#, c-format
+270 -279
View File
File diff suppressed because it is too large Load Diff
+1962 -1910
View File
File diff suppressed because it is too large Load Diff
+1 -3
View File
@@ -10919,9 +10919,7 @@ msgstr "Most már IRC Operátor vagy!"
#: modules/commands/ns_resetpass.cpp:108
#, fuzzy
msgid "You are now identified for your nick. Change your password now."
msgstr ""
"You are now identified for your nick. Change your password using \"/msg %s "
"SET PASSWORD newpassword\" now."
msgstr "You are now identified for your nick. Change your password now."
#: modules/commands/ns_group.cpp:50
#, c-format
+2 -2
View File
@@ -4513,6 +4513,7 @@ msgstr ""
"avranno l'accesso sul canale secondo le liste di accesso."
#: modules/commands/cs_set.cpp:944
#, fuzzy, c-format
msgid ""
"Enables or disables signed kicks for a\n"
"channel. When SIGNKICK is set, kicks issued with\n"
@@ -10302,8 +10303,7 @@ msgstr "Ora sei un IRC Operator."
#: modules/commands/ns_resetpass.cpp:108
msgid "You are now identified for your nick. Change your password now."
msgstr ""
"Adesso sei identificato per il tuo nick. Cambia la tua password adesso."
msgstr "Adesso sei identificato per il tuo nick. Cambia la tua password adesso."
#: modules/commands/ns_group.cpp:50
#, c-format
+557 -538
View File
File diff suppressed because it is too large Load Diff
+1 -3
View File
@@ -10846,9 +10846,7 @@ msgstr "Jesteś teraz IRC operatorem."
#: modules/commands/ns_resetpass.cpp:108
#, fuzzy
msgid "You are now identified for your nick. Change your password now."
msgstr ""
"You are now identified for your nick. Change your password using \"/msg %s "
"SET PASSWORD newpassword\" now."
msgstr "You are now identified for your nick. Change your password now."
#: modules/commands/ns_group.cpp:50
#, c-format
+1 -1
View File
@@ -10872,7 +10872,7 @@ msgstr "Você agora é um Operador de IRC."
#: modules/commands/ns_resetpass.cpp:108
#, fuzzy
msgid "You are now identified for your nick. Change your password now."
msgstr "You are now identified for your nick "
msgstr "You are now identified for your nick. Change your password now."
#: modules/commands/ns_group.cpp:50
#, c-format
+1 -3
View File
@@ -11155,9 +11155,7 @@ msgstr "Теперь вы IRC-оператор."
#: modules/commands/ns_resetpass.cpp:108
#, fuzzy
msgid "You are now identified for your nick. Change your password now."
msgstr ""
"You are now identified for your nick. Change your password using \"/msg %s "
"SET PASSWORD newpassword\" now."
msgstr "You are now identified for your nick. Change your password now."
#: modules/commands/ns_group.cpp:50
#, c-format
+1 -3
View File
@@ -10838,9 +10838,7 @@ msgstr "You are now an IRC Operator."
#: modules/commands/ns_resetpass.cpp:108
#, fuzzy
msgid "You are now identified for your nick. Change your password now."
msgstr ""
"You are now identified for your nick. Change your password using \"/msg %s "
"SET PASSWORD newpassword\" now."
msgstr "You are now identified for your nick. Change your password now."
#: modules/commands/ns_group.cpp:50
#, c-format
+4 -4
View File
@@ -75,7 +75,7 @@ class CommandBSAssign : public Command
{
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_("Assigns a bot pointed out by nick to a channel. You\n"
source.Reply(_("Assigns the specified bot to a channel. You\n"
"can then configure the bot for the channel so it fits\n"
"your needs."));
return true;
@@ -121,7 +121,7 @@ class CommandBSUnassign : public Command
if (ci->HasExt("PERSIST") && !ModeManager::FindChannelModeByName("PERM"))
{
source.Reply(_("You can not unassign bots while persist is set on the channel."));
source.Reply(_("You cannot unassign bots while persist is set on the channel."));
return;
}
@@ -195,9 +195,9 @@ class CommandBSSetNoBot : public Command
{
this->SendSyntax(source);
source.Reply(_(" \n"
"This option makes a channel be unassignable. If a bot\n"
"This option makes a channel unassignable. If a bot\n"
"is already assigned to the channel, it is unassigned\n"
"automatically when you enable the option."));
"automatically when you enable it."));
return true;
}
};
+4 -3
View File
@@ -138,7 +138,8 @@ Serializable* BadWordImpl::Unserialize(Serializable *obj, Serialize::Data &data)
bw->type = static_cast<BadWordType>(n);
BadWordsImpl *bws = ci->Require<BadWordsImpl>("badwords");
bws->badwords->push_back(bw);
if (!obj)
bws->badwords->push_back(bw);
return bw;
}
@@ -400,7 +401,7 @@ class CommandBSBadwords : public Command
if (Anope::ReadOnly)
{
source.Reply(_("Sorry, channel bad words list modification is temporarily disabled."));
source.Reply(_("Sorry, bad words list modification is temporarily disabled."));
return;
}
@@ -446,7 +447,7 @@ class CommandBSBadwords : public Command
" Lists bad words entries numbered 2 through 5 and\n"
" 7 through 9.\n"
" \n"
"The \002CLEAR\002 command clears all entries of the\n"
"The \002CLEAR\002 command clears all entries from the\n"
"bad words list."));
return true;
}
+4 -4
View File
@@ -139,7 +139,7 @@ class CommandBSBot : public Command
*/
if (nick.equals_cs(bi->nick) && (!user.empty() ? user.equals_cs(bi->GetIdent()) : 1) && (!host.empty() ? host.equals_cs(bi->host) : 1) && (!real.empty() ? real.equals_cs(bi->realname) : 1))
{
source.Reply(_("Old info is equal to the new one."));
source.Reply(_("The old information is the same as the new information specified."));
return;
}
@@ -341,13 +341,13 @@ class CommandBSBot : public Command
"hostname and realname. Since no integrity checks are done\n"
"for these settings, be really careful.\n"
" \n"
"\002BOT CHANGE\002 allows to change the nickname, username, hostname\n"
"or realname of a bot without actually having to delete it (and\n"
"\002BOT CHANGE\002 allows you to change the nickname, username, hostname\n"
"or realname of a bot without deleting it (and\n"
"all the data associated with it).\n"
" \n"
"\002BOT DEL\002 removes the given bot from the bot list.\n"
" \n"
"\002Note\002: you cannot create a bot that has a nick that is\n"
"\002Note\002: You cannot create a bot with a nick that is\n"
"currently registered. If an unregistered user is currently\n"
"using the nick, they will be killed."));
return true;
+3 -3
View File
@@ -16,7 +16,7 @@ class CommandBSSay : public Command
public:
CommandBSSay(Module *creator) : Command(creator, "botserv/say", 2, 2)
{
this->SetDesc(_("Makes the bot say the given text on the given channel"));
this->SetDesc(_("Makes the bot say the specified text on the specified channel"));
this->SetSyntax(_("\037channel\037 \037text\037"));
}
@@ -66,7 +66,7 @@ class CommandBSSay : public Command
{
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_("Makes the bot say the given text on the given channel."));
source.Reply(_("Makes the bot say the specified text on the specified channel."));
return true;
}
};
@@ -125,7 +125,7 @@ class CommandBSAct : public Command
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_("Makes the bot do the equivalent of a \"/me\" command\n"
"on the given channel using the given text."));
"on the specified channel using the specified text."));
return true;
}
};
+3 -3
View File
@@ -230,12 +230,12 @@ class CommandBSKickBase : public Command
source.Reply(_("Bot will now kick for \002%s\002."), optname.c_str());
bool override = !source.AccessFor(ci).HasPriv("SET");
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enable the " << optname << "kicker";
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enable the " << optname << " kicker";
}
else if (param.equals_ci("OFF"))
{
bool override = !source.AccessFor(ci).HasPriv("SET");
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to disable the " << optname << "kicker";
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to disable the " << optname << " kicker";
val = false;
source.Reply(_("Bot won't kick for \002%s\002 anymore."), optname.c_str());
@@ -514,7 +514,7 @@ class CommandBSKickFlood : public CommandBSKickBase
try
{
i = convertTo<int16_t>(ttb);
if (i < 1)
if (i < 0)
throw ConvertException();
}
catch (const ConvertException &)
+10 -1
View File
@@ -32,6 +32,8 @@ class CommandBSSet : public Command
source.Reply(_("Configures bot options.\n"
" \n"
"Available options:"));
bool hide_privileged_commands = Config->GetBlock("options")->Get<bool>("hideprivilegedcommands"),
hide_registered_commands = Config->GetBlock("options")->Get<bool>("hideregisteredcommands");
Anope::string this_name = source.command;
for (CommandInfo::map::const_iterator it = source.service->commands.begin(), it_end = source.service->commands.end(); it != it_end; ++it)
{
@@ -42,6 +44,13 @@ class CommandBSSet : public Command
ServiceReference<Command> command("Command", info.name);
if (command)
{
// XXX dup
if (hide_registered_commands && !command->AllowUnregistered() && !source.GetAccount())
continue;
if (hide_privileged_commands && !info.permission.empty() && !source.HasCommand(info.permission))
continue;
source.command = it->first;
command->OnServHelp(source);
}
@@ -100,7 +109,7 @@ class CommandBSSetBanExpire : public Command
if (Anope::ReadOnly)
{
source.Reply(_("Sorry, bot option setting is temporarily disabled."));
source.Reply(_("Sorry, changing bot options is temporarily disabled."));
return;
}
+9 -2
View File
@@ -122,6 +122,7 @@ class CommandCSAccess : public Command
tmp_access.level = level;
bool override = false;
const NickAlias *na = NULL;
if ((!highest || *highest <= tmp_access) && !u_access.founder)
{
@@ -158,7 +159,8 @@ class CommandCSAccess : public Command
}
else
{
const NickAlias *na = NickAlias::Find(mask);
na = NickAlias::Find(mask);
if (!na && Config->GetModule("chanserv")->Get<bool>("disallow_hostmask_access"))
{
source.Reply(_("Masks and unregistered users may not be on access lists."));
@@ -175,12 +177,15 @@ class CommandCSAccess : public Command
return;
}
}
if (na)
mask = na->nick;
}
for (unsigned i = ci->GetAccessCount(); i > 0; --i)
{
const ChanAccess *access = ci->GetAccess(i - 1);
if (mask.equals_ci(access->Mask()))
if ((na && na->nc == access->GetAccount()) || mask.equals_ci(access->Mask()))
{
/* Don't allow lowering from a level >= u_level */
if ((!highest || *access >= *highest) && !u_access.founder && !source.HasPriv("chanserv/access/modify"))
@@ -518,6 +523,8 @@ class CommandCSAccess : public Command
bool has_access = false;
if (source.HasPriv("chanserv/access/modify"))
has_access = true;
else if (is_list && source.HasPriv("chanserv/access/list"))
has_access = true;
else if (is_list && source.AccessFor(ci).HasPriv("ACCESS_LIST"))
has_access = true;
else if (source.AccessFor(ci).HasPriv("ACCESS_CHANGE"))
+12 -4
View File
@@ -71,10 +71,10 @@ class CommandCSAKick : public Command
/* Check excepts BEFORE we get this far */
if (ci->c)
{
std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> modes = ci->c->GetModeList("EXCEPT");
for (; modes.first != modes.second; ++modes.first)
std::vector<Anope::string> modes = ci->c->GetModeList("EXCEPT");
for (unsigned int i = 0; i < modes.size(); ++i)
{
if (Anope::Match(modes.first->second, mask))
if (Anope::Match(modes[i], mask))
{
source.Reply(CHAN_EXCEPTED, mask.c_str(), ci->name.c_str());
return;
@@ -441,9 +441,17 @@ class CommandCSAKick : public Command
return;
}
bool is_list = cmd.equals_ci("LIST") || cmd.equals_ci("VIEW");
bool has_access = false;
if (source.AccessFor(ci).HasPriv("AKICK") || source.HasPriv("chanserv/access/modify"))
has_access = true;
else if (is_list && source.HasPriv("chanserv/access/list"))
has_access = true;
if (mask.empty() && (cmd.equals_ci("ADD") || cmd.equals_ci("DEL")))
this->OnSyntaxError(source, cmd);
else if (!source.AccessFor(ci).HasPriv("AKICK") && !source.HasPriv("chanserv/access/modify"))
else if (!has_access)
source.Reply(ACCESS_DENIED);
else if (!cmd.equals_ci("LIST") && !cmd.equals_ci("VIEW") && !cmd.equals_ci("ENFORCE") && Anope::ReadOnly)
source.Reply(_("Sorry, channel autokick list modification is temporarily disabled."));
+25 -11
View File
@@ -101,6 +101,9 @@ class CommandCSBan : public Command
if (reason.length() > reasonmax)
reason = reason.substr(0, reasonmax);
Anope::string signkickformat = Config->GetModule("chanserv")->Get<Anope::string>("signkickformat", "%m (%n)");
signkickformat = signkickformat.replace_all_cs("%n", source.GetNick());
User *u = source.GetUser();
User *u2 = User::Find(target, true);
@@ -146,7 +149,10 @@ class CommandCSBan : public Command
if (block->Get<bool>("kick", "yes"))
{
if (ci->HasExt("SIGNKICK") || (ci->HasExt("SIGNKICK_LEVEL") && !source.AccessFor(ci).HasPriv("SIGNKICK")))
c->Kick(ci->WhoSends(), u2, "%s (%s)", reason.c_str(), source.GetNick().c_str());
{
signkickformat = signkickformat.replace_all_cs("%m", reason);
c->Kick(ci->WhoSends(), u2, "%s", signkickformat.c_str());
}
else
c->Kick(ci->WhoSends(), u2, "%s", reason.c_str());
}
@@ -156,15 +162,18 @@ class CommandCSBan : public Command
{
bool founder = u_access.HasPriv("FOUNDER");
bool override = !founder && !u_access.HasPriv("BAN");
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "for " << target;
if (!c->HasMode(mode, target))
Anope::string mask = IRCD->NormalizeMask(target);
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "for " << mask;
if (!c->HasMode(mode, mask))
{
c->SetMode(NULL, mode, target);
c->SetMode(NULL, mode, mask);
if (ban_time)
{
new TempBan(ban_time, c, target, mode);
source.Reply(_("Ban on \002%s\002 expires in %s."), target.c_str(), Anope::Duration(ban_time, source.GetAccount()).c_str());
new TempBan(ban_time, c, mask, mode);
source.Reply(_("Ban on \002%s\002 expires in %s."), mask.c_str(), Anope::Duration(ban_time, source.GetAccount()).c_str());
}
}
@@ -174,7 +183,8 @@ class CommandCSBan : public Command
ChanUserContainer *uc = it->second;
++it;
if (Anope::Match(uc->user->nick, target) || Anope::Match(uc->user->GetDisplayedMask(), target))
Entry e(mode, mask);
if (e.Matches(uc->user))
{
++matched;
@@ -193,17 +203,21 @@ class CommandCSBan : public Command
{
++kicked;
if (ci->HasExt("SIGNKICK") || (ci->HasExt("SIGNKICK_LEVEL") && !u_access.HasPriv("SIGNKICK")))
c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s) (%s)", reason.c_str(), target.c_str(), source.GetNick().c_str());
{
reason += " (Matches " + mask + ")";
signkickformat = signkickformat.replace_all_cs("%m", reason);
c->Kick(ci->WhoSends(), uc->user, "%s", signkickformat.c_str());
}
else
c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s)", reason.c_str(), target.c_str());
c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s)", reason.c_str(), mask.c_str());
}
}
}
if (matched)
source.Reply(_("Kicked %d/%d users matching %s from %s."), kicked, matched, target.c_str(), c->name.c_str());
source.Reply(_("Kicked %d/%d users matching %s from %s."), kicked, matched, mask.c_str(), c->name.c_str());
else
source.Reply(_("No users on %s match %s."), c->name.c_str(), target.c_str());
source.Reply(_("No users on %s match %s."), c->name.c_str(), mask.c_str());
}
}
+115 -67
View File
@@ -14,6 +14,100 @@
class CommandCSClone : public Command
{
void CopySetting(ChannelInfo *ci, ChannelInfo *target_ci, const Anope::string &setting)
{
if (ci->HasExt(setting))
target_ci->Extend<bool>(setting);
}
void CopyAccess(CommandSource &source, ChannelInfo *ci, ChannelInfo *target_ci)
{
std::set<Anope::string> masks;
unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1024");
unsigned count = 0;
for (unsigned i = 0; i < target_ci->GetAccessCount(); ++i)
masks.insert(target_ci->GetAccess(i)->Mask());
for (unsigned i = 0; i < ci->GetAccessCount(); ++i)
{
const ChanAccess *taccess = ci->GetAccess(i);
AccessProvider *provider = taccess->provider;
if (access_max && target_ci->GetDeepAccessCount() >= access_max)
break;
if (masks.count(taccess->Mask()))
continue;
masks.insert(taccess->Mask());
ChanAccess *newaccess = provider->Create();
newaccess->SetMask(taccess->Mask(), target_ci);
newaccess->creator = taccess->creator;
newaccess->last_seen = taccess->last_seen;
newaccess->created = taccess->created;
newaccess->AccessUnserialize(taccess->AccessSerialize());
target_ci->AddAccess(newaccess);
++count;
}
source.Reply(_("%d access entries from \002%s\002 have been cloned to \002%s\002."), count, ci->name.c_str(), target_ci->name.c_str());
}
void CopyAkick(CommandSource &source, ChannelInfo *ci, ChannelInfo *target_ci)
{
target_ci->ClearAkick();
for (unsigned i = 0; i < ci->GetAkickCount(); ++i)
{
const AutoKick *akick = ci->GetAkick(i);
if (akick->nc)
target_ci->AddAkick(akick->creator, akick->nc, akick->reason, akick->addtime, akick->last_used);
else
target_ci->AddAkick(akick->creator, akick->mask, akick->reason, akick->addtime, akick->last_used);
}
source.Reply(_("All akick entries from \002%s\002 have been cloned to \002%s\002."), ci->name.c_str(), target_ci->name.c_str());
}
void CopyBadwords(CommandSource &source, ChannelInfo *ci, ChannelInfo *target_ci)
{
BadWords *target_badwords = target_ci->Require<BadWords>("badwords"),
*badwords = ci->Require<BadWords>("badwords");
if (!target_badwords || !badwords)
{
source.Reply(ACCESS_DENIED); // BotServ doesn't exist/badwords isn't loaded
return;
}
target_badwords->ClearBadWords();
for (unsigned i = 0; i < badwords->GetBadWordCount(); ++i)
{
const BadWord *bw = badwords->GetBadWord(i);
target_badwords->AddBadWord(bw->word, bw->type);
}
badwords->Check();
target_badwords->Check();
source.Reply(_("All badword entries from \002%s\002 have been cloned to \002%s\002."), ci->name.c_str(), target_ci->name.c_str());
}
void CopyLevels(CommandSource &source, ChannelInfo *ci, ChannelInfo *target_ci)
{
const Anope::map<int16_t> &cilevels = ci->GetLevelEntries();
for (Anope::map<int16_t>::const_iterator it = cilevels.begin(); it != cilevels.end(); ++it)
{
target_ci->SetLevel(it->first, it->second);
}
source.Reply(_("All level entries from \002%s\002 have been cloned into \002%s\002."), ci->name.c_str(), target_ci->name.c_str());
}
public:
CommandCSClone(Module *creator) : Command(creator, "chanserv/clone", 2, 3)
{
@@ -100,82 +194,36 @@ public:
else
target_ci->last_topic_setter = source.service->nick;
const Anope::string settings[] = { "NOAUTOOP", "CS_KEEP_MODES", "PEACE", "PERSIST", "RESTRICTED",
"CS_SECURE", "SECUREFOUNDER", "SECUREOPS", "SIGNKICK", "SIGNKICK_LEVEL", "CS_NO_EXPIRE" };
for (unsigned int i = 0; i < sizeof(settings) / sizeof(Anope::string); ++i)
CopySetting(ci, target_ci, settings[i]);
CopyAccess(source, ci, target_ci);
CopyAkick(source, ci, target_ci);
CopyBadwords(source, ci, target_ci);
CopyLevels(source, ci, target_ci);
FOREACH_MOD(OnChanRegistered, (target_ci));
source.Reply(_("All settings from \002%s\002 have been cloned to \002%s\002."), channel.c_str(), target.c_str());
source.Reply(_("All settings from \002%s\002 have been cloned to \002%s\002."), ci->name.c_str(), target_ci->name.c_str());
}
else if (what.equals_ci("ACCESS"))
{
std::set<Anope::string> masks;
unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1024");
unsigned count = 0;
for (unsigned i = 0; i < target_ci->GetAccessCount(); ++i)
masks.insert(target_ci->GetAccess(i)->Mask());
for (unsigned i = 0; i < ci->GetAccessCount(); ++i)
{
const ChanAccess *taccess = ci->GetAccess(i);
AccessProvider *provider = taccess->provider;
if (access_max && target_ci->GetDeepAccessCount() >= access_max)
break;
if (masks.count(taccess->Mask()))
continue;
masks.insert(taccess->Mask());
ChanAccess *newaccess = provider->Create();
newaccess->SetMask(taccess->Mask(), target_ci);
newaccess->creator = taccess->creator;
newaccess->last_seen = taccess->last_seen;
newaccess->created = taccess->created;
newaccess->AccessUnserialize(taccess->AccessSerialize());
target_ci->AddAccess(newaccess);
++count;
}
source.Reply(_("%d access entries from \002%s\002 have been cloned to \002%s\002."), count, channel.c_str(), target.c_str());
CopyAccess(source, ci, target_ci);
}
else if (what.equals_ci("AKICK"))
{
target_ci->ClearAkick();
for (unsigned i = 0; i < ci->GetAkickCount(); ++i)
{
const AutoKick *akick = ci->GetAkick(i);
if (akick->nc)
target_ci->AddAkick(akick->creator, akick->nc, akick->reason, akick->addtime, akick->last_used);
else
target_ci->AddAkick(akick->creator, akick->mask, akick->reason, akick->addtime, akick->last_used);
}
source.Reply(_("All akick entries from \002%s\002 have been cloned to \002%s\002."), channel.c_str(), target.c_str());
CopyAkick(source, ci, target_ci);
}
else if (what.equals_ci("BADWORDS"))
{
BadWords *target_badwords = target_ci->Require<BadWords>("badwords"),
*badwords = ci->Require<BadWords>("badwords");
if (!target_badwords || !badwords)
{
source.Reply(ACCESS_DENIED); // BotServ doesn't exist/badwords isn't loaded
return;
}
target_badwords->ClearBadWords();
for (unsigned i = 0; i < badwords->GetBadWordCount(); ++i)
{
const BadWord *bw = badwords->GetBadWord(i);
target_badwords->AddBadWord(bw->word, bw->type);
}
badwords->Check();
target_badwords->Check();
source.Reply(_("All badword entries from \002%s\002 have been cloned to \002%s\002."), channel.c_str(), target.c_str());
CopyBadwords(source, ci, target_ci);
}
else if (what.equals_ci("LEVELS"))
{
CopyLevels(source, ci, target_ci);
}
else
{
@@ -191,8 +239,8 @@ public:
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_("Copies all settings, access, akicks, etc from \002channel\002 to the\n"
"\002target\002 channel. If \037what\037 is \002ACCESS\002, \002AKICK\002, or \002BADWORDS\002\n"
"then only the respective settings are cloned.\n"
"\002target\002 channel. If \037what\037 is \002ACCESS\002, \002AKICK\002, \002BADWORDS\002,\n"
"or \002LEVELS\002 then only the respective settings are cloned.\n"
"You must be the founder of \037channel\037 and \037target\037."));
return true;
}
+2 -2
View File
@@ -71,8 +71,8 @@ class CommandCSDrop : public Command
this->SendSyntax(source);
source.Reply(" ");
if (source.IsServicesOper())
source.Reply(_("Unregisters the named channel. Only \002Services Operators\002\n"
"can drop a channel of which they are not the founder."));
source.Reply(_("Unregisters the specified channel. Only \002Services Operators\002\n"
"can drop a channel of which they are not the founder of."));
else
source.Reply(_("Unregisters the named channel. Can only be used by\n"
"the \002channel founder\002."));
+13 -10
View File
@@ -143,7 +143,7 @@ class CommandEntryMessage : public Command
else
{
(*messages)->push_back(new EntryMsgImpl(ci, source.GetNick(), message));
Log(source.IsFounder(ci) ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to add a message";
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to add a message";
source.Reply(_("Entry message added to \002%s\002"), ci->name.c_str());
}
}
@@ -166,7 +166,7 @@ class CommandEntryMessage : public Command
delete (*messages)->at(i - 1);
if ((*messages)->empty())
ci->Shrink<EntryMessageList>("entrymsg");
Log(source.IsFounder(ci) ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to remove a message";
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to remove a message";
source.Reply(_("Entry message \002%i\002 for \002%s\002 deleted."), i, ci->name.c_str());
}
else
@@ -183,7 +183,7 @@ class CommandEntryMessage : public Command
{
ci->Shrink<EntryMessageList>("entrymsg");
Log(source.IsFounder(ci) ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to remove all messages";
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to remove all messages";
source.Reply(_("Entry messages for \002%s\002 have been cleared."), ci->name.c_str());
}
@@ -212,7 +212,7 @@ class CommandEntryMessage : public Command
return;
}
if (!source.IsFounder(ci) && !source.HasPriv("chanserv/administration"))
if (!source.AccessFor(ci).HasPriv("SET") && !source.HasPriv("chanserv/administration"))
{
source.Reply(ACCESS_DENIED);
return;
@@ -239,20 +239,23 @@ class CommandEntryMessage : public Command
source.Reply(_("Controls what messages will be sent to users when they join the channel."));
source.Reply(" ");
source.Reply(_("The \002ENTRYMSG ADD\002 command adds the given message to\n"
"the list of messages to be shown to users when they join\n"
"the list of messages shown to users when they join\n"
"the channel."));
source.Reply(" ");
source.Reply(_("The \002ENTRYMSG DEL\002 command removes the given message from\n"
"the list of messages to be shown to users when they join\n"
"the channel. You can remove the message by specifying its number\n"
source.Reply(_("The \002ENTRYMSG DEL\002 command removes the specified message from\n"
"the list of messages shown to users when they join\n"
"the channel. You can remove a message by specifying its number\n"
"which you can get by listing the messages as explained below."));
source.Reply(" ");
source.Reply(_("The \002ENTRYMSG LIST\002 command displays a listing of messages\n"
"to be shown to users when they join the channel."));
"shown to users when they join the channel."));
source.Reply(" ");
source.Reply(_("The \002ENTRYMSG CLEAR\002 command clears all entries from\n"
"the list of messages to be shown to users when they join\n"
"the list of messages shown to users when they join\n"
"the channel, effectively disabling entry messages."));
source.Reply(" ");
source.Reply(_("Adding, deleting, or clearing entry messages requires the\n"
"SET permission."));
return true;
}
};
+30 -15
View File
@@ -78,11 +78,8 @@ FlagsAccessProvider* FlagsAccessProvider::ap;
class CommandCSFlags : public Command
{
void DoModify(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> &params)
void DoModify(CommandSource &source, ChannelInfo *ci, Anope::string mask, const Anope::string &flags)
{
Anope::string mask = params.size() > 2 ? params[2] : "";
Anope::string flags = params.size() > 3 ? params[3] : "";
if (flags.empty())
{
this->OnSyntaxError(source, "");
@@ -91,6 +88,7 @@ class CommandCSFlags : public Command
AccessGroup u_access = source.AccessFor(ci);
const ChanAccess *highest = u_access.Highest();
const NickAlias *na = NULL;
if (IRCD->IsChannelValid(mask))
{
@@ -116,7 +114,7 @@ class CommandCSFlags : public Command
}
else
{
const NickAlias *na = NickAlias::Find(mask);
na = NickAlias::Find(mask);
if (!na && Config->GetModule("chanserv")->Get<bool>("disallow_hostmask_access"))
{
source.Reply(_("Masks and unregistered users may not be on access lists."));
@@ -133,6 +131,9 @@ class CommandCSFlags : public Command
return;
}
}
if (na)
mask = na->nick;
}
ChanAccess *current = NULL;
@@ -142,7 +143,7 @@ class CommandCSFlags : public Command
for (current_idx = ci->GetAccessCount(); current_idx > 0; --current_idx)
{
ChanAccess *access = ci->GetAccess(current_idx - 1);
if (mask.equals_ci(access->Mask()))
if ((na && na->nc == access->GetAccount()) || mask.equals_ci(access->Mask()))
{
// Flags allows removing others that have the same access as you,
// but no other access system does.
@@ -227,7 +228,7 @@ class CommandCSFlags : public Command
override = true;
else
{
source.Reply(_("You can not set the \002%c\002 flag."), f);
source.Reply(_("You cannot set the \002%c\002 flag."), f);
break;
}
}
@@ -370,7 +371,7 @@ class CommandCSFlags : public Command
CommandCSFlags(Module *creator) : Command(creator, "chanserv/flags", 1, 4)
{
this->SetDesc(_("Modify the list of privileged users"));
this->SetSyntax(_("\037channel\037 MODIFY \037mask\037 \037changes\037"));
this->SetSyntax(_("\037channel\037 [MODIFY] \037mask\037 \037changes\037"));
this->SetSyntax(_("\037channel\037 LIST [\037mask\037 | +\037flags\037]"));
this->SetSyntax(_("\037channel\037 CLEAR"));
}
@@ -391,6 +392,8 @@ class CommandCSFlags : public Command
bool has_access = false;
if (source.HasPriv("chanserv/access/modify"))
has_access = true;
else if (is_list && source.HasPriv("chanserv/access/list"))
has_access = true;
else if (is_list && source.AccessFor(ci).HasPriv("ACCESS_LIST"))
has_access = true;
else if (source.AccessFor(ci).HasPriv("ACCESS_CHANGE"))
@@ -400,14 +403,26 @@ class CommandCSFlags : public Command
source.Reply(ACCESS_DENIED);
else if (Anope::ReadOnly && !is_list)
source.Reply(_("Sorry, channel access list modification is temporarily disabled."));
else if (cmd.equals_ci("MODIFY"))
this->DoModify(source, ci, params);
else if (is_list)
this->DoList(source, ci, params);
else if (cmd.equals_ci("CLEAR"))
this->DoClear(source, ci);
else
this->OnSyntaxError(source, cmd);
{
Anope::string mask, flags;
if (cmd.equals_ci("MODIFY"))
{
mask = params.size() > 2 ? params[2] : "";
flags = params.size() > 3 ? params[3] : "";
}
else
{
mask = cmd;
flags = params.size() > 2 ? params[2] : "";
}
this->DoModify(source, ci, mask, flags);
}
}
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
@@ -417,19 +432,19 @@ class CommandCSFlags : public Command
source.Reply(_("%s is another way to modify the channel access list, similar to\n"
"the XOP and ACCESS methods."), source.command.c_str());
source.Reply(" ");
source.Reply(_("The \002MODIFY\002 command allows you to modify the access list. If mask is\n"
"not already on the access list is it added, then the changes are applied.\n"
source.Reply(_("The \002MODIFY\002 command allows you to modify the access list. If the mask is\n"
"not already on the access list it is added, then the changes are applied.\n"
"If the mask has no more flags, then the mask is removed from the access list.\n"
"Additionally, you may use +* or -* to add or remove all flags, respectively. You are\n"
"only able to modify the access list if you have the proper permission on the channel,\n"
"and even then you can only give other people access to up what you already have."));
"and even then you can only give other people access to the equivalent of what your access is."));
source.Reply(" ");
source.Reply(_("The \002LIST\002 command allows you to list existing entries on the channel access list.\n"
"If a mask is given, the mask is wildcard matched against all existing entries on the\n"
"access list, and only those entries are returned. If a set of flags is given, only those\n"
"on the access list with the specified flags are returned."));
source.Reply(" ");
source.Reply(_("The \002CLEAR\002 command clears the channel access list, which requires channel founder."));
source.Reply(_("The \002CLEAR\002 command clears the channel access list. This requires channel founder access."));
source.Reply(" ");
source.Reply(_("The available flags are:"));
+7 -7
View File
@@ -16,7 +16,7 @@ class CommandCSInfo : public Command
public:
CommandCSInfo(Module *creator) : Command(creator, "chanserv/info", 1, 2)
{
this->SetDesc(_("Lists information about the named registered channel"));
this->SetDesc(_("Lists information about the specified registered channel"));
this->SetSyntax(_("\037channel\037"));
this->AllowUnregistered(true);
}
@@ -73,12 +73,12 @@ class CommandCSInfo : public Command
{
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_("Lists information about the named registered channel,\n"
"including its founder, time of registration, and last\n"
"time used. If the user issuing the command has the\n"
"appropriate access for it, then the description, successor,\n"
"last topic set, settings and expiration time will also\n"
"be displayed when applicable."));
source.Reply(_("Lists information about the specified registered channel,\n"
"including its founder, time of registration, last\n"
"time used, and description. If the user issuing the\n"
"command has the appropriate access for it, then the\n"
"successor, last topic set, settings and expiration\n"
"time will also be displayed when applicable."));
return true;
}
};
+1 -1
View File
@@ -91,7 +91,7 @@ class CommandCSInvite : public Command
source.Reply(_("Tells %s to invite you or an optionally specified\n"
"nick into the given channel.\n"
" \n"
"By default, limited to AOPs or those with level 5 and above\n"
"By default, limited to AOPs or those with level 5 access and above\n"
"on the channel."), source.service->nick.c_str());
return true;
}
+21 -8
View File
@@ -47,6 +47,9 @@ class CommandCSKick : public Command
if (reason.length() > reasonmax)
reason = reason.substr(0, reasonmax);
Anope::string signkickformat = Config->GetModule("chanserv")->Get<Anope::string>("signkickformat", "%m (%n)");
signkickformat = signkickformat.replace_all_cs("%n", source.GetNick());
AccessGroup u_access = source.AccessFor(ci);
if (!u_access.HasPriv("KICK") && !source.HasPriv("chanserv/kick"))
@@ -66,14 +69,19 @@ class CommandCSKick : public Command
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "for " << u2->nick;
if (ci->HasExt("SIGNKICK") || (ci->HasExt("SIGNKICK_LEVEL") && !u_access.HasPriv("SIGNKICK")))
c->Kick(ci->WhoSends(), u2, "%s (%s)", reason.c_str(), source.GetNick().c_str());
{
signkickformat = signkickformat.replace_all_cs("%m", reason);
c->Kick(ci->WhoSends(), u2, "%s", signkickformat.c_str());
}
else
c->Kick(ci->WhoSends(), u2, "%s", reason.c_str());
}
}
else if (u_access.HasPriv("FOUNDER"))
{
Log(LOG_COMMAND, source, this, ci) << "for " << target;
Anope::string mask = IRCD->NormalizeMask(target);
Log(LOG_COMMAND, source, this, ci) << "for " << mask;
int matched = 0, kicked = 0;
for (Channel::ChanUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end;)
@@ -81,7 +89,8 @@ class CommandCSKick : public Command
ChanUserContainer *uc = it->second;
++it;
if (Anope::Match(uc->user->nick, target) || Anope::Match(uc->user->GetDisplayedMask(), target))
Entry e("", mask);
if (e.Matches(uc->user))
{
++matched;
@@ -93,16 +102,20 @@ class CommandCSKick : public Command
++kicked;
if (ci->HasExt("SIGNKICK") || (ci->HasExt("SIGNKICK_LEVEL") && !u_access.HasPriv("SIGNKICK")))
c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s) (%s)", reason.c_str(), target.c_str(), source.GetNick().c_str());
{
reason += " (Matches " + mask + ")";
signkickformat = signkickformat.replace_all_cs("%m", reason);
c->Kick(ci->WhoSends(), uc->user, "%s", signkickformat.c_str());
}
else
c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s)", reason.c_str(), target.c_str());
c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s)", reason.c_str(), mask.c_str());
}
}
if (matched)
source.Reply(_("Kicked %d/%d users matching %s from %s."), kicked, matched, target.c_str(), c->name.c_str());
source.Reply(_("Kicked %d/%d users matching %s from %s."), kicked, matched, mask.c_str(), c->name.c_str());
else
source.Reply(_("No users on %s match %s."), c->name.c_str(), target.c_str());
source.Reply(_("No users on %s match %s."), c->name.c_str(), mask.c_str());
}
else
source.Reply(NICK_X_NOT_IN_USE, target.c_str());
@@ -115,7 +128,7 @@ class CommandCSKick : public Command
source.Reply(_("Kicks a specified nick from a channel.\n"
" \n"
"By default, limited to AOPs or those with level 5 access\n"
"and above on the channel. Channel founders may use masks too."));
"and above on the channel. Channel founders can also specify masks."));
return true;
}
};
+1 -1
View File
@@ -271,7 +271,7 @@ public:
"To remove a logging method use the same syntax as you would to add it.\n"
" \n"
"Example:\n"
" %s #anope chanserv/access MESSAGE @%\n"
" %s #anope chanserv/access MESSAGE @\n"
" Would message any channel operators whenever someone used the\n"
" ACCESS command on ChanServ on the channel."),
source.command.upper().c_str(), source.command.upper().c_str());
+39 -18
View File
@@ -327,6 +327,8 @@ class CommandCSMode : public Command
source.Reply(_("Missing parameter for mode %c."), cm->mchar);
else if (cm->type == MODE_LIST && ci->c && IRCD->GetMaxListFor(ci->c) && ci->c->HasMode(cm->name) >= IRCD->GetMaxListFor(ci->c))
source.Reply(_("List for mode %c is full."), cm->mchar);
else if (modelocks->GetMLock().size() >= Config->GetModule(this->owner)->Get<unsigned>("max", "32"))
source.Reply(_("The mode lock list of \002%s\002 is full."), ci->name.c_str());
else
{
modelocks->SetMLock(cm, adding, mode_param, source.GetNick());
@@ -485,7 +487,7 @@ class CommandCSMode : public Command
case '*':
if (adding == -1 || !has_access)
break;
for (unsigned j = 0; j < ModeManager::GetChannelModes().size(); ++j)
for (unsigned j = 0; j < ModeManager::GetChannelModes().size() && ci->c; ++j)
{
ChannelMode *cm = ModeManager::GetChannelModes()[j];
@@ -613,15 +615,10 @@ class CommandCSMode : public Command
}
else
{
std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> its = ci->c->GetModeList(cm->name);
for (; its.first != its.second;)
{
const Anope::string &mask = its.first->second;
++its.first;
if (Anope::Match(mask, param))
ci->c->RemoveMode(NULL, cm, mask);
}
std::vector<Anope::string> v = ci->c->GetModeList(cm->name);
for (unsigned j = 0; j < v.size(); ++j)
if (Anope::Match(v[j], param))
ci->c->RemoveMode(NULL, cm, v[j]);
}
}
}
@@ -961,16 +958,40 @@ class CSMode : public Module
for (unsigned i = 0; i < mlock.length(); ++i)
{
if (mlock[i] == '+')
add = true;
else if (mlock[i] == '-')
add = false;
else
{
ChannelMode *cm = ModeManager::FindChannelModeByChar(mlock[i]);
Anope::string param;
if (cm && (cm->type == MODE_REGULAR || sep.GetToken(param)))
ml->SetMLock(cm, add, param);
add = true;
continue;
}
if (mlock[i] == '-')
{
add = false;
continue;
}
ChannelMode *cm = ModeManager::FindChannelModeByChar(mlock[i]);
if (!cm)
continue;
Anope::string param;
if (cm->type == MODE_PARAM)
{
ChannelModeParam *cmp = anope_dynamic_static_cast<ChannelModeParam *>(cm);
if (add || !cmp->minus_no_arg)
{
sep.GetToken(param);
if (param.empty() || !cmp->IsValid(param))
continue;
}
}
else if (cm->type != MODE_REGULAR)
{
sep.GetToken(param);
if (param.empty())
continue;
}
ml->SetMLock(cm, add, param);
}
}
ml->Check();
+3 -3
View File
@@ -45,7 +45,7 @@ class CommandCSRegister : public Command
source.Reply(CHAN_X_NOT_IN_USE, chan.c_str());
else if (ci)
source.Reply(_("Channel \002%s\002 is already registered!"), chan.c_str());
else if (c && !c->HasUserStatus(u, "OP"))
else if (c && u && !c->HasUserStatus(u, "OP"))
source.Reply(_("You must be a channel operator to register the channel."));
else if (maxregistered && nc->channelcount >= maxregistered && !source.HasPriv("chanserv/no-register-limit"))
source.Reply(nc->channelcount > maxregistered ? CHAN_EXCEEDED_CHANNEL_LIMIT : CHAN_REACHED_CHANNEL_LIMIT, maxregistered);
@@ -67,6 +67,8 @@ class CommandCSRegister : public Command
Log(LOG_COMMAND, source, this, ci);
source.Reply(_("Channel \002%s\002 registered under your account: %s"), chan.c_str(), nc->display.c_str());
FOREACH_MOD(OnChanRegistered, (ci));
/* Implement new mode lock */
if (c)
{
@@ -74,8 +76,6 @@ class CommandCSRegister : public Command
if (u)
c->SetCorrectModes(u, true);
}
FOREACH_MOD(OnChanRegistered, (ci));
}
}
+1 -1
View File
@@ -172,7 +172,7 @@ class CommandOSSeen : public Command
source.Reply(" ");
source.Reply(_("The \002STATS\002 command prints out statistics about stored nicks and memory usage."));
source.Reply(_("The \002CLEAR\002 command lets you clean the database by removing all entries from the\n"
"entries from the database that were added within \037time\037.\n"
"database that were added within \037time\037.\n"
" \n"
"Example:\n"
" %s CLEAR 30m\n"
+7 -12
View File
@@ -35,7 +35,8 @@ class CommandCSSet : public Command
" \n"
"Available options:"));
Anope::string this_name = source.command;
bool hide_privileged_commands = Config->GetBlock("options")->Get<bool>("hideprivilegedcommands");
bool hide_privileged_commands = Config->GetBlock("options")->Get<bool>("hideprivilegedcommands"),
hide_registered_commands = Config->GetBlock("options")->Get<bool>("hideregisteredcommands");
for (CommandInfo::map::const_iterator it = source.service->commands.begin(), it_end = source.service->commands.end(); it != it_end; ++it)
{
const Anope::string &c_name = it->first;
@@ -44,13 +45,12 @@ class CommandCSSet : public Command
{
ServiceReference<Command> c("Command", info.name);
// XXX dup
if (!c)
continue;
else if (!hide_privileged_commands)
; // Always show with hide_privileged_commands disabled
else if (!c->AllowUnregistered() && !source.GetAccount())
else if (hide_registered_commands && !c->AllowUnregistered() && !source.GetAccount())
continue;
else if (!info.permission.empty() && !source.HasCommand(info.permission))
else if (hide_privileged_commands && !info.permission.empty() && !source.HasCommand(info.permission))
continue;
source.command = it->first;
@@ -1010,7 +1010,7 @@ class CommandCSSetSuccessor : public Command
else
nc = NULL;
Log(!source.permission.empty() ? LOG_ADMIN : LOG_COMMAND, source, this, ci) << "to change the successor from " << (ci->GetSuccessor() ? ci->GetSuccessor()->display : "(none)") << " to " << (nc ? nc->display : "(none)");
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to change the successor from " << (ci->GetSuccessor() ? ci->GetSuccessor()->display : "(none)") << " to " << (nc ? nc->display : "(none)");
ci->SetSuccessor(nc);
@@ -1235,7 +1235,7 @@ class CSSet : public Module
ci->bantype = Config->GetModule(this)->Get<int>("defbantype", "2");
}
void OnChannelCreate(Channel *c) anope_override
void OnChannelSync(Channel *c) anope_override
{
if (c->ci && keep_modes.HasExt(c->ci))
{
@@ -1245,11 +1245,6 @@ class CSSet : public Module
}
}
void OnChannelSync(Channel *c) anope_override
{
OnChannelCreate(c);
}
EventReturn OnCheckKick(User *u, Channel *c, Anope::string &mask, Anope::string &reason) anope_override
{
if (!c->ci || !restricted.HasExt(c->ci) || c->MatchesList(u, "EXCEPT"))
+2 -2
View File
@@ -235,9 +235,9 @@ class CSSuspend : public Module
if (!si->reason.empty() && (show_hidden || Show(source, "reason")))
info[_("Suspend reason")] = si->reason;
if (si->when && (show_hidden || Show(source, "on")))
info[_("Suspended on")] = Anope::strftime(si->when, source.GetAccount(), true);
info[_("Suspended on")] = Anope::strftime(si->when, source.GetAccount());
if (si->expires && (show_hidden || Show(source, "expires")))
info[_("Suspension expires")] = Anope::strftime(si->expires, source.GetAccount(), true);
info[_("Suspension expires")] = Anope::strftime(si->expires, source.GetAccount());
}
void OnPreChanExpire(ChannelInfo *ci, bool &expire) anope_override
+19 -15
View File
@@ -114,10 +114,8 @@ class CommandCSTopic : public Command
source.Reply(_("Topic lock option for %s is now \002off\002."), ci->name.c_str());
}
void Set(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> &params)
void Set(CommandSource &source, ChannelInfo *ci, const Anope::string &topic)
{
const Anope::string &topic = params.size() > 2 ? params[2] : "";
bool has_topiclock = topiclock->HasExt(ci);
topiclock->Unset(ci);
ci->c->ChangeTopic(source.GetNick(), topic, Anope::CurTime);
@@ -141,12 +139,7 @@ class CommandCSTopic : public Command
else
new_topic = topic;
std::vector<Anope::string> new_params;
new_params.push_back("SET");
new_params.push_back(ci->name);
new_params.push_back(new_topic);
this->Set(source, ci, new_params);
this->Set(source, ci, new_topic);
}
public:
@@ -154,7 +147,7 @@ class CommandCSTopic : public Command
topiclock("TOPICLOCK")
{
this->SetDesc(_("Manipulate the topic of the specified channel"));
this->SetSyntax(_("\037channel\037 SET [\037topic\037]"));
this->SetSyntax(_("\037channel\037 [SET] [\037topic\037]"));
this->SetSyntax(_("\037channel\037 APPEND \037topic\037"));
this->SetSyntax(_("\037channel\037 [UNLOCK|LOCK]"));
}
@@ -174,12 +167,23 @@ class CommandCSTopic : public Command
this->Unlock(source, ci, params);
else if (!ci->c)
source.Reply(CHAN_X_NOT_IN_USE, ci->name.c_str());
else if (subcmd.equals_ci("SET"))
this->Set(source, ci, params);
else if (subcmd.equals_ci("APPEND") && params.size() > 2)
this->Append(source, ci, params);
else
this->SendSyntax(source);
{
Anope::string topic;
if (subcmd.equals_ci("SET"))
{
topic = params.size() > 2 ? params[2] : "";
}
else
{
topic = subcmd;
if (params.size() > 2)
topic += " " + params[2];
}
this->Set(source, ci, topic);
}
}
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
@@ -223,7 +227,7 @@ class CSTopic : public Module
}
}
void OnTopicUpdated(Channel *c, const Anope::string &user, const Anope::string &topic) anope_override
void OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic) anope_override
{
if (!c->ci)
return;
@@ -233,7 +237,7 @@ class CSTopic : public Module
* This desyncs what is really set with what we have stored, and we end up resetting the topic often when
* it is not required
*/
if (topiclock.HasExt(c->ci) && c->ci->last_topic != c->topic)
if (topiclock.HasExt(c->ci) && c->ci->last_topic != c->topic && (!source || !c->ci->AccessFor(source).HasPriv("TOPIC")))
{
c->ChangeTopic(c->ci->last_topic_setter, c->ci->last_topic, c->ci->last_topic_time);
}
+1 -1
View File
@@ -105,7 +105,7 @@ class CommandCSUnban : public Command
"given, all bans affecting you in channels you have access\n"
"in are removed.\n"
" \n"
"By default, limited to AOPs or those with level 5 and above\n"
"By default, limited to AOPs or those with level 5 access and above\n"
"on the channel."), source.service->nick.c_str());
return true;
}
+12
View File
@@ -81,6 +81,7 @@ class CommandCSUp : public Command
}
User *u = User::Find(nick, true);
User *srcu = source.GetUser();
bool override = false;
if (u == NULL)
@@ -88,6 +89,11 @@ class CommandCSUp : public Command
source.Reply(NICK_X_NOT_IN_USE, nick.c_str());
return;
}
else if (srcu && !srcu->FindChannel(c))
{
source.Reply(_("You must be in \002%s\002 to use this command."), c->name.c_str());
return;
}
else if (!u->FindChannel(c))
{
source.Reply(NICK_X_NOT_ON_CHAN, nick.c_str(), channel.c_str());
@@ -173,6 +179,7 @@ class CommandCSDown : public Command
}
User *u = User::Find(nick, true);
User *srcu = source.GetUser();
bool override = false;
if (u == NULL)
@@ -180,6 +187,11 @@ class CommandCSDown : public Command
source.Reply(NICK_X_NOT_IN_USE, nick.c_str());
return;
}
else if (srcu && !srcu->FindChannel(c))
{
source.Reply(_("You must be in \002%s\002 to use this command."), c->name.c_str());
return;
}
else if (!u->FindChannel(c))
{
source.Reply(NICK_X_NOT_ON_CHAN, nick.c_str(), channel.c_str());
+7 -8
View File
@@ -120,6 +120,7 @@ class CommandCSXOP : public Command
AccessGroup access = source.AccessFor(ci);
const ChanAccess *highest = access.Highest();
bool override = false;
const NickAlias *na = NULL;
std::vector<Anope::string>::iterator cmd_it = std::find(order.begin(), order.end(), source.command.upper()),
access_it = highest ? std::find(order.begin(), order.end(), XOPChanAccess::DetermineLevel(highest)) : order.end();
@@ -159,7 +160,7 @@ class CommandCSXOP : public Command
}
else
{
const NickAlias *na = NickAlias::Find(mask);
na = NickAlias::Find(mask);
if (!na && Config->GetModule("chanserv")->Get<bool>("disallow_hostmask_access"))
{
source.Reply(_("Masks and unregistered users may not be on access lists."));
@@ -176,13 +177,16 @@ class CommandCSXOP : public Command
return;
}
}
if (na)
mask = na->nick;
}
for (unsigned i = 0; i < ci->GetAccessCount(); ++i)
{
const ChanAccess *a = ci->GetAccess(i);
if (a->Mask().equals_ci(mask))
if ((na && na->nc == a->GetAccount()) || mask.equals_ci(a->Mask()))
{
if ((!highest || *a >= *highest) && !access.founder && !source.HasPriv("chanserv/access/modify"))
{
@@ -365,7 +369,7 @@ class CommandCSXOP : public Command
AccessGroup access = source.AccessFor(ci);
if (!access.HasPriv("ACCESS_LIST") && !source.HasCommand("chanserv/access/list"))
if (!access.HasPriv("ACCESS_LIST") && !source.HasPriv("chanserv/access/list"))
{
source.Reply(ACCESS_DENIED);
return;
@@ -562,11 +566,6 @@ class CommandCSXOP : public Command
"The \002%s CLEAR\002 command clears all entries of the\n"
"%s list."), cmd.c_str(), cmd.c_str(), cmd.c_str(), cmd.c_str(),
cmd.c_str(), cmd.c_str(), cmd.c_str(), cmd.c_str(), cmd.c_str(), cmd.c_str());
source.Reply(_(" \n"
"The \002%s\002 commands are limited to founders\n"
"(unless SECUREOPS is off). However, any user on the\n"
"VOP list or above may use the \002%s LIST\002 command.\n"
" \n"), cmd.c_str(), cmd.c_str());
BotInfo *access_bi, *flags_bi;
Anope::string access_cmd, flags_cmd;
Command::FindCommandFromService("chanserv/access", access_bi, access_cmd);
+1 -1
View File
@@ -56,7 +56,7 @@ class CommandHSDelAll : public Command
public:
CommandHSDelAll(Module *creator) : Command(creator, "hostserv/delall", 1, 1)
{
this->SetDesc(_("Delete the vhost for all nicks in a group"));
this->SetDesc(_("Deletes the vhost for all nicks in a group"));
this->SetSyntax(_("\037nick\037"));
}
+2 -2
View File
@@ -133,8 +133,8 @@ class CommandHSList : public Command
{
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_("This command lists registered vhosts to the operator\n"
"if a \037key\037 is specified, only entries whos nick or vhost match\n"
source.Reply(_("This command lists registered vhosts to the operator.\n"
"If a \037key\037 is specified, only entries whose nick or vhost match\n"
"the pattern given in \037key\037 are displayed e.g. Rob* for all\n"
"entries beginning with \"Rob\"\n"
"If a \037#X-Y\037 style is used, only entries between the range of \002X\002\n"
+7 -1
View File
@@ -96,6 +96,12 @@ class CommandHSRequest : public Command
return;
}
if (source.GetAccount()->HasExt("UNCONFIRMED"))
{
source.Reply(_("You must confirm your account before you may request a vhost."));
return;
}
Anope::string rawhostmask = params[0];
Anope::string user, host;
@@ -171,7 +177,7 @@ class CommandHSRequest : public Command
{
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_("Request the given vHost to be actived for your nick by the\n"
source.Reply(_("Request the given vHost to be activated for your nick by the\n"
"network administrators. Please be patient while your request\n"
"is being considered."));
return true;
+1 -1
View File
@@ -67,7 +67,7 @@ class CommandMSCheck : public Command
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_("Checks whether the _last_ memo you sent to \037nick\037 has been read\n"
"or not. Note that this does only work with nicks, not with channels."));
"or not. Note that this only works with nicks, not with channels."));
return true;
}
};
+6
View File
@@ -50,6 +50,12 @@ class CommandMSIgnore : public Command
source.Reply(ACCESS_DENIED);
else if (command.equals_ci("ADD") && !param.empty())
{
if (mi->ignores.size() >= Config->GetModule(this->owner)->Get<unsigned>("max", "32"))
{
source.Reply(_("Sorry, the memo ignore list for \002%s\002 is full."), channel.c_str());
return;
}
if (std::find(mi->ignores.begin(), mi->ignores.end(), param.ci_str()) == mi->ignores.end())
{
mi->ignores.push_back(param.ci_str());
+9
View File
@@ -39,9 +39,18 @@ class CommandMSSend : public Command
return;
}
if (source.GetAccount()->HasExt("UNCONFIRMED"))
{
source.Reply(_("You must confirm your account before you may send a memo."));
return;
}
MemoServService::MemoResult result = memoserv->Send(source.GetNick(), nick, text);
if (result == MemoServService::MEMO_SUCCESS)
{
source.Reply(_("Memo sent to \002%s\002."), nick.c_str());
Log(LOG_COMMAND, source, this) << "to send a memo to " << nick;
}
else if (result == MemoServService::MEMO_INVALID_TARGET)
source.Reply(_("\002%s\002 is not a registered unforbidden nick or channel."), nick.c_str());
else if (result == MemoServService::MEMO_TOO_FAST)
+5 -5
View File
@@ -318,19 +318,19 @@ class CommandNSCert : public Command
source.Reply(" ");
source.Reply(_("Modifies or displays the certificate list for your nick.\n"
"If you connect to IRC and provide a client certificate with a\n"
"matching fingerprint in the cert list, your nick will be\n"
"matching fingerprint in the cert list, you will be\n"
"automatically identified to services. Services Operators\n"
"may provide a nick to modify other users' certificate lists.\n"
" \n"));
source.Reply(_("Examples:\n"
" \n"
" \002CERT ADD <fingerprint>\002\n"
" Adds this fingerprint to the certificate list and\n"
" \002CERT ADD\002\n"
" Adds your current fingerprint to the certificate list and\n"
" automatically identifies you when you connect to IRC\n"
" using this certificate.\n"
" using this fingerprint.\n"
" \n"
" \002CERT DEL <fingerprint>\002\n"
" Reverses the previous command.\n"
" Removes the fingerprint <fingerprint> from your certificate list.\n"
" \n"
" \002CERT LIST\002\n"
" Displays the current certificate list."));
+4 -2
View File
@@ -72,7 +72,7 @@ class NSRecoverRequest : public IdentifyRequest
source.GetNick().c_str(), source.GetNick().c_str());
Anope::string buf = source.command.upper() + " command used by " + source.GetNick();
u->Kill(source.service->nick, buf);
u->Kill(*source.service, buf);
source.Reply(_("Ghost with your nick has been killed."));
@@ -95,8 +95,10 @@ class NSRecoverRequest : public IdentifyRequest
if (IRCD->CanSVSNick)
{
/* If we can svsnick then release our hold and svsnick the user using the command */
nickserv->Release(na);
if (nickserv)
nickserv->Release(na);
IRCD->SendForceNickChange(source.GetUser(), GetAccount(), Anope::CurTime);
source.Reply(_("You have regained control of \002%s\002 and are now identified as \002%s\002."), GetAccount().c_str(), na->nc->display.c_str());
}
else
source.Reply(_("The user with your nick has been removed. Use this command again\n"
+8 -4
View File
@@ -37,6 +37,7 @@ class CommandNSConfirm : public Command
else
{
na->nc->Shrink<bool>("UNCONFIRMED");
FOREACH_MOD(OnNickConfirm, (source.GetUser(), na->nc));
Log(LOG_ADMIN, source, this) << "to confirm nick " << na->nick << " (" << na->nc->display << ")";
source.Reply(_("Nick \002%s\002 has been confirmed."), na->nick.c_str());
}
@@ -51,6 +52,7 @@ class CommandNSConfirm : public Command
Log(LOG_COMMAND, source, this) << "to confirm their email";
source.Reply(_("Your email address of \002%s\002 has been confirmed."), source.nc->email.c_str());
nc->Shrink<bool>("UNCONFIRMED");
FOREACH_MOD(OnNickConfirm, (source.GetUser(), nc));
if (source.GetUser())
{
@@ -168,6 +170,8 @@ class CommandNSRegister : public Command
}
}
unsigned int passlen = Config->GetModule("nickserv")->Get<unsigned>("passlen", "32");
if (Config->GetModule("nickserv")->Get<bool>("forceemail", "yes") && email.empty())
this->OnSyntaxError(source, "");
else if (u && Anope::CurTime < u->lastnickreg + reg_delay)
@@ -176,8 +180,8 @@ class CommandNSRegister : public Command
source.Reply(NICK_ALREADY_REGISTERED, u_nick.c_str());
else if (pass.equals_ci(u_nick) || (Config->GetBlock("options")->Get<bool>("strictpasswords") && pass.length() < 5))
source.Reply(MORE_OBSCURE_PASSWORD);
else if (pass.length() > Config->GetModule("nickserv")->Get<unsigned>("passlen", "32"))
source.Reply(PASSWORD_TOO_LONG);
else if (pass.length() > passlen)
source.Reply(PASSWORD_TOO_LONG, passlen);
else if (!email.empty() && !Mail::Validate(email))
source.Reply(MAIL_X_INVALID, email.c_str());
else
@@ -198,8 +202,6 @@ class CommandNSRegister : public Command
Log(LOG_COMMAND, source, this) << "to register " << na->nick << " (email: " << (!na->nc->email.empty() ? na->nc->email : "none") << ")";
FOREACH_MOD(OnNickRegister, (source.GetUser(), na, pass));
if (na->nc->GetAccessCount())
source.Reply(_("Nickname \002%s\002 registered under your user@host-mask: %s"), u_nick.c_str(), na->nc->GetAccess(0).c_str());
else
@@ -223,6 +225,8 @@ class CommandNSRegister : public Command
}
}
FOREACH_MOD(OnNickRegister, (source.GetUser(), na, pass));
if (u)
{
u->Identify(na);
+17 -10
View File
@@ -33,7 +33,8 @@ class CommandNSSet : public Command
source.Reply(_("Sets various nickname options. \037option\037 can be one of:"));
Anope::string this_name = source.command;
bool hide_privileged_commands = Config->GetBlock("options")->Get<bool>("hideprivilegedcommands");
bool hide_privileged_commands = Config->GetBlock("options")->Get<bool>("hideprivilegedcommands"),
hide_registered_commands = Config->GetBlock("options")->Get<bool>("hideregisteredcommands");
for (CommandInfo::map::const_iterator it = source.service->commands.begin(), it_end = source.service->commands.end(); it != it_end; ++it)
{
const Anope::string &c_name = it->first;
@@ -42,13 +43,12 @@ class CommandNSSet : public Command
if (c_name.find_ci(this_name + " ") == 0)
{
ServiceReference<Command> c("Command", info.name);
// XXX dup
if (!c)
continue;
else if (!hide_privileged_commands)
; // Always show with hide_privileged_commands disabled
else if (!c->AllowUnregistered() && !source.GetAccount())
else if (hide_registered_commands && !c->AllowUnregistered() && !source.GetAccount())
continue;
else if (!info.permission.empty() && !source.HasCommand(info.permission))
else if (hide_privileged_commands && !info.permission.empty() && !source.HasCommand(info.permission))
continue;
source.command = c_name;
@@ -133,9 +133,11 @@ class CommandNSSetPassword : public Command
source.Reply(MORE_OBSCURE_PASSWORD);
return;
}
else if (len > Config->GetModule("nickserv")->Get<unsigned>("passlen", "32"))
unsigned int passlen = Config->GetModule("nickserv")->Get<unsigned>("passlen", "32");
if (len > passlen)
{
source.Reply(PASSWORD_TOO_LONG);
source.Reply(PASSWORD_TOO_LONG, passlen);
return;
}
@@ -191,14 +193,17 @@ class CommandNSSASetPassword : public Command
source.Reply(_("You may not change the password of other Services Operators."));
return;
}
else if (nc->display.equals_ci(params[1]) || (Config->GetBlock("options")->Get<bool>("strictpasswords") && len < 5))
if (nc->display.equals_ci(params[1]) || (Config->GetBlock("options")->Get<bool>("strictpasswords") && len < 5))
{
source.Reply(MORE_OBSCURE_PASSWORD);
return;
}
else if (len > Config->GetModule("nickserv")->Get<unsigned>("passlen", "32"))
unsigned int passlen = Config->GetModule("nickserv")->Get<unsigned>("passlen", "32");
if (len > passlen)
{
source.Reply(PASSWORD_TOO_LONG);
source.Reply(PASSWORD_TOO_LONG, passlen);
return;
}
@@ -414,10 +419,12 @@ class CommandNSSetEmail : public Command
message = Config->GetBlock("mail")->Get<const Anope::string>("emailchange_message");
subject = subject.replace_all_cs("%e", u->Account()->email);
subject = subject.replace_all_cs("%E", new_email);
subject = subject.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<const Anope::string>("networkname"));
subject = subject.replace_all_cs("%c", code);
message = message.replace_all_cs("%e", u->Account()->email);
message = message.replace_all_cs("%E", new_email);
message = message.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<const Anope::string>("networkname"));
message = message.replace_all_cs("%c", code);
+2 -2
View File
@@ -249,9 +249,9 @@ class NSSuspend : public Module
if (!s->reason.empty() && (show_hidden || Show(source, "reason")))
info[_("Suspend reason")] = s->reason;
if (s->when && (show_hidden || Show(source, "on")))
info[_("Suspended on")] = Anope::strftime(s->when, source.GetAccount(), true);
info[_("Suspended on")] = Anope::strftime(s->when, source.GetAccount());
if (s->expires && (show_hidden || Show(source, "expires")))
info[_("Suspension expires")] = Anope::strftime(s->expires, source.GetAccount(), true);
info[_("Suspension expires")] = Anope::strftime(s->expires, source.GetAccount());
}
void OnPreNickExpire(NickAlias *na, bool &expire) anope_override
+3 -3
View File
@@ -153,6 +153,9 @@ class CommandOSAKill : public Command
if (targ)
mask = "*@" + targ->host;
if (Config->GetModule("operserv")->Get<bool>("addakiller", "yes") && !source.GetNick().empty())
reason = "[" + source.GetNick() + "] " + reason;
if (!akills->CanAdd(source, mask, expires, reason))
return;
else if (mask.find_first_not_of("/~@.*?") == Anope::string::npos)
@@ -166,9 +169,6 @@ class CommandOSAKill : public Command
return;
}
if (Config->GetModule("operserv")->Get<bool>("addakiller", "yes") && !source.GetNick().empty())
reason = "[" + source.GetNick() + "] " + reason;
XLine *x = new XLine(mask, source.GetNick(), expires, reason);
if (Config->GetModule("operserv")->Get<bool>("akillids"))
x->id = XLineManager::GenerateUID();
+15 -11
View File
@@ -439,7 +439,16 @@ class OSDefcon : public Module
EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> &params) anope_override
{
if (command->name == "nickserv/register" || command->name == "nickserv/group")
if (DConfig.Check(DEFCON_OPER_ONLY) && !source.IsOper())
{
source.Reply(_("Services are in DefCon mode, please try again later."));
return EVENT_STOP;
}
else if (DConfig.Check(DEFCON_SILENT_OPER_ONLY) && !source.IsOper())
{
return EVENT_STOP;
}
else if (command->name == "nickserv/register" || command->name == "nickserv/group")
{
if (DConfig.Check(DEFCON_NO_NEW_NICKS))
{
@@ -487,15 +496,10 @@ class OSDefcon : public Module
XLine x("*@" + u->host, OperServ ? OperServ->nick : "defcon", Anope::CurTime + DConfig.akillexpire, DConfig.akillreason, XLineManager::GenerateUID());
akills->Send(NULL, &x);
}
if (DConfig.Check(DEFCON_NO_NEW_CLIENTS) || DConfig.Check(DEFCON_AKILL_NEW_CLIENTS))
{
u->Kill(OperServ ? OperServ->nick : "", DConfig.akillreason);
return;
}
if (DConfig.Check(DEFCON_NO_NEW_CLIENTS) || DConfig.Check(DEFCON_AKILL_NEW_CLIENTS))
{
u->Kill(OperServ ? OperServ->nick : "", DConfig.akillreason);
u->Kill(OperServ, DConfig.akillreason);
return;
}
@@ -520,13 +524,13 @@ class OSDefcon : public Module
++session->hits;
if (akills && DConfig.max_session_kill && session->hits >= DConfig.max_session_kill)
{
XLine x("*@" + u->host, OperServ ? OperServ->nick : "", Anope::CurTime + DConfig.session_autokill_expiry, "Defcon session limit exceeded", XLineManager::GenerateUID());
XLine x("*@" + session->addr.mask(), OperServ ? OperServ->nick : "", Anope::CurTime + DConfig.session_autokill_expiry, "Defcon session limit exceeded", XLineManager::GenerateUID());
akills->Send(NULL, &x);
Log(OperServ, "akill/defcon") << "[DEFCON] Added a temporary AKILL for \002*@" << u->host << "\002 due to excessive connections";
Log(OperServ, "akill/defcon") << "[DEFCON] Added a temporary AKILL for \002*@" << session->addr.mask() << "\002 due to excessive connections";
}
else
{
u->Kill(OperServ ? OperServ->nick : "", "Defcon session limit exceeded");
u->Kill(OperServ, "Defcon session limit exceeded");
}
}
}
@@ -573,7 +577,7 @@ static void runDefCon()
{
Log(OperServ, "operserv/defcon") << "DEFCON: setting " << newmodes << " on all channels";
for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it)
it->second->SetModes(OperServ, false, "%s", newmodes.c_str());
it->second->SetModes(OperServ, true, "%s", newmodes.c_str());
}
}
}
+1
View File
@@ -455,6 +455,7 @@ class CommandOSDNS : public Command
}
z->servers.erase(s->GetName());
s->zones.erase(z->name);
source.Reply(_("Removed server %s from zone %s."), s->GetName().c_str(), z->name.c_str());
return;
}
+10 -4
View File
@@ -33,20 +33,26 @@ class CommandOSKick : public Command
source.Reply(CHAN_X_NOT_IN_USE, chan.c_str());
return;
}
else if (c->bouncy_modes)
if (c->bouncy_modes)
{
source.Reply(_("Services is unable to change modes. Are your servers' U:lines configured correctly?"));
return;
}
else if (!(u2 = User::Find(nick, true)))
if (!(u2 = User::Find(nick, true)))
{
source.Reply(NICK_X_NOT_IN_USE, nick.c_str());
return;
}
c->Kick(source.service, u2, "%s (%s)", source.GetNick().c_str(), s.c_str());
if (!c->Kick(source.service, u2, "%s (%s)", source.GetNick().c_str(), s.c_str()))
{
source.Reply(ACCESS_DENIED);
return;
}
Log(LOG_ADMIN, source, this) << "on " << u2->nick << " in " << c->name << " (" << s << ")";
return;
}
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+1 -1
View File
@@ -37,7 +37,7 @@ class CommandOSKill : public Command
if (Config->GetModule("operserv")->Get<bool>("addakiller"))
reason = "(" + source.GetNick() + ") " + reason;
Log(LOG_ADMIN, source, this) << "on " << u2->nick << " for " << reason;
u2->Kill(source.service->nick, reason);
u2->Kill(*source.service, reason);
}
}
+10 -4
View File
@@ -26,7 +26,7 @@ class CommandOSMode : public Command
const Anope::string &target = params[0];
const Anope::string &modes = params[1];
Channel *c = Channel::Find(target);
Reference<Channel> c = Channel::Find(target);
if (!c)
source.Reply(CHAN_X_NOT_IN_USE, target.c_str());
else if (c->bouncy_modes)
@@ -36,9 +36,15 @@ class CommandOSMode : public Command
bool all = params.size() > 2 && params[2].equals_ci("ALL");
const Channel::ModeList chmodes = c->GetModes();
for (Channel::ModeList::const_iterator it = chmodes.begin(), it_end = chmodes.end(); it != it_end; ++it)
for (Channel::ModeList::const_iterator it = chmodes.begin(), it_end = chmodes.end(); it != it_end && c; ++it)
c->RemoveMode(c->ci->WhoSends(), it->first, it->second, false);
if (!c)
{
source.Reply(_("Modes cleared on %s and the channel destroyed."), target.c_str());
return;
}
if (all)
{
for (Channel::ChanUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end; ++it)
@@ -65,7 +71,7 @@ class CommandOSMode : public Command
Anope::string log_modes, log_params;
sep.GetToken(mode);
for (unsigned i = 0; i < mode.length(); ++i)
for (unsigned i = 0; i < mode.length() && c; ++i)
{
char ch = mode[i];
@@ -116,7 +122,7 @@ class CommandOSMode : public Command
}
if (!log_modes.replace_all_cs("+", "").replace_all_cs("-", "").empty())
Log(LOG_ADMIN, source, this) << log_modes << log_params << " on " << c->name;
Log(LOG_ADMIN, source, this) << log_modes << log_params << " on " << (c ? c->name : target);
}
}
+2 -2
View File
@@ -47,7 +47,7 @@ class CommandOSNOOP : public Command
User *u2 = it->second;
if (u2->server == s && u2->HasMode("OPER"))
u2->Kill(source.service->nick, reason);
u2->Kill(*source.service, reason);
}
}
else if (cmd.equals_ci("REVOKE"))
@@ -92,7 +92,7 @@ class OSNOOP : public Module
{
Anope::string reason = "NOOP command used by " + *setter;
BotInfo *OperServ = Config->GetClient("OperServ");
u->Kill(OperServ ? OperServ->nick : "", reason);
u->Kill(OperServ, reason);
}
}
};
+26 -2
View File
@@ -69,7 +69,7 @@ class CommandOSOper : public Command
this->SetDesc(_("View and change Services Operators"));
this->SetSyntax(_("ADD \037oper\037 \037type\037"));
this->SetSyntax(_("DEL \037oper\037"));
this->SetSyntax(_("INFO \037type\037"));
this->SetSyntax(_("INFO [\037type\037]"));
this->SetSyntax("LIST");
}
@@ -82,6 +82,12 @@ class CommandOSOper : public Command
const Anope::string &oper = params[1];
const Anope::string &otype = params[2];
if (!source.HasPriv("operserv/oper/modify"))
{
source.Reply(ACCESS_DENIED);
return;
}
const NickAlias *na = NickAlias::Find(oper);
if (na == NULL)
source.Reply(NICK_X_NOT_REGISTERED, oper.c_str());
@@ -103,6 +109,7 @@ class CommandOSOper : public Command
}
na->nc->o = new MyOper(na->nc->display, ot);
na->nc->o->require_oper = true;
if (Anope::ReadOnly)
source.Reply(READ_ONLY_MODE);
@@ -115,6 +122,12 @@ class CommandOSOper : public Command
{
const Anope::string &oper = params[1];
if (!source.HasPriv("operserv/oper/modify"))
{
source.Reply(ACCESS_DENIED);
return;
}
const NickAlias *na = NickAlias::Find(oper);
if (na == NULL)
source.Reply(NICK_X_NOT_REGISTERED, oper.c_str());
@@ -154,8 +167,19 @@ class CommandOSOper : public Command
}
}
}
else if (subcommand.equals_ci("INFO") && params.size() > 1)
else if (subcommand.equals_ci("INFO"))
{
if (params.size() < 2)
{
source.Reply(_("Available opertypes:"));
for (unsigned i = 0; i < Config->MyOperTypes.size(); ++i)
{
OperType *ot = Config->MyOperTypes[i];
source.Reply("%s", ot->GetName().c_str());
}
return;
}
Anope::string fulltype = params[1];
if (params.size() > 2)
fulltype += " " + params[2];
+7 -47
View File
@@ -424,44 +424,6 @@ class CommandOSException : public Command
return;
}
void DoMove(CommandSource &source, const std::vector<Anope::string> &params)
{
const Anope::string &n1str = params.size() > 1 ? params[1] : ""; /* From position */
const Anope::string &n2str = params.size() > 2 ? params[2] : ""; /* To position */
int n1, n2;
if (n2str.empty())
{
this->OnSyntaxError(source, "MOVE");
return;
}
n1 = n2 = -1;
try
{
n1 = convertTo<int>(n1str);
n2 = convertTo<int>(n2str);
}
catch (const ConvertException &) { }
if (n1 >= 0 && static_cast<unsigned>(n1) < session_service->GetExceptions().size() && n2 >= 0 && static_cast<unsigned>(n2) < session_service->GetExceptions().size() && n1 != n2)
{
Exception *temp = session_service->GetExceptions()[n1];
session_service->GetExceptions()[n1] = session_service->GetExceptions()[n2];
session_service->GetExceptions()[n2] = temp;
Log(LOG_ADMIN, source, this) << "to move exception " << session_service->GetExceptions()[n1]->mask << " from position " << n1 + 1 << " to position " << n2 + 1;
source.Reply(_("Exception for \002%s\002 (#%d) moved to position \002%d\002."), session_service->GetExceptions()[n1]->mask.c_str(), n1 + 1, n2 + 1);
if (Anope::ReadOnly)
source.Reply(READ_ONLY_MODE);
}
else
this->OnSyntaxError(source, "MOVE");
return;
}
void ProcessList(CommandSource &source, const std::vector<Anope::string> &params, ListFormatter &list)
{
const Anope::string &mask = params.size() > 1 ? params[1] : "";
@@ -560,7 +522,6 @@ class CommandOSException : public Command
this->SetDesc(_("Modify the session-limit exception list"));
this->SetSyntax(_("ADD [\037+expiry\037] \037mask\037 \037limit\037 \037reason\037"));
this->SetSyntax(_("DEL {\037mask\037 | \037entry-num\037 | \037list\037}"));
this->SetSyntax(_("MOVE \037num\037 \037position\037"));
this->SetSyntax(_("LIST [\037mask\037 | \037list\037]"));
this->SetSyntax(_("VIEW [\037mask\037 | \037list\037]"));
}
@@ -575,8 +536,6 @@ class CommandOSException : public Command
return this->DoAdd(source, params);
else if (cmd.equals_ci("DEL"))
return this->DoDel(source, params);
else if (cmd.equals_ci("MOVE"))
return this->DoMove(source, params);
else if (cmd.equals_ci("LIST"))
return this->DoList(source, params);
else if (cmd.equals_ci("VIEW"))
@@ -610,9 +569,6 @@ class CommandOSException : public Command
" \n"
"\002EXCEPTION DEL\002 removes the given mask from the exception list.\n"
" \n"
"\002EXCEPTION MOVE\002 moves exception \037num\037 to \037position\037. The\n"
"sessions inbetween will be shifted up or down to fill the gap.\n"
" \n"
"\002EXCEPTION LIST\002 and \002EXCEPTION VIEW\002 show all current\n"
"sessions if the optional mask is given, the list is limited\n"
"to those sessions matching the mask. The difference is that\n"
@@ -639,7 +595,10 @@ class OSSession : public Module
exception_type("Exception", Exception::Unserialize), ss(this), commandossession(this), commandosexception(this), akills("XLineManager", "xlinemanager/sgline")
{
this->SetPermanent(true);
}
void Prioritize() anope_override
{
ModuleManager::SetPriority(this, PRIORITY_FIRST);
}
@@ -713,9 +672,10 @@ class OSSession : public Module
}
++session->hits;
if (max_session_kill && session->hits >= max_session_kill && akills)
const Anope::string &akillmask = "*@" + session->addr.mask();
if (max_session_kill && session->hits >= max_session_kill && akills && !akills->HasEntry(akillmask))
{
const Anope::string &akillmask = "*@" + session->addr.mask();
XLine *x = new XLine(akillmask, OperServ ? OperServ->nick : "", Anope::CurTime + session_autokill_expiry, "Session limit exceeded", XLineManager::GenerateUID());
akills->AddXLine(x);
akills->Send(NULL, x);
@@ -723,7 +683,7 @@ class OSSession : public Module
}
else
{
u->Kill(OperServ ? OperServ->nick : "", "Session limit exceeded");
u->Kill(OperServ, "Session limit exceeded");
}
}
}
+11 -9
View File
@@ -351,6 +351,9 @@ class CommandOSSNLine : public CommandOSSXLineBase
if (mask[masklen - 1] == ' ')
mask.erase(masklen - 1);
if (Config->GetModule("operserv")->Get<bool>("addakiller", "yes") && !source.GetNick().empty())
reason = "[" + source.GetNick() + "] " + reason;
if (!this->xlm()->CanAdd(source, mask, expires, reason))
return;
else if (mask.find_first_not_of("/.*?") == Anope::string::npos)
@@ -359,9 +362,6 @@ class CommandOSSNLine : public CommandOSSXLineBase
return;
}
if (Config->GetModule("operserv")->Get<bool>("addakiller", "yes") && !source.GetNick().empty())
reason = "[" + source.GetNick() + "] " + reason;
XLine *x = new XLine(mask, source.GetNick(), expires, reason);
if (Config->GetModule("operserv")->Get<bool>("akillids"))
x->id = XLineManager::GenerateUID();
@@ -399,7 +399,7 @@ class CommandOSSNLine : public CommandOSSXLineBase
User *user = it->second;
if (!user->HasMode("OPER") && user->server != Me && this->xlm()->Check(user, x))
user->Kill(Me->GetName(), rreason);
user->Kill(Me, rreason);
}
this->xlm()->Send(NULL, x);
@@ -558,6 +558,9 @@ class CommandOSSQLine : public CommandOSSXLineBase
}
}
if (Config->GetModule("operserv")->Get<bool>("addakiller", "yes") && !source.GetNick().empty())
reason = "[" + source.GetNick() + "] " + reason;
if (!this->sqlines->CanAdd(source, mask, expires, reason))
return;
else if (mask.find_first_not_of("./?*") == Anope::string::npos)
@@ -566,9 +569,6 @@ class CommandOSSQLine : public CommandOSSXLineBase
return;
}
if (Config->GetModule("operserv")->Get<bool>("addakiller", "yes") && !source.GetNick().empty())
reason = "[" + source.GetNick() + "] " + reason;
XLine *x = new XLine(mask, source.GetNick(), expires, reason);
if (Config->GetModule("operserv")->Get<bool>("akillids"))
x->id = XLineManager::GenerateUID();
@@ -631,7 +631,7 @@ class CommandOSSQLine : public CommandOSSXLineBase
User *user = it->second;
if (!user->HasMode("OPER") && user->server != Me && this->xlm()->Check(user, x))
user->Kill(Me->GetName(), rreason);
user->Kill(Me, rreason);
}
}
@@ -664,7 +664,9 @@ class CommandOSSQLine : public CommandOSSXLineBase
"connect, Services will not allow it to pursue his IRC\n"
"session.\n"
"If the first character of the mask is #, services will\n"
"prevent the use of matching channels."));
"prevent the use of matching channels. If the mask is a\n"
"regular expression, the expression will be matched against\n"
"channels too."));
source.Reply(_(" \n"
"\002SQLINE ADD\002 adds the given (nick's) mask to the SQLINE\n"
"list for the given reason (which \002must\002 be given).\n"
+5 -1
View File
@@ -146,10 +146,14 @@ class DBFlatFile : public Module, public Pipe
Log(LOG_DEBUG) << "db_flatfile: Attempting to rename " << *it << " to " << newname;
if (rename(oldname.c_str(), newname.c_str()))
{
Log(this) << "Unable to back up database " << *it << "!";
Anope::string err = Anope::LastError();
Log(this) << "Unable to back up database " << *it << " (" << err << ")!";
if (!Config->GetModule(this)->Get<bool>("nobackupok"))
{
Anope::Quitting = true;
Anope::QuitReason = "Unable to back up database " + *it + " (" + err + ")";
}
continue;
}
+5 -2
View File
@@ -166,7 +166,7 @@ class DBMySQL : public Module, public Pipe
if (!this->CheckInit() || obj->GetTimestamp() == Anope::CurTime)
return;
Query query("SELECT * FROM `" + this->prefix + obj->GetName() + "` WHERE (`timestamp` > " + this->SQL->FromUnixtime(obj->GetTimestamp()) + " OR `timestamp` IS NULL)");
Query query("SELECT * FROM `" + this->prefix + obj->GetName() + "` WHERE (`timestamp` >= " + this->SQL->FromUnixtime(obj->GetTimestamp()) + " OR `timestamp` IS NULL)");
obj->UpdateTimestamp();
@@ -228,7 +228,10 @@ class DBMySQL : public Module, public Pipe
}
else
{
delete s;
if (!s)
this->RunQuery("UPDATE `" + prefix + obj->GetName() + "` SET `timestamp` = " + this->SQL->FromUnixtime(obj->GetTimestamp()) + " WHERE `id` = " + stringify(id));
else
delete s;
}
}
}
+1 -1
View File
@@ -873,7 +873,7 @@ class EBCRYPT : public Module
}
public:
EBCRYPT(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, ENCRYPTION | VENDOR | EXTRA),
EBCRYPT(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, ENCRYPTION | VENDOR),
rounds(10)
{
// Test a pre-calculated hash
+349 -320
View File
@@ -1,12 +1,139 @@
/* RequiredLibraries: ldap,lber */
/* RequiredWindowsLibraries: libldap,liblber */
/*
*
* (C) 2011-2015 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*
* Based on the original code of Epona by Lara.
* Based on the original code of Services by Andy Church.
*/
/* RequiredLibraries: ldap_r,lber */
/* RequiredWindowsLibraries: libldap_r,liblber */
#include "module.h"
#include "modules/ldap.h"
#include <ldap.h>
class LDAPService;
static Pipe *me;
class LDAPRequest
{
public:
LDAPService *service;
LDAPInterface *inter;
LDAPMessage *message; /* message returned by ldap_ */
LDAPResult *result; /* final result */
struct timeval tv;
QueryType type;
LDAPRequest(LDAPService *s, LDAPInterface *i)
: service(s)
, inter(i)
, message(NULL)
, result(NULL)
{
type = QUERY_UNKNOWN;
tv.tv_sec = 0;
tv.tv_usec = 100000;
}
virtual ~LDAPRequest()
{
delete result;
if (inter != NULL)
inter->OnDelete();
if (message != NULL)
ldap_msgfree(message);
}
virtual int run() = 0;
};
class LDAPBind : public LDAPRequest
{
Anope::string who, pass;
public:
LDAPBind(LDAPService *s, LDAPInterface *i, const Anope::string &w, const Anope::string &p)
: LDAPRequest(s, i)
, who(w)
, pass(p)
{
type = QUERY_BIND;
}
int run() anope_override;
};
class LDAPSearch : public LDAPRequest
{
Anope::string base;
Anope::string filter;
public:
LDAPSearch(LDAPService *s, LDAPInterface *i, const Anope::string &b, const Anope::string &f)
: LDAPRequest(s, i)
, base(b)
, filter(f)
{
type = QUERY_SEARCH;
}
int run() anope_override;
};
class LDAPAdd : public LDAPRequest
{
Anope::string dn;
LDAPMods attributes;
public:
LDAPAdd(LDAPService *s, LDAPInterface *i, const Anope::string &d, const LDAPMods &attr)
: LDAPRequest(s, i)
, dn(d)
, attributes(attr)
{
type = QUERY_ADD;
}
int run() anope_override;
};
class LDAPDel : public LDAPRequest
{
Anope::string dn;
public:
LDAPDel(LDAPService *s, LDAPInterface *i, const Anope::string &d)
: LDAPRequest(s, i)
, dn(d)
{
type = QUERY_DELETE;
}
int run() anope_override;
};
class LDAPModify : public LDAPRequest
{
Anope::string base;
LDAPMods attributes;
public:
LDAPModify(LDAPService *s, LDAPInterface *i, const Anope::string &b, const LDAPMods &attr)
: LDAPRequest(s, i)
, base(b)
, attributes(attr)
{
type = QUERY_MODIFY;
}
int run() anope_override;
};
class LDAPService : public LDAPProvider, public Thread, public Condition
{
Anope::string server;
@@ -19,7 +146,8 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
time_t last_connect;
LDAPMod **BuildMods(const LDAPMods &attributes)
public:
static LDAPMod **BuildMods(const LDAPMods &attributes)
{
LDAPMod **mods = new LDAPMod*[attributes.size() + 1];
memset(mods, 0, sizeof(LDAPMod*) * (attributes.size() + 1));
@@ -46,7 +174,7 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
return mods;
}
void FreeMods(LDAPMod **mods)
static void FreeMods(LDAPMod **mods)
{
for (int i = 0; mods[i] != NULL; ++i)
{
@@ -58,6 +186,7 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
delete [] mods;
}
private:
void Reconnect()
{
/* Only try one connect a minute. It is an expensive blocking operation */
@@ -71,11 +200,18 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
throw LDAPException("Unable to connect to LDAP service " + this->name + ": " + ldap_err2string(i));
}
void QueueRequest(LDAPRequest *r)
{
this->Lock();
this->queries.push_back(r);
this->Wakeup();
this->Unlock();
}
public:
typedef std::map<LDAPQuery, std::pair<time_t, LDAPInterface *> > query_queue;
typedef std::vector<std::pair<LDAPInterface *, LDAPResult *> > result_queue;
query_queue queries;
result_queue results;
typedef std::vector<LDAPRequest *> query_queue;
query_queue queries, results;
Mutex process_mutex; /* held when processing requests not in either queue */
LDAPService(Module *o, const Anope::string &n, const Anope::string &s, int po, const Anope::string &b, const Anope::string &p, time_t t) : LDAPProvider(o, n), server(s), port(po), admin_binddn(b), admin_pass(p), timeout(t), last_connect(0)
{
@@ -96,208 +232,178 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
~LDAPService()
{
/* At this point the thread has stopped so we don't need to hold process_mutex */
this->Lock();
for (query_queue::iterator it = this->queries.begin(), it_end = this->queries.end(); it != it_end; ++it)
for (unsigned int i = 0; i < this->queries.size(); ++i)
{
LDAPQuery msgid = it->first;
LDAPInterface *i = it->second.second;
LDAPRequest *req = this->queries[i];
ldap_abandon_ext(this->con, msgid, NULL, NULL);
if (i)
i->OnDelete();
/* queries have no results yet */
req->result = new LDAPResult();
req->result->type = req->type;
req->result->error = "LDAP Interface is going away";
if (req->inter)
req->inter->OnError(*req->result);
delete req;
}
this->queries.clear();
for (result_queue::iterator it = this->results.begin(), it_end = this->results.end(); it != it_end; ++it)
for (unsigned int i = 0; i < this->results.size(); ++i)
{
LDAPInterface *i = it->first;
LDAPResult *r = it->second;
LDAPRequest *req = this->results[i];
r->error = "LDAP Interface is going away";
if (i)
i->OnError(*r);
/* even though this may have already finished successfully we return that it didn't */
req->result->error = "LDAP Interface is going away";
if (req->inter)
req->inter->OnError(*req->result);
delete r;
delete req;
}
this->results.clear();
this->Unlock();
ldap_unbind_ext(this->con, NULL, NULL);
}
LDAPQuery BindAsAdmin(LDAPInterface *i)
void BindAsAdmin(LDAPInterface *i) anope_override
{
return this->Bind(i, this->admin_binddn, this->admin_pass);
this->Bind(i, this->admin_binddn, this->admin_pass);
}
LDAPQuery Bind(LDAPInterface *i, const Anope::string &who, const Anope::string &pass) anope_override
void Bind(LDAPInterface *i, const Anope::string &who, const Anope::string &pass) anope_override
{
berval cred;
cred.bv_val = strdup(pass.c_str());
cred.bv_len = pass.length();
LDAPQuery msgid;
int ret = ldap_sasl_bind(con, who.c_str(), LDAP_SASL_SIMPLE, &cred, NULL, NULL, &msgid);
free(cred.bv_val);
if (ret != LDAP_SUCCESS)
{
if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT)
{
this->Reconnect();
return this->Bind(i, who, pass);
}
else
throw LDAPException(ldap_err2string(ret));
}
if (i != NULL)
{
this->Lock();
this->queries[msgid] = std::make_pair(Anope::CurTime, i);
this->Unlock();
}
this->Wakeup();
return msgid;
LDAPBind *b = new LDAPBind(this, i, who, pass);
QueueRequest(b);
}
LDAPQuery Search(LDAPInterface *i, const Anope::string &base, const Anope::string &filter) anope_override
void Search(LDAPInterface *i, const Anope::string &base, const Anope::string &filter) anope_override
{
if (i == NULL)
throw LDAPException("No interface");
LDAPQuery msgid;
int ret = ldap_search_ext(this->con, base.c_str(), LDAP_SCOPE_SUBTREE, filter.c_str(), NULL, 0, NULL, NULL, NULL, 0, &msgid);
if (ret != LDAP_SUCCESS)
{
if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT)
{
this->Reconnect();
return this->Search(i, base, filter);
}
else
throw LDAPException(ldap_err2string(ret));
}
this->Lock();
this->queries[msgid] = std::make_pair(Anope::CurTime, i);
this->Unlock();
this->Wakeup();
return msgid;
LDAPSearch *s = new LDAPSearch(this, i, base, filter);
QueueRequest(s);
}
LDAPQuery Add(LDAPInterface *i, const Anope::string &dn, LDAPMods &attributes) anope_override
void Add(LDAPInterface *i, const Anope::string &dn, LDAPMods &attributes) anope_override
{
LDAPMod **mods = this->BuildMods(attributes);
LDAPQuery msgid;
int ret = ldap_add_ext(this->con, dn.c_str(), mods, NULL, NULL, &msgid);
this->FreeMods(mods);
if (ret != LDAP_SUCCESS)
{
if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT)
{
this->Reconnect();
return this->Add(i, dn, attributes);
}
else
throw LDAPException(ldap_err2string(ret));
}
if (i != NULL)
{
this->Lock();
this->queries[msgid] = std::make_pair(Anope::CurTime, i);
this->Unlock();
}
this->Wakeup();
return msgid;
LDAPAdd *add = new LDAPAdd(this, i, dn, attributes);
QueueRequest(add);
}
LDAPQuery Del(LDAPInterface *i, const Anope::string &dn) anope_override
void Del(LDAPInterface *i, const Anope::string &dn) anope_override
{
LDAPQuery msgid;
int ret = ldap_delete_ext(this->con, dn.c_str(), NULL, NULL, &msgid);
if (ret != LDAP_SUCCESS)
{
if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT)
{
this->Reconnect();
return this->Del(i, dn);
}
else
throw LDAPException(ldap_err2string(ret));
}
if (i != NULL)
{
this->Lock();
this->queries[msgid] = std::make_pair(Anope::CurTime, i);
this->Unlock();
}
this->Wakeup();
return msgid;
LDAPDel *del = new LDAPDel(this, i, dn);
QueueRequest(del);
}
LDAPQuery Modify(LDAPInterface *i, const Anope::string &base, LDAPMods &attributes) anope_override
void Modify(LDAPInterface *i, const Anope::string &base, LDAPMods &attributes) anope_override
{
LDAPMod **mods = this->BuildMods(attributes);
LDAPQuery msgid;
int ret = ldap_modify_ext(this->con, base.c_str(), mods, NULL, NULL, &msgid);
this->FreeMods(mods);
if (ret != LDAP_SUCCESS)
{
if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT)
{
this->Reconnect();
return this->Modify(i, base, attributes);
}
else
throw LDAPException(ldap_err2string(ret));
}
if (i != NULL)
{
this->Lock();
this->queries[msgid] = std::make_pair(Anope::CurTime, i);
this->Unlock();
}
this->Wakeup();
return msgid;
LDAPModify *mod = new LDAPModify(this, i, base, attributes);
QueueRequest(mod);
}
private:
void Timeout()
void BuildReply(int res, LDAPRequest *req)
{
this->Lock();
for (query_queue::iterator it = this->queries.begin(), it_end = this->queries.end(); it != it_end;)
LDAPResult *ldap_result = req->result = new LDAPResult();
req->result->type = req->type;
if (res != LDAP_SUCCESS)
{
LDAPQuery msgid = it->first;
time_t created = it->second.first;
LDAPInterface *i = it->second.second;
++it;
if (Anope::CurTime > created + timeout)
{
LDAPResult *ldap_result = new LDAPResult();
ldap_result->id = msgid;
ldap_result->error = "Query timed out";
this->queries.erase(msgid);
this->results.push_back(std::make_pair(i, ldap_result));
me->Notify();
}
ldap_result->error = ldap_err2string(res);
return;
}
if (req->message == NULL)
{
return;
}
/* a search result */
for (LDAPMessage *cur = ldap_first_message(this->con, req->message); cur; cur = ldap_next_message(this->con, cur))
{
LDAPAttributes attributes;
char *dn = ldap_get_dn(this->con, cur);
if (dn != NULL)
{
attributes["dn"].push_back(dn);
ldap_memfree(dn);
dn = NULL;
}
BerElement *ber = NULL;
for (char *attr = ldap_first_attribute(this->con, cur, &ber); attr; attr = ldap_next_attribute(this->con, cur, ber))
{
berval **vals = ldap_get_values_len(this->con, cur, attr);
int count = ldap_count_values_len(vals);
std::vector<Anope::string> attrs;
for (int j = 0; j < count; ++j)
attrs.push_back(vals[j]->bv_val);
attributes[attr] = attrs;
ldap_value_free_len(vals);
ldap_memfree(attr);
}
if (ber != NULL)
ber_free(ber, 0);
ldap_result->messages.push_back(attributes);
}
}
void SendRequests()
{
process_mutex.Lock();
query_queue q;
this->Lock();
queries.swap(q);
this->Unlock();
if (q.empty())
{
process_mutex.Unlock();
return;
}
for (unsigned int i = 0; i < q.size(); ++i)
{
LDAPRequest *req = q[i];
int ret = req->run();
if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT)
{
/* try again */
try
{
Reconnect();
}
catch (const LDAPException &)
{
}
ret = req->run();
}
BuildReply(ret, req);
this->Lock();
results.push_back(req);
this->Unlock();
}
me->Notify();
process_mutex.Unlock();
}
public:
@@ -305,154 +411,31 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
{
while (!this->GetExitState())
{
if (this->queries.empty())
{
this->Lock();
this->Lock();
/* Queries can be non empty if one is pushed during SendRequests() */
if (queries.empty())
this->Wait();
this->Unlock();
continue;
}
else
this->Timeout();
struct timeval tv = { 1, 0 };
LDAPMessage *result;
int rtype = ldap_result(this->con, LDAP_RES_ANY, 1, &tv, &result);
if (rtype <= 0)
continue;
int cur_id = ldap_msgid(result);
this->Lock();
query_queue::iterator it = this->queries.find(cur_id);
if (it == this->queries.end())
{
this->Unlock();
ldap_msgfree(result);
continue;
}
LDAPInterface *i = it->second.second;
this->queries.erase(it);
this->Unlock();
LDAPResult *ldap_result = new LDAPResult();
ldap_result->id = cur_id;
for (LDAPMessage *cur = ldap_first_message(this->con, result); cur; cur = ldap_next_message(this->con, cur))
{
int cur_type = ldap_msgtype(cur);
LDAPAttributes attributes;
char *dn = ldap_get_dn(this->con, cur);
if (dn != NULL)
{
attributes["dn"].push_back(dn);
ldap_memfree(dn);
dn = NULL;
}
switch (cur_type)
{
case LDAP_RES_BIND:
ldap_result->type = LDAPResult::QUERY_BIND;
break;
case LDAP_RES_SEARCH_ENTRY:
ldap_result->type = LDAPResult::QUERY_SEARCH;
break;
case LDAP_RES_ADD:
ldap_result->type = LDAPResult::QUERY_ADD;
break;
case LDAP_RES_DELETE:
ldap_result->type = LDAPResult::QUERY_DELETE;
break;
case LDAP_RES_MODIFY:
ldap_result->type = LDAPResult::QUERY_MODIFY;
break;
case LDAP_RES_SEARCH_RESULT:
// If we get here and ldap_result->type is LDAPResult::QUERY_UNKNOWN
// then the result set is empty
ldap_result->type = LDAPResult::QUERY_SEARCH;
break;
default:
Log(LOG_DEBUG) << "m_ldap: Unknown msg type " << cur_type;
continue;
}
switch (cur_type)
{
case LDAP_RES_BIND:
{
int errcode = -1;
int parse_result = ldap_parse_result(this->con, cur, &errcode, NULL, NULL, NULL, NULL, 0);
if (parse_result != LDAP_SUCCESS)
ldap_result->error = ldap_err2string(parse_result);
else if (errcode != LDAP_SUCCESS)
ldap_result->error = ldap_err2string(errcode);
break;
}
case LDAP_RES_SEARCH_ENTRY:
{
BerElement *ber = NULL;
for (char *attr = ldap_first_attribute(this->con, cur, &ber); attr; attr = ldap_next_attribute(this->con, cur, ber))
{
berval **vals = ldap_get_values_len(this->con, cur, attr);
int count = ldap_count_values_len(vals);
std::vector<Anope::string> attrs;
for (int j = 0; j < count; ++j)
attrs.push_back(vals[j]->bv_val);
attributes[attr] = attrs;
ldap_value_free_len(vals);
ldap_memfree(attr);
}
if (ber != NULL)
ber_free(ber, 0);
break;
}
case LDAP_RES_ADD:
case LDAP_RES_DELETE:
case LDAP_RES_MODIFY:
{
int errcode = -1;
int parse_result = ldap_parse_result(this->con, cur, &errcode, NULL, NULL, NULL, NULL, 0);
if (parse_result != LDAP_SUCCESS)
ldap_result->error = ldap_err2string(parse_result);
else if (errcode != LDAP_SUCCESS)
ldap_result->error = ldap_err2string(errcode);
break;
}
default:
continue;
}
ldap_result->messages.push_back(attributes);
}
ldap_msgfree(result);
this->Lock();
this->results.push_back(std::make_pair(i, ldap_result));
this->Unlock();
me->Notify();
SendRequests();
}
}
LDAP* GetConnection()
{
return con;
}
};
class ModuleLDAP : public Module, public Pipe
{
std::map<Anope::string, LDAPService *> LDAPServices;
public:
ModuleLDAP(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR)
{
me = this;
}
~ModuleLDAP()
@@ -489,6 +472,8 @@ class ModuleLDAP : public Module, public Pipe
s->SetExitState();
s->Wakeup();
s->Join();
delete s;
this->LDAPServices.erase(cname);
}
}
@@ -513,7 +498,7 @@ class ModuleLDAP : public Module, public Pipe
ss->Start();
this->LDAPServices.insert(std::make_pair(connname, ss));
Log(LOG_NORMAL, "ldap") << "LDAP: Successfully connected to server " << connname << " (" << server << ")";
Log(LOG_NORMAL, "ldap") << "LDAP: Successfully initialized server " << connname << " (" << server << ")";
}
catch (const LDAPException &ex)
{
@@ -528,32 +513,36 @@ class ModuleLDAP : public Module, public Pipe
for (std::map<Anope::string, LDAPService *>::iterator it = this->LDAPServices.begin(); it != this->LDAPServices.end(); ++it)
{
LDAPService *s = it->second;
s->Lock();
for (LDAPService::query_queue::iterator it2 = s->queries.begin(); it2 != s->queries.end();)
{
LDAPQuery msgid = it2->first;
LDAPInterface *i = it2->second.second;
++it2;
if (i && i->owner == m)
s->process_mutex.Lock();
s->Lock();
for (unsigned int i = s->queries.size(); i > 0; --i)
{
LDAPRequest *req = s->queries[i - 1];
LDAPInterface *li = req->inter;
if (li && li->owner == m)
{
i->OnDelete();
s->queries.erase(msgid);
s->queries.erase(s->queries.begin() + i - 1);
delete req;
}
}
for (unsigned i = s->results.size(); i > 0; --i)
for (unsigned int i = s->results.size(); i > 0; --i)
{
LDAPInterface *li = s->results[i - 1].first;
LDAPResult *r = s->results[i - 1].second;
LDAPRequest *req = s->results[i - 1];
LDAPInterface *li = req->inter;
if (li && li->owner == m)
{
s->results.erase(s->results.begin() + i - 1);
delete r;
delete req;
}
}
s->Unlock();
}
s->process_mutex.Unlock();
}
}
void OnNotify() anope_override
@@ -562,15 +551,16 @@ class ModuleLDAP : public Module, public Pipe
{
LDAPService *s = it->second;
LDAPService::result_queue results;
LDAPService::query_queue results;
s->Lock();
results.swap(s->results);
s->Unlock();
for (unsigned i = 0; i < results.size(); ++i)
for (unsigned int i = 0; i < results.size(); ++i)
{
LDAPInterface *li = results[i].first;
LDAPResult *r = results[i].second;
LDAPRequest *req = results[i];
LDAPInterface *li = req->inter;
LDAPResult *r = req->result;
if (li != NULL)
{
@@ -583,11 +573,50 @@ class ModuleLDAP : public Module, public Pipe
li->OnResult(*r);
}
delete r;
delete req;
}
}
}
};
int LDAPBind::run()
{
berval cred;
cred.bv_val = strdup(pass.c_str());
cred.bv_len = pass.length();
int i = ldap_sasl_bind_s(service->GetConnection(), who.c_str(), LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL);
free(cred.bv_val);
return i;
}
int LDAPSearch::run()
{
return ldap_search_ext_s(service->GetConnection(), base.c_str(), LDAP_SCOPE_SUBTREE, filter.c_str(), NULL, 0, NULL, NULL, &tv, 0, &message);
}
int LDAPAdd::run()
{
LDAPMod **mods = LDAPService::BuildMods(attributes);
int i = ldap_add_ext_s(service->GetConnection(), dn.c_str(), mods, NULL, NULL);
LDAPService::FreeMods(mods);
return i;
}
int LDAPDel::run()
{
return ldap_delete_ext_s(service->GetConnection(), dn.c_str(), NULL, NULL);
}
int LDAPModify::run()
{
LDAPMod **mods = LDAPService::BuildMods(attributes);
int i = ldap_modify_ext_s(service->GetConnection(), base.c_str(), mods, NULL, NULL);
LDAPService::FreeMods(mods);
return i;
}
MODULE_INIT(ModuleLDAP)
+51 -96
View File
@@ -30,36 +30,29 @@ struct IdentifyInfo
class IdentifyInterface : public LDAPInterface
{
std::map<LDAPQuery, IdentifyInfo *> requests;
IdentifyInfo *ii;
public:
IdentifyInterface(Module *m) : LDAPInterface(m) { }
IdentifyInterface(Module *m, IdentifyInfo *i) : LDAPInterface(m), ii(i) { }
void Add(LDAPQuery id, IdentifyInfo *ii)
~IdentifyInterface()
{
std::map<LDAPQuery, IdentifyInfo *>::iterator it = this->requests.find(id);
if (it != this->requests.end())
delete it->second;
this->requests[id] = ii;
delete ii;
}
void OnDelete() anope_override
{
delete this;
}
void OnResult(const LDAPResult &r) anope_override
{
std::map<LDAPQuery, IdentifyInfo *>::iterator it = this->requests.find(r.id);
if (it == this->requests.end())
return;
IdentifyInfo *ii = it->second;
this->requests.erase(it);
if (!ii->lprov)
{
delete ii;
return;
}
switch (r.type)
{
case LDAPResult::QUERY_SEARCH:
case QUERY_SEARCH:
{
if (!r.empty())
{
@@ -68,9 +61,9 @@ class IdentifyInterface : public LDAPInterface
const LDAPAttributes &attr = r.get(0);
ii->dn = attr.get("dn");
Log(LOG_DEBUG) << "m_ldap_authenticationn: binding as " << ii->dn;
LDAPQuery id = ii->lprov->Bind(this, ii->dn, ii->req->GetPassword());
this->Add(id, ii);
return;
ii->lprov->Bind(new IdentifyInterface(this->owner, ii), ii->dn, ii->req->GetPassword());
ii = NULL;
}
catch (const LDAPException &ex)
{
@@ -79,7 +72,7 @@ class IdentifyInterface : public LDAPInterface
}
break;
}
case LDAPResult::QUERY_BIND:
case QUERY_BIND:
{
if (ii->admin_bind)
{
@@ -87,10 +80,9 @@ class IdentifyInterface : public LDAPInterface
try
{
Log(LOG_DEBUG) << "m_ldap_authentication: searching for " << sf;
LDAPQuery id = ii->lprov->Search(this, basedn, sf);
this->Add(id, ii);
ii->lprov->Search(new IdentifyInterface(this->owner, ii), basedn, sf);
ii->admin_bind = false;
return;
ii = NULL;
}
catch (const LDAPException &ex)
{
@@ -120,40 +112,28 @@ class IdentifyInterface : public LDAPInterface
default:
break;
}
delete ii;
}
void OnError(const LDAPResult &r) anope_override
{
std::map<LDAPQuery, IdentifyInfo *>::iterator it = this->requests.find(r.id);
if (it == this->requests.end())
return;
IdentifyInfo *ii = it->second;
this->requests.erase(it);
delete ii;
}
};
class OnIdentifyInterface : public LDAPInterface
{
std::map<LDAPQuery, Anope::string> requests;
Anope::string uid;
public:
OnIdentifyInterface(Module *m) : LDAPInterface(m) { }
OnIdentifyInterface(Module *m, const Anope::string &i) : LDAPInterface(m), uid(i) { }
void Add(LDAPQuery id, const Anope::string &nick)
void OnDelete() anope_override
{
this->requests[id] = nick;
delete this;
}
void OnResult(const LDAPResult &r) anope_override
{
std::map<LDAPQuery, Anope::string>::iterator it = this->requests.find(r.id);
if (it == this->requests.end())
return;
User *u = User::Find(it->second);
this->requests.erase(it);
User *u = User::Find(uid);
if (!u || !u->Account() || r.empty())
return;
@@ -180,7 +160,6 @@ class OnIdentifyInterface : public LDAPInterface
void OnError(const LDAPResult &r) anope_override
{
this->requests.erase(r.id);
Log(this->owner) << r.error;
}
};
@@ -201,11 +180,9 @@ class OnRegisterInterface : public LDAPInterface
}
};
class NSIdentifyLDAP : public Module
class ModuleLDAPAuthentication : public Module
{
ServiceReference<LDAPProvider> ldap;
IdentifyInterface iinterface;
OnIdentifyInterface oninterface;
OnRegisterInterface orinterface;
PrimitiveExtensibleItem<Anope::string> dn;
@@ -214,13 +191,15 @@ class NSIdentifyLDAP : public Module
Anope::string disable_register_reason;
Anope::string disable_email_reason;
public:
NSIdentifyLDAP(const Anope::string &modname, const Anope::string &creator) :
Module(modname, creator, EXTRA | VENDOR), ldap("LDAPProvider", "ldap/main"), iinterface(this), oninterface(this), orinterface(this),
ModuleLDAPAuthentication(const Anope::string &modname, const Anope::string &creator) :
Module(modname, creator, EXTRA | VENDOR), ldap("LDAPProvider", "ldap/main"), orinterface(this),
dn(this, "m_ldap_authentication_dn")
{
me = this;
}
void Prioritize() anope_override
{
ModuleManager::SetPriority(this, PRIORITY_FIRST);
}
@@ -268,16 +247,7 @@ class NSIdentifyLDAP : public Module
return;
IdentifyInfo *ii = new IdentifyInfo(u, req, this->ldap);
try
{
LDAPQuery id = this->ldap->BindAsAdmin(&this->iinterface);
this->iinterface.Add(id, ii);
}
catch (const LDAPException &ex)
{
delete ii;
Log(this) << ex.GetReason();
}
this->ldap->BindAsAdmin(new IdentifyInterface(this, ii));
}
void OnNickIdentify(User *u) anope_override
@@ -289,15 +259,7 @@ class NSIdentifyLDAP : public Module
if (!d || d->empty())
return;
try
{
LDAPQuery id = this->ldap->Search(&this->oninterface, *d, "(" + email_attribute + "=*)");
this->oninterface.Add(id, u->nick);
}
catch (const LDAPException &ex)
{
Log(this) << ex.GetReason();
}
this->ldap->Search(new OnIdentifyInterface(this, u->GetUID()), *d, "(" + email_attribute + "=*)");
}
void OnNickRegister(User *, NickAlias *na, const Anope::string &pass) anope_override
@@ -305,37 +267,30 @@ class NSIdentifyLDAP : public Module
if (!this->disable_register_reason.empty() || !this->ldap)
return;
try
this->ldap->BindAsAdmin(NULL);
LDAPMods attributes;
attributes.resize(4);
attributes[0].name = "objectClass";
attributes[0].values.push_back("top");
attributes[0].values.push_back(object_class);
attributes[1].name = username_attribute;
attributes[1].values.push_back(na->nick);
if (!na->nc->email.empty())
{
this->ldap->BindAsAdmin(NULL);
LDAPMods attributes;
attributes.resize(4);
attributes[0].name = "objectClass";
attributes[0].values.push_back("top");
attributes[0].values.push_back(object_class);
attributes[1].name = username_attribute;
attributes[1].values.push_back(na->nick);
if (!na->nc->email.empty())
{
attributes[2].name = email_attribute;
attributes[2].values.push_back(na->nc->email);
}
attributes[3].name = this->password_attribute;
attributes[3].values.push_back(pass);
Anope::string new_dn = username_attribute + "=" + na->nick + "," + basedn;
this->ldap->Add(&this->orinterface, new_dn, attributes);
}
catch (const LDAPException &ex)
{
Log(this) << ex.GetReason();
attributes[2].name = email_attribute;
attributes[2].values.push_back(na->nc->email);
}
attributes[3].name = this->password_attribute;
attributes[3].values.push_back(pass);
Anope::string new_dn = username_attribute + "=" + na->nick + "," + basedn;
this->ldap->Add(&this->orinterface, new_dn, attributes);
}
};
MODULE_INIT(NSIdentifyLDAP)
MODULE_INIT(ModuleLDAPAuthentication)
+11 -21
View File
@@ -6,27 +6,15 @@ static Anope::string opertype_attribute;
class IdentifyInterface : public LDAPInterface
{
std::map<LDAPQuery, Anope::string> requests;
Reference<User> u;
public:
IdentifyInterface(Module *m) : LDAPInterface(m)
IdentifyInterface(Module *m, User *user) : LDAPInterface(m), u(user)
{
}
void Add(LDAPQuery id, const Anope::string &nick)
{
this->requests[id] = nick;
}
void OnResult(const LDAPResult &r) anope_override
{
std::map<LDAPQuery, Anope::string>::iterator it = this->requests.find(r.id);
if (it == this->requests.end())
return;
User *u = User::Find(it->second);
this->requests.erase(it);
if (!u || !u->Account())
return;
@@ -50,7 +38,7 @@ class IdentifyInterface : public LDAPInterface
o = new Oper(u->nick, ot);
my_opers.insert(o);
nc->o = o;
Log(this->owner) << "m_ldap_oper: Tied " << u->nick << " (" << nc->display << ") to opertype " << ot->GetName();
Log(this->owner) << "Tied " << u->nick << " (" << nc->display << ") to opertype " << ot->GetName();
}
}
catch (const LDAPException &ex)
@@ -64,21 +52,24 @@ class IdentifyInterface : public LDAPInterface
}
nc->o = NULL;
Log() << "Removed services operator from " << u->nick << " (" << nc->display << ")";
Log(this->owner) << "Removed services operator from " << u->nick << " (" << nc->display << ")";
}
}
}
void OnError(const LDAPResult &r) anope_override
{
this->requests.erase(r.id);
}
void OnDelete() anope_override
{
delete this;
}
};
class LDAPOper : public Module
{
ServiceReference<LDAPProvider> ldap;
IdentifyInterface iinterface;
Anope::string binddn;
Anope::string password;
@@ -86,7 +77,7 @@ class LDAPOper : public Module
Anope::string filter;
public:
LDAPOper(const Anope::string &modname, const Anope::string &creator) :
Module(modname, creator, EXTRA | VENDOR), ldap("LDAPProvider", "ldap/main"), iinterface(this)
Module(modname, creator, EXTRA | VENDOR), ldap("LDAPProvider", "ldap/main")
{
}
@@ -117,8 +108,7 @@ class LDAPOper : public Module
if (!this->binddn.empty())
this->ldap->Bind(NULL, this->binddn.replace_all_cs("%a", u->Account()->display), this->password.c_str());
LDAPQuery id = this->ldap->Search(&this->iinterface, this->basedn, this->filter.replace_all_cs("%a", u->Account()->display));
this->iinterface.Add(id, u->nick);
this->ldap->Search(new IdentifyInterface(this, u), this->basedn, this->filter.replace_all_cs("%a", u->Account()->display));
}
catch (const LDAPException &ex)
{
+1 -1
View File
@@ -157,7 +157,7 @@ class DHAES : public Mechanism
std::string username = &decrypted[0];
std::string password = &decrypted[username.length() + 1];
if (username.empty() || password.empty())
if (username.empty() || password.empty() || !IRCD->IsNickValid(username) || password.find_first_of("\r\n") != Anope::string::npos)
return Err(sess, pubkey);
SASL::IdentifyRequest* req = new SASL::IdentifyRequest(this->owner, m.source, username, password);
+2 -2
View File
@@ -152,7 +152,7 @@ class DHBS : public Mechanism
const Anope::string username = reinterpret_cast<const char*>(&data[pos]);
// Check that the username is valid, and that we have at least one block of data
// 2 + 1 + 8 = uint16_t size for keylen, \0 for username, 8 for one block of data
if (username.empty() || username.length() + keysize + 2 + 1 + 8 > decodedlen)
if (username.empty() || username.length() + keysize + 2 + 1 + 8 > decodedlen || !IRCD->IsNickValid(username))
return Err(sess, pubkey);
pos += username.length() + 1;
@@ -167,7 +167,7 @@ class DHBS : public Mechanism
BF_ecb_encrypt(&data[pos + i], reinterpret_cast<unsigned char*>(&decrypted[i]), &BFKey, BF_DECRYPT);
std::string password = &decrypted[0];
if (password.empty())
if (password.empty() || password.find_first_of("\r\n") != Anope::string::npos)
return Err(sess, pubkey);
SASL::IdentifyRequest* req = new SASL::IdentifyRequest(this->owner, m.source, username, password);
+18
View File
@@ -103,6 +103,10 @@ class SSLModule : public Module
if (!client_ctx || !server_ctx)
throw ModuleException("Error initializing SSL CTX");
long opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_CIPHER_SERVER_PREFERENCE;
SSL_CTX_set_options(client_ctx, opts);
SSL_CTX_set_options(server_ctx, opts);
SSL_CTX_set_mode(client_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
SSL_CTX_set_mode(server_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
@@ -158,6 +162,20 @@ class SSLModule : public Module
Log() << "Unable to open private key " << this->keyfile;
}
// Allow disabling SSLv3
if (!config->Get<Anope::string>("sslv3").empty())
{
if (config->Get<bool>("sslv3"))
{
SSL_CTX_clear_options(client_ctx, SSL_OP_NO_SSLv3);
SSL_CTX_clear_options(server_ctx, SSL_OP_NO_SSLv3);
}
else
{
SSL_CTX_set_options(client_ctx, SSL_OP_NO_SSLv3);
SSL_CTX_set_options(server_ctx, SSL_OP_NO_SSLv3);
}
}
}
void OnPreServerConnect() anope_override
+1 -1
View File
@@ -243,7 +243,7 @@ void IRC2SQL::OnLeaveChannel(User *u, Channel *c)
this->RunQuery(query);
}
void IRC2SQL::OnTopicUpdated(Channel *c, const Anope::string &user, const Anope::string &topic)
void IRC2SQL::OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic)
{
query = "UPDATE `" + prefix + "chan` "
"SET topic=@topic@, topicauthor=@author@, topictime=FROM_UNIXTIME(@time@) "
+1 -1
View File
@@ -69,7 +69,7 @@ class IRC2SQL : public Module
EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) anope_override;
EventReturn OnChannelModeUnset(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) anope_override;
void OnTopicUpdated(Channel *c, const Anope::string &user, const Anope::string &topic) anope_override;
void OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic) anope_override;
void OnBotNotice(User *u, BotInfo *bi, Anope::string &message) anope_override;
};
+4 -5
View File
@@ -309,7 +309,7 @@ class MChanstats : public Module
"KEY `nick` (`nick`),"
"KEY `chan_` (`chan`),"
"KEY `type` (`type`)"
") ENGINE=InnoDB DEFAULT CHARSET=utf8;";
") ENGINE=MyISAM DEFAULT CHARSET=utf8;";
this->RunQuery(query);
}
/* There is no CREATE OR REPLACE PROCEDURE in MySQL */
@@ -517,14 +517,13 @@ class MChanstats : public Module
info.AddOption(_("Chanstats"));
}
void OnTopicUpdated(Channel *c, const Anope::string &user, const Anope::string &topic) anope_override
void OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic) anope_override
{
User *u = User::Find(user);
if (!u || !u->Account() || !c->ci || !cs_stats.HasExt(c->ci))
if (!source || !source->Account() || !c->ci || !cs_stats.HasExt(c->ci))
return;
query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);";
query.SetValue("channel", c->name);
query.SetValue("nick", GetDisplay(u));
query.SetValue("nick", GetDisplay(source));
this->RunQuery(query);
}
+23 -7
View File
@@ -103,12 +103,28 @@ class Fantasy : public Module
std::vector<Anope::string> params;
spacesepstream(msg).GetTokens(params);
if (!msg.find(c->ci->bi->nick))
params.erase(params.begin());
else if (!msg.find_first_of(Config->GetModule(this)->Get<const Anope::string>("fantasycharacter", "!")))
params[0].erase(params[0].begin());
else
if (params.empty())
return;
Anope::string normalized_param0 = Anope::NormalizeBuffer(params[0]);
Anope::string fantasy_chars = Config->GetModule(this)->Get<Anope::string>("fantasycharacter", "!");
if (!normalized_param0.find(c->ci->bi->nick))
{
params.erase(params.begin());
}
else if (!normalized_param0.find_first_of(fantasy_chars))
{
size_t sz = params[0].find_first_of(fantasy_chars);
if (sz == Anope::string::npos)
return; /* normalized_param0 is a subset of params[0] so this can't happen */
params[0].erase(0, sz + 1);
}
else
{
return;
}
if (params.empty())
return;
@@ -123,7 +139,7 @@ class Fantasy : public Module
full_command.erase(full_command.begin());
++count;
it = Config->Fantasy.find(full_command);
it = Config->Fantasy.find(Anope::NormalizeBuffer(full_command));
}
if (it == Config->Fantasy.end())
@@ -163,7 +179,7 @@ class Fantasy : public Module
source.permission = info.permission;
AccessGroup ag = c->ci->AccessFor(u);
bool has_fantasia = ag.HasPriv("FANTASIA") || source.HasPriv("chanserv/administration");
bool has_fantasia = ag.HasPriv("FANTASIA") || source.HasPriv("botserv/fantasy");
EventReturn MOD_RESULT;
if (has_fantasia)

Some files were not shown because too many files have changed in this diff Show More