pax_global_header00006660000000000000000000000064147722677320014533gustar00rootroot0000000000000052 comment=d44eb911ba7f69238686c21ffe8dc82c23f3377c inspircd-4.7.0+ds1/000077500000000000000000000000001477226773200140415ustar00rootroot00000000000000inspircd-4.7.0+ds1/.github/000077500000000000000000000000001477226773200154015ustar00rootroot00000000000000inspircd-4.7.0+ds1/.github/ISSUE_TEMPLATE/000077500000000000000000000000001477226773200175645ustar00rootroot00000000000000inspircd-4.7.0+ds1/.github/ISSUE_TEMPLATE/BUG.yml000066400000000000000000000023271477226773200207300ustar00rootroot00000000000000--- name: Bug report description: Report a non-security bug in InspIRCd. body: - type: markdown attributes: value: | Thanks for taking the time to fill out this bug report! If you're looking for help with setting up your server please post on [our support forum](https://github.com/orgs/inspircd/discussions/categories/support) instead. If you're reporting a crash or other security issue [please read our security policy](https://github.com/inspircd/inspircd/security/policy#reporting-a-vulnerability) for how to report security issues privately. - type: textarea attributes: label: Description validations: required: true - type: textarea attributes: label: Steps to reproduce the issue validations: required: true - type: textarea attributes: label: Describe the results you received validations: required: true - type: textarea attributes: label: Describe the results you expected validations: required: true - type: input attributes: label: InspIRCd version description: |- Either the output of `inspircd --version` or `./src/version.sh`. validations: required: true inspircd-4.7.0+ds1/.github/ISSUE_TEMPLATE/FEATURE.yml000066400000000000000000000006511477226773200214040ustar00rootroot00000000000000--- name: Feature request description: Request that a new feature is added to InspIRCd. body: - type: markdown attributes: value: | Thanks for taking the time to fill out this feature request! - type: textarea attributes: label: Description validations: required: true - type: textarea attributes: label: Why this would be useful? validations: required: true inspircd-4.7.0+ds1/.github/ISSUE_TEMPLATE/config.yml000066400000000000000000000002721477226773200215550ustar00rootroot00000000000000blank_issues_enabled: false contact_links: - name: Support forum url: https://github.com/orgs/inspircd/discussions/categories/support about: Please ask support questions here. inspircd-4.7.0+ds1/.github/PULL_REQUEST_TEMPLATE.md000066400000000000000000000021351477226773200212030ustar00rootroot00000000000000 ## Summary ## Rationale ## Testing Environment I have tested this pull request on: **Operating system name and version:** **Compiler name and version:** ## Checks I have ensured that: - [ ] The code I am submitting is my own work and/or I have permission from the author to share it. - [ ] Generative AI (Copilot, ChatGPT, etc) was not used to create any part of this pull request. - [ ] I have documented any features added by this pull request. - [ ] This pull request does not introduce any incompatible API changes (stable branches only, delete if not applicable). - [ ] If ABI changes have been made I have incremented MODULE_ABI in `moduledefs.h` (stable branches only, delete if not applicable). inspircd-4.7.0+ds1/.github/SECURITY.md000066400000000000000000000014771477226773200172030ustar00rootroot00000000000000# Security Policy ## Supported Versions Currently the v3 (old stable) and v4 (stable) branches are actively receiving security fixes. Support for v3 will end at the end of 2025. The v5 branch is still early in development and only receives security fixes when they are synced from the v3 and v4 branches. Version | Supported ------- | --------- 5.x.y | :warning: 4.x.y | :white_check_mark: 3.x.y | :white_check_mark: 2.0.x | :x: 1.2.y | :x: 1.1.y | :x: 1.0.y | :x: ## Reporting a Vulnerability Please do not report security vulnerabilities on GitHub. Instead, get the attention of a developer in our development IRC channel at ircs://irc.teranova.net/inspircd.dev and PM them the details. We will triage your issue as soon as possible and try to release a fixed version within a week of receiving your report. inspircd-4.7.0+ds1/.github/dependabot.yml000066400000000000000000000001611477226773200202270ustar00rootroot00000000000000version: 2 updates: - package-ecosystem: github-actions directory: / schedule: interval: monthly inspircd-4.7.0+ds1/.github/workflows/000077500000000000000000000000001477226773200174365ustar00rootroot00000000000000inspircd-4.7.0+ds1/.github/workflows/ci-alpine.yml000066400000000000000000000036511477226773200220270ustar00rootroot00000000000000name: Alpine CI on: pull_request: push: schedule: - cron: '0 0 * * 0' jobs: build: if: "!contains(github.event.head_commit.message, '[skip alpine ci]')" container: alpine:3.20 runs-on: ubuntu-latest env: CXX: ${{ matrix.compiler }} INSPIRCD_DEBUG: 3 INSPIRCD_VERBOSE: 1 steps: - uses: actions/checkout@v4 - name: Install dependencies run: | apk update apk add \ argon2-dev \ clang \ g++ \ git \ gnutls-dev \ libmaxminddb-dev \ libpq-dev \ libpsl-dev \ make \ mariadb-dev \ openldap-dev \ openssl-dev \ pcre2-dev \ perl \ pkgconf \ re2-dev \ sqlite-dev \ yyjson-dev - name: Run configure run: | ./configure --enable-extras "argon2 geo_maxmind ldap log_json log_syslog mysql pgsql regex_pcre2 regex_posix regex_re2 sqlite3 ssl_gnutls ssl_openssl sslrehashsignal" ./configure --development --disable-auto-extras --disable-ownership --socketengine ${{ matrix.socketengine }} - name: Build core run: | INSPIRCD_TARGET=inspircd make --jobs $(($(getconf _NPROCESSORS_ONLN) + 1)) - name: Build core modules run: | INSPIRCD_TARGET=coremods make --jobs $(($(getconf _NPROCESSORS_ONLN) + 1)) - name: Build modules run: | INSPIRCD_TARGET=modules make --jobs $(($(getconf _NPROCESSORS_ONLN) + 1)) - name: Install run: | make install - name: Run run: | touch ./run/conf/inspircd.conf ./run/inspircd start --runasroot strategy: fail-fast: false matrix: compiler: - clang++ - g++ socketengine: - epoll - poll - select inspircd-4.7.0+ds1/.github/workflows/ci-irctest.yml000066400000000000000000000060131477226773200222270ustar00rootroot00000000000000# This workflow has four tasks: # # 1. the first builds inspircd (with some optimizations for irctest), and uploads it # to a temporary storage # 2. the other three download the binary we just built, and run it through inspircd, # with either Anope, Atheme, or runs service-independent tests name: irctest on: pull_request: push: schedule: - cron: 0 0 * * 0 jobs: build: if: "!contains(github.event.head_commit.message, '[skip irctest ci]')" runs-on: ubuntu-24.04-arm steps: - name: Checkout repository uses: actions/checkout@v4 - name: Run configure run: ./configure --development --disable-auto-extras --prefix=$HOME/inspircd # Speed-up build (6 min -> 5 min) - name: Precompile inspircd.h run: c++ -Ivendor include/inspircd.h - name: Build and install env: CXXFLAGS: -DINSPIRCD_UNLIMITED_MAINLOOP run: make install --jobs $(($(getconf _NPROCESSORS_ONLN) + 1)) - name: Make artifact tarball run: |- cd ~ tar -czf artifacts-inspircd.tar.gz inspircd - name: Upload build artifacts uses: actions/upload-artifact@v4 with: name: installed-inspircd-for-irctest path: ~/artifacts-inspircd.tar.gz retention-days: 1 test: if: "!contains(github.event.head_commit.message, '[skip irctest ci]')" runs-on: ubuntu-24.04-arm env: IRCTEST_DEBUG_LOGS: "1" needs: - build steps: - name: Download build artifacts uses: actions/download-artifact@v4 with: name: installed-inspircd-for-irctest path: "~" - name: Unpack artifacts run: |- cd ~ find -name 'artifacts-inspircd.tar.gz' -exec tar -xzf '{}' \; - name: Checkout irctest uses: actions/checkout@v4 with: path: irctest ref: 2680502dfe496a597bf8fb3cfc08cd3b6a698b17 repository: progval/irctest - name: Install irctest dependencies run: sudo apt-get install --assume-yes faketime python3-pytest - name: Run irctest (no services) if: matrix.services == 'no services' run: PATH=$HOME/inspircd/bin:$PATH make -C irctest inspircd - name: Checkout Anope if: matrix.services == 'anope' uses: actions/checkout@v4 with: path: anope ref: 2.1.10 repository: anope/anope - name: Build and install Anope if: matrix.services == 'anope' run: | cd $GITHUB_WORKSPACE/anope sudo apt-get install ninja-build --no-install-recommends mkdir build && cd build cmake -DCMAKE_INSTALL_PREFIX=$HOME/anope -DPROGRAM_NAME=anope -GNinja .. ninja install - name: Run irctest (Anope services) if: matrix.services == 'anope' run: PATH=$HOME/anope/bin:$HOME/inspircd/bin:$PATH make -C irctest inspircd-anope strategy: fail-fast: false matrix: services: - no services - anope inspircd-4.7.0+ds1/.github/workflows/ci-linux.yml000066400000000000000000000037541477226773200217220ustar00rootroot00000000000000name: Ubuntu CI on: pull_request: push: schedule: - cron: '0 0 * * 0' jobs: build: if: "!contains(github.event.head_commit.message, '[skip ubuntu ci]')" runs-on: ubuntu-22.04 env: CXX: ${{ matrix.compiler }} INSPIRCD_DEBUG: 3 INSPIRCD_VERBOSE: 1 steps: - uses: actions/checkout@v4 - name: Install dependencies run: | sudo apt-get update --assume-yes sudo apt-get install --assume-yes --no-install-recommends \ clang \ g++ \ git \ libargon2-dev \ libgnutls28-dev \ libldap2-dev \ libmaxminddb-dev \ libmysqlclient-dev \ libpcre2-dev \ libpq-dev \ libpsl-dev \ libre2-dev \ libsqlite3-dev \ libssl-dev \ make \ pkg-config \ rapidjson-dev - name: Run configure run: | ./configure --enable-extras "argon2 geo_maxmind ldap log_json log_syslog mysql pgsql regex_pcre2 regex_posix regex_re2 sqlite3 ssl_gnutls ssl_openssl sslrehashsignal" ./configure --development --disable-auto-extras --socketengine ${{ matrix.socketengine }} - name: Build core run: | INSPIRCD_TARGET=inspircd make --jobs $(($(getconf _NPROCESSORS_ONLN) + 1)) - name: Build core modules run: | INSPIRCD_TARGET=coremods make --jobs $(($(getconf _NPROCESSORS_ONLN) + 1)) - name: Build modules run: | INSPIRCD_TARGET=modules make --jobs $(($(getconf _NPROCESSORS_ONLN) + 1)) - name: Install run: | make install - name: Run run: | touch ${{ github.workspace }}/run/conf/inspircd.conf ${{ github.workspace }}/run/inspircd start strategy: fail-fast: false matrix: compiler: - clang++ - g++ socketengine: - epoll - poll - select inspircd-4.7.0+ds1/.github/workflows/ci-macos.yml000066400000000000000000000045241477226773200216610ustar00rootroot00000000000000name: macOS CI on: pull_request: push: schedule: - cron: '0 0 * * 0' jobs: build: if: "!contains(github.event.head_commit.message, '[skip macos ci]')" runs-on: macos-14 env: HOMEBREW_NO_AUTO_UPDATE: 1 HOMEBREW_NO_INSTALL_CLEANUP: 1 HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1 INSPIRCD_DEBUG: 3 INSPIRCD_VERBOSE: 1 steps: - uses: actions/checkout@v4 - name: Prepare the build environment run: | echo "CPPFLAGS=-I$(brew --prefix)/include" >> $GITHUB_ENV echo "LDFLAGS=-L$(brew --prefix)/lib" >> $GITHUB_ENV - name: Install dependencies run: | brew update || true for PACKAGE in pkg-config argon2 gnutls libmaxminddb libpq libpsl mysql-client openssl openldap pcre2 re2 sqlite yyjson do brew install $PACKAGE || brew upgrade $PACKAGE BREW_PREFIX=$(brew --prefix $PACKAGE) if [ -d "$BREW_PREFIX/bin" ] then export PATH="$PATH:$BREW_PREFIX/bin" fi if [ -d "$BREW_PREFIX/lib/pkgconfig" ] then export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$BREW_PREFIX/lib/pkgconfig" fi done echo "PATH=$PATH" >> $GITHUB_ENV echo "PKG_CONFIG_PATH=$PKG_CONFIG_PATH" >> $GITHUB_ENV - name: Run configure run: | ./configure --enable-extras "argon2 geo_maxmind ldap log_json log_syslog mysql pgsql regex_pcre2 regex_posix regex_re2 sqlite3 ssl_gnutls ssl_openssl sslrehashsignal" ./configure --development --disable-auto-extras --socketengine ${{ matrix.socketengine }} - name: Build core run: | INSPIRCD_TARGET=inspircd make --jobs $(($(sysctl -n hw.activecpu) + 1)) - name: Build core modules run: | INSPIRCD_TARGET=coremods make --jobs $(($(sysctl -n hw.activecpu) + 1)) - name: Build modules run: | INSPIRCD_TARGET=modules make --jobs $(($(sysctl -n hw.activecpu) + 1)) - name: Install run: | make install - name: Run run: | touch ${{ github.workspace }}/run/conf/inspircd.conf ${{ github.workspace }}/run/inspircd start strategy: fail-fast: false matrix: socketengine: - kqueue - poll - select inspircd-4.7.0+ds1/.github/workflows/ci-windows.yml000066400000000000000000000031461477226773200222500ustar00rootroot00000000000000name: Windows CI on: pull_request: push: release: types: - published schedule: - cron: '0 0 * * 0' jobs: build: if: "!contains(github.event.head_commit.message, '[skip windows ci]')" runs-on: windows-2019 steps: - uses: actions/checkout@v4 - name: Setup MSBuild uses: microsoft/setup-msbuild@v2.0.0 with: msbuild-architecture: x64 - name: Setup Conan uses: turtlebrowser/get-conan@v1.2 with: version: 1.66.0 - name: Install libraries working-directory: ${{ github.workspace }}/win/build run: | (Get-Content ../conanfile.txt).replace('##', '') | Set-Content ../conanfile.txt conan install .. --build=missing - name: Run CMake working-directory: ${{ github.workspace }}/win/build env: LDFLAGS: /DEBUG:FASTLINK /INCREMENTAL run: | cmake -A x64 -D CMAKE_BUILD_TYPE=${{ github.event_name == 'release' && 'Release' || 'Debug' }} -G "Visual Studio 16 2019" -Wdev .. - name: Build InspIRCd working-directory: ${{ github.workspace }}/win/build run: | msbuild PACKAGE.vcxproj /M:3 /P:Configuration=${{ github.event_name == 'release' && 'Release' || 'Debug' }} /P:Platform=x64 /VERBOSITY:MINIMAL - name: Upload installer if: "${{ github.event_name == 'release' }}" working-directory: ${{ github.workspace }}/win/build env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | gh release upload ${{ github.event.release.tag_name }} $(Get-ChildItem InspIRCd-*.exe) inspircd-4.7.0+ds1/.github/workflows/misspell-fixer.yml000066400000000000000000000025211477226773200231240ustar00rootroot00000000000000name: Misspell fixer on: schedule: - cron: '0 0 15 * *' jobs: build: if: github.repository == 'inspircd/inspircd' runs-on: ubuntu-latest env: REF_BRANCH: ${{ github.ref }} steps: - uses: actions/checkout@v4 - name : Set a couple env variables run: | echo "DATE=$(date +'%Y-%m-%d')" >> $GITHUB_ENV echo "REF_BRANCH=${REF_BRANCH//refs\/heads\//}" >> $GITHUB_ENV # The below creates a file used by grep '-f' # These are compared to './folder/file:line_num:word' - name: Whitelist some directories, files, and words. run: | echo "\ ^./.github/workflows ^./.mailmap ^./vendor ^./make/directive.pm:.*:atleast ALLTIME$ alltime$ Alltime$ setts$" > \ ${{ runner.workspace }}/inspircd/.misspell-fixer.ignore - uses: sobolevn/misspell-fixer-action@master with: options: '-rvnfuRVD .' - uses: peter-evans/create-pull-request@v7 with: token: ${{ secrets.GITHUB_TOKEN }} branch: ${{ env.REF_BRANCH }}+fix-spellings-${{ env.DATE }} author: 'InspIRCd Robot ' committer: 'InspIRCd Robot ' commit-message: 'Fixes by misspell-fixer' title: 'Typos fix by misspell-fixer' reviewers: 'genius3000' inspircd-4.7.0+ds1/.gitignore000066400000000000000000000010541477226773200160310ustar00rootroot00000000000000*~ *.pem *.swp .* !.git* /.configure /GNUmakefile /build /core /core.* /vgcore /vgcore.* /docs/doxygen /run /include/config.h /src/modules/m_argon2.cpp /src/modules/m_geo_maxmind.cpp /src/modules/m_ldap.cpp /src/modules/m_log_json.cpp /src/modules/m_log_syslog.cpp /src/modules/m_mysql.cpp /src/modules/m_pgsql.cpp /src/modules/m_regex_pcre2.cpp /src/modules/m_regex_posix.cpp /src/modules/m_regex_re2.cpp /src/modules/m_sqlite3.cpp /src/modules/m_ssl_gnutls.cpp /src/modules/m_ssl_openssl.cpp /src/modules/m_sslrehashsignal.cpp /win/Win32 /win/*.dir inspircd-4.7.0+ds1/.mailmap000066400000000000000000000121071477226773200154630ustar00rootroot00000000000000Adam Adam Adam Adam Ariadne Conill nenolod Ariadne Conill William Pitcock Attila Molnar Attila Molnar Attila Molnar attilamolnar Attila Molnar attilamolnar blitmap Pogs McPoggerson blitmap Sir Poggles blitmap Sir Pogsalot ChrisTX ChrisTX Craig Edwards (no author) <(no author)@e03df62e-2008-0410-955e-edbf42e46eb7> Craig Edwards brain Craig Edwards root Craig McLure frostycoolslug Daniel De Graaf danieldg Daniel Vassdal Daniel Vassdal Daniel Vassdal Daniel Vassdal Daniel Vassdal Daniel Vassdal Daniel Vassdal Daniel Vassdal Daniel Vassdal ShutterQuick Dennis Friis peavey DjSlash Rutger Geoff Bricker bricker Herman GermanAizek iwalkalone iwalkalone jackmcbarn Jackmcbarn James Lu James Lu John Brooks special Justin Crawford Justasic linuxdaemon linuxdaemon linuxdaemon linuxdaemon Matt Schatz genius3000 Matt Smith dz md_5 md-5 Oliver Lupton om Pippijn van Steenhoven pippijn Robby Robby Robby Robby- Robby Robby- Robin Burchell Robin Burchell Robin Burchell w00t Sadie Powell Peter Powell satmd satmd satmd satmd Thomas Stagner aquanight typobox43 typobox43 Uli Schlachter psychon Val Lorentz Valentin Lorentz Val Lorentz Val Lorentz # The identities of the following people could not be verified. If you have an # email address for them please contact Sadie. burlex burlex eggy eggy fez fez jamie jamie katsklaw katsklaw PhilSliderS Philouuu PhilSliderS PhilSliderS randomdan randomdan inspircd-4.7.0+ds1/README.md000066400000000000000000000050511477226773200153210ustar00rootroot00000000000000## About InspIRCd is a modular C++ Internet Relay Chat (IRC) server for UNIX-like and Windows systems. ## Supported Platforms InspIRCd is supported on the following platforms: - Most recent BSD variants using the Clang 5+ or GCC 7+ compilers and the GNU toolchains (Make, etc). - Most recent Linux distributions using the Clang 5+ or GCC 7+ compilers and the GNU toolchain. - The three most recent major releases of macOS using the AppleClang 10, Clang 5+, or GCC 7+ compilers and the GNU toolchain. - Windows 10 April 2018 Update or newer using the MSVC 19.15+ (Visual Studio 15.8 2017) compiler and CMake 3.20 or newer. Other platforms and toolchains may also work but are not officially supported by the InspIRCd team. Generally speaking if you are using a reasonably modern UNIX-like system you should be able to build InspIRCd on it. If you can not and you wish to submit a patch we are happy to accept it as long as it is not extremely large. If you encounter any bugs then [please file an issue](https://github.com/inspircd/inspircd/issues/new/choose). ## Installation Most InspIRCd users running a UNIX-like system build from source. A guide about how to do this is available on [the InspIRCd docs site](https://docs.inspircd.org/4/installation/source). Building from source on Windows is generally not recommended but [a guide is available](https://docs.inspircd.org/4/installation/windows-source/) if you wish to do this. If you are running on Debian 12/13, RHEL 8/9, Ubuntu 22.04/24.04, or Windows 10+ binary packages are available from [the downloads page](https://github.com/inspircd/inspircd/releases/latest). A [Docker](https://www.docker.com) image is also available. See [the inspircd-docker repository](https://github.com/inspircd/inspircd-docker) for more information. Some distributions ship an InspIRCd package in their package managers. We generally do not recommend the use of such packages as in the past distributions have made broken modifications to InspIRCd and not kept their packages up to date with essential security updates. ## License InspIRCd is licensed under [version 2 of the GNU General Public License](https://docs.inspircd.org/license). ## External Links * [Website](https://www.inspircd.org) * [Documentation](https://docs.inspircd.org) * [GitHub](https://github.com/inspircd) * [Support](https://docs.inspircd.org/support) * Support IRC channel — \#inspircd on irc.teranova.net (TLS only) * Development IRC channel — \#inspircd.dev on irc.teranova.net (TLS only) * InspIRCd test network — testnet.inspircd.org (TLS only) inspircd-4.7.0+ds1/configure000077500000000000000000000611301477226773200157510ustar00rootroot00000000000000#!/usr/bin/env perl # # InspIRCd -- Internet Relay Chat Daemon # # Copyright (C) 2019 Matt Schatz # Copyright (C) 2013-2022, 2024 Sadie Powell # Copyright (C) 2012, 2019 Robby # Copyright (C) 2012 ChrisTX # Copyright (C) 2010 Daniel De Graaf # Copyright (C) 2008 Thomas Stagner # Copyright (C) 2008 Robin Burchell # Copyright (C) 2007 Dennis Friis # Copyright (C) 2006, 2008 Craig Edwards # # This file is part of InspIRCd. InspIRCd is free software: you can # redistribute it and/or modify it under the terms of the GNU General Public # License as published by the Free Software Foundation, version 2. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # use v5.26.0; use strict; use warnings FATAL => qw(all); use Config qw(%Config); use Cwd qw(getcwd); use File::Basename qw(basename); use File::Copy (); use File::Spec::Functions qw(abs2rel catfile catdir rel2abs); use FindBin qw($RealDir); use Getopt::Long qw(GetOptions); use POSIX qw(getgid getuid); use lib $RealDir; use make::common; use make::configure; use make::console; use make::directive; my ($opt_binary_dir, $opt_config_dir, $opt_data_dir, $opt_development, $opt_disable_auto_extras, $opt_disable_interactive, $opt_disable_ownership, $opt_distribution_label, $opt_example_dir, $opt_gid, $opt_log_dir, $opt_manual_dir, $opt_module_dir, $opt_portable, $opt_prefix, $opt_runtime_dir, $opt_script_dir, $opt_socketengine, $opt_system, $opt_uid); sub list_extras (); sub enable_extras (@); sub disable_extras (@); my @opt_enableextras; my @opt_disableextras; exit 1 unless GetOptions( 'clean' => \&cmd_clean, 'help' => \&cmd_help, 'update' => \&cmd_update, 'binary-dir=s' => \$opt_binary_dir, 'config-dir=s' => \$opt_config_dir, 'data-dir=s' => \$opt_data_dir, 'development' => \$opt_development, 'disable-auto-extras' => \$opt_disable_auto_extras, 'disable-interactive' => \$opt_disable_interactive, 'disable-ownership' => \$opt_disable_ownership, 'distribution-label=s' => \$opt_distribution_label, 'example-dir=s' => \$opt_example_dir, 'gid=s' => \$opt_gid, 'log-dir=s' => \$opt_log_dir, 'manual-dir=s' => \$opt_manual_dir, 'module-dir=s' => \$opt_module_dir, 'portable' => \$opt_portable, 'prefix=s' => \$opt_prefix, 'runtime-dir=s' => \$opt_runtime_dir, 'script-dir=s' => \$opt_script_dir, 'socketengine=s' => \$opt_socketengine, 'system' => \$opt_system, 'uid=s' => \$opt_uid, 'disable-extras=s@' => \@opt_disableextras, 'enable-extras=s@' => \@opt_enableextras, 'list-extras' => sub { list_extras; exit 0; }, ); if (scalar(@opt_enableextras) + scalar(@opt_disableextras) > 0) { @opt_enableextras = grep { /\S/ } split /[, ]+/, join(',', @opt_enableextras); @opt_disableextras = grep { /\S/ } split /[, ]+/, join(',', @opt_disableextras); enable_extras(@opt_enableextras); disable_extras(@opt_disableextras); list_extras; print "Remember: YOU are responsible for making sure any libraries needed have been installed!\n"; exit 0; } our $interactive = !( !-t STDIN || !-t STDOUT || defined $opt_binary_dir || defined $opt_config_dir || defined $opt_data_dir || defined $opt_development || defined $opt_disable_auto_extras || defined $opt_disable_interactive || defined $opt_disable_ownership || defined $opt_distribution_label || defined $opt_example_dir || defined $opt_gid || defined $opt_log_dir || defined $opt_manual_dir || defined $opt_module_dir || defined $opt_portable || defined $opt_prefix || defined $opt_runtime_dir || defined $opt_script_dir || defined $opt_socketengine || defined $opt_system || defined $opt_uid ); my %version = get_version $opt_distribution_label; chomp(my $platform = `uname -mrs 2>/dev/null` || "$Config{osname} $Config{osvers} $Config{archname}"); say console_format "Configuring <|GREEN InspIRCd $version{FULL}|> on <|GREEN $platform|>."; my %config; if ($interactive) { %config = read_config_file(CONFIGURE_CACHE_FILE); run_test abs2rel(CONFIGURE_CACHE_FILE, $RealDir), %config; if (!defined $config{VERSION}) { $config{VERSION} = CONFIGURE_CACHE_VERSION; } elsif ($config{VERSION} != CONFIGURE_CACHE_VERSION) { print_warning "ignoring contents of ${\CONFIGURE_CACHE_FILE} as it was generated by an incompatible version of $0!"; %config = ('VERSION', CONFIGURE_CACHE_VERSION); } } unless (run_test $RealDir, -w $RealDir, 'writable') { print_error <<"EOE"; the source directory is not writable. This most likely means that you downloaded InspIRCd as root but tried to build as an unprivileged user. To fix this issue redownload the source as the user you want to build as or fix the permissions of <|GREEN $RealDir|>. EOE }; $config{CXX} = find_compiler($config{CXX} // $ENV{CXX}); unless ($config{CXX}) { say 'A suitable C++ compiler could not be detected on your system!'; unless ($interactive) { say 'Set the CXX environment variable to the path to a C++ compiler binary if this is incorrect.'; exit 1; } until ($config{CXX}) { my $compiler_path = prompt_string 1, 'Please enter the path to a C++ compiler binary:', 'c++'; $config{CXX} = find_compiler $compiler_path; } } my %compiler = get_compiler_info($config{CXX}); $config{HAS_ARC4RANDOM_BUF} = run_test 'arc4random_buf()', test_file($config{CXX}, 'arc4random_buf.cpp'); $config{HAS_CLOCK_GETTIME} = run_test 'clock_gettime()', test_file($config{CXX}, 'clock_gettime.cpp', $^O eq 'darwin' ? undef : '-lrt'); $config{HAS_GETENTROPY} = run_test 'getentropy()', test_file($config{CXX}, 'getentropy.cpp'); my @socketengines; push @socketengines, 'epoll' if run_test 'epoll', test_header $config{CXX}, 'sys/epoll.h'; push @socketengines, 'kqueue' if run_test 'kqueue', test_file $config{CXX}, 'kqueue.cpp'; push @socketengines, 'poll' if run_test 'poll', test_header $config{CXX}, 'poll.h'; push @socketengines, 'select'; if (defined $opt_socketengine) { unless (grep { $_ eq $opt_socketengine } @socketengines) { my $reason = -f "src/socketengines/$opt_socketengine.cpp" ? 'is not available on this platform' : 'does not exist'; print_error "The socket engine you requested ($opt_socketengine) $reason!", 'Available socket engines are:', map { " * $_" } @socketengines; } } $config{SOCKETENGINE} = $opt_socketengine // $socketengines[0]; if (defined $opt_portable) { print_error '--portable and --system can not be used together!' if defined $opt_system; $config{DESTDIR} = catfile $RealDir, 'run', ''; $config{BASE_DIR} = $opt_prefix // ''; $config{BINARY_DIR} = $opt_binary_dir // 'bin'; $config{CONFIG_DIR} = $opt_config_dir // 'conf'; $config{DATA_DIR} = $opt_data_dir // 'data'; $config{EXAMPLE_DIR} = $opt_example_dir // catdir $config{CONFIG_DIR}, 'examples'; $config{LOG_DIR} = $opt_log_dir // 'logs'; $config{MANUAL_DIR} = $opt_manual_dir // 'manuals'; $config{MODULE_DIR} = $opt_module_dir // 'modules'; $config{RUNTIME_DIR} = $opt_runtime_dir // $config{DATA_DIR}; $config{SCRIPT_DIR} = $opt_script_dir // $config{BASE_DIR}; } elsif (defined $opt_system) { $config{BASE_DIR} = $opt_prefix // '/'; $config{BINARY_DIR} = $opt_binary_dir // catdir $config{BASE_DIR}, 'usr/bin'; $config{CONFIG_DIR} = $opt_config_dir // catdir $config{BASE_DIR}, 'etc/inspircd'; $config{DATA_DIR} = $opt_data_dir // catdir $config{BASE_DIR}, 'var/lib/inspircd'; $config{EXAMPLE_DIR} = $opt_example_dir // catdir $config{BASE_DIR}, 'usr/share/doc/inspircd/examples'; $config{LOG_DIR} = $opt_log_dir // catdir $config{BASE_DIR}, 'var/log/inspircd'; $config{MANUAL_DIR} = $opt_manual_dir // catdir $config{BASE_DIR}, 'usr/share/man/man1'; $config{MODULE_DIR} = $opt_module_dir // catdir $config{BASE_DIR}, 'usr/lib/inspircd'; $config{RUNTIME_DIR} = $opt_runtime_dir // catdir $config{BASE_DIR}, $^O eq 'linux' ? '/run/inspircd' : '/var/run/inspircd'; $config{SCRIPT_DIR} = $opt_script_dir // catdir $config{BASE_DIR}, 'usr/share/inspircd'; } else { $config{BASE_DIR} = rel2abs $opt_prefix // $config{BASE_DIR} // catdir $RealDir, 'run'; $config{BINARY_DIR} = $opt_binary_dir // $config{BINARY_DIR} // catdir $config{BASE_DIR}, 'bin'; $config{CONFIG_DIR} = $opt_config_dir // $config{CONFIG_DIR} // catdir $config{BASE_DIR}, 'conf'; $config{DATA_DIR} = $opt_data_dir // $config{DATA_DIR} // catdir $config{BASE_DIR}, 'data'; $config{EXAMPLE_DIR} = $opt_example_dir // $config{EXAMPLE_DIR} // catdir $config{CONFIG_DIR}, 'examples'; $config{LOG_DIR} = $opt_log_dir // $config{LOG_DIR} // catdir $config{BASE_DIR}, 'logs'; $config{MANUAL_DIR} = $opt_manual_dir // $config{MANUAL_DIR} // catdir $config{BASE_DIR}, 'manuals'; $config{MODULE_DIR} = $opt_module_dir // $config{MODULE_DIR} // catdir $config{BASE_DIR}, 'modules'; $config{RUNTIME_DIR} = $opt_runtime_dir // $config{RUNTIME_DIR} // $config{DATA_DIR}; $config{SCRIPT_DIR} = $opt_script_dir // $config{SCRIPT_DIR} // $config{BASE_DIR}; } # Parse --gid=123 or --gid=foo and extract the group id. my @group; if (defined $opt_gid) { @group = $opt_gid =~ /^\d+$/ ? getgrgid($opt_gid) : getgrnam($opt_gid); print_error "there is no '$opt_gid' group on this system!" unless @group; } elsif (defined $opt_disable_ownership) { @group = qw(insert-group-here . -1); } else { @group = $opt_system ? getgrnam('irc') : getgrgid($config{GID} // getgid()); print_error "you need to specify a group to run as using '--gid [id|name]'!" unless @group; unless ($group[2]) { print_warning <<"EOW"; You are building as the privileged $group[0] group and have not specified an unprivileged group to run InspIRCd as. This is almost never what you should do. You should probably either create a new unprivileged user/group to build and run as or pass the '--gid [id|name]' flag to specify an unprivileged group to run as. EOW if (!prompt_bool $interactive, "Are you sure you want to build as the $group[0] group?", 0) { # PACKAGERS: You do not need to delete this check. Use `--disable-ownership` instead. say STDERR "If you are sure you want to build as the $group[0] group pass the --gid $group[2] flag." unless $interactive; exit 1; } } } $config{GROUP} = $group[0]; $config{GID} = $group[2]; # Parse --uid=123 or --uid=foo and extract the user id. my @user; if (defined $opt_uid) { @user = $opt_uid =~ /^\d+$/ ? getpwuid($opt_uid) : getpwnam($opt_uid); print_error "there is no '$opt_uid' user on this system!" unless @user; } elsif (defined $opt_disable_ownership) { @user = qw(insert-user-here . -1); } else { @user = $opt_system ? getpwnam('irc') : getpwuid($config{UID} // getuid()); print_error "you need to specify a user to run as using '--uid [id|name]'!" unless @user; unless ($user[2]) { print_warning <<"EOW"; You are building as the privileged $user[0] user and have not specified an unprivileged user to run InspIRCd as. This is almost never what you should do. You should probably either create a new unprivileged user/group to build and run as or pass the '--uid [id|name]' flag to specify an unprivileged user to run as. EOW if (!prompt_bool $interactive, "Are you sure you want to build as the $user[0] user?", 0) { # PACKAGERS: You do not need to delete this check. Use `--disable-ownership` instead. say STDERR "If you are sure you want to build as the $user[0] user pass the --uid $user[2] flag." unless $interactive; exit 1; } } } $config{USER} = $user[0]; $config{UID} = $user[2]; # Warn the user about clock drifting when running on OpenVZ. if (-e '/proc/user_beancounters' || -e '/proc/vz/vzaquota') { print_warning <<'EOW'; You are building InspIRCd inside of an OpenVZ container. If you plan to use InspIRCd in this container then you should make sure that NTP is configured on the Hardware Node. Failure to do so may result in clock drifting! EOW } # Warn the user about OpenBSD shipping incredibly broken compilers/linkers. if ($^O eq 'openbsd') { print_warning <<'EOW'; You are building InspIRCd on OpenBSD. The C++ compilers and linkers that OpenBSD ship are incredibly broken. You may have strange linker errors and crashes. Please consider using a different OS like FreeBSD/NetBSD instead. EOW } # Warn about how quirky musl's libdl implementation is. chomp(my $machine = `$config{CXX} -dumpmachine 2>/dev/null`); if ($machine =~ /-musl$/) { print_warning <<'EOW'; You are building InspIRCd with musl. This libc does not have a useful dlclose() implementation which causes problems with unloading and reloading modules. Please complain to the musl maintainers if this is an issue for you. EOW } # Check that the user actually wants this version. if (defined $version{REAL_LABEL}) { print_warning <<'EOW'; You are building a development version. This contains code which has not been tested as heavily and may contain various faults which could seriously affect the running of your server. It is recommended that you use a stable version instead. You can obtain the latest stable version from https://www.inspircd.org or by running `<|GREEN git checkout $(git describe --abbrev=0 --tags insp4)|>` if you are installing from Git. EOW if (!prompt_bool $interactive, 'I understand this warning and want to continue anyway.', $opt_development // 0) { say STDERR 'If you understand this warning and still want to continue pass the --development flag.' unless $interactive; exit 1; } } # Configure directory settings. my $question = <<"EOQ"; Currently, InspIRCd is configured with the following paths: <|BOLD Binary:|> $config{BINARY_DIR} <|BOLD Config:|> $config{CONFIG_DIR} <|BOLD Data:|> $config{DATA_DIR} <|BOLD Log:|> $config{LOG_DIR} <|BOLD Manual:|> $config{MANUAL_DIR} <|BOLD Module:|> $config{MODULE_DIR} <|BOLD Script:|> $config{SCRIPT_DIR} Do you want to change these settings? EOQ if (prompt_bool $interactive, $question, 0) { my $original_base_dir = $config{BASE_DIR}; $config{BASE_DIR} = prompt_dir $interactive, 'In what directory do you wish to install the InspIRCd base?', $config{BASE_DIR}; for my $key (qw(BINARY_DIR CONFIG_DIR DATA_DIR LOG_DIR MANUAL_DIR MODULE_DIR SCRIPT_DIR)) { $config{$key} =~ s/^\Q$original_base_dir\E/$config{BASE_DIR}/; } $config{BINARY_DIR} = prompt_dir $interactive, 'In what directory should the InspIRCd binary be placed?', $config{BINARY_DIR}; $config{CONFIG_DIR} = prompt_dir $interactive, 'In what directory are configuration files to be stored?', $config{CONFIG_DIR}; $config{DATA_DIR} = prompt_dir $interactive, 'In what directory are variable data files to be stored?', $config{DATA_DIR}; $config{LOG_DIR} = prompt_dir $interactive, 'In what directory are log files to be stored?', $config{LOG_DIR}; $config{MANUAL_DIR} = prompt_dir $interactive, 'In what directory are manual pages to be placed?', $config{MANUAL_DIR}; $config{MODULE_DIR} = prompt_dir $interactive, 'In what directory are modules to be placed?', $config{MODULE_DIR}; $config{SCRIPT_DIR} = prompt_dir $interactive, 'In what directory are scripts to be placed?', $config{SCRIPT_DIR}; $config{EXAMPLE_DIR} = $config{CONFIG_DIR} . '/examples'; $config{RUNTIME_DIR} = $config{DATA_DIR}; } # Configure module settings. $question = <<'EOQ'; Currently, InspIRCd is configured to automatically enable all available extra modules. Would you like to enable extra modules manually? EOQ if (prompt_bool $interactive, $question, 0) { for my $extra (<$RealDir/src/modules/extra/m_*.cpp>) { my $module_name = module_shrink $extra; if (prompt_bool $interactive, "Would you like to enable the <|BOLD $module_name|> module?", 0) { enable_extras $module_name; } } } elsif (!defined $opt_disable_auto_extras) { my %modules = ( 'argon2' => 'pkg-config --exists libargon2', 'geo_maxmind' => 'pkg-config --exists libmaxminddb', 'mysql' => 'mysql_config --version', 'pgsql' => 'pg_config --version', 'ldap' => "pkg-config --exists lber && pkg-config --exists ldap", 'log_json' => 'pkg-config --exists yyjson', 'log_syslog' => undef, 'regex_pcre2' => 'pkg-config --exists libpcre2-8', 'regex_posix' => undef, 'regex_re2' => 'pkg-config --exists re2', 'sqlite3' => 'pkg-config --exists sqlite3', 'ssl_gnutls' => 'pkg-config --exists "gnutls >= 3.3.5"', 'ssl_openssl' => 'pkg-config --exists "openssl >= 1.1.1"', 'sslrehashsignal' => undef, ); while (my ($module, $command) = each %modules) { unless (defined $command && system "$command 1>/dev/null 2>/dev/null") { enable_extras $module; } } } if (!<$RealDir/src/modules/m_ssl_*.cpp> && !defined $opt_disable_auto_extras) { print_error <<"EOM"; you MUST build with at least one TLS module. TLS greatly enhances the security and privacy of your IRC server and is required for linking servers. Please read the following documentation pages on how to enable TLS support: Configuration: https://docs.inspircd.org/tutorials/enable-tls GnuTLS module: https://docs.inspircd.org/$version{MAJOR}/modules/ssl_gnutls OpenSSL module: https://docs.inspircd.org/$version{MAJOR}/modules/ssl_openssl EOM } # Cache the distribution label so that its not lost when --update is run. $config{DISTRIBUTION} = $opt_distribution_label if $opt_distribution_label; $config{DISABLE_OWNERSHIP} = $opt_disable_ownership // 0; write_configure_cache %config; parse_templates \%config, \%compiler, \%version; print console_format <<"EOM"; Configuration is complete! You have chosen to build with the following settings: <|GREEN Compiler:|> <|GREEN Binary:|> $config{CXX} <|GREEN Name:|> $compiler{NAME} <|GREEN Version:|> $compiler{VERSION} <|GREEN Extra Modules:|> EOM for my $file (<$RealDir/src/modules/m_*>) { say " * ${\module_shrink $file}" if -l $file; } my @makeargs; push @makeargs, "-C${\abs2rel $RealDir}" unless getcwd eq $RealDir; push @makeargs, "-j${\(get_cpu_count() + 1)}"; print console_format <<"EOM"; <|GREEN Paths:|> <|GREEN Binary:|> $config{BINARY_DIR} <|GREEN Config:|> $config{CONFIG_DIR} <|GREEN Data:|> $config{DATA_DIR} <|GREEN Example:|> $config{EXAMPLE_DIR} <|GREEN Log:|> $config{LOG_DIR} <|GREEN Manual:|> $config{MANUAL_DIR} <|GREEN Module:|> $config{MODULE_DIR} <|GREEN Runtime:|> $config{RUNTIME_DIR} <|GREEN Script:|> $config{SCRIPT_DIR} <|GREEN Execution Group:|> $config{GROUP} ($config{GID}) <|GREEN Execution User:|> $config{USER} ($config{UID}) <|GREEN Socket Engine:|> $config{SOCKETENGINE} To build with these settings run '<|GREEN make ${\join ' ', @makeargs} install|>' now. EOM # Routine to list out the extra/ modules that have been enabled. # Note: when getting any filenames out and comparing, it's important to lc it if the # file system is not case-sensitive (== Epoc, MacOS, OS/2 (incl DOS/DJGPP), VMS, Win32 # (incl NetWare, Symbian)). Cygwin may or may not be case-sensitive, depending on # configuration, however, File::Spec does not currently tell us (it assumes Unix behavior). sub list_extras () { use File::Spec; # @_ not used my $srcdir = File::Spec->catdir("src", "modules"); my $abs_srcdir = File::Spec->rel2abs($srcdir); local $_; my $dd; opendir $dd, File::Spec->catdir($abs_srcdir, "extra") or die (File::Spec->catdir($abs_srcdir, "extra") . ": $!\n"); my @extras = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd)); closedir $dd; undef $dd; opendir $dd, $abs_srcdir or die "$abs_srcdir: $!\n"; my @sources = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd)); closedir $dd; undef $dd; my $maxlen = (sort { $b <=> $a } (map { length module_shrink $_ } (@extras)))[0]; my %extras = (); EXTRA: for my $extra (@extras) { next if (File::Spec->curdir() eq $extra || File::Spec->updir() eq $extra); my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra); my $abs_source = File::Spec->catfile($abs_srcdir, $extra); next unless ($extra =~ m/\.(cpp|h)$/ || (-d $abs_extra)); # C++ Source/Header, or directory if (-l $abs_source) { # Symlink, is it in the right place? my $targ = readlink($abs_source); my $abs_targ = File::Spec->rel2abs($targ, $abs_srcdir); if ($abs_targ eq $abs_extra) { $extras{$extra} = "\e[32;1menabled\e[0m"; } else { $extras{$extra} = sprintf("\e[31;1mwrong symlink target (%s)\e[0m", $abs_targ); } } elsif (-e $abs_source) { my ($devext, $inoext) = stat($abs_extra); my ($devsrc, $inosrc, undef, $lnksrc) = stat($abs_source); if ($lnksrc > 1) { if ($devsrc == $devext && $inosrc == $inoext) { $extras{$extra} = "\e[32;1menabled\e[0m"; } else { $extras{$extra} = sprintf("\e[31;1mwrong hardlink target (%d:%d)\e[0m", $devsrc, $inosrc); } } else { open my $extfd, "<", $abs_extra; open my $srcfd, "<", $abs_source; local $/ = undef; if (scalar(<$extfd>) eq scalar(<$srcfd>)) { $extras{$extra} = "\e[32;1menabled\e[0m"; } else { $extras{$extra} = sprintf("\e[31;1mout of synch (re-copy)\e[0m"); } } } else { $extras{$extra} = "\e[33;1mdisabled\e[0m"; } } # Now let's add dependency info for my $extra (keys(%extras)) { next unless $extras{$extra} =~ m/enabled/; # only process enabled extras. my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra); my @deps = split /\s+/, get_directive($abs_extra, 'ModDep', ''); for my $dep (@deps) { if (exists($extras{$dep})) { my $ref = \$extras{$dep}; # Take reference. if ($$ref !~ m/needed by/) { # First dependency found. if ($$ref =~ m/enabled/) { $$ref .= " (needed by \e[32;1m$extra\e[0m"; } else { $$ref =~ s/\e\[.*?m//g; # Strip out previous coloring. Will be set in bold+red+blink later. $$ref .= " (needed by \e[0;32;1;5m$extra\e[0;31;1;5m"; } } else { if ($$ref =~ m/enabled/) { $$ref .= ", \e[32;1m$extra\e[0m"; } else { $$ref .= ", \e[0;32;1;5m$extra\e[0;31;1;5m"; } } } } } for my $extra (sort {$a cmp $b} keys(%extras)) { my $text = $extras{$extra}; if ($text =~ m/needed by/ && $text !~ m/enabled/) { printf "\e[31;1;5m%-*s = %s%s\e[0m\n", $maxlen, module_shrink($extra), $text, ($text =~ m/needed by/ ? ")" : ""); } else { printf "%-*s = %s%s\n", $maxlen, module_shrink($extra), $text, ($text =~ m/needed by/ ? "\e[0m)" : ""); } } return keys(%extras) if wantarray; # Can be used by manage_extras. } sub enable_extras(@) { my $moduledir = catdir $RealDir, 'src', 'modules'; my $extradir = catdir $moduledir, 'extra'; for my $extra (@_) { my $shortname = module_shrink $extra; my $extrafile = module_expand $extra; my $extrapath = catfile $extradir, $extrafile; if (!-f $extrapath) { print_error "<|GREEN $extra|> is not an extra module!"; } my $modulepath = catfile $moduledir, $extrafile; if (-l $modulepath) { if (readlink($modulepath) ne $extrapath) { unlink $modulepath; # Remove the dead symlink. } else { next; # Module is already enabled. } } if (-e $modulepath) { print_error "unable to symlink <|GREEN ${\abs2rel $modulepath}|> to <|GREEN ${\abs2rel $extrapath}|>: the target exists and is not a symlink."; } else { say console_format "Enabling the <|GREEN $shortname|> module ..."; symlink $extrapath, $modulepath or print_error "unable to symlink <|GREEN ${\abs2rel $modulepath}|> to <|GREEN ${\abs2rel $extrapath}|>: $!"; } } } sub disable_extras(@) { my $moduledir = catdir $RealDir, 'src', 'modules'; my $extradir = catdir $moduledir, 'extra'; for my $extra (@_) { my $shortname = module_shrink $extra; my $extrafile = module_expand $extra; my $modulepath = catfile $moduledir, $extrafile; my $extrapath = catfile $extradir, $extrafile; if (!-e $modulepath && !-e $extrapath) { print_error "the <|GREEN $shortname|> module does not exist!"; } elsif (!-e $modulepath && -e $extrapath) { print_error "the <|GREEN $shortname|> module is not currently enabled!"; } elsif ((-e $modulepath && !-e $extrapath) || !-l $modulepath) { print_error "the <|GREEN $shortname|> module is not an extra module!"; } else { say console_format "Disabling the <|GREEN $shortname|> module ..."; unlink $modulepath or print_error "unable to unlink <|GREEN $extrapath|>: $!"; } } } inspircd-4.7.0+ds1/contrib/000077500000000000000000000000001477226773200155015ustar00rootroot00000000000000inspircd-4.7.0+ds1/contrib/.gitattributes000066400000000000000000000000141477226773200203670ustar00rootroot00000000000000*.cpp ident inspircd-4.7.0+ds1/contrib/.github/000077500000000000000000000000001477226773200170415ustar00rootroot00000000000000inspircd-4.7.0+ds1/contrib/.github/dependabot.yml000066400000000000000000000001611477226773200216670ustar00rootroot00000000000000version: 2 updates: - package-ecosystem: github-actions directory: / schedule: interval: monthly inspircd-4.7.0+ds1/contrib/.github/workflows/000077500000000000000000000000001477226773200210765ustar00rootroot00000000000000inspircd-4.7.0+ds1/contrib/.github/workflows/check-v3.yml000066400000000000000000000047501477226773200232320ustar00rootroot00000000000000name: Check v3 modules on: push: paths: - '.github/*' - '3/*' pull_request: paths: - '.github/*' - '3/*' workflow_dispatch: jobs: build: runs-on: ubuntu-latest env: CXXFLAGS: -std=${{ matrix.standard }} -Wno-error=deprecated-declarations CXX: ${{ matrix.compiler }} INSPIRCD_DEBUG: 3 INSPIRCD_VERBOSE: 1 steps: - name: Install dependencies run: | sudo apt-get update --assume-yes sudo apt-get install --assume-yes --no-install-recommends clang g++ git make pkg-config - name: Checkout InspIRCd@insp3 uses: actions/checkout@v4 with: repository: 'inspircd/inspircd' ref: 'insp3' path: 'inspircd' - name: Checkout self uses: actions/checkout@v4 with: path: 'contrib' - name: (Pull Request) Set the build target to only the changed modules if: github.event_name == 'pull_request' run: | cd contrib git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/* echo INSPIRCD_TARGET=$( \ git diff --name-only origin/${{ github.base_ref }} ${{ github.sha }} | \ for f in `cat`; do if [[ "$f" = "3/"*".cpp" ]]; \ then echo "$(basename $f .cpp) "; fi; done) >> $GITHUB_ENV - name: (Push/PR Fallback) Set the build target to all of the modules if: github.event_name == 'push' || env.INSPIRCD_TARGET == '' run: echo INSPIRCD_TARGET=$(for f in contrib/3/*; do echo "$(basename $f .cpp) "; done) >> $GITHUB_ENV - name: Symlink the modules run: | cd inspircd/src/modules ln -s ../../../contrib/3/* . - name: Check for additional dependencies run: | cd inspircd echo PACKAGES=$( \ for f in ../contrib/3/*; do if [[ "$INSPIRCD_TARGET" = *"$(basename $f .cpp)"* ]]; \ then ./tools/directive $f PackageInfo; fi; done) >> $GITHUB_ENV - name: Install additional dependencies if: env.PACKAGES != '' run: sudo apt-get install --assume-yes --no-install-recommends ${{ env.PACKAGES }} - name: Build the modules run: | cd inspircd ./configure --development --disable-auto-extras make --jobs $(($(getconf _NPROCESSORS_ONLN) + 1)) strategy: fail-fast: false matrix: compiler: - clang++ - g++ standard: - gnu++98 - c++14 inspircd-4.7.0+ds1/contrib/.github/workflows/check-v4.yml000066400000000000000000000054571477226773200232400ustar00rootroot00000000000000name: Check v4 modules on: push: paths: - .github/workflows/check-v4.yml - 4/* pull_request: paths: - .github/workflows/check-v4.yml - 4/* schedule: - cron: '0 0 * * 0' workflow_dispatch: jobs: build: runs-on: ubuntu-latest env: CXX: ${{ matrix.compiler }} INSPIRCD_DEBUG: 3 steps: - name: Install dependencies run: | sudo apt-get update --assume-yes sudo apt-get install --assume-yes --no-install-recommends \ clang \ curl \ g++ \ git \ jq \ make \ pkg-config - name: Retrieve latest release run: | echo INSPIRCD_VERSION=$(curl https://api.github.com/repos/inspircd/inspircd/releases | jq --raw-output 'map(select((.draft or .prerelease | not) and (.tag_name | startswith("v4.")))) | first .tag_name') >> $GITHUB_ENV - name: Checkout InspIRCd uses: actions/checkout@v4 with: repository: inspircd/inspircd ref: ${{ env.INSPIRCD_VERSION }} path: inspircd - name: Checkout InspIRCd contrib uses: actions/checkout@v4 with: path: contrib - name: Get changed modules id: changed-modules uses: tj-actions/changed-files@v45 with: files: 4/*.cpp path: contrib - name: Work out what modules to build working-directory: inspircd run: | if [ '${{ steps.changed-modules.outputs.any_changed }}' = true ] then export FILES=$(cd ${{ github.workspace }}/contrib && readlink -f ${{ steps.changed-modules.outputs.all_changed_files }}) else export FILES=$(readlink -f ${{ github.workspace }}/contrib/4/*.cpp) fi for FILE in ${FILES} do export MODULES="${MODULES} ${FILE}" export PACKAGES="${PACKAGES} $(./tools/directive ${FILE} PackageInfo)" export TARGETS="${TARGETS} $(basename $FILE .cpp)" done echo "INSPIRCD_MODULES=${MODULES%% }" >> $GITHUB_ENV echo "INSPIRCD_PACKAGES=${PACKAGES%% }" >> $GITHUB_ENV echo "INSPIRCD_TARGET=${TARGETS%% }" >> $GITHUB_ENV - name: Install module dependencies if: env.INSPIRCD_PACKAGES != '' working-directory: inspircd run: | sudo apt-get install --assume-yes --no-install-recommends ${INSPIRCD_PACKAGES} - name: Build the changed modules working-directory: inspircd run: | cp -v ${INSPIRCD_MODULES} src/modules ./configure --development --disable-auto-extras make --jobs $(($(getconf _NPROCESSORS_ONLN) + 1)) strategy: fail-fast: false matrix: compiler: - clang++ - g++ inspircd-4.7.0+ds1/contrib/.github/workflows/regen-modules.yml000066400000000000000000000013751477226773200243750ustar00rootroot00000000000000name: Update the module list on: - push jobs: build: if: github.repository == 'inspircd/inspircd-contrib' && github.ref_name == 'master' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Regenerate the module list run: ./regen-modules - name: Commit the updated module list run: | git config --global user.name "InspIRCd Robot" git config --global user.email "noreply@inspircd.org" git add modules.lst git commit --message "Regenerate the module list." || true - name: Push the updated module list run: git push https://${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git ${{ github.ref }} inspircd-4.7.0+ds1/contrib/.mailmap000066400000000000000000000017321477226773200171250ustar00rootroot00000000000000Adam Attila Molnar Colgate Minuette Daniel De Graaf linuxdaemon linuxdaemon Nikos Papakonstantinou reverse <129334336+revrsedev@users.noreply.github.com> reverse <129334336+revrsefr@users.noreply.github.com> Robby Robin Burchell Robin Burchell Sadie Powell satmd satmd James Lu inspircd-4.7.0+ds1/contrib/1.1/000077500000000000000000000000001477226773200160005ustar00rootroot00000000000000inspircd-4.7.0+ds1/contrib/1.1/m_antirandom.cpp000066400000000000000000000421621477226773200211610ustar00rootroot00000000000000/* +------------------------------------+ * | Inspire Internet Relay Chat Daemon | * +------------------------------------+ * * InspIRCd: (C) 2002-2008 InspIRCd Development Team * See: http://www.inspircd.org/wiki/index.php/Credits * * This program is free but copyrighted software; see * the file COPYING for details. * * (C) Copyright 2008 Robin Burchell * (C) Copyright 2004-2005, Bram Matthys (Syzop) * - Contains ideas from Keith Dunnett * - Most of the detection mechanisms come from SpamAssassin FVGT_Tripwire. * --------------------------------------------------- */ #include "inspircd.h" #include "xline.h" /* $ModDesc: A module to prevent against bots using random patterns. */ /* $ModAuthor: w00t */ /* $ModAuthorMail: w00t@inspircd.org */ /* $ModDepends: core 1.1 */ /* $ModVersion: $Rev: 78 $ */ #define ANTIRANDOM_ACT_KILL 0 #define ANTIRANDOM_ACT_ZLINE 1 static const char *triples_txt[] = { "aj", "fqtvxz", "aq", "deghjkmnprtxyz", "av", "bfhjqwxz", "az", "jwx", "bd", "bghjkmpqvxz", "bf", "bcfgjknpqvwxyz", "bg", "bdfghjkmnqstvxz", "bh", "bfhjkmnqvwxz", "bj", "bcdfghjklmpqtvwxyz", "bk", "dfjkmqrvwxyz", "bl", "bgpqwxz", "bm", "bcdflmnqz", "bn", "bghjlmnpqtvwx", "bp", "bfgjknqvxz", "bq", "bcdefghijklmnopqrstvwxyz", "bt", "dgjkpqtxz", "bv", "bfghjklnpqsuvwxz", "bw", "bdfjknpqsuwxyz", "bx", "abcdfghijklmnopqtuvwxyz", "bz", "bcdfgjklmnpqrstvwxz", "cb", "bfghjkpqyz", "cc", "gjqxz", "cd", "hjkqvwxz", "cf", "gjknqvwyz", "cg", "bdfgjkpqvz", "cl", "fghjmpqxz", "cm", "bjkqv", "cn", "bghjkpqwxz", "cp", "gjkvxyz", "cq", "abcdefghijklmnopqsvwxyz", "cr", "gjqx", "cs", "gjxz", "cv", "bdfghjklmnquvwxyz", "cx", "abdefghjklmnpqrstuvwxyz", "cy", "jqy", "cz", "bcdfghjlpqrtvwxz", "db", "bdgjnpqtxz", "dc", "gjqxz", "dd", "gqz", "df", "bghjknpqvxyz", "dg", "bfgjqvxz", "dh", "bfkmnqwxz", "dj", "bdfghjklnpqrwxz", "dk", "cdhjkpqrtuvwxz", "dl", "bfhjknqwxz", "dm", "bfjnqw", "dn", "fgjkmnpqvwz", "dp", "bgjkqvxz", "dq", "abcefghijkmnopqtvwxyz", "dr", "bfkqtvx", "dt", "qtxz", "dv", "bfghjknqruvwyz", "dw", "cdfjkmnpqsvwxz", "dx", "abcdeghjklmnopqrsuvwxyz", "dy", "jyz", "dz", "bcdfgjlnpqrstvxz", "eb", "jqx", "eg", "cjvxz", "eh", "hxz", "ej", "fghjpqtwxyz", "ek", "jqxz", "ep", "jvx", "eq", "bcghijkmotvxyz", "ev", "bfpq", "fc", "bdjkmnqvxz", "fd", "bgjklqsvyz", "fg", "fgjkmpqtvwxyz", "fh", "bcfghjkpqvwxz", "fj", "bcdfghijklmnpqrstvwxyz", "fk", "bcdfghjkmpqrstvwxz", "fl", "fjkpqxz", "fm", "dfhjlmvwxyz", "fn", "bdfghjklnqrstvwxz", "fp", "bfjknqtvwxz", "fq", "abcefghijklmnopqrstvwxyz", "fr", "nqxz", "fs", "gjxz", "ft", "jqx", "fv", "bcdfhjklmnpqtuvwxyz", "fw", "bcfgjklmpqstuvwxyz", "fx", "bcdfghjklmnpqrstvwxyz", "fy", "ghjpquvxy", "fz", "abcdfghjklmnpqrtuvwxyz", "gb", "bcdknpqvwx", "gc", "gjknpqwxz", "gd", "cdfghjklmqtvwxz", "gf", "bfghjkmnpqsvwxyz", "gg", "jkqvxz", "gj", "bcdfghjklmnpqrstvwxyz", "gk", "bcdfgjkmpqtvwxyz", "gl", "fgjklnpqwxz", "gm", "dfjkmnqvxz", "gn", "jkqvxz", "gp", "bjknpqtwxyz", "gq", "abcdefghjklmnopqrsvwxyz", "gr", "jkqt", "gt", "fjknqvx", "gu", "qwx", "gv", "bcdfghjklmpqstvwxyz", "gw", "bcdfgjknpqtvwxz", "gx", "abcdefghjklmnopqrstvwxyz", "gy", "jkqxy", "gz", "bcdfgjklmnopqrstvxyz", "hb", "bcdfghjkqstvwxz", "hc", "cjknqvwxz", "hd", "fgjnpvz", "hf", "bfghjkmnpqtvwxyz", "hg", "bcdfgjknpqsxyz", "hh", "bcgklmpqrtvwxz", "hj", "bcdfgjkmpqtvwxyz", "hk", "bcdgkmpqrstvwxz", "hl", "jxz", "hm", "dhjqrvwxz", "hn", "jrxz", "hp", "bjkmqvwxyz", "hq", "abcdefghijklmnopqrstvwyz", "hr", "cjqx", "hs", "jqxz", "hv", "bcdfgjklmnpqstuvwxz", "hw", "bcfgjklnpqsvwxz", "hx", "abcdefghijklmnopqrstuvwxyz", "hz", "bcdfghjklmnpqrstuvwxz", "ib", "jqx", "if", "jqvwz", "ih", "bgjqx", "ii", "bjqxy", "ij", "cfgqxy", "ik", "bcfqx", "iq", "cdefgjkmnopqtvxyz", "iu", "hiwxy", "iv", "cfgmqx", "iw", "dgjkmnpqtvxz", "ix", "jkqrxz", "iy", "bcdfghjklpqtvwx", "jb", "bcdghjklmnopqrtuvwxyz", "jc", "cfgjkmnopqvwxy", "jd", "cdfghjlmnpqrtvwx", "jf", "abcdfghjlnopqrtuvwxyz", "jg", "bcdfghijklmnopqstuvwxyz", "jh", "bcdfghjklmnpqrxyz", "jj", "bcdfghjklmnopqrstuvwxyz", "jk", "bcdfghjknqrtwxyz", "jl", "bcfghjmnpqrstuvwxyz", "jm", "bcdfghiklmnqrtuvwyz", "jn", "bcfjlmnpqsuvwxz", "jp", "bcdfhijkmpqstvwxyz", "jq", "abcdefghijklmnopqrstuvwxyz", "jr", "bdfhjklpqrstuvwxyz", "js", "bfgjmoqvxyz", "jt", "bcdfghjlnpqrtvwxz", "jv", "abcdfghijklpqrstvwxyz", "jw", "bcdefghijklmpqrstuwxyz", "jx", "abcdefghijklmnopqrstuvwxyz", "jy", "bcdefghjkpqtuvwxyz", "jz", "bcdfghijklmnopqrstuvwxyz", "kb", "bcdfghjkmqvwxz", "kc", "cdfgjknpqtwxz", "kd", "bfghjklmnpqsvwxyz", "kf", "bdfghjkmnpqsvwxyz", "kg", "cghjkmnqtvwxyz", "kh", "cfghjkqx", "kj", "bcdfghjkmnpqrstwxyz", "kk", "bcdfgjmpqswxz", "kl", "cfghlmqstwxz", "km", "bdfghjknqrstwxyz", "kn", "bcdfhjklmnqsvwxz", "kp", "bdfgjkmpqvxyz", "kq", "abdefghijklmnopqrstvwxyz", "kr", "bcdfghjmqrvwx", "ks", "jqx", "kt", "cdfjklqvx", "ku", "qux", "kv", "bcfghjklnpqrstvxyz", "kw", "bcdfgjklmnpqsvwxz", "kx", "abcdefghjklmnopqrstuvwxyz", "ky", "vxy", "kz", "bcdefghjklmnpqrstuvwxyz", "lb", "cdgkqtvxz", "lc", "bqx", "lg", "cdfgpqvxz", "lh", "cfghkmnpqrtvx", "lk", "qxz", "ln", "cfjqxz", "lp", "jkqxz", "lq", "bcdefhijklmopqrstvwxyz", "lr", "dfgjklmpqrtvwx", "lv", "bcfhjklmpwxz", "lw", "bcdfgjknqxz", "lx", "bcdfghjklmnpqrtuwz", "lz", "cdjptvxz", "mb", "qxz", "md", "hjkpvz", "mf", "fkpqvwxz", "mg", "cfgjnpqsvwxz", "mh", "bchjkmnqvx", "mj", "bcdfghjknpqrstvwxyz", "mk", "bcfgklmnpqrvwxz", "ml", "jkqz", "mm", "qvz", "mn", "fhjkqxz", "mq", "bdefhjklmnopqtwxyz", "mr", "jklqvwz", "mt", "jkq", "mv", "bcfghjklmnqtvwxz", "mw", "bcdfgjklnpqsuvwxyz", "mx", "abcefghijklmnopqrstvwxyz", "mz", "bcdfghjkmnpqrstvwxz", "nb", "hkmnqxz", "nf", "bghqvxz", "nh", "fhjkmqtvxz", "nk", "qxz", "nl", "bghjknqvwxz", "nm", "dfghjkqtvwxz", "np", "bdjmqwxz", "nq", "abcdfghjklmnopqrtvwxyz", "nr", "bfjkqstvx", "nv", "bcdfgjkmnqswxz", "nw", "dgjpqvxz", "nx", "abfghjknopuyz", "nz", "cfqrxz", "oc", "fjvw", "og", "qxz", "oh", "fqxz", "oj", "bfhjmqrswxyz", "ok", "qxz", "oq", "bcdefghijklmnopqrstvwxyz", "ov", "bfhjqwx", "oy", "qxy", "oz", "fjpqtvx", "pb", "fghjknpqvwz", "pc", "gjq", "pd", "bgjkvwxz", "pf", "hjkmqtvwyz", "pg", "bdfghjkmqsvwxyz", "ph", "kqvx", "pk", "bcdfhjklmpqrvx", "pl", "ghkqvwx", "pm", "bfhjlmnqvwyz", "pn", "fjklmnqrtvwz", "pp", "gqwxz", "pq", "abcdefghijklmnopqstvwxyz", "pr", "hjkqrwx", "pt", "jqxz", "pv", "bdfghjklquvwxyz", "pw", "fjkmnpqsuvwxz", "px", "abcdefghijklmnopqrstuvwxyz", "pz", "bdefghjklmnpqrstuvwxyz", "qa", "ceghkopqxy", "qb", "bcdfghjklmnqrstuvwxyz", "qc", "abcdfghijklmnopqrstuvwxyz", "qd", "defghijklmpqrstuvwxyz", "qe", "abceghjkmopquwxyz", "qf", "abdfghijklmnopqrstuvwxyz", "qg", "abcdefghijklmnopqrtuvwxz", "qh", "abcdefghijklmnopqrstuvwxyz", "qi", "efgijkmpwx", "qj", "abcdefghijklmnopqrstuvwxyz", "qk", "abcdfghijklmnopqrsuvwxyz", "ql", "abcefghjklmnopqrtuvwxyz", "qm", "bdehijklmnoqrtuvxyz", "qn", "bcdefghijklmnoqrtuvwxyz", "qo", "abcdefgijkloqstuvwxyz", "qp", "abcdefghijkmnopqrsuvwxyz", "qq", "bcdefghijklmnopstwxyz", "qr", "bdefghijklmnoqruvwxyz", "qs", "bcdefgijknqruvwxz", "qt", "befghjklmnpqtuvwxz", "qu", "cfgjkpwz", "qv", "abdefghjklmnopqrtuvwxyz", "qw", "bcdfghijkmnopqrstuvwxyz", "qx", "abcdefghijklmnopqrstuvwxyz", "qy", "abcdefghjklmnopqrstuvwxyz", "qz", "abcdefghijklmnopqrstuvwxyz", "rb", "fxz", "rg", "jvxz", "rh", "hjkqrxz", "rj", "bdfghjklmpqrstvwxz", "rk", "qxz", "rl", "jnq", "rp", "jxz", "rq", "bcdefghijklmnopqrtvwxy", "rr", "jpqxz", "rv", "bcdfghjmpqrvwxz", "rw", "bfgjklqsvxz", "rx", "bcdfgjkmnopqrtuvwxz", "rz", "djpqvxz", "sb", "kpqtvxz", "sd", "jqxz", "sf", "bghjkpqw", "sg", "cgjkqvwxz", "sj", "bfghjkmnpqrstvwxz", "sk", "qxz", "sl", "gjkqwxz", "sm", "fkqwxz", "sn", "dhjknqvwxz", "sq", "bfghjkmopstvwxz", "sr", "jklqrwxz", "sv", "bfhjklmnqtwxyz", "sw", "jkpqvwxz", "sx", "bcdefghjklmnopqrtuvwxyz", "sy", "qxy", "sz", "bdfgjpqsvxz", "tb", "cghjkmnpqtvwx", "tc", "jnqvx", "td", "bfgjkpqtvxz", "tf", "ghjkqvwyz", "tg", "bdfghjkmpqsx", "tj", "bdfhjklmnpqstvwxyz", "tk", "bcdfghjklmpqvwxz", "tl", "jkqwxz", "tm", "bknqtwxz", "tn", "fhjkmqvwxz", "tp", "bjpqvwxz", "tq", "abdefhijklmnopqrstvwxyz", "tr", "gjqvx", "tv", "bcfghjknpquvwxz", "tw", "bcdfjknqvz", "tx", "bcdefghjklmnopqrsuvwxz", "tz", "jqxz", "uc", "fjmvx", "uf", "jpqvx", "ug", "qvx", "uh", "bcgjkpvxz", "uj", "wbfghklmqvwx", "uk", "fgqxz", "uq", "bcdfghijklmnopqrtwxyz", "uu", "fijkqvwyz", "uv", "bcdfghjkmpqtwxz", "uw", "dgjnquvxyz", "ux", "jqxz", "uy", "jqxyz", "uz", "fgkpqrx", "vb", "bcdfhijklmpqrtuvxyz", "vc", "bgjklnpqtvwxyz", "vd", "bdghjklnqvwxyz", "vf", "bfghijklmnpqtuvxz", "vg", "bcdgjkmnpqtuvwxyz", "vh", "bcghijklmnpqrtuvwxyz", "vj", "abcdfghijklmnpqrstuvwxyz", "vk", "bcdefgjklmnpqruvwxyz", "vl", "hjkmpqrvwxz", "vm", "bfghjknpquvxyz", "vn", "bdhjkmnpqrtuvwxz", "vp", "bcdeghjkmopqtuvwyz", "vq", "abcdefghijklmnopqrstvwxyz", "vr", "fghjknqrtvwxz", "vs", "dfgjmqz", "vt", "bdfgjklmnqtx", "vu", "afhjquwxy", "vv", "cdfghjkmnpqrtuwxz", "vw", "abcdefghijklmnopqrtuvwxyz", "vx", "abcefghjklmnopqrstuvxyz", "vy", "oqx", "vz", "abcdefgjklmpqrstvwxyz", "wb", "bdfghjpqtvxz", "wc", "bdfgjkmnqvwx", "wd", "dfjpqvxz", "wf", "cdghjkmqvwxyz", "wg", "bcdfgjknpqtvwxyz", "wh", "cdghjklpqvwxz", "wj", "bfghijklmnpqrstvwxyz", "wk", "cdfgjkpqtuvxz", "wl", "jqvxz", "wm", "dghjlnqtvwxz", "wp", "dfgjkpqtvwxz", "wq", "abcdefghijklmnopqrstvwxyz", "wr", "cfghjlmpqwx", "wt", "bdgjlmnpqtvx", "wu", "aikoquvwy", "wv", "bcdfghjklmnpqrtuvwxyz", "ww", "bcdgkpqstuvxyz", "wx", "abcdefghijklmnopqrstuvwxz", "wy", "jquwxy", "wz", "bcdfghjkmnopqrstuvwxz", "xa", "ajoqy", "xb", "bcdfghjkmnpqsvwxz", "xc", "bcdgjkmnqsvwxz", "xd", "bcdfghjklnpqstuvwxyz", "xf", "bcdfghjkmnpqtvwxyz", "xg", "bcdfghjkmnpqstvwxyz", "xh", "cdfghjkmnpqrstvwxz", "xi", "jkqy", "xj", "abcdefghijklmnopqrstvwxyz", "xk", "abcdfghjkmnopqrstuvwxyz", "xl", "bcdfghjklmnpqrvwxz", "xm", "bcdfghjknpqvwxz", "xn", "bcdfghjklmnpqrvwxyz", "xp", "bcfjknpqvxz", "xq", "abcdefghijklmnopqrstvwxyz", "xr", "bcdfghjklnpqrsvwyz", "xs", "bdfgjmnqrsvxz", "xt", "jkpqvwxz", "xu", "fhjkquwx", "xv", "bcdefghjklmnpqrsuvwxyz", "xw", "bcdfghjklmnpqrtuvwxyz", "xx", "bcdefghjkmnpqrstuwyz", "xy", "jxy", "xz", "abcdefghjklmnpqrstuvwxyz", "yb", "cfghjmpqtvwxz", "yc", "bdfgjmpqsvwx", "yd", "chjkpqvwx", "yf", "bcdghjmnpqsvwx", "yg", "cfjkpqtxz", "yh", "bcdfghjkpqx", "yi", "hjqwxy", "yj", "bcdfghjklmnpqrstvwxyz", "yk", "bcdfgpqvwxz", "ym", "dfgjqvxz", "yp", "bcdfgjkmqxz", "yq", "abcdefghijklmnopqrstvwxyz", "yr", "jqx", "yt", "bcfgjnpqx", "yv", "bcdfghjlmnpqstvwxz", "yw", "bfgjklmnpqstuvwxz", "yx", "bcdfghjknpqrstuvwxz", "yy", "bcdfghjklpqrstvwxz", "yz", "bcdfjklmnpqtvwx", "zb", "dfgjklmnpqstvwxz", "zc", "bcdfgjmnpqstvwxy", "zd", "bcdfghjklmnpqstvwxy", "zf", "bcdfghijkmnopqrstvwxyz", "zg", "bcdfgjkmnpqtvwxyz", "zh", "bcfghjlpqstvwxz", "zj", "abcdfghjklmnpqrstuvwxyz", "zk", "bcdfghjklmpqstvwxz", "zl", "bcdfghjlnpqrstvwxz", "zm", "bdfghjklmpqstvwxyz", "zn", "bcdfghjlmnpqrstuvwxz", "zp", "bcdfhjklmnpqstvwxz", "zq", "abcdefghijklmnopqrstvwxyz", "zr", "bcfghjklmnpqrstvwxyz", "zs", "bdfgjmnqrsuwxyz", "zt", "bcdfgjkmnpqtuvwxz", "zu", "ajqx", "zv", "bcdfghjklmnpqrstuvwxyz", "zw", "bcdfghjklmnpqrstuvwxyz", "zx", "abcdefghijklmnopqrstuvwxyz", "zy", "fxy", "zz", "cdfhjnpqrvx", NULL, NULL }; class ModuleAntiRandom : public Module { private: bool ShowFailedConnects; bool DebugMode; unsigned int Threshold; unsigned int BanAction; unsigned int BanDuration; std::string BanReason; public: ModuleAntiRandom(InspIRCd* Me) : Module(Me) { OnRehash(NULL, ""); } virtual ~ModuleAntiRandom() { } virtual Version GetVersion() { return Version(1,1,0,0,VF_VENDOR,API_VERSION); } void Implements(char* List) { List[I_OnUserConnect] = List[I_OnRehash] = 1; } unsigned int GetStringScore(const char *original_str) { const char **ci; const char *s; unsigned int score = 0; unsigned int highest_vowels = 0; unsigned int highest_consonants = 0; unsigned int highest_digits = 0; unsigned int vowels = 0; unsigned int consonants = 0; unsigned int digits = 0; /* Fast digit/consonant/vowel checks... */ for (s = original_str; *s; s++) { if ((*s >= '0') && (*s <= '9')) { digits++; } else { if (digits > highest_digits) highest_digits = digits; digits = 0; } /* Check consonants */ switch (*s) { case 'b': case 'c': case 'd': case 'f': case 'g': case 'h': case 'j': case 'k': case 'l': case 'm': case 'n': case 'p': case 'q': case 'r': case 's': case 't': case 'v': case 'w': case 'x': case 'z': consonants++; break; default: if (consonants > highest_consonants) highest_consonants = consonants; consonants = 0; break; } /* Check vowels */ switch (*s) { case 'a': case 'e': case 'i': case 'o': case 'u': vowels++; break; default: if (vowels > highest_vowels) highest_vowels = vowels; vowels = 0; break; } } /* Now set up for our checks. */ if (highest_digits > digits) digits = highest_digits; if (highest_consonants > consonants) consonants = highest_consonants; if (highest_vowels > vowels) vowels = highest_vowels; if (digits >= 5) { score += 5 + (digits - 5); ServerInstance->WriteOpers("antirandom: %s:MATCH digits", original_str); } if (vowels >= 4) { score += 4 + (vowels - 4); if (this->DebugMode) ServerInstance->WriteOpers("antirandom: %s:MATCH vowels", original_str); } if (consonants >= 4) { score += 4 + (consonants - 4); if (this->DebugMode) ServerInstance->WriteOpers("antirandom: %s:MATCH consonants", original_str); } /* * Now, do the triples checks. For each char in the string we're checking ... * XXX - on reading this, I wonder why we can't strcmp()/strchr() it.. */ for (s = original_str; *s; s++) { /* * ..run it through each triple. */ for (ci = triples_txt; *ci; *ci++) { // At this point, ci[0] and ci[1] point to the first two chars in the triples array. if (*ci[0] == s[0] && *ci[1] == s[1] && s[2]) { // First half of triple matches. Try match the other half. *ci++; if (strchr(*ci, s[2])) { // Triple matches! score++; if (this->DebugMode) ServerInstance->WriteOpers("antirandom: %s:MATCH triple (%s:%c/%c/%c)", original_str, *ci, s[0], s[1], s[2]); } } else { // No match. Just blindly increment half a triple. *ci++; } } } return score; } unsigned int GetUserScore(userrec *user) { int nscore, uscore, gscore, score; struct timeval tv_alpha, tv_beta; gettimeofday(&tv_alpha, NULL); nscore = GetStringScore(user->nick); uscore = GetStringScore(user->ident); gscore = GetStringScore(user->fullname); score = nscore + uscore + gscore; gettimeofday(&tv_beta, NULL); if (this->DebugMode) ServerInstance->WriteOpers("AntiRandom Timing: %ld microseconds", ((tv_beta.tv_sec - tv_alpha.tv_sec) * 1000000) + (tv_beta.tv_usec - tv_alpha.tv_usec)); if (this->DebugMode) ServerInstance->WriteOpers("Got score: %d/%d/%d = %d", nscore, uscore, gscore, score); return score; } virtual void OnUserConnect(userrec* user) { unsigned int score = GetUserScore(user); if (score > this->Threshold) { if (this->ShowFailedConnects) { ServerInstance->WriteOpers("Connection from %s was killed by AntiRandom with a score of %d - exceeds set threshold of %d", user->GetIPString(), score, this->Threshold); } switch (this->BanAction) { case ANTIRANDOM_ACT_KILL: userrec::QuitUser(ServerInstance, user, this->BanReason, this->BanReason.c_str()); break; case ANTIRANDOM_ACT_ZLINE: if (ServerInstance->XLines->add_zline(this->BanDuration, ServerInstance->Config->ServerName, this->BanReason.c_str(), user->GetIPString())) { ServerInstance->XLines->apply_lines(APPLY_ZLINES); } break; } } } virtual void OnRehash(userrec* user, const std::string ¶meter) { ConfigReader Conf(ServerInstance); std::string tmp; this->ShowFailedConnects = Conf.ReadFlag("antirandom", "failedconnects", 0); this->DebugMode = Conf.ReadFlag("antirandom", "debugmode", 0); tmp = Conf.ReadValue("antirandom", "threshold", 0); if (!tmp.empty()) this->Threshold = atoi(tmp.c_str()); else this->Threshold = 10; // fairly safe this->BanAction = ANTIRANDOM_ACT_KILL; tmp = Conf.ReadValue("antirandom", "banaction", 0); if (tmp == "ZLINE") { this->BanAction = ANTIRANDOM_ACT_ZLINE; } else if (tmp == "KILL") { this->BanAction = ANTIRANDOM_ACT_KILL; } tmp = Conf.ReadValue("antirandom", "banduration", 0); if (!tmp.empty()) this->BanDuration = ServerInstance->Duration(tmp.c_str()); else this->BanDuration = 86400; // One day. tmp = Conf.ReadValue("antirandom", "banreason", 0); if (!tmp.empty()) this->BanReason = tmp; else this->BanReason = "You look like a bot. Change your nick/ident/gecos and try reconnecting."; } }; MODULE_INIT(ModuleAntiRandom) inspircd-4.7.0+ds1/contrib/1.1/m_banreason.cpp000066400000000000000000000153271477226773200210000ustar00rootroot00000000000000#include #include "users.h" #include "channels.h" #include "modules.h" #include "helperfuncs.h" #include "inspircd.h" /* $ModDesc: Adds the abiliy to store the reason a user was banned from a channel */ /* $ModAuthor: Om */ /* $ModAuthorMail: om@inspircd.org */ /* $ModDepends: core 1.1 */ /* $ModVersion: $Rev: 78 $ */ /* Written by Om, April 2005. */ /* Originally based on m_exception, which was based on m_chanprotect and m_silence */ /* * This module stores a reason with every +b channel ban. * Instead of doing this by modifying the command, m_banreason detects the next kick after the ban is set, * and if the kicked user matches the ban host, then the kick reason is stored as the ban reason for that ban. */ class ModuleBanReason : public Module { InspIRCd* Srv; public: ModuleBanReason(InspIRCd* serv) : Module::Module(serv), Srv(serv) { } void Implements(char* List) { List[I_OnUserKick] = List[I_On005Numeric] = List[I_OnRawMode] = List[I_OnChannelDelete] = List[I_OnCleanup] = List[I_OnSyncUserMetaData] = List[I_OnDecodeMetaData] = 1; } virtual void OnUserKick(userrec* kicker, userrec* user, chanrec* chan, const std::string &rsn) { BanList bl = chan->bans; if(bl.size() > 0) { BanItem ban = chan->bans.back(); if(Srv->MatchText(user->GetFullHost(), ban.data) || Srv->MatchText(user->GetFullRealHost(), ban.data)) { // If the host of the kicked user matches the last ban set... Srv->Log(DEBUG, "m_banreason.so: %s was kicked by %s, and they match the last ban set on the channel (%s)", user->nick, kicker->nick, chan->name); if(get_reason(chan, ban.data).empty()) { // And there isn't a ban reason set for the last ban. // If this was the second kick after a ban then the reason would already be set, and we wouldn't need to do anything here. // But it was, so we make an extension to the channel record, holding the ban reason. add_reason(chan, ban.data, rsn); } } } } virtual void On005Numeric(std::string &output) { output += " BANREASON"; } virtual int OnRawMode(userrec* user, chanrec* chan, char mode, const std::string ¶m, bool adding, int pcnt) { if(mode == 'b') { if((pcnt > 0) && (!adding)) { // Basically, if someone sets -b... remove_reason(chan, param); } else { // We're listing the bans... Srv->Log(DEBUG, "Listing ban reasons..."); user->WriteServ("NOTICE %s :%s Listing ban reasons", user->nick, chan->name); for(BanList::iterator it = chan->bans.begin(); it != chan->bans.end(); it++) { std::string rsn = get_reason(chan, it->data); if(rsn.empty()) { Srv->Log(DEBUG, "No ban reason set for ban %s not sending list item", it->data); continue; } user->WriteServ("NOTICE %s :%s %s %s", user->nick, chan->name, it->data, rsn.c_str()); Srv->Log(DEBUG, "Sent reason (%s) for ban %s", rsn.c_str(), it->data); } user->WriteServ("NOTICE %s :%s End of channel ban reason list", user->nick, chan->name); } } return 0; } virtual void OnChannelDelete(chanrec* channel) { // For tidying up our ban reason lists when the last user leaves the channel... for (BanList::iterator it = channel->bans.begin(); it != channel->bans.end(); it++) { // For each one of the bans, try and remove the associated reason. remove_reason(channel, std::string(it->data)); } } virtual void OnSyncChannelMetaData(chanrec* chan, Module* proto, void* opaque, const std::string &extname) { // check if the linking module wants to know about some of our metadata if(extname.substr(0, 11) == "ban_reason_") { std::string reason = get_reason(chan, extname.substr(11)); if(reason.length()) { // Should always be true, but check the data actually exists before we try and sync it. // And give it to the protocol module to send out across the network proto->ProtoSendMetaData(opaque, TYPE_CHANNEL, chan, extname, reason); Srv->Log(DEBUG, "m_banreason.so: Sent the reason (" + reason + ") for ban '" + extname.substr(11) + "' on channel '" + std::string(chan->name) + "' out"); } else { Srv->Log(DEBUG, "m_banreason.so: Core asked us to sync some channel metadata (Key: " + extname + ") that doesn't exsist :/!"); } } } virtual void OnDecodeMetaData(int target_type, void* target, const std::string &extname, const std::string &extdata) { // check if its our metadata key, and its associated with a user if ((target_type == TYPE_CHANNEL) && (extname.substr(0, 11) == "ban_reason_")) { chanrec* chan = (chanrec*)target; std::string mask = extname.substr(11); if(get_reason(chan, mask).empty()) { add_reason(chan, mask, extdata); } } } virtual void OnCleanup(int target_type, void* item) { if(target_type == TYPE_CHANNEL) { chanrec* chan = (chanrec*)item; for(BanList::iterator it = chan->bans.begin(); it != chan->bans.end(); it++) { remove_reason(chan, it->data); } } } virtual ~ModuleBanReason() { } virtual Version GetVersion() { return Version(1, 2, 0, 3, 0, API_VERSION);// VF_STATIC); } void add_reason(chanrec* chan, const std::string &mask, const std::string &reason) { std::string* rs = new std::string(reason); chan->Extend("ban_reason_" + std::string(mask), rs); Srv->Log(DEBUG, "m_banreason.so: Extended %s record with ban reason %s for banmask %s", chan->name, reason.c_str(), mask.c_str()); } std::string get_reason(chanrec* chan, const std::string &mask) { std::string* reason; if(chan->GetExt("ban_reason_" + mask, reason)) { Srv->Log(DEBUG, "m_banreason.so: Retreived reason '" + *reason + "' for banmask '" + mask + "' on '" + std::string(chan->name) + "'"); return *reason; } else { Srv->Log(DEBUG, "m_banreason.so: Failed to retrieve ban reason for mask '" + mask + "' on '" + std::string(chan->name) + "'"); return ""; } } void remove_reason(chanrec* chan, const std::string &mask) { std::string* reason; if(chan->GetExt("ban_reason_" + mask, reason)) { if(chan->Shrink("ban_reason_" + mask)) { Srv->Log(DEBUG, "m_banreason.so: Ban reason (" + *reason + ") successfully removed on -b, banmask: " + mask); delete reason; } else { Srv->Log(DEBUG, "m_banreason.so: Failed to remove a ban reason which apparently existed. WTF?"); } } else { Srv->Log(DEBUG, "m_banreason.so: No ban reason to remove for ban " + mask); } } }; class ModuleBanReasonFactory : public ModuleFactory { public: ModuleBanReasonFactory() { } ~ModuleBanReasonFactory() { } virtual Module* CreateModule(InspIRCd* serv) { return new ModuleBanReason(serv); } }; extern "C" void * init_module( void ) { return new ModuleBanReasonFactory; } inspircd-4.7.0+ds1/contrib/1.1/m_exception.cpp000066400000000000000000000046341477226773200210250ustar00rootroot00000000000000#include #include #include #include "users.h" #include "channels.h" #include "modules.h" #include "mode.h" #include "u_listmode.h" /* $ModDesc: Provides support for the +x channel mode */ /* $ModAuthor: Om */ /* $ModAuthorMail: om@inspircd.org */ /* $ModDepends: core 1.1 */ /* $ModVersion: $Rev: 78 $ */ /* Written by Om , April 2005. */ /* Rewritten by Om, December 2005 */ /* Originally based on m_chanprotect and m_silence */ // The +x channel mode takes a nick!ident@host, glob patterns allowed, // and if a user matches an entry on the +x list then they can join the channel, overriding _all_ other restrictions (+k, +i, +b, +whatever) class GeneralException : public ListModeBase { public: GeneralException(InspIRCd* serv) : ListModeBase(serv, 'x', "End of General Exception List", "446", "447", true) { } }; class ModuleGeneralException : public Module { GeneralException* be; InspIRCd* Srv; public: ModuleGeneralException(InspIRCd* serv) : Module::Module(serv), Srv(serv) { be = new GeneralException(serv); Srv->AddMode(be, 'x'); } virtual void Implements(char* List) { be->DoImplements(List); List[I_On005Numeric] = List[I_OnUserPreJoin] = 1; } virtual void On005Numeric(std::string &output) { output.append(" EX=x"); } virtual int OnUserPreJoin(userrec* user, chanrec* chan, const char* cname, std::string &privs) { if(chan != NULL) { modelist* list; if(chan->GetExt(be->GetInfoKey(), list)) for(modelist::iterator it = list->begin(); it != list->end(); it++) if (match(user->GetFullRealHost(), it->mask.c_str()) || match(user->GetFullHost(), it->mask.c_str())) // They match an entry on the list, so let them in. return -1; // or if there wasn't a list, there can't be anyone on it, so we don't need to do anything. } return 0; } virtual void OnCleanup(int target_type, void* item) { be->DoCleanup(target_type, item); } virtual void OnSyncChannel(chanrec* chan, Module* proto, void* opaque) { be->DoSyncChannel(chan, proto, opaque); } virtual void OnChannelDelete(chanrec* chan) { be->DoChannelDelete(chan); } virtual void OnRehash(userrec* user, const std::string ¶meter) { be->DoRehash(); } virtual Version GetVersion() { return Version(1, 0, 0, 4, VF_STATIC|VF_COMMON, API_VERSION); } virtual ~ModuleGeneralException() { DELETE(be); } }; MODULE_INIT(ModuleGeneralException) inspircd-4.7.0+ds1/contrib/1.1/m_fantasy.cpp000066400000000000000000000172071477226773200204740ustar00rootroot00000000000000/* +------------------------------------+ * | Inspire Internet Relay Chat Daemon | * +------------------------------------+ * * InspIRCd: (C) 2002-2008 InspIRCd Development Team * See: http://www.inspircd.org/wiki/index.php/Credits * * This program is free but copyrighted software; see * the file COPYING for details. * * --------------------------------------------------- */ #include "inspircd.h" #include "users.h" #include "channels.h" #include "modules.h" #include "wildcard.h" /* $ModDesc: Provides ircd-side fantasy commands. */ /* $ModAuthor: w00t */ /* $ModAuthorMail: w00t@inspircd.org */ /* $ModDepends: core 1.1 */ /* $ModVersion: $Rev: 78 $ */ /** Fantasy command definition */ class FantasyCommand : public classbase { public: /** The text of the fantasy command */ irc::string text; /** Text to replace with */ std::string replace_with; /** Requires oper? */ bool operonly; /* is case sensitive params */ bool case_sensitive; /** Format that must be matched for use */ std::string format; }; class ModuleAlias : public Module { private: /** We cant use a map, there may be multiple aliases with the same name */ std::vector FantasyCommands; std::map FantasyMap; std::vector pars; virtual void ReadAliases() { ConfigReader MyConf(ServerInstance); FantasyCommands.clear(); FantasyMap.clear(); for (int i = 0; i < MyConf.Enumerate("fcommand"); i++) { FantasyCommand a; std::string txt; txt = MyConf.ReadValue("fcommand", "text", i); std::transform(txt.begin(), txt.end(), txt.begin(), ::toupper); a.text = txt.c_str(); a.replace_with = MyConf.ReadValue("fcommand", "replace", i, true); a.operonly = MyConf.ReadFlag("fcommand", "operonly", i); a.format = MyConf.ReadValue("fcommand", "format", i); a.case_sensitive = MyConf.ReadFlag("fcommands", "matchcase", i); FantasyCommands.push_back(a); FantasyMap[txt] = 1; } } public: ModuleAlias(InspIRCd* Me) : Module(Me) { ReadAliases(); pars.resize(127); } void Implements(char* List) { List[I_OnUserPreMessage] = List[I_OnRehash] = 1; } virtual ~ModuleAlias() { } virtual Version GetVersion() { return Version(1,1,0,1,VF_VENDOR,API_VERSION); } std::string GetVar(std::string varname, const std::string &original_line) { irc::spacesepstream ss(original_line); varname.erase(varname.begin()); int index = *(varname.begin()) - 48; varname.erase(varname.begin()); bool everything_after = (varname == "-"); std::string word; for (int j = 0; j < index; j++) ss.GetToken(word); if (everything_after) { std::string more; while (ss.GetToken(more)) { word.append(" "); word.append(more); } } return word; } void SearchAndReplace(std::string& newline, const std::string &find, const std::string &replace) { std::string::size_type x = newline.find(find); while (x != std::string::npos) { newline.erase(x, find.length()); newline.insert(x, replace); x = newline.find(find); } } virtual int OnUserPreMessage(userrec* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list) { if (target_type != TYPE_CHANNEL) { ServerInstance->Log(DEBUG, "fantasy: not a channel msg"); return 0; } // fcommands are only for local users. Spanningtree will send them back out as their original cmd. if (!IS_LOCAL(user)) { ServerInstance->Log(DEBUG, "fantasy: not local"); return 0; } chanrec* c = (chanrec*)dest; std::string fcommand; // text is like "!moo cows bite me", we want "!moo" first irc::spacesepstream ss(text); ss.GetToken(fcommand); if (fcommand.empty()) { ServerInstance->Log(DEBUG, "fantasy: empty (??)"); return 0; // wtfbbq } ServerInstance->Log(DEBUG, "fantasy: looking at fcommand %s", fcommand.c_str()); // we don't want to touch non-fantasy stuff if (*fcommand.c_str() != '!') { ServerInstance->Log(DEBUG, "fantasy: not a fcommand"); return 0; } // nor do we give a shit about the ! fcommand.erase(fcommand.begin()); std::transform(fcommand.begin(), fcommand.end(), fcommand.begin(), ::toupper); ServerInstance->Log(DEBUG, "fantasy: now got %s", fcommand.c_str()); /* We dont have any commands looking like this, no point continuing.. */ if (FantasyMap.find(fcommand) == FantasyMap.end()) return 0; ServerInstance->Log(DEBUG, "fantasy: in the map"); /* The parameters for the command in their original form, with the command stripped off */ std::string compare = text.substr(fcommand.length() + 1); while (*(compare.c_str()) == ' ') compare.erase(compare.begin()); std::string safe(compare); /* Escape out any $ symbols in the user provided text (ugly, but better than crashy) */ SearchAndReplace(safe, "$", "\r"); ServerInstance->Log(DEBUG, "fantasy: compare is %s and safe is %s", compare.c_str(), safe.c_str()); for (unsigned int i = 0; i < FantasyCommands.size(); i++) { ServerInstance->Log(DEBUG, "fantasy: looking for %s, current item is %s", fcommand.c_str(), FantasyCommands[i].text.c_str()); if (!strcasecmp(FantasyCommands[i].text.c_str(), fcommand.c_str())) // XXX a stl comparison would be nicer, but I can't get it working right now. { /* Does it match the pattern? */ if (!FantasyCommands[i].format.empty()) { if (!match(FantasyCommands[i].case_sensitive, compare.c_str(), FantasyCommands[i].format.c_str())) { ServerInstance->Log(DEBUG, "fantasy: no match on pattern %s (comparing %s)", FantasyCommands[i].format.c_str(), compare.c_str()); continue; } } if ((FantasyCommands[i].operonly) && (!IS_OPER(user))) { ServerInstance->Log(DEBUG, "fantasy: oper only"); return 0; } /* Now, search and replace in a copy of the original_line, replacing $1 through $9 and $1- etc */ std::string::size_type crlf = FantasyCommands[i].replace_with.find('\n'); if (crlf == std::string::npos) { ServerInstance->Log(DEBUG, "fantasy: running it"); DoCommand(FantasyCommands[i].replace_with, user, c, safe); return 0; } else { irc::sepstream commands(FantasyCommands[i].replace_with, '\n'); std::string command; while (commands.GetToken(command)) { DoCommand(command, user, c, safe); } return 0; } } } return 0; } void DoCommand(std::string newline, userrec* user, chanrec *c,const std::string &original_line) { for (int v = 1; v < 10; v++) { std::string var = "$"; var.append(ConvToStr(v)); var.append("-"); std::string::size_type x = newline.find(var); while (x != std::string::npos) { newline.erase(x, var.length()); newline.insert(x, GetVar(var, original_line)); x = newline.find(var); } var = "$"; var.append(ConvToStr(v)); x = newline.find(var); while (x != std::string::npos) { newline.erase(x, var.length()); newline.insert(x, GetVar(var, original_line)); x = newline.find(var); } } /* Special variables */ SearchAndReplace(newline, "$nick", user->nick); SearchAndReplace(newline, "$ident", user->ident); SearchAndReplace(newline, "$host", user->host); SearchAndReplace(newline, "$vhost", user->dhost); SearchAndReplace(newline, "$chan", c->name); /* Unescape any variable names in the user text before sending */ SearchAndReplace(newline, "\r", "$"); irc::tokenstream ss(newline); const char* parv[127]; int x = 0; while (ss.GetToken(pars[x])) { parv[x] = pars[x].c_str(); x++; } ServerInstance->Parser->CallHandler(parv[0], &parv[1], x-1, user); } virtual void OnRehash(userrec* user, const std::string ¶meter) { ReadAliases(); } }; MODULE_INIT(ModuleAlias) inspircd-4.7.0+ds1/contrib/1.1/m_freeformadmin.cpp000066400000000000000000000024321477226773200216370ustar00rootroot00000000000000#include "inspircd.h" #include "users.h" #include "channels.h" #include "modules.h" /* $ModDesc: Allows a freeform reply to the /ADMIN command */ /* $ModAuthor: jackmcbarn */ /* $ModAuthorMail: w00t@inspircd.org */ /* $ModDepends: core 1.1 */ class ModuleFreeformAdmin : public Module { std::string admintext; public: ModuleFreeformAdmin(InspIRCd* Me) : Module(Me) { this->OnRehash(NULL,""); } virtual ~ModuleFreeformAdmin() { } virtual Version GetVersion() { return Version(1, 1, 0, 0, 0, API_VERSION); } void Implements(char* List) { List[I_OnRehash] = List[I_OnPostCommand] = 1; } virtual void OnPostCommand(const std::string &command, const char** parameters, int pcnt, userrec *user, CmdResult result, const std::string &original_line) { if (command != "ADMIN") return; std::string adminstr = "304 " + std::string(user->nick) + " :ADMIN "; irc::sepstream stream(admintext, '\n'); std::string token = "*"; while (stream.GetToken(token)) user->WriteServ("%s%s", adminstr.c_str(), token.c_str()); } virtual void OnRehash(userrec* user, const std::string ¶meter) { ConfigReader myConfigReader = ConfigReader(ServerInstance); admintext = myConfigReader.ReadValue("admin", "text", "Misconfigured", 0, true); } }; MODULE_INIT(ModuleFreeformAdmin) inspircd-4.7.0+ds1/contrib/1.1/m_modeaccess.cpp000066400000000000000000000256371477226773200211430ustar00rootroot00000000000000/* +------------------------------------+ * | Inspire Internet Relay Chat Daemon | * +------------------------------------+ * * InspIRCd is copyright (C) 2002-2008 ChatSpike-Dev. * E-mail: * * * * * Written by Craig Edwards, Craig McLure, and others. * This program is free but copyrighted software; see * the file COPYING for details. * * --------------------------------------------------- */ #include #include #include #include #include "inspircd.h" #include "channels.h" #include "modules.h" /* $ModDesc: Allows fine configuration of what users can set arbitrary channel modes, based on usermodes, channel modes and prefixes. */ /* $ModAuthor: Om */ /* $ModAuthorMail: om@inspircd.org */ /* $ModDepends: core 1.1 */ /* $ModVersion: $Rev: 78 $ */ typedef std::pair CharPair; typedef std::vector CharPairList; bool cmp(CharPair a, CharPair b) { return a.second > b.second; } class OnOff { private: void MakeStrRep() { bool doneplus; bool doneminus; doneplus = doneminus = false; for(CharPairList::iterator i = modes.begin(); i != modes.end(); i++) { if((i->second == 1) && !doneplus) { doneplus = true; strrep.append("+"); } if((i->second == 0) && !doneminus) { doneminus = true; strrep.append("-"); } strrep.append(1, i->first); } } public: std::string strrep; CharPairList modes; short modecount; OnOff(const std::string &combined) : modecount(0) { bool adding = true; for(std::string::const_iterator i = combined.begin(); i != combined.end(); i++) { switch(*i) { case '+': adding = true; break; case '-': adding = false; break; default: modes.push_back(std::make_pair(*i, adding)); modecount++; break; } } sort(modes.begin(), modes.end(), cmp); MakeStrRep(); } OnOff(const std::string &on, const std::string &off) : modecount(0) { for(std::string::const_iterator i = on.begin(); i != on.end(); i++) { modes.push_back(std::make_pair(*i, 1)); modecount++; } for(std::string::const_iterator i = off.begin(); i != off.end(); i++) { modes.push_back(std::make_pair(*i, 0)); modecount++; } MakeStrRep(); } const char* str() { return strrep.c_str(); } }; class Prefix { public: InspIRCd* Srv; std::string prefixstr; unsigned int lowestrequired; char lowestprefixrequired; Prefix(InspIRCd* me, const std::string &pstr) : Srv(me), prefixstr(pstr), lowestrequired(0), lowestprefixrequired(' ') { bool haveparsedrealprefix = false; /* First find what the lowest prefix level required is */ for(std::string::const_iterator i = pstr.begin(); i != pstr.end(); i++) { ModeHandler* handler = Srv->Modes->FindPrefix(*i); if(handler) { unsigned int newlevel = handler->GetPrefixRank(); if(!haveparsedrealprefix || (newlevel < lowestrequired)) { lowestrequired = newlevel; lowestprefixrequired = *i; } } } } /** bool UserQualifies(user, channel) * Return true if the user has the prefixes stored in this class on the channel * passed as an argument, false otherwise. */ bool UserQualifies(User* user, Channel* chan) { if(chan->GetPrefixValue(user) >= lowestrequired) { return true; } else { return false; } } }; class PermInfo { public: char mode; OnOff umodes; OnOff cmodes; Prefix prefix; PermInfo(InspIRCd* me, char m, const std::string &u, const std::string &c, const std::string &p) : mode(m), umodes(u), cmodes(c), prefix(me, p) { } }; typedef std::vector PermSet; typedef std::vector PermissionList; class ModuleModeAccess : public Module { private: InspIRCd *Srv; PermissionList perms; public: ModuleModeAccess(InspIRCd* Me) : Module::Module(Me), Srv(Me) { OnRehash(NULL, ""); Implementation list[] = { I_On005Numeric, I_OnRawMode, I_OnRehash }; Me->Modules->Attach(list, this, 3); } /** * Load the configuration for the priveleges required to use a certain mode. * If a more than one tag is defined for a mode, then the user only needs * to have *one* of those priveleges. * However if more than one privelege is defined inside one tag, all those * requirements much be met. * Prefixes are considered as levels, so if a user has ~ they are considered * to have &@%+ as well etc. * If no requirements are set for a mode it is allowed for prefix % and above (default behaviour) Ex: * - +P may only be set on channels which are +s * - Only users with usermode +h set can set +c * - Same as above * - Only users without usermode +h set can set +c * - Only users with prefix @ on a channel can set +c on that channel * - Only opers who are have the ~ prefix on a channel can set +S on the channel * - +A can be set by a user with umode +z, or by anyone if the channel has cmode +z */ virtual void OnRehash(User* user, const std::string ¶meter) { ConfigReader Conf(Srv); perms.clear(); perms.assign(127, PermSet()); for(int i = 0; i < Conf.Enumerate("access"); i++) { std::string rmodes = Conf.ReadValue("access", "modes", i); std::string umodes = Conf.ReadValue("access", "umodes", i); std::string cmodes = Conf.ReadValue("access", "cmodes", i); std::string prefix = Conf.ReadValue("access", "prefix", i); for(std::string::iterator j = rmodes.begin(); j != rmodes.end(); j++) { /* Add a structure for permissions for each mode in the tag. */ perms[ *j ].push_back(PermInfo(Srv, *j, umodes, cmodes, prefix)); Srv->Log(DEBUG, "m_modeaccess.so: Adding mode %c, requires umodes '%s', prefix '%s', and cmodes '%s'", *j, umodes.c_str(), prefix.c_str(), cmodes.c_str()); } } } virtual void On005Numeric(std::string &output) { /* Have fun designing some ludicrously complicated format here later... */ /* ALLOWEDMODES=MODE:UMODES:CMODES:PREFIXES */ /* Make a copy of this. Then we load in the modes from the core/other modules * into the copy and let the code below generate the 005. */ PermissionList tempperms = perms; std::string umodes = Srv->Modes->ChannelModeList(); for(std::string::iterator i = umodes.begin(); i != umodes.end(); i++) { char& mchar = *i; if((mchar != ',') && (tempperms[mchar].empty())) { ModeHandler* handler = Srv->Modes->FindMode(mchar, MODETYPE_CHANNEL); if(handler) { tempperms[mchar].push_back(PermInfo(Srv, mchar, handler->NeedsOper() ? "+o" : "", "", std::string(1, handler->GetNeededPrefix()))); } } } std::string ourstring(" ALLOWEDMODES="); bool addedamode = false; for(PermissionList::iterator i = tempperms.begin(); i != tempperms.end(); i++) { PermSet& modeperms = *i; for(PermSet::iterator k = modeperms.begin(); k != modeperms.end(); k++) { PermInfo& pinfo = *k; ourstring.append(1, pinfo.mode).append(1, ':').append(pinfo.umodes.strrep).append(1, ':'); ourstring.append(pinfo.cmodes.strrep).append(1, ':').append(pinfo.prefix.prefixstr).append(1, ','); addedamode = true; } } if(addedamode) { ourstring.resize(ourstring.size() - 1); output.append(ourstring); } } virtual int OnRawMode(User* source, Channel* channel, const char modechar, const std::string ¶m, bool adding, int pcnt) { /* We're only concerned with channel modes */ if(!channel) return ACR_DEFAULT; Srv->Log(DEBUG, "OnRawMode(%s, %s, %c, %s, %s, %d)", source->nick, channel->name, modechar, param.c_str(), adding ? "true" : "false", pcnt); /* We don't care about remote users, this module on the remote server handles them */ if(!IS_LOCAL(source)) return ACR_DEFAULT; PermSet& criteria = perms[modechar]; char error[MAXBUF]; *error = '\0'; /* Search the rules for this mode, now we iterate over them until we find one that matches */ for(PermSet::iterator iter = criteria.begin(); iter != criteria.end(); iter++) { Srv->Log(DEBUG, "Checking over rules for mode %c, possible: umodes='%s', prefix='%s', cmodes='%s'", modechar, iter->umodes.str(), iter->prefix.prefixstr.c_str(), iter->cmodes.str()); /* If the user trying to set the mode matches the criteria for setting it, allow it by returning true */ if(this->HasModes(channel, iter->cmodes)) { if(this->HasModes(source, iter->umodes)) { if(iter->prefix.UserQualifies(source, channel)) { return ACR_ALLOW; } else { snprintf(error, MAXBUF, "482 %s %s :You must have channel privilege %c or above to %sset channel mode %c", source->nick, channel->name, iter->prefix.lowestprefixrequired, adding ? "" : "un", modechar); } } else { snprintf(error, MAXBUF, "482 %s %s :You must have user mode%s %s to %sset channel mode %c", source->nick, channel->name, (iter->umodes.modecount > 1) ? "s" : "", iter->umodes.str(), adding ? "" : "un", modechar); } } else { snprintf(error, MAXBUF, "482 %s %s :Channel mode%s %s must to set to %sset channel mode %c", source->nick, channel->name, (iter->cmodes.modecount > 1) ? "s" : "", iter->cmodes.str(), adding ? "" : "un", modechar); } } if(*error) { source->WriteServ(error); return ACR_DENY; } else { return ACR_DEFAULT; } } /** HasModes(user, modes) * Return true if user has all the usermodes in 'modes' set. * Return false otherwise. */ bool HasModes(User* user, const OnOff &modes) { for(CharPairList::const_iterator i = modes.modes.begin(); i != modes.modes.end(); i++) { if(user->IsModeSet(i->first) == i->second) { Srv->Log(DEBUG, "Mode %c was %s on %s as configured", i->first, i->second ? "set" : "not set", user->nick); } else { Srv->Log(DEBUG, "Mode %c was %s on %s, not allowed by configuration", i->first, i->second ? "set" : "not set", user->nick); return false; } } return true; } /** HasModes(chan, modes) * Return true if all the chanmodes in 'modes' are set on 'chan' * Return false otherwise. */ bool HasModes(Channel* chan, const OnOff &modes) { for(CharPairList::const_iterator i = modes.modes.begin(); i != modes.modes.end(); i++) { if(chan->IsModeSet(i->first) == i->second) { Srv->Log(DEBUG, "Mode %c was %s on %s as configured", i->first, i->second ? "set" : "not set", chan->name); } else { Srv->Log(DEBUG, "Mode %s was %s on %s, not allowed by configuration", i->first, i->second ? "set" : "not set", chan->name); return false; } } return true; } virtual ~ModuleModeAccess() { } virtual Version GetVersion() { return Version(1,2,0,3,0,API_VERSION); } }; MODULE_INIT(ModuleModeAccess) inspircd-4.7.0+ds1/contrib/1.1/m_modesquish.cpp000066400000000000000000000111621477226773200212020ustar00rootroot00000000000000/* +------------------------------------+ * | Inspire Internet Relay Chat Daemon | * +------------------------------------+ * * InspIRCd: (C) 2002-2007 InspIRCd Development Team * See: http://www.inspircd.org/wiki/index.php/Credits * * This program is free but copyrighted software; see * the file COPYING for details. * * --------------------------------------------------- */ #include "inspircd.h" #include "users.h" #include "channels.h" #include "modules.h" #include "mode.h" /* $ModDesc: Pre-parses MODE command to remove redundant modes */ /* $ModAuthor: Skip */ /* $ModREMOVEAuthorMail: unknown */ /* $ModDepends: core 1.1 */ /* $ModVersion: $Rev: 78 $ */ class module_modesquish : public Module { public: module_modesquish(InspIRCd* Me) : Module(Me) { } void Implements(char* List) { List[I_OnPreCommand] = 1; } virtual ~module_modesquish() { } virtual Version GetVersion() { return Version(1,1,0,1,0,API_VERSION); } virtual int OnPreCommand(const std::string &command, const char** parameters, int pcnt, userrec *user, bool validated, const std::string &original_line) { if (validated && command == "MODE" && pcnt > 1) { class squishy { public: squishy() {}; ~squishy() {}; bool adding; unsigned char flag; std::string *param; }; /* * Find out what we are */ chanrec* targetchannel = ServerInstance->FindChan(parameters[0]); userrec* targetuser = ServerInstance->FindNick(parameters[0]); ModeType type; ModeHandler* handler; bool adding = true; bool abort = false; squishy* squish; std::vector squish_list; if (targetchannel) type = MODETYPE_CHANNEL; else if (targetuser) type = MODETYPE_USER; else return 0; std::string mode_sequence = parameters[1]; std::string parameter; int parameter_index = 2; /* * Loop through all the flags */ for (std::string::const_iterator letter = mode_sequence.begin(); letter != mode_sequence.end(); letter++) { unsigned char modechar = *letter; switch (modechar) { case '+': case '-': adding = (modechar == '+' ? true : false ); break; default: handler = ServerInstance->Modes->FindMode(modechar, type); parameter.clear(); /* * Grab us a param ? */ if (handler && handler->GetModeType() == type && handler->GetNumParams(adding) && parameter_index < pcnt) parameter = parameters[parameter_index++]; squish = NULL; abort = false; for (std::vector::iterator i = squish_list.begin(); i != squish_list.end(); i++) { squish = (squishy*)(*i); if (squish->flag == modechar && ((squish->param->empty() && parameter.empty()) || !strcmp(squish->param->c_str(),parameter.c_str()))) { abort = true; if (adding != squish->adding) { squish_list.erase(i); delete squish->param; delete squish; } break; } } if (abort) break; /* * Add it to our squish list */ squish = new squishy(); squish->flag = modechar; squish->adding = adding; squish_list.push_back((void*)squish); if (!parameter.empty()) squish->param = new std::string (parameter); else squish->param = new std::string (); break; } } /* * Ok, build our mode string back from squish list */ const char *squish_p[127]; int squish_pcnt = 2; std::string squish_mode_sequence; squish_p[0] = parameters[0]; /* target */ adding = true; for (std::vector::iterator i = squish_list.begin(); i != squish_list.end(); i++) { squish = (squishy*)(*i); if (squish_mode_sequence.empty() || adding != squish->adding) squish_mode_sequence.append((squish->adding ? "+" : "-")); adding = squish->adding; squish_mode_sequence.append(1, squish->flag); if (!squish->param->empty()) squish_p[squish_pcnt++] = squish->param->c_str(); } squish_p[1] = squish_mode_sequence.c_str(); /* * Finally, send out our new and improved mode! * (provided we didn't squish it to nothingness) */ if (!squish_mode_sequence.empty()) ServerInstance->CallCommandHandler("MODE", squish_p, squish_pcnt, user); /* * Clean up */ for (std::vector::iterator i = squish_list.begin(); i != squish_list.end(); i++) { squish = (squishy*)(*i); delete squish->param; delete squish; } squish_list.clear(); /* * And stop *this* MODE getting through */ return 1; } return 0; } }; MODULE_INIT(module_modesquish) inspircd-4.7.0+ds1/contrib/1.1/m_operflood.cpp000066400000000000000000000025131477226773200210120ustar00rootroot00000000000000/* +------------------------------------+ * | Inspire Internet Relay Chat Daemon | * +------------------------------------+ * * InspIRCd: (C) 2002-2007 InspIRCd Development Team * See: http://www.inspircd.org/wiki/index.php/Credits * * This program is free but copyrighted software; see * the file COPYING for details. * * --------------------------------------------------- */ #include "inspircd.h" #include "users.h" #include "channels.h" #include "modules.h" /* $ModDesc: Removes flood limits from users upon opering up. */ /* $ModAuthor: ? */ /* $ModAuthorMailXXX: */ /* $ModDepends: core 1.1 */ /* $ModVersion: $Rev: 78 $ */ class ModuleOperFlood : public Module { public: ModuleOperFlood(InspIRCd * Me) : Module(Me) {} void Implements(char * List) { List[I_OnPostOper] = 1; } Version GetVersion() { return Version(1,1,0,1,VF_VENDOR,API_VERSION); } void OnPostOper(userrec* user, const std::string &opertype) { if(!IS_LOCAL(user)) return; user->flood = 0; user->WriteServ("NOTICE %s :*** You are now free from flood limits.", user->nick); } }; class ModuleOperFloodFactory : public ModuleFactory { public: Module * CreateModule(InspIRCd * Me) { return new ModuleOperFlood(Me); } }; extern "C" DllExport void * init_module( void ) { return new ModuleOperFloodFactory; } inspircd-4.7.0+ds1/contrib/1.1/m_operperms.cpp000066400000000000000000000124271477226773200210420ustar00rootroot00000000000000/* m_operperms - Written by Om - April 2005 */ /* Updated by Om - Feburary 2006 */ #include #include #include "inspircd.h" #include "modules.h" /* $ModDesc: Provides an /operperms command, allowing opers to view what commands they and other opers have access to. */ /* $ModAuthor: Om */ /* $ModAuthorMail: om@inspircd.org */ /* $ModDepends: core 1.1 */ /* $ModVersion: $Rev: 78 $ */ typedef std::set strset; inline strset& split(strset &out, const std::string &in) { unsigned int a = 0; unsigned int b = 0; while(b <= in.size()) { if(in[b] == ' ' || in[b] == '\t' || b == in.size()) { out.insert(in.substr(a, b-a)); a = b+1; } b++; } return out; } class ModuleOperCmdsBase { public: ConfigReader* Conf; InspIRCd* Srv; int perline; }; class cmd_operperms : public command_t { ModuleOperCmdsBase* base; public: cmd_operperms(ModuleOperCmdsBase* b) : command_t(b->Srv, "OPERPERMS", 'o', 1), base(b) { this->source = "m_operperms.so"; } CmdResult Handle(const char** parameters, int pcnt, userrec* user) { // Find a userrec for the parameter. userrec* target = base->Srv->FindNick(parameters[0]); // Lists of classes and commands for the oper strset classlist; strset commandlist; if(!target) { // If the user was invalid tell the person who used the command that it was invalid...and stop executing the command. user->WriteServ("401 %s %s :No such nick/channel", user->nick, parameters[0]); return CMD_FAILURE; } if(!*target->oper) { // If target->oper is null then the user isn't an oper. user->WriteServ("NOTICE %s :%s is not an oper", user->nick, target->nick); return CMD_FAILURE; } base->Srv->WriteOpers("*** %s used /OPERPERMS to view permissions of %s", user->nick, target->nick); for(int i = 0; i < base->Conf->Enumerate("type"); i++) { // For each oper type in the configuration file. if(base->Conf->ReadValue("type", "name", i) == target->oper) { // If the tag in the config corresponds to the oper type of the target, eg, we've found the user's oper type // Reset the error. base->Conf->GetError(); long level = base->Conf->ReadInteger("type", "level", i, false); if(base->Conf->GetError() == 0) user->WriteServ("NOTICE %s :%s's oper level is %ld", user->nick, target->nick, level); else user->WriteServ("NOTICE %s :%s does not have an oper level", user->nick, target->nick); // Read the classes the target oper has. split(classlist, base->Conf->ReadValue("type", "classes", i)); for(int j = 0; j < base->Conf->Enumerate("class"); j++) { // Loop through all classes in the config.. if(classlist.count(base->Conf->ReadValue("class", "name", j))) { // And if our user has that oper class std::string classcmds = base->Conf->ReadValue("class", "commands", j); if(classcmds.size()) split(commandlist, classcmds); } } int num = 0; std::string line; for(strset::iterator iter = commandlist.begin(); iter != commandlist.end(); iter++) { // For each one of the commands the oper has access to. if(num < base->perline) { if(base->Srv->Parser->cmdlist.count(*iter)) line.append(" " + *iter); else line.append(" [" + *iter + "]"); num++; } else { user->WriteServ("NOTICE %s :%s", user->nick, line.c_str()); line = " " + *iter; num = 1; } } for(nspace::hash_map::iterator iter = base->Srv->Parser->cmdlist.begin(); iter != base->Srv->Parser->cmdlist.end(); iter++) { // For each one of the commands the oper doesn't have access to. if((iter->second->flags_needed == 'o') && !commandlist.count(iter->first)) { if(num < base->perline) { line.append(" (" + iter->first + ")"); num++; } else { user->WriteServ("NOTICE %s :%s", user->nick, line.c_str()); line = " " + iter->first; num = 1; } } } // All done, and we don't want to carry on reading tags, so return. user->WriteServ("NOTICE %s :End of %s's allowed command list", user->nick, target->nick); return CMD_SUCCESS; } } // We shouldn't ever get here, as the handler should return after it finds the tag. base->Srv->Log(DEBUG, "m_operperms.so: Oper type not found in config for a user who has +o, something is messed up..."); return CMD_FAILURE; } }; class ModuleOperCmds : public Module, public ModuleOperCmdsBase { cmd_operperms* cmd; public: ModuleOperCmds(InspIRCd* serv) : Module::Module(serv) { Srv = serv; Conf = new ConfigReader(Srv); cmd = new cmd_operperms(this); OnRehash(NULL, ""); Srv->AddCommand(cmd); } void Implements(char* List) { List[I_OnRehash] = 1; } virtual ~ModuleOperCmds() { delete Conf; } virtual Version GetVersion() { return Version(1, 1, 0, 2, 0, API_VERSION); } virtual void OnRehash(userrec* user, const std::string ¶meter) { delete Conf; Conf = new ConfigReader(Srv); perline = Conf->ReadInteger("operperms", "perline", 0, false); if(perline <= 0 || perline > 10) perline = 3; } }; MODULE_INIT(ModuleOperCmds) inspircd-4.7.0+ds1/contrib/1.1/m_rpg.cpp000066400000000000000000000156711477226773200176220ustar00rootroot00000000000000/* +------------------------------------+ * | Inspire Internet Relay Chat Daemon | * +------------------------------------+ * * InspIRCd: (C) 2002-2008 InspIRCd Development Team * See: http://www.inspircd.org/wiki/index.php/Credits * * This program is free but copyrighted software; see * the file COPYING for details. * * --------------------------------------------------- */ #include "inspircd.h" #include "channels.h" #include "modules.h" /* $ModDesc: Provides NPC, NPCA, and AMBIANCE commands for use by Game Masters doing pen & paper RPGs via IRC */ /* $ModAuthor: Naram Qashat (CyberBotX) */ /* $ModAuthorMail: cyberbotx@cyberbotx.com */ /* $ModDepends: core 1.1 */ /* $ModVersion: $Rev: 78 $ */ /** Base class for /NPC and /NPCA */ class NPCx { InspIRCd *ServerInstance; public: NPCx(InspIRCd *Instance) : ServerInstance(Instance) { } /* Removes any ! characters from a given nick */ std::string strip_npc_nick(const std::string &nick) { std::string newnick = ""; unsigned len = nick.size(); for (unsigned x = 0; x < len; ++x) { char c = nick[x]; if (c != '!') newnick += c; } return newnick; } CmdResult Handle(const char **parameters, int pcnt, userrec *user, bool action) { chanrec *c = ServerInstance->FindChan(parameters[0]); if (c) { if (!c->HasUser(user)) { user->WriteServ("492 %s %s :You are not on that channel!", user->nick, parameters[0]); return CMD_FAILURE; } if (c->GetStatus(user) < STATUS_OP) { user->WriteServ("482 %s %s :You're not a channel operator", user->nick, parameters[0]); return CMD_FAILURE; } } else { user->WriteServ("401 %s %s :No such channel", user->nick, parameters[0]); return CMD_FAILURE; } /* Source is in the form of: *[nick]*!npc@[server-name] */ std::string source = std::string("*") + strip_npc_nick(parameters[1]) + "*!npc@" + ServerInstance->Config->ServerName; std::string line = ""; for (int i = 2; i < pcnt - 1; ++i) { line = line + parameters[i] + " "; } line = line + parameters[pcnt - 1]; c->WriteChannelWithServ(source.c_str(), "PRIVMSG %s :%s%s%s", c->name, action ? "\1ACTION " : "", line.c_str(), action ? "\1" : ""); /* we want this routed out! */ return CMD_SUCCESS; } }; /** Handle /NPC */ class cmd_npc : public command_t, public NPCx { public: cmd_npc(InspIRCd *Instance) : command_t(Instance, "NPC", 0, 3), NPCx(Instance) { this->source = "m_rpg.so"; syntax = " "; } CmdResult Handle(const char **parameters, int pcnt, userrec *user) { return NPCx::Handle(parameters, pcnt, user, false); } }; /** Handle /NPCA */ class cmd_npca : public command_t, public NPCx { public: cmd_npca(InspIRCd *Instance) : command_t(Instance, "NPCA", 0, 3), NPCx(Instance) { this->source = "m_rpg.so"; syntax = " "; } CmdResult Handle(const char **parameters, int pcnt, userrec *user) { return NPCx::Handle(parameters, pcnt, user, true); } }; /** Handle /AMBIANCE */ class cmd_ambiance : public command_t { public: cmd_ambiance(InspIRCd *Instance) : command_t(Instance, "AMBIANCE", 0, 2) { this->source = "m_rpg.so"; syntax = " "; } CmdResult Handle(const char **parameters, int pcnt, userrec *user) { chanrec *c = ServerInstance->FindChan(parameters[0]); if (c) { if (!c->HasUser(user)) { user->WriteServ("492 %s %s :You are not on that channel!", user->nick, parameters[0]); return CMD_FAILURE; } if (c->GetStatus(user) < STATUS_OP) { user->WriteServ("482 %s %s :You're not a channel operator", user->nick, parameters[0]); return CMD_FAILURE; } } else { user->WriteServ("401 %s %s :No such channel", user->nick, parameters[0]); return CMD_FAILURE; } /* Source is in the form of: >AmbianceAmbianceConfig->ServerName; std::string line = ""; for (int i = 1; i < pcnt - 1; ++i) { line = line + parameters[i] + " "; } line = line + parameters[pcnt - 1]; c->WriteChannelWithServ(source.c_str(), "PRIVMSG %s :%s", c->name, line.c_str()); /* we want this routed out! */ return CMD_SUCCESS; } }; /** Base class for /NARRATOR and /NARRATORA */ class Narrator { InspIRCd *ServerInstance; public: Narrator(InspIRCd *Instance) : ServerInstance(Instance) { } CmdResult Handle(const char **parameters, int pcnt, userrec *user, bool action) { chanrec *c = ServerInstance->FindChan(parameters[0]); if (c) { if (!c->HasUser(user)) { user->WriteServ("492 %s %s :You are not on that channel!", user->nick, parameters[0]); return CMD_FAILURE; } if (c->GetStatus(user) < STATUS_OP) { user->WriteServ("482 %s %s :You're not a channel operator", user->nick, parameters[0]); return CMD_FAILURE; } } else { user->WriteServ("401 %s %s :No such channel", user->nick, parameters[0]); return CMD_FAILURE; } /* Source is in the form of: -Narrator-!npc@[server-name] */ std::string source = std::string("-Narrator-!npc@") + ServerInstance->Config->ServerName; std::string line = ""; for (int i = 1; i < pcnt - 1; ++i) { line = line + parameters[i] + " "; } line = line + parameters[pcnt - 1]; c->WriteChannelWithServ(source.c_str(), "PRIVMSG %s :%s%s%s", c->name, action ? "\1ACTION " : "", line.c_str(), action ? "\1" : ""); /* we want this routed out! */ return CMD_SUCCESS; } }; /** Handle /NARRATOR */ class cmd_narrator : public command_t, public Narrator { public: cmd_narrator(InspIRCd *Instance) : command_t(Instance, "NARRATOR", 0, 2), Narrator(Instance) { this->source = "m_rpg.so"; syntax = " "; } CmdResult Handle(const char **parameters, int pcnt, userrec *user) { return Narrator::Handle(parameters, pcnt, user, false); } }; /** Handle /NARRATORA */ class cmd_narratora : public command_t, public Narrator { public: cmd_narratora(InspIRCd *Instance) : command_t(Instance, "NARRATORA", 0, 2), Narrator(Instance) { this->source = "m_rpg.so"; syntax = " "; } CmdResult Handle(const char **parameters, int pcnt, userrec *user) { return Narrator::Handle(parameters, pcnt, user, true); } }; class RPGCommandsModule : public Module { cmd_npc *npc; cmd_npca *npca; cmd_ambiance *ambiance; cmd_narrator *narrator; cmd_narratora *narratora; public: RPGCommandsModule(InspIRCd *Me) : Module::Module(Me) { npc = new cmd_npc(ServerInstance); ServerInstance->AddCommand(npc); npca = new cmd_npca(ServerInstance); ServerInstance->AddCommand(npca); ambiance = new cmd_ambiance(ServerInstance); ServerInstance->AddCommand(ambiance); narrator = new cmd_narrator(ServerInstance); ServerInstance->AddCommand(narrator); narratora = new cmd_narratora(ServerInstance); ServerInstance->AddCommand(narratora); } virtual ~RPGCommandsModule() { } virtual Version GetVersion() { return Version(1, 1, 0, 0, VF_COMMON, API_VERSION); } }; MODULE_INIT(RPGCommandsModule) inspircd-4.7.0+ds1/contrib/1.1/m_shun.cpp000066400000000000000000000136651477226773200200100ustar00rootroot00000000000000/* Om - (c) 2006 */ #include #include #include #include #include "inspircd.h" #include "modules.h" #include "hashcomp.h" #include "configreader.h" /* $ModDesc: Gives the /shun command, which stops a user executing all commands except PING and PONG. */ /* $ModAuthor: Om */ /* $ModAuthorMail: om@inspircd.org */ /* $ModDepends: core 1.1 */ /* $ModVersion: $Rev: 80 $ */ class Shun { public: std::string banmask; std::string set_by; time_t set_on; long length; std::string reason; Shun() { } Shun(std::string bm, std::string sb, time_t so, long ln, std::string rs) : banmask(bm), set_by(sb), set_on(so), length(ln), reason(rs) { } bool operator<(const Shun &ban2) const { return ((this->set_on + this->length) < (ban2.set_on + ban2.length)); } }; typedef std::vector shunlist; class ModuleShunBase { public: /* shuns is declared here, as our type is right above. Don't try move it. */ shunlist shuns; InspIRCd* Srv; std::string EncodeShun(const Shun &shun) { std::ostringstream stream; stream << shun.banmask << " " << shun.set_by << " " << shun.set_on << " " << shun.length << " " << shun.reason; return stream.str(); } Shun DecodeShun(const std::string &data) { Shun res; std::istringstream stream(data); stream >> res.banmask; stream >> res.set_by; stream >> res.set_on; stream >> res.length; res.reason = stream.str(); return res; } void ExpireBans() { while(shuns.size() && shuns.begin()->length && ((shuns.begin()->set_on + shuns.begin()->length) <= Srv->Time())) { shunlist::iterator iter = shuns.begin(); Srv->WriteOpers("*** %d second shun on '%s' (%s) set by %s %d seconds ago expired", iter->length, iter->banmask.c_str(), iter->reason.c_str(), iter->set_by.c_str(), Srv->Time() - iter->set_on); shuns.erase(iter); } } }; class cmd_shun : public command_t { private: InspIRCd *Srv; ModuleShunBase* base; public: cmd_shun(InspIRCd* Me, ModuleShunBase* b) : command_t(Me, "SHUN", 'o', 1), Srv(Me), base(b) { this->source = "m_shun.so"; } CmdResult Handle(const char **parameters, int pcnt, userrec *user) { /* syntax: SHUN nick!user@host time :reason goes here */ /* 'time' is a human-readable timestring, like 2d3h2s. */ base->ExpireBans(); if(pcnt == 1) { /* form: SHUN mask removes a SHUN */ for(shunlist::iterator iter = base->shuns.begin(); iter != base->shuns.end(); iter++) { if(parameters[0] == iter->banmask) { Srv->WriteOpers("*** %s removed shun '%s', set %d seconds ago with reason '%s'", user->nick, iter->banmask.c_str(), Srv->Time() - iter->set_on, iter->reason.c_str()); base->shuns.erase(iter); return CMD_SUCCESS; } } user->WriteServ("NOTICE %s :*** The mask %s is not currently shunned, try /stats s", user->nick, parameters[0]); return CMD_FAILURE; } else if (pcnt >= 2) { /* full form to add a shun */ if(Srv->IsValidMask(parameters[0])) { // parameters[0] = Foamy!*@* // parameters[1] = 1h3m2s // parameters[2] = Tortoise abuser for(shunlist::iterator iter = base->shuns.begin(); iter != base->shuns.end(); iter++) { if (parameters[0] == iter->banmask) { user->WriteServ("NOTICE %s :*** Shun on %s already exists", user->nick, parameters[0]); return CMD_FAILURE; } } long length = Srv->Duration(parameters[1]); std::string reason = (pcnt > 2) ? parameters[2] : "No reason supplied"; base->shuns.push_back(Shun(parameters[0], user->nick, Srv->Time(), length, reason)); std::sort(base->shuns.begin(), base->shuns.end()); if(length > 0) Srv->WriteOpers("*** %s added %d second shun on '%s' (%s)", user->nick, length, parameters[0], reason.c_str()); else Srv->WriteOpers("*** %s added permanent shun on '%s' (%s)", user->nick, parameters[0], reason.c_str()); return CMD_SUCCESS; } else { user->WriteServ("NOTICE %s :*** Invalid ban mask", user->nick, parameters[0]); } } return CMD_FAILURE; } }; class ModuleShun : public Module, public ModuleShunBase { cmd_shun* mycommand; public: ModuleShun(InspIRCd* Me) : Module::Module(Me) { this->Srv = Me; mycommand = new cmd_shun(Srv, this); Srv->AddCommand(mycommand); } void Implements(char* List) { List[I_OnPreCommand] = List[I_OnSyncOtherMetaData] = List[I_OnDecodeMetaData] = List[I_OnStats] = 1; } virtual int OnStats(char symbol, userrec* user, string_list& out) { ExpireBans(); if(symbol == 's') { for(shunlist::iterator iter = shuns.begin(); iter != shuns.end(); iter++) { std::ostringstream format; format << Srv->Config->ServerName << " 223 " << user->nick << " :" << iter->banmask << " " << iter->set_on << " " << iter->length << " " << iter->set_by << " " << iter->reason; out.push_back(format.str()); } } return 0; } virtual int OnPreCommand(const std::string &command, const char** parameters, int pcnt, userrec* user, bool validated, const std::string &original_line) { if((command != "PONG") && (command != "PING")) { ExpireBans(); for(shunlist::iterator iter = shuns.begin(); iter != shuns.end(); iter++) if(Srv->MatchText(user->GetFullHost(), iter->banmask) || Srv->MatchText(user->GetFullRealHost(), iter->banmask)) return 1; } return 0; } virtual void OnSyncOtherMetaData(Module* proto, void* opaque, bool displayable) { for(shunlist::iterator iter = shuns.begin(); iter != shuns.end(); iter++) { proto->ProtoSendMetaData(opaque, TYPE_OTHER, NULL, "shun", EncodeShun(*iter)); } } virtual void OnDecodeMetaData(int target_type, void* target, const std::string &extname, const std::string &extdata) { if((target_type == TYPE_OTHER) && (extname == "shun")) { shuns.push_back(DecodeShun(extdata)); std::sort(shuns.begin(), shuns.end()); } } virtual ~ModuleShun() { } virtual Version GetVersion() { return Version(1,0,0,0,0,API_VERSION); } }; MODULE_INIT(ModuleShun) inspircd-4.7.0+ds1/contrib/1.1/m_syncbans.cpp000066400000000000000000000112701477226773200206410ustar00rootroot00000000000000/* Copyright (c) 2007, Special (special at inspircd org) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the author nor the names of contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * This software is provided ``as is'' and any express or implied warranties, * including, but not limited to, the implied warranties of merchantability * and fitness for a particular purpose are disclaimed. In no event shall the * copyright holder be liable for any direct, indirect, incidental, special, * exemplary, or consequential damages (including, but not limited to, * procurement of substitute goods or services; loss of use, data, or profits; * or business interruption) however caused and on any theory of liability, * whether in contract, strict liability, or tort (including negligence or * otherwise) arising in any way out of the use of this software, even if * advised of the possibility of such damage. */ #include "inspircd.h" #include "users.h" #include "channels.h" #include "modules.h" #include "modes/cmode_b.h" /* $ModDesc: Automatically synchronize bans between lists of channels */ /* $ModConfig: */ /* $ModAuthor: Special */ /* $ModAuthorMail: special@inspircd.org */ /* $ModDepends: core 1.1 */ /* $ModVersion: $Rev: 78 $ */ class ModuleSyncBans : public Module { private: std::map ChannelList; bool doingprop; public: ModuleSyncBans(InspIRCd *Me) : Module::Module(Me), doingprop(false) { OnRehash(NULL, ""); } virtual ~ModuleSyncBans() { for (std::map::iterator i = ChannelList.begin(); i != ChannelList.end(); i++) delete i->second; ChannelList.clear(); } virtual Version GetVersion() { return Version(1, 1, 11, 1, VF_COMMON, API_VERSION); } void Implements(char *List) { List[I_OnAddBan] = List[I_OnDelBan] = List[I_OnRehash] = 1; } virtual void OnRehash(userrec *user, const std::string ¶meter) { ConfigReader MyConf(ServerInstance); for (std::map::iterator i = ChannelList.begin(); i != ChannelList.end(); i++) delete i->second; ChannelList.clear(); for (int i = 0; i < MyConf.Enumerate("syncbans"); i++) { std::string *cset = new std::string(MyConf.ReadValue("syncbans", "channels", i)); irc::sepstream sep(*cset, ','); std::string ch; while (sep.GetToken(ch)) { if (ch.empty()) continue; ChannelList.insert(std::make_pair(ch, cset)); } } } void SyncBan(userrec *source, chanrec *channel, const std::string &banmask, bool adding, const std::string &channelset) { std::string banmaskc = banmask; ModeChannelBan *mh = (ModeChannelBan*) ServerInstance->Modes->FindMode('b', MODETYPE_CHANNEL); if (!mh) return; irc::sepstream sep(channelset, ','); std::string sch; doingprop = true; while (sep.GetToken(sch)) { if (sch.empty() || sch == channel->name) continue; chanrec *schannel = ServerInstance->FindChan(sch); if (schannel) { if (adding) mh->AddBan(source, banmaskc, schannel, 0); else mh->DelBan(source, banmaskc, schannel, 0); // Handle server modes properly if (*source->nick) schannel->WriteChannel(source, "MODE %s %cb %s", schannel->name, (adding) ? '+' : '-', banmask.c_str()); else schannel->WriteChannelWithServ(NULL, "MODE %s %cb %s", schannel->name, (adding) ? '+' : '-', banmask.c_str()); } } doingprop = false; } virtual int OnAddBan(userrec *source, chanrec *channel, const std::string &banmask) { if (doingprop) return 0; std::map::iterator it = ChannelList.find(channel->name); if (it == ChannelList.end()) return 0; SyncBan(source, channel, banmask, true, *it->second); return 0; } virtual int OnDelBan(userrec *source, chanrec *channel, const std::string &banmask) { if (doingprop) return 0; std::map::iterator it = ChannelList.find(channel->name); if (it == ChannelList.end()) return 0; SyncBan(source, channel, banmask, false, *it->second); return 0; } }; MODULE_INIT(ModuleSyncBans); inspircd-4.7.0+ds1/contrib/1.1/m_ulinemessages.cpp000066400000000000000000000052061477226773200216670ustar00rootroot00000000000000/* +------------------------------------+ * | Inspire Internet Relay Chat Daemon | * +------------------------------------+ * * InspIRCd: (C) 2002-2008 InspIRCd Development Team * See: http://www.inspircd.org/wiki/index.php/Credits * * This program is free but copyrighted software; see * the file COPYING for details. * * --------------------------------------------------- */ #include "inspircd.h" #include "users.h" #include "channels.h" #include "modules.h" /* $ModDesc: Provides user mode +m, which converts uline notices to privmsg */ /* $ModAuthor: w00t */ /* $ModAuthorMail: w00t@inspircd.org */ /* $ModDepends: core 1.1 */ /* $ModVersion: $Rev: 78 $ */ /** Handles user mode +m */ class UserMessages : public ModeHandler { public: UserMessages(InspIRCd* Instance) : ModeHandler(Instance, 'm', 0, 0, false, MODETYPE_USER, false) { } ModeAction OnModeChange(userrec* source, userrec* dest, chanrec* channel, std::string ¶meter, bool adding) { if (source != dest) return MODEACTION_DENY; if (adding) { if (!dest->IsModeSet('m')) { dest->SetMode('m',true); return MODEACTION_ALLOW; } } else { if (dest->IsModeSet('m')) { dest->SetMode('m',false); return MODEACTION_ALLOW; } } return MODEACTION_DENY; } }; class ModuleFoobar : public Module { private: UserMessages *m; public: ModuleFoobar(InspIRCd* Me) : Module(Me) { m = new UserMessages(ServerInstance); if (!ServerInstance->AddMode(m, 'm')) throw ModuleException("Could not add new modes!"); } virtual ~ModuleFoobar() { ServerInstance->Modes->DelMode(m); delete m; } virtual Version GetVersion() { return Version(1,1,0,1,VF_VENDOR,API_VERSION); } void Implements(char* List) { List[I_OnUserPreNotice] = 1; } virtual int OnUserPreNotice(userrec* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list) { userrec *target; // Since we rewrite the command as PRIVMSG ..we don't want to do this all the time. // Return if sender is not local. if (!IS_LOCAL(user)) { return 0; } if (target_type != TYPE_USER) { return 0; } target = (userrec *)dest; // Check if sender is ULined, return if not if (!ServerInstance->ULine(user->server)) { return 0; } // Check if target is +m, return if not if (!target->IsModeSet('m')) { return 0; } // Rewrite message as a PRIVMSG via command parser, drop event const char *parameters[2]; parameters[0] = target->nick; parameters[1] = text.c_str(); ServerInstance->Parser->CallHandler("PRIVMSG", parameters, 2, user); return 1; } }; MODULE_INIT(ModuleFoobar) inspircd-4.7.0+ds1/contrib/1.1/m_whoismodes.cpp000066400000000000000000000022271477226773200212040ustar00rootroot00000000000000// m_whoismodes.cpp - ViaraiX // Updated for new API - LeaChim // Updated for even newer API - Om // Updated for 1.1-beta5 - AnMaster #include "inspircd.h" #include "modules.h" /* $ModDesc: Allows opers to see users modes on whois */ /* $ModAuthor: Om */ /* $ModAuthorMail: om@inspircd.org */ /* $ModDepends: core 1.1 */ /* $ModVersion: $Rev: 78 $ */ class ModuleWhoismodes : public Module { public: ModuleWhoismodes(InspIRCd* Me) : Module::Module(Me) { } virtual Version GetVersion() { return Version(1,1,0,0,0,API_VERSION); } virtual void Implements(char* List) { List[I_OnWhois] = 1; } virtual void OnWhois(userrec* source, userrec* dest) { if(*source->oper) { if (dest->modes[UM_SNOMASK] != 0) { ServerInstance->SendWhoisLine(source, dest, 379, "%s %s :usermodes [+%s +%s]", source->nick, dest->nick, dest->FormatModes(), dest->FormatNoticeMasks()); } else { ServerInstance->SendWhoisLine(source, dest, 379, "%s %s :usermodes [+%s]", source->nick, dest->nick, dest->FormatModes()); } } } }; MODULE_INIT(ModuleWhoismodes) inspircd-4.7.0+ds1/contrib/1.2/000077500000000000000000000000001477226773200160015ustar00rootroot00000000000000inspircd-4.7.0+ds1/contrib/1.2/m_antirandom.cpp000066400000000000000000000435321477226773200211640ustar00rootroot00000000000000/* +------------------------------------+ * | Inspire Internet Relay Chat Daemon | * +------------------------------------+ * * InspIRCd: (C) 2002-2008 InspIRCd Development Team * See: http://www.inspircd.org/wiki/index.php/Credits * * This program is free but copyrighted software; see * the file COPYING for details. * * (C) Copyright 2008 Robin Burchell * (C) Copyright 2004-2005, Bram Matthys (Syzop) * - Contains ideas from Keith Dunnett * - Most of the detection mechanisms come from SpamAssassin FVGT_Tripwire. * --------------------------------------------------- */ #include "inspircd.h" #include "xline.h" /* $ModDesc: A module to prevent against bots using random patterns. */ /* $ModAuthor: w00t */ /* $ModAuthorMail: w00t@inspircd.org */ /* $ModDepends: core 1.2-1.3 */ /* $ModVersion: $Rev: 79 $ */ #define ANTIRANDOM_ACT_KILL 0 #define ANTIRANDOM_ACT_ZLINE 1 #define ANTIRANDOM_ACT_GLINE 2 static const char *triples_txt[] = { "aj", "fqtvxz", "aq", "deghjkmnprtxyz", "av", "bfhjqwxz", "az", "jwx", "bd", "bghjkmpqvxz", "bf", "bcfgjknpqvwxyz", "bg", "bdfghjkmnqstvxz", "bh", "bfhjkmnqvwxz", "bj", "bcdfghjklmpqtvwxyz", "bk", "dfjkmqrvwxyz", "bl", "bgpqwxz", "bm", "bcdflmnqz", "bn", "bghjlmnpqtvwx", "bp", "bfgjknqvxz", "bq", "bcdefghijklmnopqrstvwxyz", "bt", "dgjkpqtxz", "bv", "bfghjklnpqsuvwxz", "bw", "bdfjknpqsuwxyz", "bx", "abcdfghijklmnopqtuvwxyz", "bz", "bcdfgjklmnpqrstvwxz", "cb", "bfghjkpqyz", "cc", "gjqxz", "cd", "hjkqvwxz", "cf", "gjknqvwyz", "cg", "bdfgjkpqvz", "cl", "fghjmpqxz", "cm", "bjkqv", "cn", "bghjkpqwxz", "cp", "gjkvxyz", "cq", "abcdefghijklmnopqsvwxyz", "cr", "gjqx", "cs", "gjxz", "cv", "bdfghjklmnquvwxyz", "cx", "abdefghjklmnpqrstuvwxyz", "cy", "jqy", "cz", "bcdfghjlpqrtvwxz", "db", "bdgjnpqtxz", "dc", "gjqxz", "dd", "gqz", "df", "bghjknpqvxyz", "dg", "bfgjqvxz", "dh", "bfkmnqwxz", "dj", "bdfghjklnpqrwxz", "dk", "cdhjkpqrtuvwxz", "dl", "bfhjknqwxz", "dm", "bfjnqw", "dn", "fgjkmnpqvwz", "dp", "bgjkqvxz", "dq", "abcefghijkmnopqtvwxyz", "dr", "bfkqtvx", "dt", "qtxz", "dv", "bfghjknqruvwyz", "dw", "cdfjkmnpqsvwxz", "dx", "abcdeghjklmnopqrsuvwxyz", "dy", "jyz", "dz", "bcdfgjlnpqrstvxz", "eb", "jqx", "eg", "cjvxz", "eh", "hxz", "ej", "fghjpqtwxyz", "ek", "jqxz", "ep", "jvx", "eq", "bcghijkmotvxyz", "ev", "bfpq", "fc", "bdjkmnqvxz", "fd", "bgjklqsvyz", "fg", "fgjkmpqtvwxyz", "fh", "bcfghjkpqvwxz", "fj", "bcdfghijklmnpqrstvwxyz", "fk", "bcdfghjkmpqrstvwxz", "fl", "fjkpqxz", "fm", "dfhjlmvwxyz", "fn", "bdfghjklnqrstvwxz", "fp", "bfjknqtvwxz", "fq", "abcefghijklmnopqrstvwxyz", "fr", "nqxz", "fs", "gjxz", "ft", "jqx", "fv", "bcdfhjklmnpqtuvwxyz", "fw", "bcfgjklmpqstuvwxyz", "fx", "bcdfghjklmnpqrstvwxyz", "fy", "ghjpquvxy", "fz", "abcdfghjklmnpqrtuvwxyz", "gb", "bcdknpqvwx", "gc", "gjknpqwxz", "gd", "cdfghjklmqtvwxz", "gf", "bfghjkmnpqsvwxyz", "gg", "jkqvxz", "gj", "bcdfghjklmnpqrstvwxyz", "gk", "bcdfgjkmpqtvwxyz", "gl", "fgjklnpqwxz", "gm", "dfjkmnqvxz", "gn", "jkqvxz", "gp", "bjknpqtwxyz", "gq", "abcdefghjklmnopqrsvwxyz", "gr", "jkqt", "gt", "fjknqvx", "gu", "qwx", "gv", "bcdfghjklmpqstvwxyz", "gw", "bcdfgjknpqtvwxz", "gx", "abcdefghjklmnopqrstvwxyz", "gy", "jkqxy", "gz", "bcdfgjklmnopqrstvxyz", "hb", "bcdfghjkqstvwxz", "hc", "cjknqvwxz", "hd", "fgjnpvz", "hf", "bfghjkmnpqtvwxyz", "hg", "bcdfgjknpqsxyz", "hh", "bcgklmpqrtvwxz", "hj", "bcdfgjkmpqtvwxyz", "hk", "bcdgkmpqrstvwxz", "hl", "jxz", "hm", "dhjqrvwxz", "hn", "jrxz", "hp", "bjkmqvwxyz", "hq", "abcdefghijklmnopqrstvwyz", "hr", "cjqx", "hs", "jqxz", "hv", "bcdfgjklmnpqstuvwxz", "hw", "bcfgjklnpqsvwxz", "hx", "abcdefghijklmnopqrstuvwxyz", "hz", "bcdfghjklmnpqrstuvwxz", "ib", "jqx", "if", "jqvwz", "ih", "bgjqx", "ii", "bjqxy", "ij", "cfgqxy", "ik", "bcfqx", "iq", "cdefgjkmnopqtvxyz", "iu", "hiwxy", "iv", "cfgmqx", "iw", "dgjkmnpqtvxz", "ix", "jkqrxz", "iy", "bcdfghjklpqtvwx", "jb", "bcdghjklmnopqrtuvwxyz", "jc", "cfgjkmnopqvwxy", "jd", "cdfghjlmnpqrtvwx", "jf", "abcdfghjlnopqrtuvwxyz", "jg", "bcdfghijklmnopqstuvwxyz", "jh", "bcdfghjklmnpqrxyz", "jj", "bcdfghjklmnopqrstuvwxyz", "jk", "bcdfghjknqrtwxyz", "jl", "bcfghjmnpqrstuvwxyz", "jm", "bcdfghiklmnqrtuvwyz", "jn", "bcfjlmnpqsuvwxz", "jp", "bcdfhijkmpqstvwxyz", "jq", "abcdefghijklmnopqrstuvwxyz", "jr", "bdfhjklpqrstuvwxyz", "js", "bfgjmoqvxyz", "jt", "bcdfghjlnpqrtvwxz", "jv", "abcdfghijklpqrstvwxyz", "jw", "bcdefghijklmpqrstuwxyz", "jx", "abcdefghijklmnopqrstuvwxyz", "jy", "bcdefghjkpqtuvwxyz", "jz", "bcdfghijklmnopqrstuvwxyz", "kb", "bcdfghjkmqvwxz", "kc", "cdfgjknpqtwxz", "kd", "bfghjklmnpqsvwxyz", "kf", "bdfghjkmnpqsvwxyz", "kg", "cghjkmnqtvwxyz", "kh", "cfghjkqx", "kj", "bcdfghjkmnpqrstwxyz", "kk", "bcdfgjmpqswxz", "kl", "cfghlmqstwxz", "km", "bdfghjknqrstwxyz", "kn", "bcdfhjklmnqsvwxz", "kp", "bdfgjkmpqvxyz", "kq", "abdefghijklmnopqrstvwxyz", "kr", "bcdfghjmqrvwx", "ks", "jqx", "kt", "cdfjklqvx", "ku", "qux", "kv", "bcfghjklnpqrstvxyz", "kw", "bcdfgjklmnpqsvwxz", "kx", "abcdefghjklmnopqrstuvwxyz", "ky", "vxy", "kz", "bcdefghjklmnpqrstuvwxyz", "lb", "cdgkqtvxz", "lc", "bqx", "lg", "cdfgpqvxz", "lh", "cfghkmnpqrtvx", "lk", "qxz", "ln", "cfjqxz", "lp", "jkqxz", "lq", "bcdefhijklmopqrstvwxyz", "lr", "dfgjklmpqrtvwx", "lv", "bcfhjklmpwxz", "lw", "bcdfgjknqxz", "lx", "bcdfghjklmnpqrtuwz", "lz", "cdjptvxz", "mb", "qxz", "md", "hjkpvz", "mf", "fkpqvwxz", "mg", "cfgjnpqsvwxz", "mh", "bchjkmnqvx", "mj", "bcdfghjknpqrstvwxyz", "mk", "bcfgklmnpqrvwxz", "ml", "jkqz", "mm", "qvz", "mn", "fhjkqxz", "mq", "bdefhjklmnopqtwxyz", "mr", "jklqvwz", "mt", "jkq", "mv", "bcfghjklmnqtvwxz", "mw", "bcdfgjklnpqsuvwxyz", "mx", "abcefghijklmnopqrstvwxyz", "mz", "bcdfghjkmnpqrstvwxz", "nb", "hkmnqxz", "nf", "bghqvxz", "nh", "fhjkmqtvxz", "nk", "qxz", "nl", "bghjknqvwxz", "nm", "dfghjkqtvwxz", "np", "bdjmqwxz", "nq", "abcdfghjklmnopqrtvwxyz", "nr", "bfjkqstvx", "nv", "bcdfgjkmnqswxz", "nw", "dgjpqvxz", "nx", "abfghjknopuyz", "nz", "cfqrxz", "oc", "fjvw", "og", "qxz", "oh", "fqxz", "oj", "bfhjmqrswxyz", "ok", "qxz", "oq", "bcdefghijklmnopqrstvwxyz", "ov", "bfhjqwx", "oy", "qxy", "oz", "fjpqtvx", "pb", "fghjknpqvwz", "pc", "gjq", "pd", "bgjkvwxz", "pf", "hjkmqtvwyz", "pg", "bdfghjkmqsvwxyz", "ph", "kqvx", "pk", "bcdfhjklmpqrvx", "pl", "ghkqvwx", "pm", "bfhjlmnqvwyz", "pn", "fjklmnqrtvwz", "pp", "gqwxz", "pq", "abcdefghijklmnopqstvwxyz", "pr", "hjkqrwx", "pt", "jqxz", "pv", "bdfghjklquvwxyz", "pw", "fjkmnpqsuvwxz", "px", "abcdefghijklmnopqrstuvwxyz", "pz", "bdefghjklmnpqrstuvwxyz", "qa", "ceghkopqxy", "qb", "bcdfghjklmnqrstuvwxyz", "qc", "abcdfghijklmnopqrstuvwxyz", "qd", "defghijklmpqrstuvwxyz", "qe", "abceghjkmopquwxyz", "qf", "abdfghijklmnopqrstuvwxyz", "qg", "abcdefghijklmnopqrtuvwxz", "qh", "abcdefghijklmnopqrstuvwxyz", "qi", "efgijkmpwx", "qj", "abcdefghijklmnopqrstuvwxyz", "qk", "abcdfghijklmnopqrsuvwxyz", "ql", "abcefghjklmnopqrtuvwxyz", "qm", "bdehijklmnoqrtuvxyz", "qn", "bcdefghijklmnoqrtuvwxyz", "qo", "abcdefgijkloqstuvwxyz", "qp", "abcdefghijkmnopqrsuvwxyz", "qq", "bcdefghijklmnopstwxyz", "qr", "bdefghijklmnoqruvwxyz", "qs", "bcdefgijknqruvwxz", "qt", "befghjklmnpqtuvwxz", "qu", "cfgjkpwz", "qv", "abdefghjklmnopqrtuvwxyz", "qw", "bcdfghijkmnopqrstuvwxyz", "qx", "abcdefghijklmnopqrstuvwxyz", "qy", "abcdefghjklmnopqrstuvwxyz", "qz", "abcdefghijklmnopqrstuvwxyz", "rb", "fxz", "rg", "jvxz", "rh", "hjkqrxz", "rj", "bdfghjklmpqrstvwxz", "rk", "qxz", "rl", "jnq", "rp", "jxz", "rq", "bcdefghijklmnopqrtvwxy", "rr", "jpqxz", "rv", "bcdfghjmpqrvwxz", "rw", "bfgjklqsvxz", "rx", "bcdfgjkmnopqrtuvwxz", "rz", "djpqvxz", "sb", "kpqtvxz", "sd", "jqxz", "sf", "bghjkpqw", "sg", "cgjkqvwxz", "sj", "bfghjkmnpqrstvwxz", "sk", "qxz", "sl", "gjkqwxz", "sm", "fkqwxz", "sn", "dhjknqvwxz", "sq", "bfghjkmopstvwxz", "sr", "jklqrwxz", "sv", "bfhjklmnqtwxyz", "sw", "jkpqvwxz", "sx", "bcdefghjklmnopqrtuvwxyz", "sy", "qxy", "sz", "bdfgjpqsvxz", "tb", "cghjkmnpqtvwx", "tc", "jnqvx", "td", "bfgjkpqtvxz", "tf", "ghjkqvwyz", "tg", "bdfghjkmpqsx", "tj", "bdfhjklmnpqstvwxyz", "tk", "bcdfghjklmpqvwxz", "tl", "jkqwxz", "tm", "bknqtwxz", "tn", "fhjkmqvwxz", "tp", "bjpqvwxz", "tq", "abdefhijklmnopqrstvwxyz", "tr", "gjqvx", "tv", "bcfghjknpquvwxz", "tw", "bcdfjknqvz", "tx", "bcdefghjklmnopqrsuvwxz", "tz", "jqxz", "uc", "fjmvx", "uf", "jpqvx", "ug", "qvx", "uh", "bcgjkpvxz", "uj", "wbfghklmqvwx", "uk", "fgqxz", "uq", "bcdfghijklmnopqrtwxyz", "uu", "fijkqvwyz", "uv", "bcdfghjkmpqtwxz", "uw", "dgjnquvxyz", "ux", "jqxz", "uy", "jqxyz", "uz", "fgkpqrx", "vb", "bcdfhijklmpqrtuvxyz", "vc", "bgjklnpqtvwxyz", "vd", "bdghjklnqvwxyz", "vf", "bfghijklmnpqtuvxz", "vg", "bcdgjkmnpqtuvwxyz", "vh", "bcghijklmnpqrtuvwxyz", "vj", "abcdfghijklmnpqrstuvwxyz", "vk", "bcdefgjklmnpqruvwxyz", "vl", "hjkmpqrvwxz", "vm", "bfghjknpquvxyz", "vn", "bdhjkmnpqrtuvwxz", "vp", "bcdeghjkmopqtuvwyz", "vq", "abcdefghijklmnopqrstvwxyz", "vr", "fghjknqrtvwxz", "vs", "dfgjmqz", "vt", "bdfgjklmnqtx", "vu", "afhjquwxy", "vv", "cdfghjkmnpqrtuwxz", "vw", "abcdefghijklmnopqrtuvwxyz", "vx", "abcefghjklmnopqrstuvxyz", "vy", "oqx", "vz", "abcdefgjklmpqrstvwxyz", "wb", "bdfghjpqtvxz", "wc", "bdfgjkmnqvwx", "wd", "dfjpqvxz", "wf", "cdghjkmqvwxyz", "wg", "bcdfgjknpqtvwxyz", "wh", "cdghjklpqvwxz", "wj", "bfghijklmnpqrstvwxyz", "wk", "cdfgjkpqtuvxz", "wl", "jqvxz", "wm", "dghjlnqtvwxz", "wp", "dfgjkpqtvwxz", "wq", "abcdefghijklmnopqrstvwxyz", "wr", "cfghjlmpqwx", "wt", "bdgjlmnpqtvx", "wu", "aikoquvwy", "wv", "bcdfghjklmnpqrtuvwxyz", "ww", "bcdgkpqstuvxyz", "wx", "abcdefghijklmnopqrstuvwxz", "wy", "jquwxy", "wz", "bcdfghjkmnopqrstuvwxz", "xa", "ajoqy", "xb", "bcdfghjkmnpqsvwxz", "xc", "bcdgjkmnqsvwxz", "xd", "bcdfghjklnpqstuvwxyz", "xf", "bcdfghjkmnpqtvwxyz", "xg", "bcdfghjkmnpqstvwxyz", "xh", "cdfghjkmnpqrstvwxz", "xi", "jkqy", "xj", "abcdefghijklmnopqrstvwxyz", "xk", "abcdfghjkmnopqrstuvwxyz", "xl", "bcdfghjklmnpqrvwxz", "xm", "bcdfghjknpqvwxz", "xn", "bcdfghjklmnpqrvwxyz", "xp", "bcfjknpqvxz", "xq", "abcdefghijklmnopqrstvwxyz", "xr", "bcdfghjklnpqrsvwyz", "xs", "bdfgjmnqrsvxz", "xt", "jkpqvwxz", "xu", "fhjkquwx", "xv", "bcdefghjklmnpqrsuvwxyz", "xw", "bcdfghjklmnpqrtuvwxyz", "xx", "bcdefghjkmnpqrstuwyz", "xy", "jxy", "xz", "abcdefghjklmnpqrstuvwxyz", "yb", "cfghjmpqtvwxz", "yc", "bdfgjmpqsvwx", "yd", "chjkpqvwx", "yf", "bcdghjmnpqsvwx", "yg", "cfjkpqtxz", "yh", "bcdfghjkpqx", "yi", "hjqwxy", "yj", "bcdfghjklmnpqrstvwxyz", "yk", "bcdfgpqvwxz", "ym", "dfgjqvxz", "yp", "bcdfgjkmqxz", "yq", "abcdefghijklmnopqrstvwxyz", "yr", "jqx", "yt", "bcfgjnpqx", "yv", "bcdfghjlmnpqstvwxz", "yw", "bfgjklmnpqstuvwxz", "yx", "bcdfghjknpqrstuvwxz", "yy", "bcdfghjklpqrstvwxz", "yz", "bcdfjklmnpqtvwx", "zb", "dfgjklmnpqstvwxz", "zc", "bcdfgjmnpqstvwxy", "zd", "bcdfghjklmnpqstvwxy", "zf", "bcdfghijkmnopqrstvwxyz", "zg", "bcdfgjkmnpqtvwxyz", "zh", "bcfghjlpqstvwxz", "zj", "abcdfghjklmnpqrstuvwxyz", "zk", "bcdfghjklmpqstvwxz", "zl", "bcdfghjlnpqrstvwxz", "zm", "bdfghjklmpqstvwxyz", "zn", "bcdfghjlmnpqrstuvwxz", "zp", "bcdfhjklmnpqstvwxz", "zq", "abcdefghijklmnopqrstvwxyz", "zr", "bcfghjklmnpqrstvwxyz", "zs", "bdfgjmnqrsuwxyz", "zt", "bcdfgjkmnpqtuvwxz", "zu", "ajqx", "zv", "bcdfghjklmnpqrstuvwxyz", "zw", "bcdfghjklmnpqrstuvwxyz", "zx", "abcdefghijklmnopqrstuvwxyz", "zy", "fxy", "zz", "cdfhjnpqrvx", NULL, NULL }; class ModuleAntiRandom : public Module { private: bool ShowFailedConnects; bool DebugMode; unsigned int Threshold; unsigned int BanAction; unsigned int BanDuration; std::string BanReason; public: ModuleAntiRandom(InspIRCd* Me) : Module(Me) { Implementation eventlist[] = { I_OnRehash, I_OnUserConnect }; ServerInstance->Modules->Attach(eventlist, this, 2); OnRehash(NULL); } virtual ~ModuleAntiRandom() { } virtual Version GetVersion() { return Version("$Id$", VF_VENDOR,API_VERSION); } unsigned int GetStringScore(const char *original_str) { const char **ci; const char *s; unsigned int score = 0; unsigned int highest_vowels = 0; unsigned int highest_consonants = 0; unsigned int highest_digits = 0; unsigned int vowels = 0; unsigned int consonants = 0; unsigned int digits = 0; /* Fast digit/consonant/vowel checks... */ for (s = original_str; *s; s++) { if ((*s >= '0') && (*s <= '9')) { digits++; } else { if (digits > highest_digits) highest_digits = digits; digits = 0; } /* Check consonants */ switch (*s) { case 'b': case 'c': case 'd': case 'f': case 'g': case 'h': case 'j': case 'k': case 'l': case 'm': case 'n': case 'p': case 'q': case 'r': case 's': case 't': case 'v': case 'w': case 'x': case 'z': consonants++; break; default: if (consonants > highest_consonants) highest_consonants = consonants; consonants = 0; break; } /* Check vowels */ switch (*s) { case 'a': case 'e': case 'i': case 'o': case 'u': vowels++; break; default: if (vowels > highest_vowels) highest_vowels = vowels; vowels = 0; break; } } /* Now set up for our checks. */ if (highest_digits > digits) digits = highest_digits; if (highest_consonants > consonants) consonants = highest_consonants; if (highest_vowels > vowels) vowels = highest_vowels; if (digits >= 5) { score += 5 + (digits - 5); ServerInstance->SNO->WriteToSnoMask('O', "antirandom: %s:MATCH digits", original_str); } if (vowels >= 4) { score += 4 + (vowels - 4); if (this->DebugMode) ServerInstance->SNO->WriteToSnoMask('O', "antirandom: %s:MATCH vowels", original_str); } if (consonants >= 4) { score += 4 + (consonants - 4); if (this->DebugMode) ServerInstance->SNO->WriteToSnoMask('O', "antirandom: %s:MATCH consonants", original_str); } /* * Now, do the triples checks. For each char in the string we're checking ... * XXX - on reading this, I wonder why we can't strcmp()/strchr() it.. */ for (s = original_str; *s; s++) { /* * ..run it through each triple. */ for (ci = triples_txt; *ci; *ci++) { // At this point, ci[0] and ci[1] point to the first two chars in the triples array. if (*ci[0] == s[0] && *ci[1] == s[1] && s[2]) { // First half of triple matches. Try match the other half. *ci++; if (strchr(*ci, s[2])) { // Triple matches! score++; if (this->DebugMode) ServerInstance->SNO->WriteToSnoMask('O', "antirandom: %s:MATCH triple (%s:%c/%c/%c)", original_str, *ci, s[0], s[1], s[2]); } } else { // No match. Just blindly increment half a triple. *ci++; } } } return score; } unsigned int GetUserScore(User *user) { int nscore, uscore, gscore, score; struct timeval tv_alpha, tv_beta; gettimeofday(&tv_alpha, NULL); nscore = GetStringScore(user->nick.c_str()); uscore = GetStringScore(user->ident.c_str()); gscore = GetStringScore(user->fullname.c_str()); score = nscore + uscore + gscore; gettimeofday(&tv_beta, NULL); if (this->DebugMode) ServerInstance->SNO->WriteToSnoMask('O', "AntiRandom Timing: %ld microseconds", ((tv_beta.tv_sec - tv_alpha.tv_sec) * 1000000) + (tv_beta.tv_usec - tv_alpha.tv_usec)); if (this->DebugMode) ServerInstance->SNO->WriteToSnoMask('O', "Got score: %d/%d/%d = %d", nscore, uscore, gscore, score); return score; } virtual void OnUserConnect(User* user) { unsigned int score = GetUserScore(user); if (score > this->Threshold) { if (this->ShowFailedConnects) { ServerInstance->SNO->WriteToSnoMask('O', "Connection from %s was killed by AntiRandom with a score of %d - exceeds set threshold of %d", user->GetIPString(), score, this->Threshold); } switch (this->BanAction) { case ANTIRANDOM_ACT_KILL: { ServerInstance->Users->QuitUser(user, this->BanReason); break; } case ANTIRANDOM_ACT_ZLINE: { ZLine* zl = new ZLine(ServerInstance, ServerInstance->Time(), this->BanDuration, ServerInstance->Config->ServerName, this->BanReason.c_str(), user->GetIPString()); if (ServerInstance->XLines->AddLine(zl,user)) ServerInstance->XLines->ApplyLines(); else delete zl; break; } case ANTIRANDOM_ACT_GLINE: { GLine* gl = new GLine(ServerInstance, ServerInstance->Time(), this->BanDuration, ServerInstance->Config->ServerName, this->BanReason.c_str(), "*", user->GetIPString()); if (ServerInstance->XLines->AddLine(gl,user)) ServerInstance->XLines->ApplyLines(); else delete gl; break; } } } } virtual void OnRehash(User* user) { ConfigReader Conf(ServerInstance); std::string tmp; this->ShowFailedConnects = Conf.ReadFlag("antirandom", "failedconnects", 0); this->DebugMode = Conf.ReadFlag("antirandom", "debugmode", 0); tmp = Conf.ReadValue("antirandom", "threshold", 0); if (!tmp.empty()) this->Threshold = atoi(tmp.c_str()); else this->Threshold = 10; // fairly safe this->BanAction = ANTIRANDOM_ACT_KILL; tmp = Conf.ReadValue("antirandom", "banaction", 0); if (tmp == "GLINE") { this->BanAction = ANTIRANDOM_ACT_GLINE; } if (tmp == "ZLINE") { this->BanAction = ANTIRANDOM_ACT_ZLINE; } else if (tmp == "KILL") { this->BanAction = ANTIRANDOM_ACT_KILL; } tmp = Conf.ReadValue("antirandom", "banduration", 0); if (!tmp.empty()) this->BanDuration = ServerInstance->Duration(tmp.c_str()); else this->BanDuration = 86400; // One day. tmp = Conf.ReadValue("antirandom", "banreason", 0); if (!tmp.empty()) this->BanReason = tmp; else this->BanReason = "You look like a bot. Change your nick/ident/gecos and try reconnecting."; } }; MODULE_INIT(ModuleAntiRandom) inspircd-4.7.0+ds1/contrib/1.2/m_bandetails.cpp000066400000000000000000000030231477226773200211250ustar00rootroot00000000000000#include "inspircd.h" /* $ModDesc: Synchronises setter and time set of channel bans, so details are not lost. */ /* $ModAuthor: Aleksey */ /* $ModAuthorMail: w00t@inspircd.org */ /* $ModDepends: core 1.2-1.3 */ class ModuleBanDetails : public Module { public: virtual void OnSyncChannel (Channel *chan, Module *proto, void *opaque) { for (BanList::iterator i = chan->bans.begin(); i != chan->bans.end(); i++) { std::string meta(i->data); meta.append(" ").append(i->set_by).append(" ").append(ConvToStr(i->set_time)); proto->ProtoSendMetaData(opaque, TYPE_CHANNEL, chan, "m_bandetails", meta); } } virtual void OnDecodeMetaData (int target_type, void *target, const std::string &extname, const std::string &extdata) { if ((target_type == TYPE_CHANNEL) && (extname == "m_bandetails")) { Channel* chan = (Channel*)target; std::string banmask,sb,st; irc::spacesepstream list(extdata); list.GetToken(banmask); list.GetToken(sb); list.GetToken(st); for (BanList::iterator i = chan->bans.begin(); i != chan->bans.end(); i++) { if (!strcasecmp(i->data.c_str(), banmask.c_str())) { i->set_time=ConvToInt(st); i->set_by=sb; break; } } } } ModuleBanDetails(InspIRCd* Me) : Module(Me) { Implementation eventlist[] = { I_OnSyncChannel,I_OnDecodeMetaData}; ServerInstance->Modules->Attach(eventlist, this, 2); } virtual Version GetVersion() { return Version("$Id$",VF_COMMON,API_VERSION); } }; MODULE_INIT(ModuleBanDetails) inspircd-4.7.0+ds1/contrib/1.2/m_chanmode.cpp000066400000000000000000000043641477226773200206060ustar00rootroot00000000000000/* ** * m_chanmode.cpp * * Module adds snomasks v and V allows opers to view any and ALL mode changes * that are done by users to channels on the network. * * Changes: * -------------------------- * 1.1: - Fixed UUID display * - Made the output look all purdy with some nice formatting * * author: j. newing (synmuffin) * email: jnewing@gmail.com * * homeless :( I'm currently looking for a network that where I can get back into developing InspIRCd modules and working on * my Orion Services web front end. * */ #include "inspircd.h" /* $ModDesc: Module adds snomasks v and V allows opers to view any and ALL mode changes that are done by users to channels on the network. */ /* $ModDepends: core 1.2-1.3 */ class ModuleChanMode : public Module { public: ModuleChanMode(InspIRCd* Me) : Module(Me) { ServerInstance->SNO->EnableSnomask('v', "CHANMODE"); ServerInstance->SNO->EnableSnomask('V', "REMOTECHANMODE"); Implementation eventlist[] = { I_OnMode }; ServerInstance->Modules->Attach(eventlist, this, 1); } virtual ~ModuleChanMode() { ServerInstance->SNO->DisableSnomask('v'); ServerInstance->SNO->DisableSnomask('V'); } virtual Version GetVersion() { return Version("m_chanmode ver 1.1 - synmuffin", 0, API_VERSION); } virtual void OnMode(User* user, void* dest, int target_type, const std::deque &text, const std::deque &translate) { // Mode changes std::string output_text; // Make the text look nice, I'm 100% sure there is a better way to do this however I don't know it yet :/ std::deque::const_iterator i; for (i = text.begin(); i != text.end(); i++) { if (*i == text.back()) output_text.append(*i); else if (*i == text.front()) output_text.append(*i + " "); else output_text.append(*i + ", "); } if (target_type == TYPE_CHANNEL) { Channel* c = (Channel*)dest; if (IS_LOCAL(user)) { ServerInstance->SNO->WriteToSnoMask('v', "%s sets mode: %s on channel: %s", user->nick.c_str(), output_text.c_str(), c->name.c_str()); } else { ServerInstance->SNO->WriteToSnoMask('V', "%s sets mode: %s on channel: %s", user->nick.c_str(), output_text.c_str(), c->name.c_str()); } } } }; MODULE_INIT(ModuleChanMode) inspircd-4.7.0+ds1/contrib/1.2/m_channelnames.cpp000066400000000000000000000023221477226773200214540ustar00rootroot00000000000000/* +------------------------------------+ * | Inspire Internet Relay Chat Daemon | * +------------------------------------+ * * InspIRCd: (C) 2002-2009 InspIRCd Development Team * See: http://wiki.inspircd.org/Credits * * This program is free but copyrighted software; see * the file COPYING for details. * * --------------------------------------------------- */ #include "inspircd.h" /* $ModDesc: Implements a filter for channel names */ /* $ModAuthor: danieldg */ /* $ModDepends: core 1.2-1.3 */ class ModuleChannelNames: public Module { private: public: ModuleChannelNames(InspIRCd* Me) : Module(Me) { ServerInstance->Modules->Attach(I_OnUserPreJoin, this); } virtual Version GetVersion() { return Version("$Id$", VF_COMMON, API_VERSION); } int OnUserPreJoin(User* user, Channel* chan, const char* name, std::string& privs, const std::string& key) { if (chan) return 0; const char* walk = name; while (*walk) { char c = *walk++; if (c <= 0x20 || c >= 0x7F) { user->WriteNumeric(ERR_NOSUCHCHANNEL, "%s %s :Cannot join channel (invalid name)", user->nick.c_str(), name); return 1; } } return 0; } }; MODULE_INIT(ModuleChannelNames) inspircd-4.7.0+ds1/contrib/1.2/m_codepage.cpp000066400000000000000000000611371477226773200206000ustar00rootroot00000000000000/* +------------------------------------+ * | Inspire Internet Relay Chat Daemon | * +------------------------------------+ * * InspIRCd: (C) 2002-2008 InspIRCd Development Team * See: http://www.inspircd.org/wiki/index.php/Credits * * This program is free but copyrighted software; see * the file COPYING for details. * * --------------------------------------------------- */ /* by Chernov-Phoenix Alexey (Phoenix@RusNet) mailto:phoenix /email address separator/ pravmail.ru */ /* $ModDesc: Recodes messages from one encoding to another based on port bindings. */ /* $ModAuthor: Alexey */ /* $ModAuthorMail: Phoenix@RusNet */ /* $ModDepends: core 1.2-1.3 */ /* $ModVersion: $Rev: 78 $ */ #include "inspircd.h" #include #include "modules.h" /* a record containing incoming and outgoing convertion descriptors and encoding name */ struct io_iconv { iconv_t in,out; std::string encoding; char * intable; char * outtable; }; /* a read buffer for incomplete multibyte characters. As they are just characters and they are incomplete, it's 3 bytes long :) */ struct io_buffer { char buffer[3]; char count; }; typedef nspace::hash_map hash_common; /* port/file descriptor -> encoding index */ typedef nspace::hash_map hash_str; /* encoding name -> encoding index */ typedef nspace::hash_map hash_io; /* file descriptor -> old io handler */ typedef nspace::hash_map hash_save; /* file descriptor -> encoding name */ typedef nspace::hash_map hash_buffer; /* file descriptor -> read multibyte buffer */ const char * modulenames[]={"m_ssl_gnutls.so","m_ssl_openssl.so","m_xmlsocket.so"}; static Implementation eventlist[] = { I_OnRehash, I_OnCleanup, I_OnHookUserIO, I_OnUnloadModule, I_OnRawSocketRead, I_OnRawSocketWrite, I_OnRawSocketAccept, I_OnRawSocketClose, I_OnRawSocketConnect }; static hash_common fd_hash, port_hash; static hash_str name_hash; static hash_io io_hash; static hash_save save_hash; static hash_buffer buffer_hash; static std::vector recode; /* the main encoding storage */ char toUpper_ (char c) { return std::toupper(c); } void ToUpper(std::string& s) {std::transform(s.begin(), s.end(), s.begin(),toUpper_);} class CommandCodepage : public Command { public: CommandCodepage (InspIRCd* Instance) : Command(Instance, "CODEPAGE", 0, 1) { this->source = "m_codepage.so"; syntax = "{ | SHOW | NEXT }"; TRANSLATE3(TR_NICK, TR_TEXT, TR_END); } CmdResult Handle (const std::vector& parameters, User *user) { std::string codepage=parameters[0]; ToUpper(codepage); hash_str::iterator iter; if (codepage=="SHOW") /* A horrible expression! to find the name of users's current codepage! Although that works. */ { codepage=recode[fd_hash[user->GetFd()]].encoding; user->WriteNumeric(700, "%s :Your codepage is: %s",user->nick.c_str(),codepage.c_str()); return CMD_LOCALONLY; } if (codepage=="NEXT") { int index=fd_hash[user->GetFd()]+1; if ((unsigned int)index>=recode.size()) index=0; codepage=recode[index].encoding; } iter=name_hash.find(codepage); if (iter!=name_hash.end()) { if (fd_hash[user->GetFd()]!=iter->second) { fd_hash[user->GetFd()]=iter->second; user->WriteNumeric(700, "%s :Your codepage is: %s",user->nick.c_str(),codepage.c_str()); return CMD_LOCALONLY; } else { user->WriteNumeric(752, "%s :Codepage is already: %s",user->nick.c_str(),codepage.c_str()); } } else { user->WriteNumeric(750, "%s :Wrong or unsupported codepage: %s",user->nick.c_str(),codepage.c_str()); } return CMD_FAILURE; } }; /* took it from SAQUIT :) */ class CommandSacodepage : public Command { public: CommandSacodepage (InspIRCd* Instance) : Command(Instance, "SACODEPAGE", "o", 2, false, 0) { this->source = "m_codepage.so"; syntax = " { | NEXT }"; TRANSLATE3(TR_NICK, TR_TEXT, TR_END); } CmdResult Handle (const std::vector& parameters, User *user) { User* dest = ServerInstance->FindNick(parameters[0]); if (dest) { if (ServerInstance->ULine(dest->server)) { user->WriteNumeric(990, "%s :Cannot use an SA command on a u-lined client",user->nick.c_str()); return CMD_FAILURE; } std::string codepage=parameters[1]; ToUpper(codepage); ServerInstance->SNO->WriteToSnoMask('A', std::string(user->nick)+" used SACODEPAGE to force "+std::string(dest->nick)+" have a codepage of "+codepage); /* Pass the command on, so the client's server can handle it properly.*/ if (!IS_LOCAL(dest)) return CMD_SUCCESS; /* SACODEPAGE will be a bit different */ hash_str::iterator iter; if (codepage=="SHOW") { codepage=recode[fd_hash[dest->GetFd()]].encoding; dest->WriteNumeric(700, "%s :Your codepage is: %s",dest->nick.c_str(),codepage.c_str()); return CMD_LOCALONLY; } if (codepage=="NEXT") { int index=fd_hash[dest->GetFd()]+1; if ((unsigned int)index>=recode.size()) index=0; codepage=recode[index].encoding; } iter=name_hash.find(codepage); if (iter!=name_hash.end()) { if (fd_hash[dest->GetFd()]!=iter->second) { fd_hash[dest->GetFd()]=iter->second; dest->WriteNumeric(700, "%s :Your codepage is: %s",dest->nick.c_str(),codepage.c_str()); return CMD_LOCALONLY; } else { user->WriteNumeric(752, "%s :Codepage is already: %s",user->nick.c_str(),codepage.c_str()); } } else { user->WriteNumeric(750, "%s :Wrong or unsupported codepage: %s",user->nick.c_str(),codepage.c_str()); } return CMD_FAILURE; /* -- end of CODEPAGE cut */ } else { user->WriteServ("NOTICE %s :*** Invalid nickname '%s'", user->nick.c_str(), parameters[0].c_str()); } return CMD_FAILURE; } }; class CommandCodepages : public Command { public: CommandCodepages (InspIRCd* Instance) : Command(Instance, "CODEPAGES", 0, 0, false, 0) { this->source = "m_codepage.so"; syntax = "[server]"; TRANSLATE3(TR_NICK, TR_TEXT, TR_END); } CmdResult Handle (const std::vector& parameters, User *user) { std::string servname; if (parameters.size()<1) { servname=std::string(ServerInstance->Config->ServerName); } else { servname=parameters[0]; } if (ServerInstance->FindServerName(servname)) { /* Pass the command on, so the client's server can handle it properly. */ if (servname!=ServerInstance->Config->ServerName) return CMD_SUCCESS; for (unsigned int i=0; iWriteNumeric(701, "%s : Codepage available: %s",user->nick.c_str(),recode[i].encoding.c_str()); user->WriteNumeric(702, "%s :*** End of CODEPAGES",user->nick.c_str()); return CMD_LOCALONLY; } else { user->WriteServ("NOTICE %s :*** Invalid server name '%s'", user->nick.c_str(), parameters[0].c_str()); } return CMD_FAILURE; } }; class ModuleCodepage : public Module { private: InspIRCd* ServerInstance; CommandCodepage* mycommand; CommandSacodepage* mycommand2; CommandCodepages* mycommand3; std::string icodepage, dcodepage; public: ModuleCodepage(InspIRCd* Me) : Module(Me) { ServerInstance=Me; recode.clear(); fd_hash.clear(); OnRehash(NULL); mycommand = new CommandCodepage(ServerInstance); ServerInstance->AddCommand(mycommand); mycommand2 = new CommandSacodepage(ServerInstance); ServerInstance->AddCommand(mycommand2); mycommand3 = new CommandCodepages(ServerInstance); ServerInstance->AddCommand(mycommand3); ServerInstance->Modules->Attach(eventlist, this, 9); } void SaveExisting() { std::vector::iterator iter; save_hash.clear(); for (iter=ServerInstance->Users->local_users.begin();iter!=ServerInstance->Users->local_users.end();++iter) { int fd=(*iter)->GetFd(); hash_common::iterator iter2=fd_hash.find(fd); if (iter2!=fd_hash.end()) { std::string codepage=recode[iter2->second].encoding; save_hash[fd]=codepage; } } } void HookExisting() { std::vector::iterator iter; for (iter=ServerInstance->Users->local_users.begin();iter!=ServerInstance->Users->local_users.end();++iter) { /* Hook the user with our module for stacking... (and save his/her/its (that may be also a bot ;) ) ->IOHook ) */ int fd=(*iter)->GetFd(); Module * hk = (*iter)->GetIOHook(); if (hk && (hk!=this)) { hash_io::iterator iter3=io_hash.find(fd); if (iter3==io_hash.end()) { io_hash[fd]=hk; } } (*iter)->DelIOHook(); (*iter)->AddIOHook(this); /* restoring saved or the default encoding on a port for a user, OnRawSocketAccept code */ bool found=false; hash_save::iterator iter4=save_hash.find(fd); if (iter4!=save_hash.end()) { hash_str::iterator iter5=name_hash.find(iter4->second); if (iter5!=name_hash.end()) { fd_hash[fd]=iter5->second; found=true; } } if (!found) { hash_common::iterator iter2; iter2=port_hash.find((*iter)->GetPort()); if (iter2!=port_hash.end()) fd_hash[fd]=iter2->second; } } save_hash.clear(); } bool isin(const std::string &host, int port, const std::vector &portlist) { if (std::find(portlist.begin(), portlist.end(), "*:" + ConvToStr(port)) != portlist.end()) return true; if (std::find(portlist.begin(), portlist.end(), ":" + ConvToStr(port)) != portlist.end()) return true; return std::find(portlist.begin(), portlist.end(), host + ":" + ConvToStr(port)) != portlist.end(); } void itableconvert(char* table, char* dest, const char* source, int n) { --n; for (;n>=0;--n) { dest[n]=table[(unsigned char)source[n]]; } } void makeitable(iconv_t cd, char * &table) { int i; char tmp[2]; tmp[1]=0; /* trailing 0 */ table=new char[256]; for (i=0;i<0x100;++i) { tmp[0]=(char)i; char * src=tmp; char * dest=table+i; size_t inbytesleft=1,outbytesleft=1; size_t ret_val = iconv(cd, &src, &inbytesleft, &dest, &outbytesleft); if (ret_val==size_t(-1)) { if (errno==EILSEQ) table[i]='?'; else { delete [] table; table=NULL; break; } } } return; } unsigned int addavailable(const std::string &codepage) { io_iconv tmpio; hash_str::iterator iter=name_hash.find(codepage); if (iter==name_hash.end()) /* not found, so let's create it */ { /* wrong convertion, assuming default (0) */ if (((tmpio.in = iconv_open(icodepage.c_str(), codepage.c_str())) == (iconv_t)-1) || ((tmpio.out = iconv_open(codepage.c_str(), icodepage.c_str())) == (iconv_t)-1)) { ServerInstance->Logs->Log("m_codepage.so",DEFAULT, "WARNING: wrong conversion between %s and %s. Assuming internal codepage!",icodepage.c_str(), codepage.c_str()); } else /* right convertion, pushing it into the vector */ { tmpio.encoding=codepage; makeitable(tmpio.in ,tmpio.intable ); makeitable(tmpio.out,tmpio.outtable); name_hash[codepage]=recode.size(); recode.push_back(tmpio); return recode.size()-1; } } else /* it exists already */ { return iter->second; } return 0; } virtual void OnRehash(User* user) { SaveExisting(); iClose(); fd_hash.clear(); port_hash.clear(); name_hash.clear(); recode.clear(); buffer_hash.clear(); ConfigReader* conf = new ConfigReader(ServerInstance); icodepage=""; /* load the internal && default codepage */ for (int i = 0; i < conf->Enumerate("codepage"); i++) /* <- seek for internal */ { std::string tmp; tmp = conf->ReadValue("codepage", "internal", i); if (!tmp.empty()) { icodepage=tmp; break; } } if (icodepage.empty()) { /* NO internal encoding set*/ ServerInstance->Logs->Log("m_codepage",DEBUG,"WARNING: no internal encoding is set but module loaded"); return; } ToUpper(icodepage); dcodepage=icodepage; /* set default codepage to the internal one by default ;) */ for (int i = 0; i < conf->Enumerate("codepage"); i++) /* <- seek for default */ { std::string tmp; tmp = conf->ReadValue("codepage", "default", i); if (!tmp.empty()) { dcodepage=tmp; break; } } ToUpper(dcodepage); ServerInstance->Logs->Log("m_codepage",DEFAULT,"INFO: internal encoding is %s now, default is %s ",icodepage.c_str(),dcodepage.c_str()); io_iconv tmpio; /* first we push a record for internal CP for no any convertion to be applied */ tmpio.encoding=icodepage; tmpio.in=tmpio.out=(iconv_t)-1; tmpio.intable=tmpio.outtable=NULL; name_hash[icodepage]=0; recode.push_back(tmpio); /* list of available encodings */ for (int i = 0; i < conf->Enumerate("codepage"); i++) /* <- seek for default */ { std::string tmp; tmp = conf->ReadValue("codepage", "available", i); if (!tmp.empty()) { irc::commasepstream css(tmp.c_str()); std::string tok; while(css.GetToken(tok)) { ToUpper(tok); addavailable(tok); } break; } } /* setting up encodings on ports */ for (int i = 0; i < conf->Enumerate("bind"); i++) { std::string type,codepage,port,addr; int recodeindex=0; type = conf->ReadValue("bind", "type", i); if (type!="clients") {continue;} /* oh, that's a server port, sorry, skipping :( */ codepage = conf->ReadValue("bind", "codepage", i); port = conf->ReadValue("bind", "port", i); addr = conf->ReadValue("bind", "address", i); if (codepage.empty()) /* no encoding specified explicitly. assuming default */ { codepage=dcodepage; } else { ToUpper(codepage); } recodeindex=addavailable(codepage); irc::portparser portrange(port, false); long portno = -1; while ((portno = portrange.GetToken())) { port_hash[portno]=recodeindex; ServerInstance->Logs->Log("m_codepage.so",DEFAULT, "INFO: adding %s encoding on the port %ld",recode[port_hash[portno]].encoding.c_str(),portno); } } delete conf; HookExisting(); } virtual void OnRawSocketClose(int fd) { fd_hash.erase(fd); io_hash.erase(fd); hash_io::iterator iter2; iter2=io_hash.find(fd); if (iter2!=io_hash.end()) { iter2->second->OnRawSocketClose(fd); } } virtual void OnRawSocketConnect(int fd) { hash_io::iterator iter2; iter2=io_hash.find(fd); if (iter2!=io_hash.end()) { iter2->second->OnRawSocketConnect(fd); } } virtual void OnRawSocketAccept(int fd, const std::string &ip, int localport) { hash_common::iterator iter; iter=port_hash.find(localport); if (iter!=port_hash.end()) fd_hash[fd]=iter->second; hash_io::iterator iter2; iter2=io_hash.find(fd); if (iter2!=io_hash.end()) { iter2->second->OnRawSocketAccept(fd,ip,localport); } } virtual void OnHookUserIO(User* user, const std::string &targetip) { /* Hook the user with our module... (and save his/her/its (that may be also a bot ;) ) ->IOHook ) */ if (user->GetIOHook()) { io_hash[user->GetFd()]=user->GetIOHook(); } user->DelIOHook(); user->AddIOHook(this); } size_t i_convert(iconv_t cd,char* dest,char* src,int countin,int countout,bool omiteinval=true, int fd=-1) { size_t ret_val=(size_t)0; size_t inbytesleft=countin,outbytesleft=countout; char* src1=src; char* dest1=dest; if (cd!=(iconv_t)-1) { for(;inbytesleft && !((ret_val==(size_t)-1)&&((errno==E2BIG)||(errno==EINVAL)));--inbytesleft,++src1) { ret_val = iconv(cd, &src1, &inbytesleft, &dest1, &outbytesleft); if (!inbytesleft) break; } /* Saving incomplete character. let's be paranoid, (inbytesleft<4) */ if ((errno==EINVAL)&&(!omiteinval)&&(inbytesleft<4)) { io_buffer tmpio_b; memcpy(tmpio_b.buffer,src1,inbytesleft); tmpio_b.count=inbytesleft; buffer_hash[fd]=tmpio_b; } return countout-outbytesleft; } memcpy(dest,src,countin); return countin; } virtual int OnRawSocketRead(int fd, char* buffer, unsigned int count, int &readresult) { io_iconv tmpio; int result; User* user = dynamic_cast(ServerInstance->SE->GetRef(fd)); if (user == NULL) return -1; hash_io::iterator iter2; iter2=io_hash.find(fd); if (iter2!=io_hash.end()) { result = iter2->second->OnRawSocketRead(fd, buffer, count, readresult); } else { result = user->ReadData(buffer, count); readresult = result; } hash_common::iterator iter=fd_hash.find(fd); if (iter==fd_hash.end()) /* no any value in a hash? */ tmpio.in=(iconv_t)-1; else tmpio=recode[iter->second]; if ((result == -1) && (errno == EAGAIN)) return -1; else if (result < 1) return 0; if (tmpio.in!=(iconv_t)-1) { /* translating encodings here */ char * tmpbuffer=new char[count+4]; char * writestart=tmpbuffer; hash_buffer::iterator iter3=buffer_hash.find(fd); if (iter3!=buffer_hash.end()) { memcpy(tmpbuffer,iter3->second.buffer,iter3->second.count); writestart+=iter3->second.count; buffer_hash.erase(iter3); } memcpy(writestart,buffer,readresult); if (tmpio.intable!=NULL) { itableconvert(tmpio.intable, buffer, tmpbuffer, readresult); } else { size_t cnt=i_convert(tmpio.in,buffer,tmpbuffer,readresult,readresult, false, fd); readresult=cnt; } delete [] tmpbuffer; } return result; } virtual int OnRawSocketWrite(int fd, const char* buffer, int count) { hash_io::iterator iter2; iter2=io_hash.find(fd); io_iconv tmpio; User* user = dynamic_cast(ServerInstance->SE->GetRef(fd)); if (user == NULL) return -1; hash_common::iterator iter=fd_hash.find(fd); if (iter==fd_hash.end()) /* no any value in a hash? */ tmpio.out=(iconv_t)-1; else tmpio=recode[iter->second]; size_t cnt=count; char * tmpbuffer=new char[count*4+1]; /* assuming UTF-8 is 4 chars wide max. */ if (tmpio.out!=(iconv_t)-1) { /* translating encodings here */ if (tmpio.outtable!=NULL) { itableconvert(tmpio.outtable, tmpbuffer, buffer, count); tmpbuffer[count]=0; } else cnt=i_convert(tmpio.out,tmpbuffer,(char *)buffer,count,count*4); } else { memcpy(tmpbuffer, buffer, count); tmpbuffer[count]=0; } if (iter2!=io_hash.end()) { int tmpres=iter2->second->OnRawSocketWrite(fd, tmpbuffer, cnt); delete [] tmpbuffer; return tmpres; } else { user->AddWriteBuf(std::string(tmpbuffer,cnt)); } delete [] tmpbuffer; return 1; } virtual void OnCleanup(int target_type, void* item) { if(target_type == TYPE_USER) { User* user = (User*)item; if(user->GetIOHook()==this) { hash_io::iterator iter=io_hash.find(user->GetFd()); if (iter!=io_hash.end()) { user->DelIOHook(); user->AddIOHook(iter->second); } else { user->DelIOHook(); } } } } void Prioritize() { for (unsigned int i=0;i<3;++i) { Module* mod = ServerInstance->Modules->Find(modulenames[i]); if (mod==NULL) { continue; } for (unsigned int j=0;j<9;++j) { ServerInstance->Modules->SetPriority(this, eventlist[j], PRIORITY_AFTER, &mod,1); } } } void OnUnloadModule (Module* mod, const std::string &name) { std::vector cleanup; cleanup.clear(); for (hash_io::iterator iter=io_hash.begin();iter!=io_hash.end();++iter) { if (iter->second==mod) { User* user = dynamic_cast(ServerInstance->SE->GetRef(iter->first)); user->DelIOHook(); user->AddIOHook(mod); cleanup.push_back(user); } } for(std::vector::iterator iter2=cleanup.begin();iter2!=cleanup.end();++iter2) { int fd=(* iter2)->GetFd(); mod->OnCleanup(TYPE_USER,(* iter2)); io_hash.erase(fd); /* Let's handle XML Socket etc. properly */ if ((* iter2)->quitting) fd_hash.erase(fd); else (* iter2)->DelIOHook(); (* iter2)->AddIOHook(this); } /* give us back our users!!! >:( */ if (mod!=this) /* A horrible bug, yes :E */ for (hash_common::iterator iter=fd_hash.begin();iter!=fd_hash.end();++iter) { User* user = dynamic_cast(ServerInstance->SE->GetRef(iter->first)); user->DelIOHook(); user->AddIOHook(this); /* Welcome back ;) */ } } void iClose() { for (std::vector::iterator iter=recode.begin();iter!=recode.end();iter++) { if ((*iter).in!=(iconv_t)-1) { iconv_close((*iter).in); if ((*iter).intable!=NULL) delete [] (*iter).intable; } if ((*iter).out!=(iconv_t)-1) iconv_close((*iter).out); if ((*iter).outtable!=NULL) delete [] (*iter).outtable; } } virtual ~ModuleCodepage() { for (hash_io::iterator iter=io_hash.begin();iter!=io_hash.end();iter++) { User* user = dynamic_cast(ServerInstance->SE->GetRef(iter->first)); if (user==NULL) continue; user->DelIOHook(); user->AddIOHook(iter->second); } iClose(); save_hash.clear(); fd_hash.clear(); port_hash.clear(); name_hash.clear(); recode.clear(); io_hash.clear(); buffer_hash.clear(); } virtual Version GetVersion() { return Version("$Id$",0,API_VERSION); } }; MODULE_INIT(ModuleCodepage) inspircd-4.7.0+ds1/contrib/1.2/m_conn_pass_nickserv.cpp000066400000000000000000000047051477226773200227160ustar00rootroot00000000000000#include "inspircd.h" /* $ModDesc: Forwards NickServ credentials from PASS */ /* $ModAuthor: satmd */ /* $ModAuthorMail: http://lain.at/blog/ */ /* $ModDepends: core 1.2-1.3 */ void SearchAndReplace(std::string& newline, const std::string &find, const std::string &replace) { std::string::size_type x = newline.find(find); while (x != std::string::npos) { newline.erase(x, find.length()); newline.insert(x, replace); x = newline.find(find); } } class ModuleConnPassNickserv : public Module { private: std::string nickrequired, unavailablemsg, forwardmsg, forwardcmd; public: ModuleConnPassNickserv(InspIRCd* Me) : Module(Me) { OnRehash(NULL); Implementation eventlist[] = { I_OnPostConnect, I_OnRehash }; ServerInstance->Modules->Attach(eventlist, this, 2); } virtual ~ModuleConnPassNickserv() { } virtual Version GetVersion() { return Version("$Id$", 0, API_VERSION); } virtual void OnRehash(User* user) { ConfigReader Conf(ServerInstance); nickrequired = Conf.ReadValue("passnickserv", "nick", "NickServ", 0); unavailablemsg = Conf.ReadValue("passnickserv", "nonickmsg", "401 $nick $nickrequired :is currently unavailable. Please try again later.", 0); forwardmsg = Conf.ReadValue("passnickserv", "forwardmsg", "NOTICE $nick :*** Forwarding PASS to $nickrequired", 0); forwardcmd = Conf.ReadValue("passnickserv", "cmd", "PRIVMSG $nickrequired :IDENTIFY $pass", 0); } void FormatStr(std::string& newline, const std::string &nick, const std::string &nickrequired, const std::string &pass) { SearchAndReplace(newline,"$nickrequired",nickrequired); SearchAndReplace(newline,"$nick",nick); SearchAndReplace(newline,"$pass",pass); } virtual void OnPostConnect(User* user) { if (!IS_LOCAL(user)) return; if (user->password.empty()) return; if (!nickrequired.empty()) { /* Check if nick exists and its server is ulined */ User* u = ServerInstance->FindNick(nickrequired.c_str()); if (!u || !ServerInstance->ULine(u->server)) { std::string tmp(unavailablemsg); FormatStr(tmp,user->nick,nickrequired,user->password); user->WriteServ(tmp); return; } } std::string tmp(forwardmsg); FormatStr(tmp,user->nick,nickrequired,user->password); user->WriteServ(tmp); tmp.assign(forwardcmd); FormatStr(tmp,user->nick,nickrequired,user->password); ServerInstance->Parser->ProcessBuffer(tmp,user); } }; MODULE_INIT(ModuleConnPassNickserv) inspircd-4.7.0+ds1/contrib/1.2/m_delaymsg.cpp000066400000000000000000000110471477226773200206310ustar00rootroot00000000000000/* +------------------------------------+ * | Inspire Internet Relay Chat Daemon | * +------------------------------------+ * * InspIRCd: (C) 2002-2009 InspIRCd Development Team * See: http://wiki.inspircd.org/Credits * * This program is free but copyrighted software; see * the file COPYING for details. * * --------------------------------------------------- */ #include "inspircd.h" #include /* $ModDesc: channel mode +d