diff --git a/admin/.codespellignore b/admin/.codespellignore new file mode 100644 index 00000000..f9960803 --- /dev/null +++ b/admin/.codespellignore @@ -0,0 +1,2 @@ +ede +EDE diff --git a/admin/.editorconfig b/admin/.editorconfig new file mode 100644 index 00000000..81d63a06 --- /dev/null +++ b/admin/.editorconfig @@ -0,0 +1,39 @@ +# EditorConfig is awesome: https://editorconfig.org/ + +# top-most EditorConfig file +root = true + +# A newline ending every file +[*] +insert_final_newline = true +indent_style = space +indent_size = 4 +charset = utf-8 +trim_trailing_whitespace = true + +[*.css] +indent_size = 2 + +[*.js] +indent_size = 2 + +[package.json] +indent_size = 2 + +[.yamllint.conf] +indent_size = 2 + +[*.yml] +indent_size = 2 + +[*.md] +indent_size = 2 + +# Ignore paths +[**/vendor/**] +charset = unset +end_of_line = unset +insert_final_newline = unset +trim_trailing_whitespace = unset +indent_style = unset +indent_size = unset diff --git a/admin/.gitattributes b/admin/.gitattributes new file mode 100644 index 00000000..176a458f --- /dev/null +++ b/admin/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/admin/.github/ISSUE_TEMPLATE.md b/admin/.github/ISSUE_TEMPLATE.md new file mode 100644 index 00000000..829de9da --- /dev/null +++ b/admin/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,38 @@ +**In raising this issue, I confirm the following:** `{please fill the checkboxes, e.g: [X]}` + +- [] I have read and understood the [contributors guide](https://github.com/pi-hole/AdminLTE/blob/master/CONTRIBUTING.md). +- [] The issue I am reporting can be _replicated_. +- [] The issue I am reporting isn't a duplicate (see [FAQs](https://github.com/pi-hole/pi-hole/wiki/FAQs), [closed issues](https://github.com/pi-hole/AdminLTE/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20), and [open issues](https://github.com/pi-hole/AdminLTE/issues)). + +**How familiar are you with the the source code relevant to this issue?:** + +`{Replace this with a number from 1 to 10. 1 being not familiar, and 10 being very familiar}` + +--- + +**Expected behavior:** + +`{A detailed description of what you expect to see}` + +**Actual behavior:** + +`{A detailed description and/or screenshots of what you do see}` + +**Steps to reproduce:** + +`{Detailed steps of how we can reproduce this}` + +**Debug token provided by [uploading `pihole -d` log](https://discourse.pi-hole.net/t/the-pihole-command-with-examples/738#debug):** + +`{Alphanumeric token}` + +**Troubleshooting undertaken, and/or other relevant information:** + +`{Steps of what you have done to fix this}` + +> - `{Please delete this quoted section when opening your issue}` +> - You must follow the template instructions. Failure to do so will result in your issue being closed. +> - Please [submit any feature requests here](https://discourse.pi-hole.net/c/feature-requests), so it is votable and trackable by the community. +> - Please respect that Pi-hole is developed by volunteers, who can only reply in their spare time. +> - Detail helps us understand and resolve an issue quicker, but please ensure it's relevant. +> - _This template was created based on the work of [`udemy-dl`](https://github.com/nishad/udemy-dl/blob/master/LICENSE)._ diff --git a/admin/.github/dco.yml b/admin/.github/dco.yml new file mode 100644 index 00000000..0c4b142e --- /dev/null +++ b/admin/.github/dco.yml @@ -0,0 +1,2 @@ +require: + members: false diff --git a/admin/.github/dependabot.yml b/admin/.github/dependabot.yml new file mode 100644 index 00000000..47653171 --- /dev/null +++ b/admin/.github/dependabot.yml @@ -0,0 +1,33 @@ +version: 2 +updates: +- package-ecosystem: npm + directory: "/" + schedule: + interval: weekly + day: saturday + time: "10:00" + open-pull-requests-limit: 10 + target-branch: devel + versioning-strategy: increase + reviewers: + - "pi-hole/web-maintainers" +- package-ecosystem: github-actions + directory: "/" + schedule: + interval: weekly + day: saturday + time: "10:00" + open-pull-requests-limit: 10 + target-branch: devel + reviewers: + - "pi-hole/web-maintainers" +- package-ecosystem: composer + directory: "/" + schedule: + interval: weekly + day: saturday + time: "10:00" + open-pull-requests-limit: 10 + target-branch: devel + reviewers: + - "pi-hole/web-maintainers" diff --git a/admin/.github/release.yml b/admin/.github/release.yml new file mode 100644 index 00000000..2e8776e9 --- /dev/null +++ b/admin/.github/release.yml @@ -0,0 +1,7 @@ +changelog: + exclude: + labels: + - internal + authors: + - dependabot + - github-actions diff --git a/admin/.github/workflows/codeql.yml b/admin/.github/workflows/codeql.yml new file mode 100644 index 00000000..b0d85197 --- /dev/null +++ b/admin/.github/workflows/codeql.yml @@ -0,0 +1,35 @@ +name: "CodeQL" + +on: + push: + branches: + - master + - devel + - "!dependabot/**" + pull_request: + # The branches below must be a subset of the branches above + branches: + - master + - devel + schedule: + - cron: "0 0 * * 0" + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3.3.0 + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: "javascript" + + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 diff --git a/admin/.github/workflows/codespell.yml b/admin/.github/workflows/codespell.yml new file mode 100644 index 00000000..03a72d2f --- /dev/null +++ b/admin/.github/workflows/codespell.yml @@ -0,0 +1,20 @@ +name: Codespell + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + +jobs: + spell-check: + if: github.event.pull_request.draft == false + runs-on: ubuntu-latest + steps: + - + name: Checkout repository + uses: actions/checkout@v3.3.0 + - + name: Spell-Checking + uses: codespell-project/actions-codespell@master + with: + ignore_words_file: .codespellignore + skip: ./scripts/vendor,./style/vendor,./package.json,./package-lock.json,./composer.json,./composer.lock diff --git a/admin/.github/workflows/editorconfig-checker.yml b/admin/.github/workflows/editorconfig-checker.yml new file mode 100644 index 00000000..fb47c4a2 --- /dev/null +++ b/admin/.github/workflows/editorconfig-checker.yml @@ -0,0 +1,14 @@ +name: editorconfig-checker + +on: + pull_request: + push: + +jobs: + build: + name: editorconfig-checker + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3.3.0 + - uses: editorconfig-checker/action-editorconfig-checker@main + - run: editorconfig-checker diff --git a/admin/.github/workflows/merge-conflict.yml b/admin/.github/workflows/merge-conflict.yml new file mode 100644 index 00000000..438b23c6 --- /dev/null +++ b/admin/.github/workflows/merge-conflict.yml @@ -0,0 +1,21 @@ +name: "Check for merge conflicts" +on: + # So that PRs touching the same files as the push are updated + push: + # So that the `dirtyLabel` is removed if conflicts are resolve + # We recommend `pull_request_target` so that github secrets are available. + # In `pull_request` we wouldn't be able to change labels of fork PRs + pull_request_target: + types: [synchronize] + +jobs: + main: + runs-on: ubuntu-latest + steps: + - name: Check if PRs are have merge conflicts + uses: eps1lon/actions-label-merge-conflict@v2.1.0 + with: + dirtyLabel: "Merge Conflicts" + repoToken: "${{ secrets.GITHUB_TOKEN }}" + commentOnDirty: "This pull request has conflicts, please resolve those before we can evaluate the pull request." + commentOnClean: "Conflicts have been resolved." diff --git a/admin/.github/workflows/php-cs-fixer.yml b/admin/.github/workflows/php-cs-fixer.yml new file mode 100644 index 00000000..9af3f914 --- /dev/null +++ b/admin/.github/workflows/php-cs-fixer.yml @@ -0,0 +1,13 @@ +# .github/workflows/php-cs-fixer.yml +on: [push, pull_request] +name: Lint +jobs: + php-cs-fixer: + name: PHP-CS-Fixer + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3.3.0 + - name: PHP-CS-Fixer + uses: docker://oskarstark/php-cs-fixer-ga + with: + args: --diff --dry-run diff --git a/admin/.github/workflows/phpstan.yml b/admin/.github/workflows/phpstan.yml new file mode 100644 index 00000000..adc09008 --- /dev/null +++ b/admin/.github/workflows/phpstan.yml @@ -0,0 +1,21 @@ +name: PHPStan + +on: + push: + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3.3.0 + + - name: Install composer + uses: php-actions/composer@v6 + + - name: Run PHPStan + uses: php-actions/phpstan@v3 + with: + configuration: phpstan.neon.dist + memory_limit: 256M + diff --git a/admin/.github/workflows/stale.yml b/admin/.github/workflows/stale.yml new file mode 100644 index 00000000..6c6a2eae --- /dev/null +++ b/admin/.github/workflows/stale.yml @@ -0,0 +1,26 @@ +name: Mark stale issues + +on: + schedule: + - cron: '0 8 * * *' + workflow_dispatch: + +jobs: + stale: + + runs-on: ubuntu-latest + permissions: + issues: write + + steps: + - uses: actions/stale@v7.0.0 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + days-before-stale: 30 + days-before-close: 5 + stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Please comment or update this issue or it will be closed in 5 days.' + stale-issue-label: 'stale' + exempt-issue-labels: 'internal, Fixed In Next Release, Bug, never-stale' + exempt-all-issue-assignees: true + operations-per-run: 300 + close-issue-reason: 'not_planned' diff --git a/admin/.github/workflows/stale_pr.yml b/admin/.github/workflows/stale_pr.yml new file mode 100644 index 00000000..ff04afd9 --- /dev/null +++ b/admin/.github/workflows/stale_pr.yml @@ -0,0 +1,35 @@ +name: Close stale PR +# This action will add a `stale` label and close immediately every PR that meets the following conditions: +# - it is already marked with "merge conflict" label +# - there was no update/comment on the PR in the last 30 days. + +on: + schedule: + - cron: '0 10 * * *' + workflow_dispatch: + +jobs: + stale: + + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + + steps: + - uses: actions/stale@v7.0.0 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + # Do not automatically mark PR/issue as stale + days-before-stale: -1 + # Override 'days-before-stale' for PR only + days-before-pr-stale: 30 + # Close PRs immediately, after marking them 'stale' + days-before-pr-close: 0 + # only run the action on merge conflict PR + any-of-labels: 'Merge Conflicts' + exempt-pr-labels: 'internal, never-stale, ON HOLD, WIP' + exempt-all-pr-assignees: true + operations-per-run: 300 + stale-pr-message: '' + close-pr-message: 'Existing merge conflicts have not been addressed. This PR is considered abandoned.' diff --git a/admin/.github/workflows/sync-back-to-dev.yml b/admin/.github/workflows/sync-back-to-dev.yml new file mode 100644 index 00000000..5a8bde29 --- /dev/null +++ b/admin/.github/workflows/sync-back-to-dev.yml @@ -0,0 +1,18 @@ +name: Sync Back to Development + +on: + push: + branches: + - master + +jobs: + sync-branches: + runs-on: ubuntu-latest + name: Syncing branches + steps: + - name: Checkout + uses: actions/checkout@v3.3.0 + - name: Opening pull request + run: gh pr create -B devel -H master --title 'Sync master back into development' --body 'Created by Github action' --label 'internal' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/admin/.github/workflows/test.yml b/admin/.github/workflows/test.yml new file mode 100644 index 00000000..5cfc6fa9 --- /dev/null +++ b/admin/.github/workflows/test.yml @@ -0,0 +1,34 @@ +name: Tests + +on: + push: + branches: + - devel + - master + pull_request: + branches: + - "**" + +env: + FORCE_COLOR: 2 + +jobs: + run: + name: Node + runs-on: ubuntu-latest + + steps: + - name: Clone repository + uses: actions/checkout@v3.3.0 + + - name: Set up Node.js + uses: actions/setup-node@v3.6.0 + with: + node-version: "16.x" + cache: npm + + - name: Install npm dependencies + run: npm ci + + - name: Run tests + run: npm run testpr diff --git a/admin/.gitignore b/admin/.gitignore new file mode 100644 index 00000000..c8bdf0d6 --- /dev/null +++ b/admin/.gitignore @@ -0,0 +1,21 @@ +*.DS_Store +.idea +/nbproject/private/ +/nbproject/ +/node_modules/ +TODO +*.zip +test.html +*.log +.php-cs-fixer.cache + +# Intellij IDEA Project Files +*.iml +*.ipr +*.iws + +# vim +*.swp + +# Composer +/vendor/ diff --git a/admin/.php-cs-fixer.dist.php b/admin/.php-cs-fixer.dist.php new file mode 100644 index 00000000..dfcb0c3e --- /dev/null +++ b/admin/.php-cs-fixer.dist.php @@ -0,0 +1,31 @@ +ignoreDotFiles(false) + ->ignoreVCSIgnored(true) + ->exclude('scripts/vendor') + ->in(__DIR__) +; + +$config = new PhpCsFixer\Config(); +$config + ->setRules(array( + '@Symfony' => true, + 'array_syntax' => array('syntax' => 'long'), + 'yoda_style' => array('equal' => false, 'identical' => false, 'less_and_greater' => false, 'always_move_variable' => false), + )) + ->setLineEnding(PHP_EOL) + ->setFinder($finder) +; + +return $config; diff --git a/admin/.stickler.yml b/admin/.stickler.yml new file mode 100644 index 00000000..92beabd9 --- /dev/null +++ b/admin/.stickler.yml @@ -0,0 +1,9 @@ +--- +linters: + yamllint: + config: ./.yamllint.conf + remarklint: +files: + ignore: + - 'scripts/vendor/*' + - 'style/vendor/*' diff --git a/admin/.yamllint.conf b/admin/.yamllint.conf new file mode 100644 index 00000000..d1b0953b --- /dev/null +++ b/admin/.yamllint.conf @@ -0,0 +1,3 @@ +rules: + line-length: disable + document-start: disable diff --git a/admin/api.php b/admin/api.php index 4caecfec..46b4dc34 100644 --- a/admin/api.php +++ b/admin/api.php @@ -54,23 +54,6 @@ } $data = array_merge($data, array('status' => 'disabled')); } elseif (isset($_GET['versions'])) { - // Determine if updates are available for Pi-hole - // using the same script that we use for the footer - // on the dashboard (update notifications are - // suppressed if on development branches) - require 'scripts/pi-hole/php/update_checker.php'; - $updates = array('core_update' => $core_update, - 'web_update' => $web_update, - 'FTL_update' => $FTL_update, ); - $current = array('core_current' => $core_current, - 'web_current' => $web_current, - 'FTL_current' => $FTL_current, ); - $latest = array('core_latest' => $core_latest, - 'web_latest' => $web_latest, - 'FTL_latest' => $FTL_latest, ); - $branches = array('core_branch' => $core_branch, - 'web_branch' => $web_branch, - 'FTL_branch' => $FTL_branch, ); $data = array_merge($data, $updates); $data = array_merge($data, $current); $data = array_merge($data, $latest); diff --git a/admin/api_FTL.php b/admin/api_FTL.php index 423a49a2..7e7fb1fa 100644 --- a/admin/api_FTL.php +++ b/admin/api_FTL.php @@ -1,19 +1,16 @@ true); + } else { + if (in_array('status enabled', $return)) { + $data = array_merge($data, array('status' => 'enabled')); + } else { + $data = array_merge($data, array('status' => 'disabled')); + } + } } if ((isset($_GET['summary']) || isset($_GET['summaryRaw']) || !count($_GET)) && $auth) { require_once 'scripts/pi-hole/php/gravity.php'; - $data = getSummaryData($data); + + $return = callFTLAPI('stats'); + if (array_key_exists('FTLnotrunning', $return)) { + $data = array('FTLnotrunning' => true); + } else { + $stats = array(); + foreach ($return as $line) { + $tmp = explode(' ', $line); + + if ($tmp[0] === 'domains_being_blocked' && !is_numeric($tmp[1]) || $tmp[0] === 'status') { + // Expect string response + $stats[$tmp[0]] = $tmp[1]; + } elseif (isset($_GET['summary'])) { + // "summary" expects a formmated string response + if ($tmp[0] !== 'ads_percentage_today') { + $stats[$tmp[0]] = number_format($tmp[1]); + } else { + $stats[$tmp[0]] = number_format($tmp[1], 1, '.', ''); + } + } else { + // Expect float response + $stats[$tmp[0]] = floatval($tmp[1]); + } + } + $stats['gravity_last_updated'] = gravity_last_update(true); + $data = array_merge($data, $stats); + } } if (isset($_GET['getMaxlogage']) && $auth) { - $data = getMaxLogAgeData($data); + $return = callFTLAPI('maxlogage'); + if (array_key_exists('FTLnotrunning', $return)) { + $data = array('FTLnotrunning' => true); + } else { + // Convert seconds to hours and rounds to one decimal place. + $ret = round(intval($return[0]) / 3600, 1); + // Return 24h if value is 0, empty, null or non numeric. + $ret = $ret ?: 24; + + $data = array_merge($data, array('maxlogage' => $ret)); + } } if (isset($_GET['overTimeData10mins']) && $auth) { - $data = getOverTimeData($data); + $return = callFTLAPI('overTime'); + if (array_key_exists('FTLnotrunning', $return)) { + $data = array('FTLnotrunning' => true); + } else { + $domains_over_time = array(); + $ads_over_time = array(); + foreach ($return as $line) { + $tmp = explode(' ', $line); + $domains_over_time[intval($tmp[0])] = intval($tmp[1]); + $ads_over_time[intval($tmp[0])] = intval($tmp[2]); + } + + $result = array( + 'domains_over_time' => $domains_over_time, + 'ads_over_time' => $ads_over_time, + ); + + $data = array_merge($data, $result); + } } if (isset($_GET['topItems']) && $auth) { - $data = getTopItemsData($data); + if ($_GET['topItems'] === 'audit') { + $return = callFTLAPI('top-domains for audit'); + } elseif (is_numeric($_GET['topItems'])) { + $return = callFTLAPI('top-domains ('.$_GET['topItems'].')'); + } else { + $return = callFTLAPI('top-domains'); + } + + if (array_key_exists('FTLnotrunning', $return)) { + $data = array('FTLnotrunning' => true); + } else { + $top_queries = array(); + foreach ($return as $line) { + $tmp = explode(' ', $line); + if (count($tmp) == 2) { + $tmp[2] = ''; + } + $domain = utf8_encode($tmp[2]); + $top_queries[$domain] = intval($tmp[1]); + } + } + + if ($_GET['topItems'] === 'audit') { + $return = callFTLAPI('top-ads for audit'); + } elseif (is_numeric($_GET['topItems'])) { + $return = callFTLAPI('top-ads ('.$_GET['topItems'].')'); + } else { + $return = callFTLAPI('top-ads'); + } + + if (array_key_exists('FTLnotrunning', $return)) { + $data = array('FTLnotrunning' => true); + } else { + $top_ads = array(); + foreach ($return as $line) { + $tmp = explode(' ', $line); + $domain = utf8_encode($tmp[2]); + if (count($tmp) > 3) { + $top_ads[$domain.' ('.$tmp[3].')'] = intval($tmp[1]); + } else { + $top_ads[$domain] = intval($tmp[1]); + } + } + + $result = array( + 'top_queries' => $top_queries, + 'top_ads' => $top_ads, + ); + + $data = array_merge($data, $result); + } } if ((isset($_GET['topClients']) || isset($_GET['getQuerySources'])) && $auth) { - $data = getTopClientsData($data); + if (isset($_GET['topClients'])) { + $number = $_GET['topClients']; + } elseif (isset($_GET['getQuerySources'])) { + $number = $_GET['getQuerySources']; + } + + if (is_numeric($number)) { + $return = callFTLAPI('top-clients ('.$number.')'); + } else { + $return = callFTLAPI('top-clients'); + } + if (array_key_exists('FTLnotrunning', $return)) { + $data = array('FTLnotrunning' => true); + } else { + $top_clients = array(); + foreach ($return as $line) { + $tmp = explode(' ', $line); + $clientip = utf8_encode($tmp[2]); + if (count($tmp) > 3 && strlen($tmp[3]) > 0) { + $clientname = utf8_encode($tmp[3]); + $top_clients[$clientname.'|'.$clientip] = intval($tmp[1]); + } else { + $top_clients[$clientip] = intval($tmp[1]); + } + } + + $result = array('top_sources' => $top_clients); + $data = array_merge($data, $result); + } } if (isset($_GET['topClientsBlocked']) && $auth) { - $data = getTopBlockedClientsData($data); + if (isset($_GET['topClientsBlocked'])) { + $number = $_GET['topClientsBlocked']; + } + + if (is_numeric($number)) { + $return = callFTLAPI('top-clients blocked ('.$number.')'); + } else { + $return = callFTLAPI('top-clients blocked'); + } + if (array_key_exists('FTLnotrunning', $return)) { + $data = array('FTLnotrunning' => true); + } else { + $top_clients = array(); + foreach ($return as $line) { + $tmp = explode(' ', $line); + $clientip = utf8_encode($tmp[2]); + if (count($tmp) > 3 && strlen($tmp[3]) > 0) { + $clientname = utf8_encode($tmp[3]); + $top_clients[$clientname.'|'.$clientip] = intval($tmp[1]); + } else { + $top_clients[$clientip] = intval($tmp[1]); + } + } + + $result = array('top_sources_blocked' => $top_clients); + $data = array_merge($data, $result); + } } if (isset($_GET['getForwardDestinations']) && $auth) { - $data = getForwardDestinationsData($data); + if ($_GET['getForwardDestinations'] === 'unsorted') { + $return = callFTLAPI('forward-dest unsorted'); + } else { + $return = callFTLAPI('forward-dest'); + } + if (array_key_exists('FTLnotrunning', $return)) { + $data = array('FTLnotrunning' => true); + } else { + $forward_dest = array(); + foreach ($return as $line) { + $tmp = explode(' ', $line); + $forwardip = utf8_encode($tmp[2]); + if (count($tmp) > 3 && strlen($tmp[3]) > 0) { + $forwardname = utf8_encode($tmp[3]); + $forward_dest[$forwardname.'|'.$forwardip] = floatval($tmp[1]); + } else { + $forward_dest[$forwardip] = floatval($tmp[1]); + } + } + + $result = array('forward_destinations' => $forward_dest); + $data = array_merge($data, $result); + } } if (isset($_GET['getQueryTypes']) && $auth) { - $data = getQueryTypesData($data); + $return = callFTLAPI('querytypes'); + if (array_key_exists('FTLnotrunning', $return)) { + $data = array('FTLnotrunning' => true); + } else { + $querytypes = array(); + foreach ($return as $ret) { + $tmp = explode(': ', $ret); + // Reply cannot contain non-ASCII characters + $querytypes[$tmp[0]] = floatval($tmp[1]); + } + + $result = array('querytypes' => $querytypes); + $data = array_merge($data, $result); + } } if (isset($_GET['getCacheInfo']) && $auth) { - $data = getCacheInfoData($data); + $return = callFTLAPI('cacheinfo'); + if (array_key_exists('FTLnotrunning', $return)) { + $data = array('FTLnotrunning' => true); + } else { + $cacheinfo = array(); + foreach ($return as $ret) { + $tmp = explode(': ', $ret); + // Reply cannot contain non-ASCII characters + $cacheinfo[$tmp[0]] = floatval($tmp[1]); + } + + $result = array('cacheinfo' => $cacheinfo); + $data = array_merge($data, $result); + } } if (isset($_GET['getAllQueries']) && $auth) { - $data = getAllQueriesData($data); + if (isset($_GET['from'], $_GET['until'])) { + // Get limited time interval + $return = callFTLAPI('getallqueries-time '.$_GET['from'].' '.$_GET['until']); + } elseif (isset($_GET['domain'])) { + // Get specific domain only + $return = callFTLAPI('getallqueries-domain '.$_GET['domain']); + } elseif (isset($_GET['client']) && (isset($_GET['type']) && $_GET['type'] === 'blocked')) { + // Get specific client only + $return = callFTLAPI('getallqueries-client-blocked '.$_GET['client']); + } elseif (isset($_GET['client'])) { + // Get specific client only + $return = callFTLAPI('getallqueries-client '.$_GET['client']); + } elseif (isset($_GET['querytype'])) { + // Get specific query type only + $return = callFTLAPI('getallqueries-qtype '.$_GET['querytype']); + } elseif (isset($_GET['forwarddest'])) { + // Get specific forward destination only + $return = callFTLAPI('getallqueries-forward '.$_GET['forwarddest']); + } elseif (is_numeric($_GET['getAllQueries'])) { + $return = callFTLAPI('getallqueries ('.$_GET['getAllQueries'].')'); + } else { + // Get all queries + $return = callFTLAPI('getallqueries'); + } + + if (array_key_exists('FTLnotrunning', $return)) { + $data = array('FTLnotrunning' => true); + } else { + // Set the header + header('Content-type: application/json'); + + // Start the JSON string + echo '{"data":['; + $first = true; + + foreach ($return as $line) { + // Insert a comma before the next record (except on the first one) + if (!$first) { + echo ','; + } else { + $first = false; + } + + $row = str_getcsv($line, ' '); + // UTF-8 encode domain + $domain = utf8_encode(str_replace('~', ' ', $row[2])); + // UTF-8 encode client host name + $client = utf8_encode($row[3]); + + // Insert into array and output it in JSON format + // array: time type domain client status dnssecStatus reply response_time CNAMEDomain regexID upstream destination EDE + echo json_encode(array($row[0], $row[1], $domain, $client, $row[4], $row[5], $row[6], $row[7], $row[8], $row[9], $row[10], $row[11])); + } + // Finish the JSON string + echo ']}'; + // exit at the end + exit; + } } if (isset($_GET['recentBlocked']) && $auth) { - $data = getRecentBlockedData($data); + exit(utf8_encode(callFTLAPI('recentBlocked')[0])); + unset($data); } if (isset($_GET['getForwardDestinationNames']) && $auth) { - $data = getForwardDestinationNamesData($data); + $return = callFTLAPI('forward-names'); + + if (array_key_exists('FTLnotrunning', $return)) { + $data = array('FTLnotrunning' => true); + } else { + $forward_dest = array(); + foreach ($return as $line) { + $tmp = explode(' ', $line); + $forwardip = utf8_encode($tmp[2]); + if (count($tmp) > 3) { + $forwardname = utf8_encode($tmp[3]); + $forward_dest[$forwardname.'|'.$forwardip] = floatval($tmp[1]); + } else { + $forward_dest[$forwardip] = floatval($tmp[1]); + } + } + + $result = array('forward_destinations' => $forward_dest); + $data = array_merge($data, $result); + } } if (isset($_GET['overTimeDataQueryTypes']) && $auth) { - $data = getOverTimeDataQueryTypes($data); + $return = callFTLAPI('QueryTypesoverTime'); + if (array_key_exists('FTLnotrunning', $return)) { + $data = array('FTLnotrunning' => true); + } else { + $over_time = array(); + foreach ($return as $line) { + $tmp = explode(' ', $line); + for ($i = 0; $i < count($tmp) - 1; ++$i) { + $over_time[intval($tmp[0])][$i] = floatval($tmp[$i + 1]); + } + } + $result = array('over_time' => $over_time); + $data = array_merge($data, $result); + } } if (isset($_GET['getClientNames']) && $auth) { - $data = getClientNamesData($data); + $return = callFTLAPI('client-names'); + if (array_key_exists('FTLnotrunning', $return)) { + $data = array('FTLnotrunning' => true); + } else { + $client_names = array(); + foreach ($return as $line) { + $tmp = explode(' ', $line); + $client_names[] = array( + 'name' => utf8_encode($tmp[0]), + 'ip' => utf8_encode($tmp[1]), + ); + } + + $result = array('clients' => $client_names); + $data = array_merge($data, $result); + } } if (isset($_GET['overTimeDataClients']) && $auth) { - $data = getOverTimeDataClients($data); + $return = callFTLAPI('ClientsoverTime'); + + if (array_key_exists('FTLnotrunning', $return)) { + $data = array('FTLnotrunning' => true); + } else { + $over_time = array(); + foreach ($return as $line) { + $tmp = explode(' ', $line); + for ($i = 0; $i < count($tmp) - 1; ++$i) { + $over_time[intval($tmp[0])][$i] = floatval($tmp[$i + 1]); + } + } + $result = array('over_time' => $over_time); + $data = array_merge($data, $result); + } } if (isset($_GET['delete_lease']) && $auth) { - $data = deleteLeaseData($data); + $return = callFTLAPI('delete-lease '.$_GET['delete_lease']); + if (array_key_exists('FTLnotrunning', $return)) { + $data = array('FTLnotrunning' => true); + } else { + $data['delete_lease'] = $return[0]; + } } if (isset($_GET['dns-port']) && $auth) { - $data = getDnsPortData($data); -} - -// Output the data as JSON -header('Content-type: application/json'); -echo json_encode($data); -exit; - -// Functions to fetch data - -function callFTLAPI($command) -{ - // Function implementation here -} - -function getStatusData($data) -{ - // Function implementation here -} - -function getSummaryData($data) -{ - // Function implementation here -} - -function getMaxLogAgeData($data) -{ - // Function implementation here -} - -function getOverTimeData($data) -{ - // Function implementation here -} - -function getTopItemsData($data) -{ - // Function implementation here -} - -function getTopClientsData($data) -{ - // Function implementation here -} - -function getTopBlockedClientsData($data) -{ - // Function implementation here -} - -function getForwardDestinationsData($data) -{ - // Function implementation here -} - -function getQueryTypesData($data) -{ - // Function implementation here -} - -function getCacheInfoData($data) -{ - // Function implementation here -} - -function getAllQueriesData($data) -{ - // Function implementation here -} - -function getRecentBlockedData($data) -{ - // Function implementation here -} - -function getForwardDestinationNamesData($data) -{ - // Function implementation here -} - -function getOverTimeDataQueryTypes($data) -{ - // Function implementation here -} - -function getClientNamesData($data) -{ - // Function implementation here -} - -function getOverTimeDataClients($data) -{ - // Function implementation here -} - -function deleteLeaseData($data) -{ - // Function implementation here -} - -function getDnsPortData($data) -{ - // Function implementation here + $return = callFTLAPI('dns-port'); + if (array_key_exists('FTLnotrunning', $return)) { + $data = array('FTLnotrunning' => true); + } else { + $data['dns-port'] = $return[0]; + } } diff --git a/admin/auditlog.php b/admin/auditlog.php index 290426a0..1358b14e 100644 --- a/admin/auditlog.php +++ b/admin/auditlog.php @@ -1,99 +1,86 @@ - - -
- -Domain | -Hits | -Actions | -
---|