%1$s installed, and %2$s activated', $plugins_count, $count_active ); ?>
- -| - | - | - | - | - |
|---|---|---|---|---|
| %s | %s | %s | %s | %s |
plugin.php.' ); ?>
- - - -Plugin list.' ); ?>
-diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
new file mode 100644
index 000000000..862d102d5
--- /dev/null
+++ b/.git-blame-ignore-revs
@@ -0,0 +1,5 @@
+# End of line reformating
+3daf6593d89c608a6660a6c0b872eeb2607548ba
+# Convert all tabs to spaces
+a4cb0561f627c918cf304663fd32fd2b192f1565
+
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 1b163007b..d26197188 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -13,13 +13,11 @@ jobs:
strategy:
fail-fast: false
matrix:
- php: ['8.0', '8.1', '8.2']
- phpunit: ['9']
+ php: ['8.1', '8.2', '8.3', '8.4']
include:
- - php: '7.4'
- phpunit: '8'
- coverage: xdebug
- flags: '--coverage-clover clover.xml'
+ - php: '8.1'
+ coverage: xdebug
+ flags: '--coverage-clover clover.xml'
services:
mysql:
@@ -30,17 +28,19 @@ jobs:
MYSQL_ALLOW_EMPTY_PASSWORD: false
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: yourls_tests
- options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
+ MARIADB_MYSQL_LOCALHOST_USER: 1
+ MARIADB_MYSQL_LOCALHOST_GRANTS: USAGE
+ options: --health-cmd="healthcheck.sh --su-mysql --connect --innodb_initialized" --health-interval=10s --health-timeout=5s --health-retries=3
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v5
- name: Use PHP ${{ matrix.php }}
- uses: shivammathur/setup-php@2.24.0
+ uses: shivammathur/setup-php@2.35.5
with:
php-version: ${{ matrix.php }}
extensions: mbstring, curl, zip, dom, simplexml, intl, pdo_mysql
- tools: phpunit:${{ matrix.phpunit }}
+ tools: phpunit
coverage: ${{ matrix.coverage }}
# - name: Validate composer.json and composer.lock
@@ -71,7 +71,6 @@ jobs:
cp tests/data/config/yourls-tests-config-ci.php user/config.php
- name: Test
- run: phpunit --configuration phpunit.xml.dist ${{ matrix.flags }}
+ run: phpunit --configuration phpunit.xml.dist --testdox --display-deprecations --display-notices --display-warnings --display-errors ${{ matrix.flags }}
env:
DB_PORT: ${{ job.services.mysql.ports['3306'] }}
-
diff --git a/.github/workflows/update-certificates.yml b/.github/workflows/update-certificates.yml
index 41e6e96a2..1be5c2a50 100644
--- a/.github/workflows/update-certificates.yml
+++ b/.github/workflows/update-certificates.yml
@@ -13,6 +13,10 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
+permissions:
+ contents: write
+ pull-requests: write
+
jobs:
certificate-check:
name: "Check for updated certificate bundle"
@@ -22,7 +26,20 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
- uses: actions/checkout@v3
+ uses: actions/checkout@v5
+
+ - name: Generate token
+ uses: actions/create-github-app-token@v2
+ id: app-token
+ with:
+ app-id: ${{ vars.BOT_APP_ID }}
+ private-key: ${{ secrets.BOT_PRIVATE_KEY }}
+
+ - name: Get GitHub App User ID
+ id: get-user-id
+ run: echo "user-id=$(gh api "/users/${{ steps.app-token.outputs.app-slug }}[bot]" --jq .id)" >> "$GITHUB_OUTPUT"
+ env:
+ GH_TOKEN: ${{ steps.app-token.outputs.token }}
- name: Get current certificate bundle
working-directory: ./includes/vendor/rmccue/requests/certificates
@@ -42,8 +59,11 @@ jobs:
run: echo "DATE=$(/bin/date -u "+%F")" >> $GITHUB_OUTPUT
- name: Create pull request
- uses: peter-evans/create-pull-request@v4
+ uses: peter-evans/create-pull-request@v7
+ id: pull-request
with:
+ token: ${{ steps.app-token.outputs.token }}
+ author: "${{ steps.app-token.outputs.app-slug }}[bot] <${{ steps.get-user-id.outputs.user-id }}+${{ steps.app-token.outputs.app-slug }}[bot]@users.noreply.github.com>"
base: master
branch: auto-update-cacert
delete-branch: true
@@ -55,7 +75,17 @@ jobs:
Source: https://curl.se/docs/caextract.html
labels: |
dependencies
- reviewers: |
- ozh
- LeoColomb
- dgw
+
+ - name: Approve a PR
+ if: ${{ steps.pull-request.outputs.pull-request-url && steps.pull-request.outputs.pull-request-operation != 'none' }}
+ run: gh pr review --approve "$PR_URL"
+ env:
+ PR_URL: ${{ steps.pull-request.outputs.pull-request-url }}
+ GITHUB_TOKEN: ${{ github.token }}
+
+ - name: Enable Pull Request Automerge
+ if: ${{ steps.pull-request.outputs.pull-request-url && steps.pull-request.outputs.pull-request-operation != 'none' }}
+ run: gh pr merge --auto --rebase "$PR_URL"
+ env:
+ PR_URL: ${{ steps.pull-request.outputs.pull-request-url }}
+ GITHUB_TOKEN: ${{ github.token }}
diff --git a/.github/workflows/update-geoip.yml b/.github/workflows/update-geoip.yml
index 4bd1207e3..6800cf98e 100644
--- a/.github/workflows/update-geoip.yml
+++ b/.github/workflows/update-geoip.yml
@@ -13,6 +13,10 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
+permissions:
+ contents: write
+ pull-requests: write
+
jobs:
update-geoip:
name: "Check for updated GeoIP DB"
@@ -20,14 +24,20 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
- uses: actions/checkout@v3
+ uses: actions/checkout@v5
- name: Generate token
- uses: tibdex/github-app-token@v1
- id: generate-token
+ uses: actions/create-github-app-token@v2
+ id: app-token
with:
- app_id: ${{ secrets.BOT_APP_ID }}
- private_key: ${{ secrets.BOT_PRIVATE_KEY }}
+ app-id: ${{ vars.BOT_APP_ID }}
+ private-key: ${{ secrets.BOT_PRIVATE_KEY }}
+
+ - name: Get GitHub App User ID
+ id: get-user-id
+ run: echo "user-id=$(gh api "/users/${{ steps.app-token.outputs.app-slug }}[bot]" --jq .id)" >> "$GITHUB_OUTPUT"
+ env:
+ GH_TOKEN: ${{ steps.app-token.outputs.token }}
- name: Check if newer GeoIP DB
env:
@@ -36,12 +46,12 @@ jobs:
URL="https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&license_key=${MAXMIND_API_KEY}&suffix=tar.gz"
REMOTE_MODIFIED=$(curl --silent --head "$URL" | grep "last-modified" | sed 's/last-modified: //')
REMOTE_CTIME=$(date -d "$REMOTE_MODIFIED" +%s)
- LOCAL_MODIFIED=$(curl -sL https://api.github.com/repos/YOURLS/YOURLS/commits?path=includes/geo/GeoLite2-Country.mmdb | \
+ LOCAL_MODIFIED=$(curl -fsSL https://api.github.com/repos/YOURLS/YOURLS/commits?path=includes/geo/GeoLite2-Country.mmdb | \
jq -r '.[0]["commit"]["author"]["date"]')
LOCAL_CTIME=$(date -d "$LOCAL_MODIFIED" +%s)
echo "Remote: $REMOTE_CTIME ($(date -d @$REMOTE_CTIME))"
echo "Local: $LOCAL_CTIME ($(date -d @$LOCAL_CTIME))"
- if [ $LOCAL_CTIME -lt $REMOTE_CTIME ] ; then curl -s "$URL" | tar -zvx -C includes/geo/ --strip-components 1 -- ; fi
+ if [ $LOCAL_CTIME -lt $REMOTE_CTIME ] ; then curl -fsSL "$URL" | tar -zvx -C includes/geo/ --strip-components 1 -- ; fi
- name: "Debug info: Show git status"
run: git status -vv --untracked=all
@@ -51,9 +61,11 @@ jobs:
run: echo "DATE=$(/bin/date -u "+%F")" >> $GITHUB_OUTPUT
- name: Create pull request
- uses: peter-evans/create-pull-request@v4
+ uses: peter-evans/create-pull-request@v7
+ id: pull-request
with:
- token: ${{ steps.generate-token.outputs.token }}
+ token: ${{ steps.app-token.outputs.token }}
+ author: "${{ steps.app-token.outputs.app-slug }}[bot] <${{ steps.get-user-id.outputs.user-id }}+${{ steps.app-token.outputs.app-slug }}[bot]@users.noreply.github.com>"
base: master
branch: auto-update-geoip
commit-message: "Update GeoIP DB"
@@ -64,3 +76,17 @@ jobs:
Source: https://www.maxmind.com/en/account/login
labels: |
dependencies
+
+ - name: Approve a PR
+ if: ${{ steps.pull-request.outputs.pull-request-url && steps.pull-request.outputs.pull-request-operation != 'none' }}
+ run: gh pr review --approve "$PR_URL"
+ env:
+ PR_URL: ${{ steps.pull-request.outputs.pull-request-url }}
+ GITHUB_TOKEN: ${{ github.token }}
+
+ - name: Enable Pull Request Automerge
+ if: ${{ steps.pull-request.outputs.pull-request-url && steps.pull-request.outputs.pull-request-operation != 'none' }}
+ run: gh pr merge --auto --rebase "$PR_URL"
+ env:
+ PR_URL: ${{ steps.pull-request.outputs.pull-request-url }}
+ GITHUB_TOKEN: ${{ github.token }}
diff --git a/.github/workflows/update-translations.yml b/.github/workflows/update-translations.yml
new file mode 100644
index 000000000..9034d576a
--- /dev/null
+++ b/.github/workflows/update-translations.yml
@@ -0,0 +1,115 @@
+name: Update translations
+
+on:
+ push:
+ tags:
+ - '*'
+ workflow_dispatch:
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ translations-check:
+ name: Check for updated translations
+ if: ${{ github.event_name != 'schedule' || github.repository == 'YOURLS/YOURLS' }}
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v5
+
+ - name: Install GNU gettext
+ run: sudo apt-get install gettext
+
+ - name: Get version
+ id: get-version
+ run: echo "yourls-version=$(php -r 'require "includes/version.php"; echo YOURLS_VERSION;')" >> $GITHUB_OUTPUT
+
+ - name: Extract translations
+ env:
+ YOURLS_VERSION: ${{ steps.get-version.outputs.yourls-version }}
+ run: |
+ find . -name "*.php" ! -path "./user/*" ! -path "./tests/*" ! -path "./includes/vendor/*" \
+ | xargs xgettext \
+ --output=YOURLS.pot --package-name=YOURLS --package-version=$YOURLS_VERSION --foreign-user \
+ --add-location --language=PHP --from-code=UTF-8 --sort-by-file \
+ --keyword=yourls__ \
+ --keyword=yourls_e \
+ --keyword=yourls_s \
+ --keyword=yourls_se \
+ --keyword=yourls_esc_attr__ \
+ --keyword=yourls_esc_html__ \
+ --keyword=yourls_x \
+ --keyword=yourls_ex \
+ --keyword=yourls_esc_attr_x \
+ --keyword=yourls_esc_html_x \
+ --keyword=yourls_n:1,2 \
+ --keyword=yourls_nx:1,2 \
+ --keyword=yourls_n_noop:1,2 \
+ --keyword=yourls_nx_noop:1,2
+
+ - uses: actions/upload-artifact@v4
+ with:
+ name: YOURLS-pot
+ path: YOURLS.pot
+
+ translations-submit:
+ name: Submit updated translations
+ if: ${{ github.event_name == 'workflow_dispatch' && github.repository == 'YOURLS/YOURLS' }}
+ runs-on: ubuntu-latest
+ needs:
+ - translations-check
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v5
+ with:
+ repository: YOURLS/YOURLS.pot
+
+ - uses: actions/download-artifact@v5
+ with:
+ name: YOURLS-pot
+
+ - name: Generate token
+ uses: actions/create-github-app-token@v2
+ id: app-token
+ with:
+ app-id: ${{ vars.BOT_APP_ID }}
+ private-key: ${{ secrets.BOT_PRIVATE_KEY }}
+ owner: ${{ github.repository_owner }}
+
+ - name: Get GitHub App User ID
+ id: get-user-id
+ run: echo "user-id=$(gh api "/users/${{ steps.app-token.outputs.app-slug }}[bot]" --jq .id)" >> "$GITHUB_OUTPUT"
+ env:
+ GH_TOKEN: ${{ steps.app-token.outputs.token }}
+
+ - name: Show git status
+ run: git status -vv --untracked=all
+
+ - name: Get date
+ id: get-date
+ run: echo "DATE=$(/bin/date -u "+%F")" >> $GITHUB_OUTPUT
+
+ - name: Create pull request
+ uses: peter-evans/create-pull-request@v7
+ id: pull-request
+ with:
+ token: ${{ steps.app-token.outputs.token }}
+ author: "${{ steps.app-token.outputs.app-slug }}[bot] <${{ steps.get-user-id.outputs.user-id }}+${{ steps.app-token.outputs.app-slug }}[bot]@users.noreply.github.com>"
+ base: main
+ branch: auto-update-translations
+ delete-branch: true
+ commit-message: "Update translations"
+ title: "Update translations"
+ body: |
+ Updated translations, last verified on ${{ steps.get-date.outputs.DATE }}.
+ labels: |
+ dependencies
+
+ - name: Enable Pull Request Automerge
+ if: ${{ steps.pull-request.outputs.pull-request-url && steps.pull-request.outputs.pull-request-operation != 'none' }}
+ run: gh pr merge --auto --rebase "$PR_URL"
+ env:
+ PR_URL: ${{ steps.pull-request.outputs.pull-request-url }}
+ GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}
diff --git a/.gitignore b/.gitignore
index 3b293ef24..99aa9a942 100644
--- a/.gitignore
+++ b/.gitignore
@@ -46,6 +46,8 @@ Thumbs.db
Desktop.ini
# Mac crap
.DS_Store
-# NetBeans files
+# IDE files
/nbproject/
.idea
+.vs
+.vscode
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 58c1ddc09..2beb5f628 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,34 @@ YOURLS Changelog
_This file lists the main changes through all versions of YOURLS.
For a much more detailed list, simply refer to [commit messages](https://github.com/YOURLS/YOURLS/commits/master)._
+1.10.2
+---
+- fixed: `admin/tools.php` now uses `yourls_get_nonce_life()` (#3906)
+- fixed: "Display 1 to 0 of 0 URLs" on admin list page (#3910)
+- fixed: replace deprecated `get_all_options` filter with an action (#3683)
+- fixed: defer loading text domain after plugins (#3679)
+- removed: Gandi references (#3929)
+
+1.10.1
+---
+- fixed: sandbox exceptions when disabling plugins (#3893)
+- fixed: stats date calculation are now correct (#3895)
+- fixed: unexpected warning raised on login page
+- removed: unsupported installation cases with Composer
+
+1.10.0
+---
+- added: Support PHP 8.3 & 8.4
+- removed: Support for PHP prior to 8.1 which is now minimal requirement
+- changed: Ensure all `statusCode`/`errorCode` API values are strings (#3756)
+- fixed: Results with 0 clicks on search (#3589)
+- fixed: Upgrade Aura.SQL to fix PHP 8.4 compatibility (#3852)
+- fixed: login page accessibility (#3660)
+- fixed: MySQL 8+ compatibility (#3828)
+- changed: Upgrade dependencies
+- changed: Update GeoIP DB
+- changed: Update certificates
+
1.9.2
---
- added: Support PHP 8.2 (#3474)
diff --git a/README.md b/README.md
index ad74448be..1a57344bf 100644
--- a/README.md
+++ b/README.md
@@ -6,20 +6,15 @@
> Your Own URL Shortener
- [](https://scrutinizer-ci.com/g/YOURLS/YOURLS/?branch=master)  [](https://packagist.org/packages/yourls/yourls) [](https://opencollective.com/yourls#contributors)
+[](https://github.com/YOURLS/YOURLS/actions/workflows/ci.yml) [](https://scrutinizer-ci.com/g/YOURLS/YOURLS/?branch=master)  [](https://packagist.org/packages/yourls/yourls) [](https://opencollective.com/yourls#contributors)
[](#sponsors)
**YOURLS** is a set of PHP scripts that will allow you to run Your Own URL Shortener, on **your** server. You'll have full control over your data, detailed stats, analytics, plugins, and more. It's free and open-source.
-## Quick Start
+## Getting Started
-Get YOURLS :
-* Download the latest [release](https://github.com/YOURLS/YOURLS/releases)
-* Using Composer? You can simply `composer create-project yourls/yourls .` in an empty directory.
-
-Install YOURLS:
-* Read [yourls.org](https://yourls.org) for starters
-* The complete documentation is on [docs.yourls.org](https://docs.yourls.org) and contains everything from beginners to experts.
+Check out the complete documentation on [docs.yourls.org](https://docs.yourls.org).
+It contains everything from beginners to experts.
## Community news, tips and tricks
@@ -34,7 +29,6 @@ Feature suggestion? Bug to report?
__Before opening any issue, please search for existing [issues](https://github.com/YOURLS/YOURLS/issues) (open and closed) and read the [Contributing Guidelines](https://github.com/YOURLS/.github/blob/master/CONTRIBUTING.md).__
-
## Backers
Do you use and enjoy YOURLS? [Become a backer](https://opencollective.com/yourls#backer) and show your support to our open source project.
diff --git a/admin/admin-ajax.php b/admin/admin-ajax.php
index 88de236b2..edfa16a49 100644
--- a/admin/admin-ajax.php
+++ b/admin/admin-ajax.php
@@ -10,38 +10,38 @@
yourls_no_frame_header();
if( !isset( $_REQUEST['action'] ) )
- die();
+ die();
// Pick action
$action = $_REQUEST['action'];
switch( $action ) {
- case 'add':
- yourls_verify_nonce( 'add_url', $_REQUEST['nonce'], false, 'omg error' );
- $return = yourls_add_new_link( $_REQUEST['url'], $_REQUEST['keyword'], '', $_REQUEST['rowid'] );
- echo json_encode($return);
- break;
-
- case 'edit_display':
- yourls_verify_nonce( 'edit-link_'.$_REQUEST['id'], $_REQUEST['nonce'], false, 'omg error' );
- $row = yourls_table_edit_row ( $_REQUEST['keyword'], $_REQUEST['id'] );
- echo json_encode( array('html' => $row) );
- break;
-
- case 'edit_save':
- yourls_verify_nonce( 'edit-save_'.$_REQUEST['id'], $_REQUEST['nonce'], false, 'omg error' );
- $return = yourls_edit_link( $_REQUEST['url'], $_REQUEST['keyword'], $_REQUEST['newkeyword'], $_REQUEST['title'] );
- echo json_encode($return);
- break;
-
- case 'delete':
- yourls_verify_nonce( 'delete-link_'.$_REQUEST['id'], $_REQUEST['nonce'], false, 'omg error' );
- $query = yourls_delete_link_by_keyword( $_REQUEST['keyword'] );
- echo json_encode(array('success'=>$query));
- break;
-
- default:
- yourls_do_action( 'yourls_ajax_'.$action );
+ case 'add':
+ yourls_verify_nonce( 'add_url', $_REQUEST['nonce'], false, 'omg error' );
+ $return = yourls_add_new_link( $_REQUEST['url'], $_REQUEST['keyword'], '', $_REQUEST['rowid'] );
+ echo json_encode($return);
+ break;
+
+ case 'edit_display':
+ yourls_verify_nonce( 'edit-link_'.$_REQUEST['id'], $_REQUEST['nonce'], false, 'omg error' );
+ $row = yourls_table_edit_row ( $_REQUEST['keyword'], $_REQUEST['id'] );
+ echo json_encode( array('html' => $row) );
+ break;
+
+ case 'edit_save':
+ yourls_verify_nonce( 'edit-save_'.$_REQUEST['id'], $_REQUEST['nonce'], false, 'omg error' );
+ $return = yourls_edit_link( $_REQUEST['url'], $_REQUEST['keyword'], $_REQUEST['newkeyword'], $_REQUEST['title'] );
+ echo json_encode($return);
+ break;
+
+ case 'delete':
+ yourls_verify_nonce( 'delete-link_'.$_REQUEST['id'], $_REQUEST['nonce'], false, 'omg error' );
+ $query = yourls_delete_link_by_keyword( $_REQUEST['keyword'] );
+ echo json_encode(array('success'=>$query));
+ break;
+
+ default:
+ yourls_do_action( 'yourls_ajax_'.$action );
}
diff --git a/admin/index.php b/admin/index.php
index d1919ad71..d3a59861a 100644
--- a/admin/index.php
+++ b/admin/index.php
@@ -30,17 +30,20 @@
$search_in = $view_params->get_search_in();
$search_in_text = $view_params->get_param_long_name($search_in);
if( $search && $search_in && $search_in_text ) {
- $search_sentence = yourls_s( 'Searching for %1$s in %2$s.', yourls_esc_html( $search ), yourls_esc_html( $search_in_text ) );
- $search_text = $search;
- $search = str_replace( '*', '%', '*' . $search . '*' );
+ $search_sentence = yourls_s( 'Searching for %1$s in %2$s.', yourls_esc_html( $search ), yourls_esc_html( $search_in_text ) );
+ $search_text = $search;
+ $search = str_replace( '*', '%', '*' . $search . '*' );
if( $search_in == 'all' ) {
- $where['sql'] .= " AND CONCAT_WS('',`keyword`,`url`,`title`,`ip`) LIKE (:search)";
- // Search across all fields. The resulting SQL will be something like:
- // SELECT * FROM `yourls_url` WHERE CONCAT_WS('',`keyword`,`url`,`title`,`ip`) LIKE ("%ozh%")
- // CONCAT_WS because CONCAT('foo', 'bar', NULL) = NULL. NULL wins. Not sure if values can be NULL now or in the future, so better safe.
- // TODO: pay attention to this bit when the DB schema changes
+ $where['sql'] .= " AND `keyword` LIKE (:search)
+ OR `url` LIKE (:search)
+ OR `title` COLLATE utf8mb4_unicode_ci LIKE (:search) COLLATE utf8mb4_unicode_ci
+ OR `ip` LIKE (:search) ";
} else {
- $where['sql'] .= " AND `$search_in` LIKE (:search)";
+ $collate = '';
+ if( $search_in == 'title' ) {
+ $collate = ' COLLATE utf8mb4_unicode_ci';
+ }
+ $where['sql'] .= " AND `$search_in` $collate LIKE (:search) $collate";
}
$where['binds']['search'] = $search;
}
@@ -96,139 +99,139 @@
// Get URLs Count for current filter, total links in DB & total clicks
list( $total_urls, $total_clicks ) = array_values( yourls_get_db_stats() );
if ( !empty($where['sql']) ) {
- list( $total_items, $total_items_clicks ) = array_values( yourls_get_db_stats( $where ) );
+ list( $total_items, $total_items_clicks ) = array_values( yourls_get_db_stats( $where ) );
} else {
- $total_items = $total_urls;
- $total_items_clicks = false;
+ $total_items = $total_urls;
+ $total_items_clicks = false;
}
// This is a bookmarklet
if ( isset( $_GET['u'] ) or isset( $_GET['up'] ) ) {
- $is_bookmark = true;
- yourls_do_action( 'bookmarklet' );
-
- // No sanitization needed here: everything happens in yourls_add_new_link()
- if( isset( $_GET['u'] ) ) {
- // Old school bookmarklet: ?u= %1$s to %2$s of %3$s URLs' ), $display_on_page, $max_on_page, $total_items );
- if( $total_items_clicks !== false )
- echo ", " . sprintf( yourls_n( 'counting 1 click', 'counting %s clicks', $total_items_clicks ), yourls_number_format_i18n( $total_items_clicks ) );
- ?>. %1$s to %2$s of %3$s URLs' ), $display_on_page, $max_on_page, $total_items );
+ if( $total_items_clicks !== false )
+ echo ", " . sprintf( yourls_n( 'counting 1 click', 'counting %s clicks', $total_items_clicks ), yourls_number_format_i18n( $total_items_clicks ) );
+ }
+ ?>. %1$s links, %2$s clicks, and counting!' ), yourls_number_format_i18n( $total_urls ), yourls_number_format_i18n( $total_clicks ) ); ?> %1$s installed, and %2$s activated', $plugins_count, $count_active ); ?> plugin.php.' ); ?> Plugin list.' ); ?> %1$s installed, and %2$s activated', $plugins_count, $count_active ); ?> plugin.php.' ); ?> Plugin list.' ); ?> bookmarklets for easier link shortening and sharing.' ); ?> bookmarklets for easier link shortening and sharing.' ); ?> select text on the page you're viewing before clicking on your bookmarklet link" );
- ?> select text on the page you're viewing before clicking on your bookmarklet link" );
+ ?> Important Note: bookmarklets may fail on websites with https, especially the "Instant" bookrmarklets. There is nothing you can do about this.'); ?>
-
+
-
+
-
-
-
-
-
-
-
-
-
-
- $plugin ) {
-
- // default fields to read from the plugin header
- $fields = array(
- 'name' => 'Plugin Name',
- 'uri' => 'Plugin URI',
- 'desc' => 'Description',
- 'version' => 'Version',
- 'author' => 'Author',
- 'author_uri' => 'Author URI'
- );
-
- // Loop through all default fields, get value if any and reset it
- foreach( $fields as $field=>$value ) {
- if( isset( $plugin[ $value ] ) ) {
- $data[ $field ] = $plugin[ $value ];
- } else {
- $data[ $field ] = yourls__('(no info)');
- }
- unset( $plugin[$value] );
- }
-
- $plugindir = trim( dirname( $file ), '/' );
-
- if( yourls_is_active_plugin( $file ) ) {
- $class = 'active';
- $action_url = yourls_nonce_url( 'manage_plugins', yourls_add_query_arg( array('action' => 'deactivate', 'plugin' => $plugindir ), yourls_admin_url('plugins.php') ) );
- $action_anchor = yourls__( 'Deactivate' );
- } else {
- $class = 'inactive';
- $action_url = yourls_nonce_url( 'manage_plugins', yourls_add_query_arg( array('action' => 'activate', 'plugin' => $plugindir ), yourls_admin_url('plugins.php') ) );
- $action_anchor = yourls__( 'Activate' );
- }
-
- // Other "Fields: Value" in the header? Get them too
- if( $plugin ) {
- foreach( $plugin as $extra_field=>$extra_value ) {
- $data['desc'] .= "
-
-
-
-
-
\n$extra_field: $extra_value";
- unset( $plugin[$extra_value] );
- }
- }
-
- $data['desc'] .= '
' . yourls_s( 'plugin file location: %s', $file) . '';
-
- printf( " ",
- $class, $data['uri'], $data['name'], $data['version'], $data['desc'], $data['author_uri'], $data['author'], $action_url, $action_anchor
- );
-
- }
- ?>
-
- %s %s %s %s %s
+
+
+
+
+
+
+
+
+
+ $plugin ) {
+
+ // default fields to read from the plugin header
+ $fields = array(
+ 'name' => 'Plugin Name',
+ 'uri' => 'Plugin URI',
+ 'desc' => 'Description',
+ 'version' => 'Version',
+ 'author' => 'Author',
+ 'author_uri' => 'Author URI'
+ );
+
+ // Loop through all default fields, get value if any and reset it
+ foreach( $fields as $field=>$value ) {
+ if( isset( $plugin[ $value ] ) ) {
+ $data[ $field ] = $plugin[ $value ];
+ } else {
+ $data[ $field ] = yourls__('(no info)');
+ # If it's a URL, set to #
+ if( in_array( $field, array('uri', 'author_uri') ) ) {
+ $data[$field] = '#' . $data[$field];
+ }
+ }
+ unset( $plugin[$value] );
+ }
+
+ $plugindir = trim( dirname( $file ), '/' );
+
+ if( yourls_is_active_plugin( $file ) ) {
+ $class = 'active';
+ $action_url = yourls_nonce_url( 'manage_plugins', yourls_add_query_arg( array('action' => 'deactivate', 'plugin' => $plugindir ), yourls_admin_url('plugins.php') ) );
+ $action_anchor = yourls__( 'Deactivate' );
+ } else {
+ $class = 'inactive';
+ $action_url = yourls_nonce_url( 'manage_plugins', yourls_add_query_arg( array('action' => 'activate', 'plugin' => $plugindir ), yourls_admin_url('plugins.php') ) );
+ $action_anchor = yourls__( 'Activate' );
+ }
+
+ // Other "Fields: Value" in the header? Get them too
+ if( $plugin ) {
+ foreach( $plugin as $extra_field=>$extra_value ) {
+ $data['desc'] .= "
+
+
+
+
+
\n$extra_field: $extra_value";
+ unset( $plugin[$extra_value] );
+ }
+ }
+
+ $data['desc'] .= '
' . yourls_s( 'plugin file location: %s', $file) . '';
+
+ printf( " ",
+ $class, $data['uri'], $data['name'], $data['version'], $data['desc'], $data['author_uri'], $data['author'], $action_url, $action_anchor
+ );
+
+ }
+ ?>
+
+ %s %s %s %s %s
-
-
+
+
-
-
+
+
+
-
+
-
-
-
-
-
-
-
-
-
+
-
-
+
+
+
+
+
+
+
+
+
-
+
+
-
+
-
+
+
-
-
-
+
-
%s\" to the beginning of the current URL (right before its 'http://' part) and hit enter.", preg_replace('@https?://@', '', yourls_get_yourls_site()) . '/' ); ?>
+%s\" to the beginning of the current URL (right before its 'http://' part) and hit enter.", preg_replace('@https?://@', '', yourls_get_yourls_site()) . '/' ); ?>
-.
+.
- + - + -username and password parameters.' ); - echo "\n"; - yourls_e( "If you're worried about sending your credentials into the wild, you can also make API calls without using your login or your password, using a secret signature token." ); - ?>
+username and password parameters.' ); + echo "\n"; + yourls_e( "If you're worried about sending your credentials into the wild, you can also make API calls without using your login or your password, using a secret signature token." ); + ?>
-%s', yourls_auth_signature() ); ?>
+
%s', yourls_auth_signature() ); ?>
signature in your API requests. Example:' ); ?>
-/yourls-api.php?signature=&action=...
signature in your API requests. Example:' ); ?>
+/yourls-api.php?signature=&action=...
<?php
$timestamp = time();
// $time =
@@ -322,19 +322,19 @@
// $signature = ""
?>
- signature and timestamp in your API requests. Example:' ); ?>
-/yourls-api.php?timestamp=$timestamp&signature=$signature&action=...
- /yourls-api.php?timestamp=&signature=&action=...
signature and timestamp in your API requests. Example:' ); ?>
+/yourls-api.php?timestamp=$timestamp&signature=$signature&action=...
+ /yourls-api.php?timestamp=&signature=&action=...
Passwordless API page on the wiki.', 'https://yourls.org/passwordlessapi' ); ?> - API documentation for more', yourls_get_yourls_site() . '/readme.html#API' ); ?>
+Passwordless API page on the wiki.', 'https://yourls.org/passwordlessapi' ); ?> + API documentation for more', yourls_get_yourls_site() . '/readme.html#API' ); ?>
- + - + diff --git a/admin/upgrade.php b/admin/upgrade.php index 536a9f873..957870cda 100644 --- a/admin/upgrade.php +++ b/admin/upgrade.php @@ -8,73 +8,73 @@ yourls_html_logo(); yourls_html_menu(); ?> - + ' . yourls_s( 'Upgrade not required. Go back to play!', yourls_admin_url('index.php') ) . ''; + echo '' . yourls_s( 'Upgrade not required. Go back to play!', yourls_admin_url('index.php') ) . '
'; } else { - /* - step 1: create new tables and populate them, update old tables structure, - step 2: convert each row of outdated tables if needed - step 3: - if applicable finish updating outdated tables (indexes etc) - - update version & db_version in options, this is all done! - */ + /* + step 1: create new tables and populate them, update old tables structure, + step 2: convert each row of outdated tables if needed + step 3: - if applicable finish updating outdated tables (indexes etc) + - update version & db_version in options, this is all done! + */ - // From what are we upgrading? - if ( isset( $_GET['oldver'] ) && isset( $_GET['oldsql'] ) ) { - $oldver = yourls_sanitize_version($_GET['oldver']); - $oldsql = intval($_GET['oldsql']); - } else { - list( $oldver, $oldsql ) = yourls_get_current_version_from_sql(); - } + // From what are we upgrading? + if ( isset( $_GET['oldver'] ) && isset( $_GET['oldsql'] ) ) { + $oldver = yourls_sanitize_version($_GET['oldver']); + $oldsql = intval($_GET['oldsql']); + } else { + list( $oldver, $oldsql ) = yourls_get_current_version_from_sql(); + } - // To what are we upgrading ? - $newver = YOURLS_VERSION; - $newsql = YOURLS_DB_VERSION; + // To what are we upgrading ? + $newver = YOURLS_VERSION; + $newsql = YOURLS_DB_VERSION; - // Verbose & ugly details - yourls_debug_mode(true); + // Verbose & ugly details + yourls_debug_mode(true); - // Let's go - $step = ( isset( $_GET['step'] ) ? intval( $_GET['step'] ) : 0 ); - switch( $step ) { + // Let's go + $step = ( isset( $_GET['step'] ) ? intval( $_GET['step'] ) : 0 ); + switch( $step ) { - default: - case 0: - ?> - -backup your database
(you should do this regularly anyway)' ); ?>
should happen, but this doesn't mean it won't happen, right? ;)" ); ?>
-something goes wrong, you'll see a message and hopefully a way to fix." ); ?>
-good for you, let it go :)' ); ?>
- - - - - - - - - "; + default: + case 0: + ?> + +backup your database
(you should do this regularly anyway)' ); ?>
should happen, but this doesn't mean it won't happen, right? ;)" ); ?>
+something goes wrong, you'll see a message and hopefully a way to fix." ); ?>
+good for you, let it go :)' ); ?>
+ + + + + + + + + "; - break; + break; - case 1: - case 2: - $upgrade = yourls_upgrade( $step, $oldver, $newver, $oldsql, $newsql ); - break; + case 1: + case 2: + $upgrade = yourls_upgrade( $step, $oldver, $newver, $oldsql, $newsql ); + break; - case 3: - $upgrade = yourls_upgrade( 3, $oldver, $newver, $oldsql, $newsql ); - echo '' . yourls__( 'Your installation is now up to date ! ' ) . '
'; - echo '' . yourls_s( 'Go back to the admin interface', yourls_admin_url('index.php') ) . '
'; - } + case 3: + $upgrade = yourls_upgrade( 3, $oldver, $newver, $oldsql, $newsql ); + echo '' . yourls__( 'Your installation is now up to date ! ' ) . '
'; + echo '' . yourls_s( 'Go back to the admin interface', yourls_admin_url('index.php') ) . '
'; + } } diff --git a/composer.json b/composer.json index 5b41af073..e604afd80 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ "source": "https://github.com/YOURLS/YOURLS" }, "require": { - "php": ">=7.4", + "php": "^8.1", "ext-dom": "*", "ext-filter": "*", "ext-hash": "*", @@ -27,7 +27,7 @@ "rmccue/requests" : "^2.0", "pomo/pomo" : "^1.4", "geoip2/geoip2" : "^2.10", - "aura/sql": "^3.0", + "aura/sql": "^6.0", "jakeasmith/http_build_url": "^1.0", "symfony/polyfill-mbstring": "^1.15", "symfony/polyfill-intl-idn": "^1.17", @@ -39,7 +39,7 @@ "config": { "vendor-dir": "includes/vendor", "platform": { - "php": "7.4.0" + "php": "8.1.0" } }, "autoload": { diff --git a/composer.lock b/composer.lock index 1db41c64c..764732b14 100644 --- a/composer.lock +++ b/composer.lock @@ -4,29 +4,30 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "9b65f2d0608ea42bf57901047d69e5bb", + "content-hash": "5e687d6aa23e978bd628bd3cda68d716", "packages": [ { "name": "aura/sql", - "version": "3.1.0", + "version": "6.0.0", "source": { "type": "git", "url": "https://github.com/auraphp/Aura.Sql.git", - "reference": "88d8b8ed1bcfd588a649fdc7e7ac89ec047abbca" + "reference": "8e2bb362e8953198df3682c9122e8b9edab5ff20" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/auraphp/Aura.Sql/zipball/88d8b8ed1bcfd588a649fdc7e7ac89ec047abbca", - "reference": "88d8b8ed1bcfd588a649fdc7e7ac89ec047abbca", + "url": "https://api.github.com/repos/auraphp/Aura.Sql/zipball/8e2bb362e8953198df3682c9122e8b9edab5ff20", + "reference": "8e2bb362e8953198df3682c9122e8b9edab5ff20", "shasum": "" }, "require": { - "php": ">=5.6.0", - "psr/log": "^1.0 || ^2.0" + "ext-pdo": "*", + "php": "^8.4", + "psr/log": "^1.0 || ^2.0 || ^3.0" }, "require-dev": { "pds/skeleton": "~1.0", - "yoast/phpunit-polyfills": "~1.0" + "phpunit/phpunit": "^9.5" }, "type": "library", "autoload": { @@ -59,34 +60,34 @@ ], "support": { "issues": "https://github.com/auraphp/Aura.Sql/issues", - "source": "https://github.com/auraphp/Aura.Sql/tree/3.1.0" + "source": "https://github.com/auraphp/Aura.Sql/tree/6.0.0" }, - "time": "2022-04-28T05:11:23+00:00" + "time": "2025-01-22T06:43:21+00:00" }, { "name": "composer/ca-bundle", - "version": "1.3.4", + "version": "1.5.5", "source": { "type": "git", "url": "https://github.com/composer/ca-bundle.git", - "reference": "69098eca243998b53eed7a48d82dedd28b447cd5" + "reference": "08c50d5ec4c6ced7d0271d2862dec8c1033283e6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/ca-bundle/zipball/69098eca243998b53eed7a48d82dedd28b447cd5", - "reference": "69098eca243998b53eed7a48d82dedd28b447cd5", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/08c50d5ec4c6ced7d0271d2862dec8c1033283e6", + "reference": "08c50d5ec4c6ced7d0271d2862dec8c1033283e6", "shasum": "" }, "require": { "ext-openssl": "*", "ext-pcre": "*", - "php": "^5.3.2 || ^7.0 || ^8.0" + "php": "^7.2 || ^8.0" }, "require-dev": { - "phpstan/phpstan": "^0.12.55", - "psr/log": "^1.0", - "symfony/phpunit-bridge": "^4.2 || ^5", - "symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0 || ^6.0" + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^8 || ^9", + "psr/log": "^1.0 || ^2.0 || ^3.0", + "symfony/process": "^4.0 || ^5.0 || ^6.0 || ^7.0" }, "type": "library", "extra": { @@ -121,7 +122,7 @@ "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/ca-bundle/issues", - "source": "https://github.com/composer/ca-bundle/tree/1.3.4" + "source": "https://github.com/composer/ca-bundle/tree/1.5.5" }, "funding": [ { @@ -137,14 +138,14 @@ "type": "tidelift" } ], - "time": "2022-10-12T12:08:29+00:00" + "time": "2025-01-08T16:17:16+00:00" }, { "name": "geoip2/geoip2", "version": "v2.13.0", "source": { "type": "git", - "url": "git@github.com:maxmind/GeoIP2-php.git", + "url": "https://github.com/maxmind/GeoIP2-php.git", "reference": "6a41d8fbd6b90052bc34dff3b4252d0f88067b23" }, "dist": { @@ -191,6 +192,10 @@ "geolocation", "maxmind" ], + "support": { + "issues": "https://github.com/maxmind/GeoIP2-php/issues", + "source": "https://github.com/maxmind/GeoIP2-php/tree/v2.13.0" + }, "time": "2022-08-05T20:32:58+00:00" }, { @@ -232,29 +237,27 @@ }, { "name": "maxmind-db/reader", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/maxmind/MaxMind-DB-Reader-php.git", - "reference": "b1f3c0699525336d09cc5161a2861268d9f2ae5b" + "reference": "5b2d7a721dedfaef9dc20822c5fe7d26f9f8eb90" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maxmind/MaxMind-DB-Reader-php/zipball/b1f3c0699525336d09cc5161a2861268d9f2ae5b", - "reference": "b1f3c0699525336d09cc5161a2861268d9f2ae5b", + "url": "https://api.github.com/repos/maxmind/MaxMind-DB-Reader-php/zipball/5b2d7a721dedfaef9dc20822c5fe7d26f9f8eb90", + "reference": "5b2d7a721dedfaef9dc20822c5fe7d26f9f8eb90", "shasum": "" }, "require": { "php": ">=7.2" }, "conflict": { - "ext-maxminddb": "<1.10.1,>=2.0.0" + "ext-maxminddb": "<1.11.1 || >=2.0.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "3.*", - "php-coveralls/php-coveralls": "^2.1", "phpstan/phpstan": "*", - "phpunit/phpcov": ">=6.0.0", "phpunit/phpunit": ">=8.0.0,<10.0.0", "squizlabs/php_codesniffer": "3.*" }, @@ -291,29 +294,29 @@ ], "support": { "issues": "https://github.com/maxmind/MaxMind-DB-Reader-php/issues", - "source": "https://github.com/maxmind/MaxMind-DB-Reader-php/tree/v1.11.0" + "source": "https://github.com/maxmind/MaxMind-DB-Reader-php/tree/v1.12.0" }, - "time": "2021-10-18T15:23:10+00:00" + "time": "2024-11-14T22:43:47+00:00" }, { "name": "maxmind/web-service-common", - "version": "v0.9.0", + "version": "v0.10.0", "source": { "type": "git", "url": "https://github.com/maxmind/web-service-common-php.git", - "reference": "4dc5a3e8df38aea4ca3b1096cee3a038094e9b53" + "reference": "d7c7c42fc31bff26e0ded73a6e187bcfb193f9c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maxmind/web-service-common-php/zipball/4dc5a3e8df38aea4ca3b1096cee3a038094e9b53", - "reference": "4dc5a3e8df38aea4ca3b1096cee3a038094e9b53", + "url": "https://api.github.com/repos/maxmind/web-service-common-php/zipball/d7c7c42fc31bff26e0ded73a6e187bcfb193f9c4", + "reference": "d7c7c42fc31bff26e0ded73a6e187bcfb193f9c4", "shasum": "" }, "require": { "composer/ca-bundle": "^1.0.3", "ext-curl": "*", "ext-json": "*", - "php": ">=7.2" + "php": ">=8.1" }, "require-dev": { "friendsofphp/php-cs-fixer": "3.*", @@ -342,9 +345,9 @@ "homepage": "https://github.com/maxmind/web-service-common-php", "support": { "issues": "https://github.com/maxmind/web-service-common-php/issues", - "source": "https://github.com/maxmind/web-service-common-php/tree/v0.9.0" + "source": "https://github.com/maxmind/web-service-common-php/tree/v0.10.0" }, - "time": "2022-03-28T17:43:20+00:00" + "time": "2024-11-14T23:14:52+00:00" }, { "name": "ozh/bookmarkletgen", @@ -461,30 +464,30 @@ }, { "name": "psr/log", - "version": "1.1.4", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=8.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "3.x-dev" } }, "autoload": { "psr-4": { - "Psr\\Log\\": "Psr/Log/" + "Psr\\Log\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -505,22 +508,22 @@ "psr-3" ], "support": { - "source": "https://github.com/php-fig/log/tree/1.1.4" + "source": "https://github.com/php-fig/log/tree/3.0.2" }, - "time": "2021-05-03T11:20:27+00:00" + "time": "2024-09-11T13:17:53+00:00" }, { "name": "rmccue/requests", - "version": "v2.0.5", + "version": "v2.0.15", "source": { "type": "git", "url": "https://github.com/WordPress/Requests.git", - "reference": "b717f1d2f4ef7992ec0c127747ed8b7e170c2f49" + "reference": "877cd66169755899682f1595e057334b40d9d149" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/WordPress/Requests/zipball/b717f1d2f4ef7992ec0c127747ed8b7e170c2f49", - "reference": "b717f1d2f4ef7992ec0c127747ed8b7e170c2f49", + "url": "https://api.github.com/repos/WordPress/Requests/zipball/877cd66169755899682f1595e057334b40d9d149", + "reference": "877cd66169755899682f1595e057334b40d9d149", "shasum": "" }, "require": { @@ -538,6 +541,12 @@ "wp-coding-standards/wpcs": "^2.0", "yoast/phpunit-polyfills": "^1.0.0" }, + "suggest": { + "art4/requests-psr18-adapter": "For using Requests as a PSR-18 HTTP Client", + "ext-curl": "For improved performance", + "ext-openssl": "For secure transport support", + "ext-zlib": "For improved performance when decompressing encoded streams" + }, "type": "library", "autoload": { "files": [ @@ -588,7 +597,7 @@ "issues": "https://github.com/WordPress/Requests/issues", "source": "https://github.com/WordPress/Requests" }, - "time": "2022-10-11T08:15:28+00:00" + "time": "2025-01-21T10:13:31+00:00" }, { "name": "spatie/array-to-xml", @@ -656,34 +665,30 @@ }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.27.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "639084e360537a19f9ee352433b84ce831f3d2da" + "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/639084e360537a19f9ee352433b84ce831f3d2da", - "reference": "639084e360537a19f9ee352433b84ce831f3d2da", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/c36586dcf89a12315939e00ec9b4474adcb1d773", + "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773", "shasum": "" }, "require": { - "php": ">=7.1", - "symfony/polyfill-intl-normalizer": "^1.10", - "symfony/polyfill-php72": "^1.10" + "php": ">=7.2", + "symfony/polyfill-intl-normalizer": "^1.10" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -723,7 +728,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.31.0" }, "funding": [ { @@ -739,36 +744,33 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.27.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6" + "reference": "3833d7255cc303546435cb650316bff708a1c75c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -807,7 +809,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" }, "funding": [ { @@ -823,24 +825,24 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.27.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534" + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534", - "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-mbstring": "*" @@ -850,12 +852,9 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -890,83 +889,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-11-03T14:55:06+00:00" - }, - { - "name": "symfony/polyfill-php72", - "version": "v1.27.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "869329b1e9894268a8a61dabb69153029b7a8c97" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/869329b1e9894268a8a61dabb69153029b7a8c97", - "reference": "869329b1e9894268a8a61dabb69153029b7a8c97", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php72\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" }, "funding": [ { @@ -982,17 +905,17 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2024-09-09T11:45:10+00:00" } ], "packages-dev": [], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=7.4", + "php": "^8.1", "ext-dom": "*", "ext-filter": "*", "ext-hash": "*", @@ -1004,7 +927,7 @@ "ext-ctype": "*" }, "platform-overrides": { - "php": "7.4.0" + "php": "8.1.0" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } diff --git a/css/style.css b/css/style.css index d7f50d971..e1d350df7 100644 --- a/css/style.css +++ b/css/style.css @@ -203,7 +203,7 @@ td.actions .button_stats { background:#efe; } #login { - width: 300px; + max-width: 300px; margin: 200px auto 0px auto; } #login p{ diff --git a/includes/Config/Init.php b/includes/Config/Init.php index d9f201247..d97d9ae2f 100644 --- a/includes/Config/Init.php +++ b/includes/Config/Init.php @@ -32,11 +32,6 @@ public function __construct(InitDefaults $actions) { date_default_timezone_set( 'UTC' ); } - // Load locale - if ($actions->load_default_textdomain === true) { - yourls_load_default_textdomain(); - } - // Check if we are in maintenance mode - if yes, it will die here. if ($actions->check_maintenance_mode === true) { yourls_check_maintenance_mode(); @@ -110,6 +105,11 @@ public function __construct(InitDefaults $actions) { yourls_do_action( 'plugins_loaded' ); } + // Load locale + if ($actions->load_default_textdomain === true) { + yourls_load_default_textdomain(); + } + // Is there a new version of YOURLS ? if ($actions->check_new_version === true) { if (yourls_is_installed() && !yourls_is_upgrading()) { diff --git a/includes/Database/Logger.php b/includes/Database/Logger.php index 6c77adea8..3c256dbda 100644 --- a/includes/Database/Logger.php +++ b/includes/Database/Logger.php @@ -49,7 +49,7 @@ class Logger extends AbstractLogger { * * @return void */ - public function log($level, $message, array $context = []) { + public function log($level, string|\Stringable $message, array $context = []): void { // if it's an internal SQL query, format the message, otherwise store a string if($level === 'query') { $this->messages[] = sprintf( diff --git a/includes/Database/Options.php b/includes/Database/Options.php index 2eebb641b..f175f08be 100644 --- a/includes/Database/Options.php +++ b/includes/Database/Options.php @@ -75,7 +75,7 @@ public function get_all_options() { $this->ydb->set_option($name, yourls_maybe_unserialize($value)); } - yourls_apply_filter('get_all_options', 'deprecated'); + yourls_do_action('get_all_options', $options); return true; } @@ -172,7 +172,7 @@ public function update($name, $newvalue) { // Cache option value to save a DB query if needed later $this->ydb->set_option($name, $newvalue); - yourls_do_action( 'update_option', $name, $oldvalue, $newvalue ); + yourls_do_action( 'update_option', $name, $oldvalue, $newvalue ); return true; } diff --git a/includes/Database/Profiler.php b/includes/Database/Profiler.php index be8f56c2e..ea9e4d222 100644 --- a/includes/Database/Profiler.php +++ b/includes/Database/Profiler.php @@ -23,7 +23,7 @@ class Profiler extends \Aura\Sql\Profiler\Profiler { * @param array $values The values bound to the statement, if any. * @return void */ - public function finish($statement = null, array $values = []) + public function finish(?string $statement = null, array $values = []): void { if (! $this->active) { return; diff --git a/includes/Database/YDB.php b/includes/Database/YDB.php index f13e145d1..4053f3383 100644 --- a/includes/Database/YDB.php +++ b/includes/Database/YDB.php @@ -1,12 +1,12 @@ option, or $ydb->set_option(), use yourls_*_options() functions instead). + * function wrappers (e.g. don't use $ydb->option, or $ydb->set_option(), use yourls_*_options() functions instead). * * @since 1.7.3 */ @@ -33,7 +33,7 @@ class YDB extends ExtendedPdo { protected $context = ''; /** - * Information related to a short URL keyword (eg timestamp, long URL, ...) + * Information related to a short URL keyword (e.g. timestamp, long URL, ...) * * @var array * @@ -53,13 +53,13 @@ class YDB extends ExtendedPdo { protected $option = []; /** - * Plugin admin pages informations + * Plugin admin pages information * @var array */ protected $plugin_pages = []; /** - * Plugin informations + * Plugin information * @var array */ protected $plugins = []; @@ -78,15 +78,15 @@ class YDB extends ExtendedPdo { * @param array $options Driver-specific options * @param array $attributes Attributes to set after a connection */ - public function __construct($dsn, $user, $pass, $options, $attributes) { - parent::__construct($dsn, $user, $pass, $options, $attributes); + public function __construct($dsn, $user, $pass, $options) { + parent::__construct($dsn, $user, $pass, $options); } /** * Init everything needed * * Everything we need to set up is done here in init(), not in the constructor, so even - * when the connection fails (eg config error or DB dead), the constructor has worked + * when the connection fails (e.g. config error or DB dead), the constructor has worked, * and we have a $ydb object properly instantiated (and for instance yourls_die() can * correctly die, even if using $ydb methods) * @@ -140,7 +140,8 @@ public function get_emulate_state() { */ public function connect_to_DB() { try { - $this->connect(); + list($dsn, $_user, $_pwd, $_opt, $_queries) = $this->args; + $this->connect($dsn); } catch ( \Exception $e ) { $this->dead_or_error($e); } @@ -404,22 +405,13 @@ public function is_installed() { } /** - * Return standardized DB version - * - * The regex removes everything that's not a number at the start of the string, or remove anything that's not a number and what - * follows after that. - * 'omgmysql-5.5-ubuntu-4.20' => '5.5' - * 'mysql5.5-ubuntu-4.20' => '5.5' - * '5.5-ubuntu-4.20' => '5.5' - * '5.5-beta2' => '5.5' - * '5.5' => '5.5' + * Return MySQL version * * @since 1.7.3 * @return string */ public function mysql_version() { - $version = $this->pdo->getAttribute(PDO::ATTR_SERVER_VERSION); - return $version; + return $this->pdo->getAttribute(PDO::ATTR_SERVER_VERSION); } } diff --git a/includes/Views/AdminParams.php b/includes/Views/AdminParams.php index 75de39e90..892684da6 100644 --- a/includes/Views/AdminParams.php +++ b/includes/Views/AdminParams.php @@ -222,8 +222,15 @@ public function get_click_filter() public function get_click_limit() { // @hook Default link click threshold (unset) - return (isset($_GET['click_limit']) && intval($_GET['click_limit']) >= 0) ? - intval($_GET['click_limit']) : yourls_apply_filter('admin_view_click_limit', ''); + if ( + isset($_GET['click_limit']) // Exists in the query string + && ($_GET['click_limit'] !== '') // Not empty (&stuff=&click_limit=&otherstuff=) + && intval($_GET['click_limit']) >= 0 // A number >= 0 + ) { + return intval($_GET['click_limit']); + } else { + return yourls_apply_filter('admin_view_click_limit', ''); + } } diff --git a/includes/auth.php b/includes/auth.php index 58e15c979..be98a87da 100644 --- a/includes/auth.php +++ b/includes/auth.php @@ -6,23 +6,23 @@ if( $auth !== true ) { - // API mode, - if ( yourls_is_API() ) { - $format = ( isset($_REQUEST['format']) ? $_REQUEST['format'] : 'xml' ); - $callback = ( isset($_REQUEST['callback']) ? $_REQUEST['callback'] : '' ); - yourls_api_output( $format, array( - 'simple' => $auth, - 'message' => $auth, - 'errorCode' => 403, - 'callback' => $callback, - ) ); - - // Regular mode - } else { - yourls_login_screen( $auth ); - } - - die(); + // API mode, + if ( yourls_is_API() ) { + $format = ( isset($_REQUEST['format']) ? $_REQUEST['format'] : 'xml' ); + $callback = ( isset($_REQUEST['callback']) ? $_REQUEST['callback'] : '' ); + yourls_api_output( $format, array( + 'simple' => $auth, + 'message' => $auth, + 'errorCode' => '403', + 'callback' => $callback, + ) ); + + // Regular mode + } else { + yourls_login_screen( $auth ); + } + + die(); } yourls_do_action( 'auth_successful' ); @@ -36,12 +36,12 @@ // Did we just fail at encrypting passwords ? if ( isset( $_GET['dismiss'] ) && $_GET['dismiss'] == 'hasherror' ) { - yourls_update_option( 'defer_hashing_error', time() + 86400 * 7 ); // now + 1 week + yourls_update_option( 'defer_hashing_error', time() + 86400 * 7 ); // now + 1 week } else { - // Encrypt passwords that are clear text - if ( yourls_maybe_hash_passwords() ) { + // Encrypt passwords that are clear text + if ( yourls_maybe_hash_passwords() ) { $hash = yourls_hash_passwords_now( YOURLS_CONFIGFILE ); if ( $hash === true ) { // Hashing successful. Remove flag from DB if any. @@ -59,5 +59,5 @@ yourls_add_notice( $message ); } } - } + } } diff --git a/includes/functions-api.php b/includes/functions-api.php index 45395ac89..6ef3e2740 100644 --- a/includes/functions-api.php +++ b/includes/functions-api.php @@ -15,13 +15,13 @@ * @return array Result of API call */ function yourls_api_action_shorturl() { - $url = ( isset( $_REQUEST['url'] ) ? $_REQUEST['url'] : '' ); - $keyword = ( isset( $_REQUEST['keyword'] ) ? $_REQUEST['keyword'] : '' ); - $title = ( isset( $_REQUEST['title'] ) ? $_REQUEST['title'] : '' ); - $return = yourls_add_new_link( $url, $keyword, $title ); - $return['simple'] = ( isset( $return['shorturl'] ) ? $return['shorturl'] : '' ); // This one will be used in case output mode is 'simple' - unset( $return['html'] ); // in API mode, no need for our internal HTML output - return yourls_apply_filter( 'api_result_shorturl', $return ); + $url = ( isset( $_REQUEST['url'] ) ? $_REQUEST['url'] : '' ); + $keyword = ( isset( $_REQUEST['keyword'] ) ? $_REQUEST['keyword'] : '' ); + $title = ( isset( $_REQUEST['title'] ) ? $_REQUEST['title'] : '' ); + $return = yourls_add_new_link( $url, $keyword, $title ); + $return['simple'] = ( isset( $return['shorturl'] ) ? $return['shorturl'] : '' ); // This one will be used in case output mode is 'simple' + unset( $return['html'] ); // in API mode, no need for our internal HTML output + return yourls_apply_filter( 'api_result_shorturl', $return ); } /** @@ -31,10 +31,10 @@ function yourls_api_action_shorturl() { * @return array Result of API call */ function yourls_api_action_stats() { - $filter = ( isset( $_REQUEST['filter'] ) ? $_REQUEST['filter'] : '' ); - $limit = ( isset( $_REQUEST['limit'] ) ? $_REQUEST['limit'] : '' ); - $start = ( isset( $_REQUEST['start'] ) ? $_REQUEST['start'] : '' ); - return yourls_apply_filter( 'api_result_stats', yourls_api_stats( $filter, $limit, $start ) ); + $filter = ( isset( $_REQUEST['filter'] ) ? $_REQUEST['filter'] : '' ); + $limit = ( isset( $_REQUEST['limit'] ) ? $_REQUEST['limit'] : '' ); + $start = ( isset( $_REQUEST['start'] ) ? $_REQUEST['start'] : '' ); + return yourls_apply_filter( 'api_result_stats', yourls_api_stats( $filter, $limit, $start ) ); } /** @@ -44,7 +44,7 @@ function yourls_api_action_stats() { * @return array Result of API call */ function yourls_api_action_db_stats() { - return yourls_apply_filter( 'api_result_db_stats', yourls_api_db_stats() ); + return yourls_apply_filter( 'api_result_db_stats', yourls_api_db_stats() ); } /** @@ -54,8 +54,8 @@ function yourls_api_action_db_stats() { * @return array Result of API call */ function yourls_api_action_url_stats() { - $shorturl = ( isset( $_REQUEST['shorturl'] ) ? $_REQUEST['shorturl'] : '' ); - return yourls_apply_filter( 'api_result_url_stats', yourls_api_url_stats( $shorturl ) ); + $shorturl = ( isset( $_REQUEST['shorturl'] ) ? $_REQUEST['shorturl'] : '' ); + return yourls_apply_filter( 'api_result_url_stats', yourls_api_url_stats( $shorturl ) ); } /** @@ -65,8 +65,8 @@ function yourls_api_action_url_stats() { * @return array Result of API call */ function yourls_api_action_expand() { - $shorturl = ( isset( $_REQUEST['shorturl'] ) ? $_REQUEST['shorturl'] : '' ); - return yourls_apply_filter( 'api_result_expand', yourls_api_expand( $shorturl ) ); + $shorturl = ( isset( $_REQUEST['shorturl'] ) ? $_REQUEST['shorturl'] : '' ); + return yourls_apply_filter( 'api_result_expand', yourls_api_expand( $shorturl ) ); } /** @@ -76,10 +76,10 @@ function yourls_api_action_expand() { * @return array Result of API call */ function yourls_api_action_version() { - $return['version'] = $return['simple'] = YOURLS_VERSION; - if( isset( $_REQUEST['db'] ) && $_REQUEST['db'] == 1 ) - $return['db_version'] = YOURLS_DB_VERSION; - return yourls_apply_filter( 'api_result_version', $return ); + $return['version'] = $return['simple'] = YOURLS_VERSION; + if( isset( $_REQUEST['db'] ) && $_REQUEST['db'] == 1 ) + $return['db_version'] = YOURLS_DB_VERSION; + return yourls_apply_filter( 'api_result_version', $return ); } /** @@ -99,12 +99,12 @@ function yourls_api_action_version() { * @return string API output, as an XML / JSON / JSONP / raw text string */ function yourls_api_output( $mode, $output, $send_headers = true, $echo = true ) { - if( isset( $output['simple'] ) ) { - $simple = $output['simple']; - unset( $output['simple'] ); - } + if( isset( $output['simple'] ) ) { + $simple = $output['simple']; + unset( $output['simple'] ); + } - yourls_do_action( 'pre_api_output', $mode, $output, $send_headers, $echo ); + yourls_do_action( 'pre_api_output', $mode, $output, $send_headers, $echo ); if( $send_headers ) { if( isset( $output['statusCode'] ) ) { @@ -119,43 +119,43 @@ function yourls_api_output( $mode, $output, $send_headers = true, $echo = true ) $result = ''; - switch ( $mode ) { - case 'jsonp': + switch ( $mode ) { + case 'jsonp': if( $send_headers ) yourls_content_type_header( 'application/javascript' ); $callback = isset( $output['callback'] ) ? $output['callback'] : ''; - $result = $callback . '(' . json_encode( $output ) . ')'; - break; + $result = $callback . '(' . json_encode( $output ) . ')'; + break; - case 'json': + case 'json': if( $send_headers ) yourls_content_type_header( 'application/json' ); - $result = json_encode( $output ); - break; + $result = json_encode( $output ); + break; - case 'xml': + case 'xml': if( $send_headers ) yourls_content_type_header( 'application/xml' ); - $result = yourls_xml_encode( $output ); - break; + $result = yourls_xml_encode( $output ); + break; - case 'simple': - default: + case 'simple': + default: if( $send_headers ) yourls_content_type_header( 'text/plain' ); - $result = isset( $simple ) ? $simple : ''; - break; - } + $result = isset( $simple ) ? $simple : ''; + break; + } if( $echo ) { echo $result; } - yourls_do_action( 'api_output', $mode, $output, $send_headers, $echo ); + yourls_do_action( 'api_output', $mode, $output, $send_headers, $echo ); return $result; } @@ -169,10 +169,10 @@ function yourls_api_output( $mode, $output, $send_headers = true, $echo = true ) * @return array */ function yourls_api_stats($filter = 'top', $limit = 10, $start = 0 ) { - $return = yourls_get_stats( $filter, $limit, $start ); - $return['simple'] = 'Need either XML or JSON format for stats'; - $return['message'] = 'success'; - return yourls_apply_filter( 'api_stats', $return, $filter, $limit, $start ); + $return = yourls_get_stats( $filter, $limit, $start ); + $return['simple'] = 'Need either XML or JSON format for stats'; + $return['message'] = 'success'; + return yourls_apply_filter( 'api_stats', $return, $filter, $limit, $start ); } /** @@ -181,14 +181,14 @@ function yourls_api_stats($filter = 'top', $limit = 10, $start = 0 ) { * @return array */ function yourls_api_db_stats() { - $return = array( - 'db-stats' => yourls_get_db_stats(), - 'statusCode' => 200, - 'simple' => 'Need either XML or JSON format for stats', - 'message' => 'success', - ); - - return yourls_apply_filter( 'api_db_stats', $return ); + $return = array( + 'db-stats' => yourls_get_db_stats(), + 'statusCode' => '200', + 'simple' => 'Need either XML or JSON format for stats', + 'message' => 'success', + ); + + return yourls_apply_filter( 'api_db_stats', $return ); } /** @@ -198,12 +198,12 @@ function yourls_api_db_stats() { * @return array */ function yourls_api_url_stats( $shorturl ) { - $keyword = str_replace( yourls_get_yourls_site() . '/' , '', $shorturl ); // accept either 'http://ozh.in/abc' or 'abc' - $keyword = yourls_sanitize_keyword( $keyword ); + $keyword = str_replace( yourls_get_yourls_site() . '/' , '', $shorturl ); // accept either 'http://ozh.in/abc' or 'abc' + $keyword = yourls_sanitize_keyword( $keyword ); - $return = yourls_get_keyword_stats( $keyword ); - $return['simple'] = 'Need either XML or JSON format for stats'; - return yourls_apply_filter( 'api_url_stats', $return, $shorturl ); + $return = yourls_get_keyword_stats( $keyword ); + $return['simple'] = 'Need either XML or JSON format for stats'; + return yourls_apply_filter( 'api_url_stats', $return, $shorturl ); } /** @@ -213,29 +213,29 @@ function yourls_api_url_stats( $shorturl ) { * @return array */ function yourls_api_expand( $shorturl ) { - $keyword = str_replace( yourls_get_yourls_site() . '/' , '', $shorturl ); // accept either 'http://ozh.in/abc' or 'abc' - $keyword = yourls_sanitize_keyword( $keyword ); + $keyword = str_replace( yourls_get_yourls_site() . '/' , '', $shorturl ); // accept either 'http://ozh.in/abc' or 'abc' + $keyword = yourls_sanitize_keyword( $keyword ); - $longurl = yourls_get_keyword_longurl( $keyword ); + $longurl = yourls_get_keyword_longurl( $keyword ); - if( $longurl ) { - $return = array( - 'keyword' => $keyword, - 'shorturl' => yourls_link($keyword), - 'longurl' => $longurl, + if( $longurl ) { + $return = array( + 'keyword' => $keyword, + 'shorturl' => yourls_link($keyword), + 'longurl' => $longurl, 'title' => yourls_get_keyword_title( $keyword ), - 'simple' => $longurl, - 'message' => 'success', - 'statusCode' => 200, - ); - } else { - $return = array( - 'keyword' => $keyword, - 'simple' => 'not found', - 'message' => 'Error: short URL not found', - 'errorCode' => 404, - ); - } - - return yourls_apply_filter( 'api_expand', $return, $shorturl ); + 'simple' => $longurl, + 'message' => 'success', + 'statusCode' => '200', + ); + } else { + $return = array( + 'keyword' => $keyword, + 'simple' => 'not found', + 'message' => 'Error: short URL not found', + 'errorCode' => '404', + ); + } + + return yourls_apply_filter( 'api_expand', $return, $shorturl ); } diff --git a/includes/functions-auth.php b/includes/functions-auth.php index f074c21c6..cadf538b4 100644 --- a/includes/functions-auth.php +++ b/includes/functions-auth.php @@ -10,12 +10,12 @@ * @return void */ function yourls_maybe_require_auth() { - if( yourls_is_private() ) { - yourls_do_action( 'require_auth' ); - require_once( YOURLS_INC.'/auth.php' ); - } else { - yourls_do_action( 'require_no_auth' ); - } + if( yourls_is_private() ) { + yourls_do_action( 'require_auth' ); + require_once( YOURLS_INC.'/auth.php' ); + } else { + yourls_do_action( 'require_no_auth' ); + } } /** @@ -24,102 +24,102 @@ function yourls_maybe_require_auth() { * @return bool|string|mixed true if valid user, error message otherwise. Can also call yourls_die() or redirect to login page. Oh my. */ function yourls_is_valid_user() { - // Allow plugins to short-circuit the whole function - $pre = yourls_apply_filter( 'shunt_is_valid_user', null ); - if ( null !== $pre ) { - return $pre; - } + // Allow plugins to short-circuit the whole function + $pre = yourls_apply_filter( 'shunt_is_valid_user', null ); + if ( null !== $pre ) { + return $pre; + } - // $unfiltered_valid : are credentials valid? Boolean value. It's "unfiltered" to allow plugins to eventually filter it. - $unfiltered_valid = false; + // $unfiltered_valid : are credentials valid? Boolean value. It's "unfiltered" to allow plugins to eventually filter it. + $unfiltered_valid = false; - // Logout request - if( isset( $_GET['action'] ) && $_GET['action'] == 'logout' && isset( $_REQUEST['nonce'] ) ) { + // Logout request + if( isset( $_GET['action'] ) && $_GET['action'] == 'logout' && isset( $_REQUEST['nonce'] ) ) { // The logout nonce is associated to fake user 'logout' since at this point we don't know the real user yourls_verify_nonce('admin_logout', $_REQUEST['nonce'], 'logout'); - yourls_do_action( 'logout' ); - yourls_store_cookie( '' ); - return yourls__( 'Logged out successfully' ); - } - - // Check cookies or login request. Login form has precedence. - - yourls_do_action( 'pre_login' ); - - // Determine auth method and check credentials - if - // API only: Secure (no login or pwd) and time limited token - // ?timestamp=12345678&signature=md5(totoblah12345678) - ( yourls_is_API() && - isset( $_REQUEST['timestamp'] ) && !empty($_REQUEST['timestamp'] ) && - isset( $_REQUEST['signature'] ) && !empty($_REQUEST['signature'] ) - ) - { - yourls_do_action( 'pre_login_signature_timestamp' ); - $unfiltered_valid = yourls_check_signature_timestamp(); - } - - elseif - // API only: Secure (no login or pwd) - // ?signature=md5(totoblah) - ( yourls_is_API() && - !isset( $_REQUEST['timestamp'] ) && - isset( $_REQUEST['signature'] ) && !empty( $_REQUEST['signature'] ) - ) - { - yourls_do_action( 'pre_login_signature' ); - $unfiltered_valid = yourls_check_signature(); - } - - elseif - // API or normal: login with username & pwd - ( isset( $_REQUEST['username'] ) && isset( $_REQUEST['password'] ) - && !empty( $_REQUEST['username'] ) && !empty( $_REQUEST['password'] ) ) - { - yourls_do_action( 'pre_login_username_password' ); - $unfiltered_valid = yourls_check_username_password(); - } - - elseif - // Normal only: cookies - ( !yourls_is_API() && - isset( $_COOKIE[ yourls_cookie_name() ] ) ) - { - yourls_do_action( 'pre_login_cookie' ); - $unfiltered_valid = yourls_check_auth_cookie(); - } - - // Regardless of validity, allow plugins to filter the boolean and have final word - $valid = yourls_apply_filter( 'is_valid_user', $unfiltered_valid ); - - // Login for the win! - if ( $valid ) { - yourls_do_action( 'login' ); - - // (Re)store encrypted cookie if needed - if ( !yourls_is_API() ) { - yourls_store_cookie( YOURLS_USER ); - - // Login form : redirect to requested URL to avoid re-submitting the login form on page reload - if( isset( $_REQUEST['username'] ) && isset( $_REQUEST['password'] ) && isset( $_SERVER['REQUEST_URI'] ) ) { - // The return makes sure we exit this function before waiting for redirection. + yourls_do_action( 'logout' ); + yourls_store_cookie( '' ); + return yourls__( 'Logged out successfully' ); + } + + // Check cookies or login request. Login form has precedence. + + yourls_do_action( 'pre_login' ); + + // Determine auth method and check credentials + if + // API only: Secure (no login or pwd) and time limited token + // ?timestamp=12345678&signature=md5(totoblah12345678) + ( yourls_is_API() && + isset( $_REQUEST['timestamp'] ) && !empty($_REQUEST['timestamp'] ) && + isset( $_REQUEST['signature'] ) && !empty($_REQUEST['signature'] ) + ) + { + yourls_do_action( 'pre_login_signature_timestamp' ); + $unfiltered_valid = yourls_check_signature_timestamp(); + } + + elseif + // API only: Secure (no login or pwd) + // ?signature=md5(totoblah) + ( yourls_is_API() && + !isset( $_REQUEST['timestamp'] ) && + isset( $_REQUEST['signature'] ) && !empty( $_REQUEST['signature'] ) + ) + { + yourls_do_action( 'pre_login_signature' ); + $unfiltered_valid = yourls_check_signature(); + } + + elseif + // API or normal: login with username & pwd + ( isset( $_REQUEST['username'] ) && isset( $_REQUEST['password'] ) + && !empty( $_REQUEST['username'] ) && !empty( $_REQUEST['password'] ) ) + { + yourls_do_action( 'pre_login_username_password' ); + $unfiltered_valid = yourls_check_username_password(); + } + + elseif + // Normal only: cookies + ( !yourls_is_API() && + isset( $_COOKIE[ yourls_cookie_name() ] ) ) + { + yourls_do_action( 'pre_login_cookie' ); + $unfiltered_valid = yourls_check_auth_cookie(); + } + + // Regardless of validity, allow plugins to filter the boolean and have final word + $valid = yourls_apply_filter( 'is_valid_user', $unfiltered_valid ); + + // Login for the win! + if ( $valid ) { + yourls_do_action( 'login' ); + + // (Re)store encrypted cookie if needed + if ( !yourls_is_API() ) { + yourls_store_cookie( YOURLS_USER ); + + // Login form : redirect to requested URL to avoid re-submitting the login form on page reload + if( isset( $_REQUEST['username'] ) && isset( $_REQUEST['password'] ) && isset( $_SERVER['REQUEST_URI'] ) ) { + // The return makes sure we exit this function before waiting for redirection. // See #3189 and note in yourls_redirect() - return yourls_redirect( yourls_sanitize_url_safe($_SERVER['REQUEST_URI']) ); - } - } + return yourls_redirect( yourls_sanitize_url_safe($_SERVER['REQUEST_URI']) ); + } + } - // Login successful - return true; - } + // Login successful + return true; + } - // Login failed - yourls_do_action( 'login_failed' ); + // Login failed + yourls_do_action( 'login_failed' ); - if ( isset( $_REQUEST['username'] ) || isset( $_REQUEST['password'] ) ) { - return yourls__( 'Invalid username or password' ); - } else { - return yourls__( 'Please log in' ); - } + if ( isset( $_REQUEST['username'] ) || isset( $_REQUEST['password'] ) ) { + return yourls__( 'Invalid username or password' ); + } else { + return yourls__( 'Please log in' ); + } } /** @@ -128,18 +128,18 @@ function yourls_is_valid_user() { * @return bool true if login/pwd pair is valid (and sets user if applicable), false otherwise */ function yourls_check_username_password() { - global $yourls_user_passwords; + global $yourls_user_passwords; - // If login form (not API), check for nonce + // If login form (not API), check for nonce if(!yourls_is_API()) { yourls_verify_nonce('admin_login'); } - if( isset( $yourls_user_passwords[ $_REQUEST['username'] ] ) && yourls_check_password_hash( $_REQUEST['username'], $_REQUEST['password'] ) ) { - yourls_set_user( $_REQUEST['username'] ); - return true; - } - return false; + if( isset( $yourls_user_passwords[ $_REQUEST['username'] ] ) && yourls_check_password_hash( $_REQUEST['username'], $_REQUEST['password'] ) ) { + yourls_set_user( $_REQUEST['username'] ); + return true; + } + return false; } /** @@ -150,24 +150,24 @@ function yourls_check_username_password() { * @return bool */ function yourls_check_password_hash($user, $submitted_password ) { - global $yourls_user_passwords; + global $yourls_user_passwords; - if( !isset( $yourls_user_passwords[ $user ] ) ) - return false; + if( !isset( $yourls_user_passwords[ $user ] ) ) + return false; - if ( yourls_has_phpass_password( $user ) ) { - // Stored password is hashed - list( , $hash ) = explode( ':', $yourls_user_passwords[ $user ] ); - $hash = str_replace( '!', '$', $hash ); - return ( yourls_phpass_check( $submitted_password, $hash ) ); - } else if( yourls_has_md5_password( $user ) ) { - // Stored password is a salted md5 hash: "md5:<$r = rand(10000,99999)>:'; - echo join( "\n", yourls_get_debug_log() ); - echo ''; - } ?> - - - - + + +
'; + echo join( "\n", yourls_get_debug_log() ); + echo ''; + } ?> + +