diff --git a/.gitignore b/.gitignore
index b7fd377..9656d79 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,9 @@ user/plugins/*/vendor/*
# frontend tooling
frontend/node_modules
frontend/package-lock.json
+node_modules
+package-lock.json
+
# backend tooling
user/plugins/sleeky-backend/node_modules
diff --git a/admin/admin-ajax.php b/admin/admin-ajax.php
index 88de236..edfa16a 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 da52bca..1e60a56 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=
- $url = $_GET['u'];
- } else {
- // New style bookmarklet: ?up=&us=&ur=
- $url = $_GET['up'] . $_GET['us'] . $_GET['ur'];
- }
- $keyword = ( isset( $_GET['k'] ) ? ( $_GET['k'] ) : '' );
- $title = ( isset( $_GET['t'] ) ? ( $_GET['t'] ) : '' );
- $return = yourls_add_new_link( $url, $keyword, $title );
-
- // If fails because keyword already exist, retry with no keyword
- if ( isset( $return['status'] ) && $return['status'] == 'fail' && isset( $return['code'] ) && $return['code'] == 'error:keyword' ) {
- $msg = $return['message'];
- $return = yourls_add_new_link( $url, '' );
- $return['message'] .= ' ('.$msg.')';
- }
-
- // Stop here if bookmarklet with a JSON callback function
- if( isset( $_GET['jsonp'] ) && $_GET['jsonp'] == 'yourls' ) {
- $short = $return['shorturl'] ? $return['shorturl'] : '';
- $message = $return['message'];
- yourls_content_type_header( 'application/javascript' );
- echo yourls_apply_filter( 'bookmarklet_jsonp', "yourls_callback({'short_url':'$short','message':'$message'});" );
-
- die();
- }
-
- // Now use the URL that has been sanitized and returned by yourls_add_new_link()
- $url = $return['url']['url'];
- $where['sql'] .= ' AND `url` LIKE :url ';
+ $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=
+ $url = $_GET['u'];
+ } else {
+ // New style bookmarklet: ?up=&us=&ur=
+ $url = $_GET['up'] . $_GET['us'] . $_GET['ur'];
+ }
+ $keyword = ( isset( $_GET['k'] ) ? ( $_GET['k'] ) : '' );
+ $title = ( isset( $_GET['t'] ) ? ( $_GET['t'] ) : '' );
+ $return = yourls_add_new_link( $url, $keyword, $title );
+
+ // If fails because keyword already exist, retry with no keyword
+ if ( isset( $return['status'] ) && $return['status'] == 'fail' && isset( $return['code'] ) && $return['code'] == 'error:keyword' ) {
+ $msg = $return['message'];
+ $return = yourls_add_new_link( $url, '' );
+ $return['message'] .= ' ('.$msg.')';
+ }
+
+ // Stop here if bookmarklet with a JSON callback function
+ if( isset( $_GET['jsonp'] ) && $_GET['jsonp'] == 'yourls' ) {
+ $short = $return['shorturl'] ? $return['shorturl'] : '';
+ $message = $return['message'];
+ yourls_content_type_header( 'application/javascript' );
+ echo yourls_apply_filter( 'bookmarklet_jsonp', "yourls_callback({'short_url':'$short','message':'$message'});" );
+
+ die();
+ }
+
+ // Now use the URL that has been sanitized and returned by yourls_add_new_link()
+ $url = $return['url']['url'];
+ $where['sql'] .= ' AND `url` LIKE :url ';
$where['binds']['url'] = $url;
- $page = $total_pages = $perpage = 1;
- $offset = 0;
-
- $text = ( isset( $_GET['s'] ) ? stripslashes( $_GET['s'] ) : '' );
-
- // Sharing with social bookmarklets
- if( !empty($_GET['share']) ) {
- yourls_do_action( 'pre_share_redirect' );
- switch ( $_GET['share'] ) {
- case 'twitter':
- // share with Twitter
- $destination = sprintf( "https://twitter.com/intent/tweet?url=%s&text=%s", urlencode( $return['shorturl'] ), urlencode( $title ) );
- yourls_redirect( $destination, 303 );
-
- // Deal with the case when redirection failed:
- $return['status'] = 'error';
- $return['errorCode'] = '400';
- $return['message'] = yourls_s( 'Short URL created, but could not redirect to %s !', 'Twitter' );
- break;
-
- case 'facebook':
- // share with Facebook
- $destination = sprintf( "https://www.facebook.com/sharer/sharer.php?u=%s&t=%s", urlencode( $return['shorturl'] ), urlencode( $title ) );
- yourls_redirect( $destination, 303 );
-
- // Deal with the case when redirection failed:
- $return['status'] = 'error';
- $return['errorCode'] = '400';
- $return['message'] = yourls_s( 'Short URL created, but could not redirect to %s !', 'Facebook' );
- break;
-
- case 'tumblr':
- // share with Tumblr
- $destination = sprintf( "https://www.tumblr.com/share?v=3&u=%s&t=%s&s=%s", urlencode( $return['shorturl'] ), urlencode( $title ), urlencode( $text ) );
- yourls_redirect( $destination, 303 );
-
- // Deal with the case when redirection failed:
- $return['status'] = 'error';
- $return['errorCode'] = '400';
- $return['message'] = yourls_s( 'Short URL created, but could not redirect to %s !', 'Tumblr' );
- break;
-
- default:
- // Is there a custom registered social bookmark?
- yourls_do_action( 'share_redirect_' . $_GET['share'], $return );
-
- // Still here? That was an unknown 'share' method, then.
- $return['status'] = 'error';
- $return['errorCode'] = '400';
- $return['message'] = yourls__( 'Unknown "Share" bookmarklet' );
- break;
- }
- }
+ $page = $total_pages = $perpage = 1;
+ $offset = 0;
+
+ $text = ( isset( $_GET['s'] ) ? stripslashes( $_GET['s'] ) : '' );
+
+ // Sharing with social bookmarklets
+ if( !empty($_GET['share']) ) {
+ yourls_do_action( 'pre_share_redirect' );
+ switch ( $_GET['share'] ) {
+ case 'twitter':
+ // share with Twitter
+ $destination = sprintf( "https://twitter.com/intent/tweet?url=%s&text=%s", urlencode( $return['shorturl'] ), urlencode( $title ) );
+ yourls_redirect( $destination, 303 );
+
+ // Deal with the case when redirection failed:
+ $return['status'] = 'error';
+ $return['errorCode'] = '400';
+ $return['message'] = yourls_s( 'Short URL created, but could not redirect to %s !', 'Twitter' );
+ break;
+
+ case 'facebook':
+ // share with Facebook
+ $destination = sprintf( "https://www.facebook.com/sharer/sharer.php?u=%s&t=%s", urlencode( $return['shorturl'] ), urlencode( $title ) );
+ yourls_redirect( $destination, 303 );
+
+ // Deal with the case when redirection failed:
+ $return['status'] = 'error';
+ $return['errorCode'] = '400';
+ $return['message'] = yourls_s( 'Short URL created, but could not redirect to %s !', 'Facebook' );
+ break;
+
+ case 'tumblr':
+ // share with Tumblr
+ $destination = sprintf( "https://www.tumblr.com/share?v=3&u=%s&t=%s&s=%s", urlencode( $return['shorturl'] ), urlencode( $title ), urlencode( $text ) );
+ yourls_redirect( $destination, 303 );
+
+ // Deal with the case when redirection failed:
+ $return['status'] = 'error';
+ $return['errorCode'] = '400';
+ $return['message'] = yourls_s( 'Short URL created, but could not redirect to %s !', 'Tumblr' );
+ break;
+
+ default:
+ // Is there a custom registered social bookmark?
+ yourls_do_action( 'share_redirect_' . $_GET['share'], $return );
+
+ // Still here? That was an unknown 'share' method, then.
+ $return['status'] = 'error';
+ $return['errorCode'] = '400';
+ $return['message'] = yourls__( 'Unknown "Share" bookmarklet' );
+ break;
+ }
+ }
// This is not a bookmarklet
} else {
- $is_bookmark = false;
-
- // Checking $page, $offset, $perpage
- if( empty($page) || $page == 0 ) {
- $page = 1;
- }
- if( empty($offset) ) {
- $offset = 0;
- }
- if( empty($perpage) || $perpage == 0) {
- $perpage = 50;
- }
-
- // Determine $offset
- $offset = ( $page-1 ) * $perpage;
-
- // Determine Max Number Of Items To Display On Page
- if( ( $offset + $perpage ) > $total_items ) {
- $max_on_page = $total_items;
- } else {
- $max_on_page = ( $offset + $perpage );
- }
-
- // Determine Number Of Items To Display On Page
- if ( ( $offset + 1 ) > $total_items ) {
- $display_on_page = $total_items;
- } else {
- $display_on_page = ( $offset + 1 );
- }
-
- // Determine Total Amount Of Pages
- $total_pages = ceil( $total_items / $perpage );
+ $is_bookmark = false;
+
+ // Checking $page, $offset, $perpage
+ if( empty($page) || $page == 0 ) {
+ $page = 1;
+ }
+ if( empty($offset) ) {
+ $offset = 0;
+ }
+ if( empty($perpage) || $perpage == 0) {
+ $perpage = 50;
+ }
+
+ // Determine $offset
+ $offset = ( $page-1 ) * $perpage;
+
+ // Determine Max Number Of Items To Display On Page
+ if( ( $offset + $perpage ) > $total_items ) {
+ $max_on_page = $total_items;
+ } else {
+ $max_on_page = ( $offset + $perpage );
+ }
+
+ // Determine Number Of Items To Display On Page
+ if ( ( $offset + 1 ) > $total_items ) {
+ $display_on_page = $total_items;
+ } else {
+ $display_on_page = ( $offset + 1 );
+ }
+
+ // Determine Total Amount Of Pages
+ $total_pages = ceil( $total_items / $perpage );
}
@@ -241,18 +244,18 @@
yourls_do_action( 'admin_page_before_content' );
if ( !$is_bookmark ) { ?>
-
- %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 ) ); ?>
$(document).ready(function(){
- feedback( "' . $return['message'] . '", "'. $return['status'] .'");
- init_clipboard();
- });';
+ echo '';
}
yourls_do_action( 'admin_page_before_table' );
@@ -276,42 +279,42 @@
yourls_table_head();
if ( !$is_bookmark ) {
- $params = array(
- 'search' => $search,
- 'search_text' => $search_text,
- 'search_in' => $search_in,
- 'sort_by' => $sort_by,
- 'sort_order' => $sort_order,
- 'page' => $page,
- 'perpage' => $perpage,
- 'click_filter' => $click_filter,
- 'click_limit' => $click_limit,
- 'total_pages' => $total_pages,
- 'date_filter' => $date_filter,
- 'date_first' => $date_first,
- 'date_second' => $date_second,
- );
- yourls_html_tfooter( $params );
+ $params = array(
+ 'search' => $search,
+ 'search_text' => $search_text,
+ 'search_in' => $search_in,
+ 'sort_by' => $sort_by,
+ 'sort_order' => $sort_order,
+ 'page' => $page,
+ 'perpage' => $perpage,
+ 'click_filter' => $click_filter,
+ 'click_limit' => $click_limit,
+ 'total_pages' => $total_pages,
+ 'date_filter' => $date_filter,
+ 'date_first' => $date_first,
+ 'date_second' => $date_second,
+ );
+ yourls_html_tfooter( $params );
}
yourls_table_tbody_start();
// Main Query
$where = yourls_apply_filter( 'admin_list_where', $where );
-$url_results = yourls_get_db()->fetchObjects( "SELECT * FROM `$table_url` WHERE 1=1 {$where['sql']} ORDER BY `$sort_by` $sort_order LIMIT $offset, $perpage;", $where['binds'] );
+$url_results = yourls_get_db('read-admin_index')->fetchObjects( "SELECT * FROM `$table_url` WHERE 1=1 {$where['sql']} ORDER BY `$sort_by` $sort_order LIMIT $offset, $perpage;", $where['binds'] );
$found_rows = false;
if( $url_results ) {
- $found_rows = true;
- foreach( $url_results as $url_result ) {
- $keyword = yourls_sanitize_keyword($url_result->keyword);
- $timestamp = strtotime( $url_result->timestamp );
- $url = stripslashes( $url_result->url );
- $ip = $url_result->ip;
- $title = $url_result->title ? $url_result->title : '';
- $clicks = $url_result->clicks;
-
- echo yourls_table_add_row( $keyword, $url, $title, $ip, $clicks, $timestamp );
- }
+ $found_rows = true;
+ foreach( $url_results as $url_result ) {
+ $keyword = yourls_sanitize_keyword($url_result->keyword);
+ $timestamp = strtotime( $url_result->timestamp );
+ $url = stripslashes( $url_result->url );
+ $ip = $url_result->ip;
+ $title = $url_result->title ? $url_result->title : '';
+ $clicks = $url_result->clicks;
+
+ echo yourls_table_add_row( $keyword, $url, $title, $ip, $clicks, $timestamp );
+ }
}
$display = $found_rows ? 'display:none' : '';
@@ -323,8 +326,10 @@
yourls_do_action( 'admin_page_after_table' );
+yourls_delete_link_modal();
+
if ( $is_bookmark )
- yourls_share_box( $url, $return['shorturl'], $title, $text );
+ yourls_share_box( $url, $return['shorturl'], $title, $text );
?>
diff --git a/admin/install.php b/admin/install.php
index 3b00450..3d4b99a 100644
--- a/admin/install.php
+++ b/admin/install.php
@@ -9,44 +9,44 @@
// Check pre-requisites
if ( !yourls_check_PDO() ) {
- $error[] = yourls__( 'PHP extension for PDO not found' );
- yourls_debug_log( 'PHP PDO extension not found' );
+ $error[] = yourls__( 'PHP extension for PDO not found' );
+ yourls_debug_log( 'PHP PDO extension not found' );
}
if ( !yourls_check_database_version() ) {
- $error[] = yourls_s( '%s version is too old. Ask your server admin for an upgrade.', 'MySQL' );
- yourls_debug_log( 'MySQL version: ' . yourls_get_database_version() );
+ $error[] = yourls_s( '%s version is too old. Ask your server admin for an upgrade.', 'MySQL' );
+ yourls_debug_log( 'MySQL version: ' . yourls_get_database_version() );
}
if ( !yourls_check_php_version() ) {
- $error[] = yourls_s( '%s version is too old. Ask your server admin for an upgrade.', 'PHP' );
- yourls_debug_log( 'PHP version: ' . PHP_VERSION );
+ $error[] = yourls_s( '%s version is too old. Ask your server admin for an upgrade.', 'PHP' );
+ yourls_debug_log( 'PHP version: ' . PHP_VERSION );
}
// Is YOURLS already installed ?
if ( yourls_is_installed() ) {
- $error[] = yourls__( 'YOURLS already installed.' );
- // check if .htaccess exists, recreate otherwise. No error checking.
- if( !file_exists( YOURLS_ABSPATH.'/.htaccess' ) ) {
- yourls_create_htaccess();
- }
+ $error[] = yourls__( 'YOURLS already installed.' );
+ // check if .htaccess exists, recreate otherwise. No error checking.
+ if( !file_exists( YOURLS_ABSPATH.'/.htaccess' ) ) {
+ yourls_create_htaccess();
+ }
}
// Start install if possible and needed
if ( isset($_REQUEST['install']) && count( $error ) == 0 ) {
- // Create/update .htaccess file
- if ( yourls_create_htaccess() ) {
- $success[] = yourls__( 'File .htaccess successfully created/updated.' );
- } else {
- $warning[] = yourls__( 'Could not write file .htaccess in YOURLS root directory. You will have to do it manually. See how .' );
- }
+ // Create/update .htaccess file
+ if ( yourls_create_htaccess() ) {
+ $success[] = yourls__( 'File .htaccess successfully created/updated.' );
+ } else {
+ $warning[] = yourls__( 'Could not write file .htaccess in YOURLS root directory. You will have to do it manually. See how .' );
+ }
- // Create SQL tables
- $install = yourls_create_sql_tables();
- if ( isset( $install['error'] ) )
- $error = array_merge( $error, $install['error'] );
- if ( isset( $install['success'] ) )
- $success = array_merge( $success, $install['success'] );
+ // Create SQL tables
+ $install = yourls_create_sql_tables();
+ if ( isset( $install['error'] ) )
+ $error = array_merge( $error, $install['error'] );
+ if ( isset( $install['success'] ) )
+ $success = array_merge( $success, $install['success'] );
}
@@ -54,30 +54,30 @@
yourls_html_head( 'install', yourls__( 'Install YOURLS' ) );
?>
-
+ // Display install button or link to admin area if applicable
+ if( !yourls_is_installed() && !isset($_REQUEST['install']) ) {
+ echo '
';
+ } else {
+ if( count($error) == 0 )
+ echo '
» ' . yourls__( 'YOURLS Administration Page') . '
';
+ }
+ ?>
+
diff --git a/admin/plugins.php b/admin/plugins.php
index ad81339..8d02b96 100644
--- a/admin/plugins.php
+++ b/admin/plugins.php
@@ -5,56 +5,56 @@
// Handle plugin administration pages
if( isset( $_GET['page'] ) && !empty( $_GET['page'] ) ) {
- yourls_plugin_admin_page( $_GET['page'] );
+ yourls_plugin_admin_page( $_GET['page'] );
die();
}
// Handle activation/deactivation of plugins
if( isset( $_GET['action'] ) ) {
- // Check nonce
- yourls_verify_nonce( 'manage_plugins', $_REQUEST['nonce'] ?? '');
+ // Check nonce
+ yourls_verify_nonce( 'manage_plugins', $_REQUEST['nonce'] ?? '');
- // Check plugin file is valid
- if(isset( $_GET['plugin'] ) && yourls_is_a_plugin_file(YOURLS_PLUGINDIR . '/' . $_GET['plugin'] . '/plugin.php') ) {
+ // Check plugin file is valid
+ if(isset( $_GET['plugin'] ) && yourls_is_a_plugin_file(YOURLS_PLUGINDIR . '/' . $_GET['plugin'] . '/plugin.php') ) {
- // Activate / Deactive
- switch( $_GET['action'] ) {
- case 'activate':
- $result = yourls_activate_plugin( $_GET['plugin'].'/plugin.php' );
- if( $result === true ) {
+ // Activate / Deactive
+ switch( $_GET['action'] ) {
+ case 'activate':
+ $result = yourls_activate_plugin( $_GET['plugin'].'/plugin.php' );
+ if( $result === true ) {
yourls_redirect(yourls_admin_url('plugins.php?success=activated'), 302);
exit();
}
- break;
+ break;
- case 'deactivate':
- $result = yourls_deactivate_plugin( $_GET['plugin'].'/plugin.php' );
- if( $result === true ) {
+ case 'deactivate':
+ $result = yourls_deactivate_plugin( $_GET['plugin'].'/plugin.php' );
+ if( $result === true ) {
yourls_redirect(yourls_admin_url('plugins.php?success=deactivated'), 302);
exit();
}
- break;
+ break;
- default:
- $result = yourls__( 'Unsupported action' );
- break;
- }
- } else {
- $result = yourls__( 'No plugin specified, or not a valid plugin' );
- }
+ default:
+ $result = yourls__( 'Unsupported action' );
+ break;
+ }
+ } else {
+ $result = yourls__( 'No plugin specified, or not a valid plugin' );
+ }
- yourls_add_notice( $result );
+ yourls_add_notice( $result );
}
// Handle message upon successful (de)activation
if( isset( $_GET['success'] ) && ( ( $_GET['success'] == 'activated' ) OR ( $_GET['success'] == 'deactivated' ) ) ) {
- if( $_GET['success'] == 'activated' ) {
- $message = yourls__( 'Plugin has been activated' );
- } elseif ( $_GET['success'] == 'deactivated' ) {
- $message = yourls__( 'Plugin has been deactivated' );
- }
- yourls_add_notice( $message );
+ if( $_GET['success'] == 'activated' ) {
+ $message = yourls__( 'Plugin has been activated' );
+ } elseif ( $_GET['success'] == 'deactivated' ) {
+ $message = yourls__( 'Plugin has been deactivated' );
+ }
+ yourls_add_notice( $message );
}
yourls_html_head( 'plugins', yourls__( 'Manage Plugins' ) );
@@ -62,106 +62,110 @@
yourls_html_menu();
?>
-
-
-
-
-
- %1$s installed, and %2$s activated', $plugins_count, $count_active ); ?>
-
-
-
-
-
-
-
-
-
-
-
-
- $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( "%s %s %s %s %s ",
- $class, $data['uri'], $data['name'], $data['version'], $data['desc'], $data['author_uri'], $data['author'], $action_url, $action_anchor
- );
-
- }
- ?>
-
-
-
-
-
- plugin.php.' ); ?>
-
-
-
- Plugin list.' ); ?>
-
+
+
+
+
+
+ %1$s installed, and %2$s activated', $plugins_count, $count_active ); ?>
+
+
+
+
+
+
+
+
+
+
+
+
+ $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( "%s %s %s %s %s ",
+ $class, $data['uri'], $data['name'], $data['version'], $data['desc'], $data['author_uri'], $data['author'], $action_url, $action_anchor
+ );
+
+ }
+ ?>
+
+
+
+
+
+ plugin.php.' ); ?>
+
+
+
+ Plugin list.' ); ?>
+
diff --git a/admin/tools.php b/admin/tools.php
index b2aecf8..b772061 100644
--- a/admin/tools.php
+++ b/admin/tools.php
@@ -8,49 +8,49 @@
yourls_html_menu();
?>
-
+
-
+
- bookmarklets for easier link shortening and sharing.' ); ?>
+ bookmarklets for easier link shortening and sharing.' ); ?>
-
+
-
- Standard Bookmarklets will take you to a page where you can easily edit or delete your brand new short URL.' ); ?>
+
+ Standard Bookmarklets will take you to a page where you can easily edit or delete your brand new short URL.' ); ?>
- Instant Bookmarklets will pop the short URL without leaving the page you are viewing (depending on the page and server configuration, they may silently fail)' ); ?>
+ Instant Bookmarklets will pop the short URL without leaving the page you are viewing (depending on the page and server configuration, they may silently fail)' ); ?>
- Simple Bookmarklets will generate a short URL with a random or sequential keyword.' ); ?>
+ Simple Bookmarklets will generate a short URL with a random or sequential keyword.' ); ?>
- Custom Keyword Bookmarklets will prompt you for a custom keyword first.' ); ?>
-
+ Custom Keyword Bookmarklets will prompt you for a custom keyword first.' ); ?>
+
- 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.'); ?>
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
+
+
-
+
-
-
-
+
+
+
-
+
-
-
+
+
-
+
-
+
-
+
-
+
- %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 536a9f8..957870c 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 53ac504..9dd04fe 100644
--- a/composer.json
+++ b/composer.json
@@ -29,12 +29,12 @@
"geoip2/geoip2" : "^2.10",
"aura/sql": "^5.0 | ^6.0",
"jakeasmith/http_build_url": "^1.0",
- "platformsh/config-reader": "^3.0",
"symfony/polyfill-mbstring": "^1.15",
"symfony/polyfill-intl-idn": "^1.17",
- "spatie/array-to-xml": "^2.14",
+ "spatie/array-to-xml": "^3.4",
"yourls/seans-qrcode": "dev-develop as 1.x-dev",
- "yourls/yourls-saml": "dev-develop as 1.x-dev"
+ "yourls/yourls-saml": "dev-develop as 1.x-dev",
+ "platformsh/laravel-bridge": "^1.1"
},
"repositories": [
{
diff --git a/composer.lock b/composer.lock
index 336ed9f..988a797 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "e5787f60ad536cc14e43fd0eb078833f",
+ "content-hash": "58d57b4c8cbf687a308bed29678dcc59",
"packages": [
{
"name": "aura/sql",
@@ -456,16 +456,16 @@
},
{
"name": "maxmind/web-service-common",
- "version": "v0.11.0",
+ "version": "v0.11.1",
"source": {
"type": "git",
"url": "https://github.com/maxmind/web-service-common-php.git",
- "reference": "5b9e3d3472213361eebdb3ab8879e91b8952091b"
+ "reference": "c309236b5a5555b96cf560089ec3cead12d845d2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/maxmind/web-service-common-php/zipball/5b9e3d3472213361eebdb3ab8879e91b8952091b",
- "reference": "5b9e3d3472213361eebdb3ab8879e91b8952091b",
+ "url": "https://api.github.com/repos/maxmind/web-service-common-php/zipball/c309236b5a5555b96cf560089ec3cead12d845d2",
+ "reference": "c309236b5a5555b96cf560089ec3cead12d845d2",
"shasum": ""
},
"require": {
@@ -477,7 +477,7 @@
"require-dev": {
"friendsofphp/php-cs-fixer": "3.*",
"phpstan/phpstan": "*",
- "phpunit/phpunit": "^8.0 || ^9.0",
+ "phpunit/phpunit": "^10.0",
"squizlabs/php_codesniffer": "4.*"
},
"type": "library",
@@ -501,9 +501,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.11.0"
+ "source": "https://github.com/maxmind/web-service-common-php/tree/v0.11.1"
},
- "time": "2025-11-20T18:33:17+00:00"
+ "time": "2026-01-13T17:56:03+00:00"
},
{
"name": "onelogin/php-saml",
@@ -657,6 +657,51 @@
},
"time": "2025-02-25T17:22:15+00:00"
},
+ {
+ "name": "platformsh/laravel-bridge",
+ "version": "1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/platformsh/laravel-bridge.git",
+ "reference": "9ae82479a36dfb68d2b41bd34f7d3912b929024c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/platformsh/laravel-bridge/zipball/9ae82479a36dfb68d2b41bd34f7d3912b929024c",
+ "reference": "9ae82479a36dfb68d2b41bd34f7d3912b929024c",
+ "shasum": ""
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^7.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "platformsh-laravel-env.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Larry Garfield",
+ "email": "larry@platform.sh"
+ }
+ ],
+ "description": "Bridge library for running Symfony Flex on Platform.sh",
+ "support": {
+ "issues": "https://github.com/platformsh/laravel-bridge/issues",
+ "source": "https://github.com/platformsh/laravel-bridge/tree/master"
+ },
+ "time": "2018-10-15T18:09:39+00:00"
+ },
{
"name": "pomo/pomo",
"version": "v1.5.0",
@@ -905,29 +950,33 @@
},
{
"name": "spatie/array-to-xml",
- "version": "2.17.1",
+ "version": "3.4.4",
"source": {
"type": "git",
"url": "https://github.com/spatie/array-to-xml.git",
- "reference": "5cbec9c6ab17e320c58a259f0cebe88bde4a7c46"
+ "reference": "88b2f3852a922dd73177a68938f8eb2ec70c7224"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/5cbec9c6ab17e320c58a259f0cebe88bde4a7c46",
- "reference": "5cbec9c6ab17e320c58a259f0cebe88bde4a7c46",
+ "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/88b2f3852a922dd73177a68938f8eb2ec70c7224",
+ "reference": "88b2f3852a922dd73177a68938f8eb2ec70c7224",
"shasum": ""
},
"require": {
"ext-dom": "*",
- "php": "^7.4|^8.0"
+ "php": "^8.0"
},
"require-dev": {
"mockery/mockery": "^1.2",
"pestphp/pest": "^1.21",
- "phpunit/phpunit": "^9.0",
"spatie/pest-plugin-snapshots": "^1.1"
},
"type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.x-dev"
+ }
+ },
"autoload": {
"psr-4": {
"Spatie\\ArrayToXml\\": "src"
@@ -953,7 +1002,7 @@
"xml"
],
"support": {
- "source": "https://github.com/spatie/array-to-xml/tree/2.17.1"
+ "source": "https://github.com/spatie/array-to-xml/tree/3.4.4"
},
"funding": [
{
@@ -965,7 +1014,7 @@
"type": "github"
}
],
- "time": "2022-12-26T08:22:07+00:00"
+ "time": "2025-12-15T09:00:41+00:00"
},
{
"name": "symfony/polyfill-intl-idn",
diff --git a/css/style.css b/css/style.css
index e1d350d..1f10841 100644
--- a/css/style.css
+++ b/css/style.css
@@ -18,8 +18,6 @@ body {
border-right:3px solid #2a85b3;
border-bottom:3px solid #2a85b3;
border-top:3px solid #2a85b3;
- -moz-border-radius:20px;
- -webkit-border-radius:20px;
border-radius:20px;
}
.hide-if-no-js {display: none;}
@@ -68,8 +66,6 @@ tt {
}
input, textarea {
- -moz-border-radius:3px;
- -webkit-border-radius:3px;
border-radius:3px;
}
Input.text, select, textarea {
@@ -129,8 +125,11 @@ tr.edit-row td {
td.url small a{
color:#bbc;
}
-body.desktop td.actions input,body.desktop td.actions a {
- visibility:hidden;
+/* Hide buttons visually but keep them accessible to screen readers */
+body.desktop td.actions input, body.desktop td.actions a {
+ opacity: 0;
+ pointer-events: none;
+ transition: opacity 0.2s ease;
}
td.timestamp span.timestamp {
display:none;
@@ -138,8 +137,20 @@ td.timestamp span.timestamp {
td.actions input.disabled, td.actions input.loading {
visibility:visible;
}
+/* Show buttons on row hover */
tr:hover td.actions input, tr:hover td.actions a {
- visibility:visible;
+ opacity: 1;
+ pointer-events: auto;
+}
+/* Show buttons when any button in the actions cell receives focus */
+td.actions:focus-within input, td.actions:focus-within a {
+ opacity: 1;
+ pointer-events: auto;
+}
+/* Show all buttons when any element in the row receives focus (for keyboard nav through the entire row) */
+tr:focus-within td.actions input, tr:focus-within td.actions a {
+ opacity: 1;
+ pointer-events: auto;
}
td.actions .button {
font-family: Verdana, Arial;
@@ -148,8 +159,6 @@ td.actions .button {
font-weight: bold;
background-color: #FFFFFF;
border: 1px solid #88c0eb;
- -moz-border-radius:3px;
- -webkit-border-radius:3px;
border-radius:3px;
cursor:pointer;
height:22px;
@@ -240,8 +249,6 @@ td.actions .button_stats {
}
a.bookmarklet {
border:2px solid #2a85b3;
- -moz-border-radius:3px;
- -webkit-border-radius:3px;
border-radius:3px;
padding:5px 5px 5px 20px;
background:#eef url(../images/favicon.svg) 2px center no-repeat;
@@ -262,14 +269,8 @@ a.bookmarklet:hover {
background:white;
margin:0 auto;
max-width:950px;
- -moz-border-radius:10px;
- -webkit-border-radius:10px;
border-radius:10px;
border:2px solid #2a85b3;
- -moz-border-radius-bottomleft:30px;
- -moz-border-radius-bottomright:30px;
- -webkit-border-bottom-left-radius:25px;
- -webkit-border-bottom-right-radius:25px;
border-bottom-left-radius:25px;
border-bottom-right-radius:25px;
}
@@ -281,8 +282,6 @@ a.bookmarklet:hover {
.notice {
border:1px solid #2a85b3;
background: #F3FAFD;
- -moz-border-radius:6px;
- -webkit-border-radius:6px;
border-radius:6px;
width:70%;
margin-left:15%;
@@ -290,7 +289,6 @@ a.bookmarklet:hover {
margin-bottom:5px;
}
-
.jquery-notify-bar {
width:100%;
position:fixed;
@@ -305,11 +303,7 @@ a.bookmarklet:hover {
padding:20px 0px;
border-bottom:1px solid #bbb;
filter:alpha(opacity=95);
- -moz-opacity:0.95;
- -khtml-opacity:0.95;
opacity:0.95;
- -moz-box-shadow: 0 1px 5px rgba(0,0,0,0.5);
- -webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.5);
text-shadow: 0 1px 1px rgba(0,0,0,0.1);
}
.jquery-notify-bar.error ,.jquery-notify-bar.fail {
@@ -335,3 +329,59 @@ a.bookmarklet:hover {
tr.plugin.active a{ font-weight:bolder;}
body.desktop tr.plugin td.plugin_desc small{ visibility:hidden;}
tr:hover.plugin td.plugin_desc small{ visibility:visible;}
+
+#delete-confirm-dialog {
+ background-color: #ffffff;
+ width: 50em;
+ height: 19em;
+ padding: 0px;
+ border: 3px solid #2a85b3;
+ border-radius: 20px;
+}
+#delete-confirm-dialog > div[name="dialog_title"] {
+ background-color: #c7e7ff;
+ font-size: 20px;
+ color: #026090;
+ text-align: center;
+ padding-top: 0.5em;
+ padding-bottom: 0.5em;
+ border-start-start-radius: 17px 17px;
+ border-start-end-radius: 17px 17px;
+}
+#delete-confirm-dialog div.confirm-message {
+ background-color: #ffffff;
+ width: calc(50em - 4em);
+ height: calc(20em - 50px - 5em - 2em + 6px);
+ float: none;
+ text-align: left;
+ padding: 1em 2em;
+ overflow: hidden;
+}
+#delete-confirm-dialog div.confirm-message ul {
+ border-left: 5px solid #026090;
+ list-style-type: none;
+ padding: 0 1em;
+}
+#delete-confirm-dialog div.confirm-message ul li {
+ margin-bottom: 0.5em;
+}
+#delete-confirm-dialog div.confirm-message ul li span {
+ border: 1px solid #c7e7ff;
+ border-radius: 3px;
+ padding: 1px 5px;
+ color:#333;
+}
+#delete-confirm-dialog div.button-group {
+ background-color: #e3f3ff;
+ width: calc(50em - 4em);
+ height: 2em;
+ float: none;
+ text-align: right;
+ padding: 1em 2em;
+ border-end-start-radius: 17px 17px;
+ border-end-end-radius: 17px 17px;
+}
+#delete-confirm-dialog::backdrop {
+ background-color: #666;
+ opacity: 80%;
+}
diff --git a/frontend/package.json b/frontend/package.json
index 8760a39..72af22b 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -1,6 +1,6 @@
{
"name": "sleeky-frontend",
- "version": "2.5.0",
+ "version": "2.6.0",
"description": "",
"main": "index.js",
"scripts": {
diff --git a/includes/Database/Options.php b/includes/Database/Options.php
index b35224d..f175f08 100644
--- a/includes/Database/Options.php
+++ b/includes/Database/Options.php
@@ -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/YDB.php b/includes/Database/YDB.php
index c3313c3..803f345 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 = [];
@@ -86,7 +86,7 @@ public function __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)
*
@@ -276,7 +276,20 @@ public function get_infos($keyword) {
* @return void
*/
public function delete_infos($keyword) {
- unset($this->infos[$keyword]);
+ if (isset($this->infos[$keyword])) {
+ unset($this->infos[$keyword]);
+ }
+ }
+
+ /**
+ * @param string $keyword
+ * @param mixed $infos
+ * @return void
+ */
+ public function update_infos_if_exists($keyword, $infos) {
+ if ($this->has_infos($keyword) && $this->infos[$keyword]) {
+ $this->infos[$keyword] = array_merge($this->infos[$keyword], $infos);
+ }
}
/**
@@ -405,22 +418,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 9116fb5..892684d 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 (!empty($_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 ad9f9a8..be98a87 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/class-mysql.php b/includes/class-mysql.php
index c25c183..603c87c 100644
--- a/includes/class-mysql.php
+++ b/includes/class-mysql.php
@@ -4,9 +4,10 @@
* Connect to DB
*
* @since 1.0
+ * @param string $context Optional context. Default: ''.
* @return \YOURLS\Database\YDB
*/
-function yourls_db_connect() {
+function yourls_db_connect($context = '') {
global $ydb;
if ( !defined( 'YOURLS_DB_USER' )
@@ -26,12 +27,12 @@ function yourls_db_connect() {
yourls_do_action( 'set_DB_driver', 'deprecated' );
// Get custom port if any
- if ( false !== strpos( $dbhost, ':' ) ) {
+ if (str_contains($dbhost, ':')) {
list( $dbhost, $dbport ) = explode( ':', $dbhost );
$dbhost = sprintf( '%1$s;port=%2$d', $dbhost, $dbport );
}
- $charset = yourls_apply_filter( 'db_connect_charset', 'utf8mb4' );
+ $charset = yourls_apply_filter( 'db_connect_charset', 'utf8mb4', $context );
/**
* Data Source Name (dsn) used to connect the DB
@@ -42,7 +43,7 @@ function yourls_db_connect() {
* 'pgsql:host=192.168.13.37;port=5432;dbname=omgwtf'
*/
$dsn = sprintf( 'mysql:host=%s;dbname=%s;charset=%s', $dbhost, $dbname, $charset );
- $dsn = yourls_apply_filter( 'db_connect_custom_dsn', $dsn );
+ $dsn = yourls_apply_filter( 'db_connect_custom_dsn', $dsn, $context );
/**
* PDO driver options and attributes
@@ -52,14 +53,18 @@ function yourls_db_connect() {
* The driver options are passed to the PDO constructor, eg array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)
* The attribute options are then set in a foreach($attr as $k=>$v){$db->setAttribute($k, $v)} loop
*/
- $driver_options = yourls_apply_filter( 'db_connect_driver_option', [] ); // driver options as key-value pairs
- $attributes = yourls_apply_filter( 'db_connect_attributes', [] ); // attributes as key-value pairs
+ $driver_options = yourls_apply_filter( 'db_connect_driver_option', [], $context ); // driver options as key-value pairs
+ $attributes = yourls_apply_filter( 'db_connect_attributes', [], $context ); // attributes as key-value pairs
$ydb = new \YOURLS\Database\YDB( $dsn, $user, $pass, $driver_options, $attributes );
$ydb->init();
// Past this point, we're connected
- yourls_debug_log( sprintf( 'Connected to database %s on %s ', $dbname, $dbhost ) );
+ $msg = 'Connected to ' . $dsn;
+ if ($context !== '') {
+ $msg .= ', context: ' . $context;
+ }
+ yourls_debug_log( $msg );
yourls_debug_mode( YOURLS_DEBUG );
@@ -67,7 +72,7 @@ function yourls_db_connect() {
}
/**
- * Helper function : return instance of the DB
+ * Helper function: return instance of the DB
*
* Instead of:
* global $ydb;
@@ -76,18 +81,46 @@ function yourls_db_connect() {
* yourls_get_db()->do_stuff()
*
* @since 1.7.10
+ * @param string $context Optional context. Default: ''.
+ * If not provided, the function will trigger a notice to encourage developers to provide a context while not
+ * breaking existing code. A context is a string describing the operation for which the DB is requested.
+ * Use a naming schema starting with a prefix describing the operation, followed by a short description:
+ * - Prefix should be either "read-" or "write-", as follows:
+ * * "read-" for operations that only read from the DB (eg get_keyword_infos)
+ * * "write-" for operations that write to the DB (eg insert_link_in_db)
+ * - The description should be lowercase, words separated with underscores, eg "insert_link_in_db".
+ * Examples:
+ * - read-fetch_keyword
+ * - write-insert_link_in_db
* @return \YOURLS\Database\YDB
*/
-function yourls_get_db() {
+function yourls_get_db($context = '') {
// Allow plugins to short-circuit the whole function
- $pre = yourls_apply_filter( 'shunt_get_db', false );
+ $pre = yourls_apply_filter( 'shunt_get_db', false, $context );
if ( false !== $pre ) {
return $pre;
}
+ // Validate context and raise notice if missing or malformed
+ if ($context == '' || !preg_match('/^(read|write)-[a-z0-9_]+$/', $context)) {
+ $db = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
+ $file = $db[0]['file'];
+ $line = $db[0]['line'];
+
+ if ($context == '') {
+ $msg = 'Undefined yourls_get_db() context';
+ } else {
+ $msg = 'Improperly formatted yourls_get_db() context ("' . $context . '")';
+ }
+
+ trigger_error( $msg . ' at ' . $file . ':' . $line .' ', E_USER_NOTICE );
+ }
+
+ yourls_do_action( 'get_db_action', $context );
+
global $ydb;
- $ydb = ( isset( $ydb ) ) ? $ydb : yourls_db_connect();
- return yourls_apply_filter('get_db', $ydb);
+ $ydb = ( isset( $ydb ) ) ? $ydb : yourls_db_connect($context);
+ return yourls_apply_filter('get_db', $ydb, $context);
}
/**
diff --git a/includes/functions-api.php b/includes/functions-api.php
index b32f1cc..bd97237 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,49 @@ 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;
+ $callback = isset( $output['callback'] ) ? yourls_validate_jsonp_callback($output['callback'] ) : '';
+ if( $callback === false ) {
+ yourls_status_header( 400 );
+ $result = json_encode( ['errorCode' => '400', 'error' => 'Invalid callback parameter'] );
+ } else {
+ $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 +175,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 +187,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 +204,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 +219,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 f074c21..cadf538 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)>:"
- list( , $salt, ) = explode( ':', $yourls_user_passwords[ $user ] );
- return( $yourls_user_passwords[ $user ] == 'md5:'.$salt.':'.md5( $salt . $submitted_password ) );
- } else {
- // Password stored in clear text
- return( $yourls_user_passwords[ $user ] === $submitted_password );
- }
+ 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)>:"
+ list( , $salt, ) = explode( ':', $yourls_user_passwords[ $user ] );
+ return( $yourls_user_passwords[ $user ] == 'md5:'.$salt.':'.md5( $salt . $submitted_password ) );
+ } else {
+ // Password stored in clear text
+ return( $yourls_user_passwords[ $user ] === $submitted_password );
+ }
}
/**
@@ -178,66 +178,66 @@ function yourls_check_password_hash($user, $submitted_password ) {
* @return true|string if overwrite was successful, an error message otherwise
*/
function yourls_hash_passwords_now( $config_file ) {
- if( !is_readable( $config_file ) ) {
+ if( !is_readable( $config_file ) ) {
yourls_debug_log( 'Cannot hash passwords: cannot read file ' . $config_file );
return 'cannot read file'; // not sure that can actually happen...
}
- if( !is_writable( $config_file ) ) {
+ if( !is_writable( $config_file ) ) {
yourls_debug_log( 'Cannot hash passwords: cannot write file ' . $config_file );
- return 'cannot write file';
+ return 'cannot write file';
}
$yourls_user_passwords = [];
- // Include file to read value of $yourls_user_passwords
- // Temporary suppress error reporting to avoid notices about redeclared constants
- $errlevel = error_reporting();
- error_reporting( 0 );
- require $config_file;
- error_reporting( $errlevel );
+ // Include file to read value of $yourls_user_passwords
+ // Temporary suppress error reporting to avoid notices about redeclared constants
+ $errlevel = error_reporting();
+ error_reporting( 0 );
+ require $config_file;
+ error_reporting( $errlevel );
- $configdata = file_get_contents( $config_file );
+ $configdata = file_get_contents( $config_file );
if( $configdata == false ) {
yourls_debug_log('Cannot hash passwords: file_get_contents() false with ' . $config_file);
return 'could not read file';
}
- $to_hash = 0; // keep track of number of passwords that need hashing
- foreach ( $yourls_user_passwords as $user => $password ) {
+ $to_hash = 0; // keep track of number of passwords that need hashing
+ foreach ( $yourls_user_passwords as $user => $password ) {
// avoid "deprecated" warning when password is null -- see test case in tests/data/auth/preg_replace_problem.php
$password ??= '';
- if ( !yourls_has_phpass_password( $user ) && !yourls_has_md5_password( $user ) ) {
- $to_hash++;
- $hash = yourls_phpass_hash( $password );
- // PHP would interpret $ as a variable, so replace it in storage.
- $hash = str_replace( '$', '!', $hash );
- $quotes = "'" . '"';
- $pattern = "/[$quotes]" . preg_quote( $user, '/' ) . "[$quotes]\s*=>\s*[$quotes]" . preg_quote( $password, '/' ) . "[$quotes]/";
- $replace = "'$user' => 'phpass:$hash' /* Password encrypted by YOURLS */ ";
- $count = 0;
- $configdata = preg_replace( $pattern, $replace, $configdata, -1, $count );
- // There should be exactly one replacement. Otherwise, fast fail.
- if ( $count != 1 ) {
- yourls_debug_log( "Problem with preg_replace for password hash of user $user" );
- return 'preg_replace problem';
- }
- }
- }
-
- if( $to_hash == 0 ) {
+ if ( !yourls_has_phpass_password( $user ) && !yourls_has_md5_password( $user ) ) {
+ $to_hash++;
+ $hash = yourls_phpass_hash( $password );
+ // PHP would interpret $ as a variable, so replace it in storage.
+ $hash = str_replace( '$', '!', $hash );
+ $quotes = "'" . '"';
+ $pattern = "/[$quotes]" . preg_quote( $user, '/' ) . "[$quotes]\s*=>\s*[$quotes]" . preg_quote( $password, '/' ) . "[$quotes]/";
+ $replace = "'$user' => 'phpass:$hash' /* Password encrypted by YOURLS */ ";
+ $count = 0;
+ $configdata = preg_replace( $pattern, $replace, $configdata, -1, $count );
+ // There should be exactly one replacement. Otherwise, fast fail.
+ if ( $count != 1 ) {
+ yourls_debug_log( "Problem with preg_replace for password hash of user $user" );
+ return 'preg_replace problem';
+ }
+ }
+ }
+
+ if( $to_hash == 0 ) {
yourls_debug_log('Cannot hash passwords: no password found in ' . $config_file);
return 'no password found';
}
- $success = file_put_contents( $config_file, $configdata );
- if ( $success === FALSE ) {
- yourls_debug_log( 'Failed writing to ' . $config_file );
- return 'could not write file';
- }
+ $success = file_put_contents( $config_file, $configdata );
+ if ( $success === FALSE ) {
+ yourls_debug_log( 'Failed writing to ' . $config_file );
+ return 'could not write file';
+ }
yourls_debug_log('Successfully encrypted passwords in ' . basename($config_file));
- return true;
+ return true;
}
/**
@@ -277,7 +277,7 @@ function yourls_phpass_hash( $password ) {
* @return bool true if the hash matches the password, false otherwise
*/
function yourls_phpass_check( $password, $hash ) {
- return password_verify($password, $hash);
+ return password_verify($password, $hash);
}
@@ -288,13 +288,13 @@ function yourls_phpass_check( $password, $hash ) {
* @return bool true if any passwords are cleartext
*/
function yourls_has_cleartext_passwords() {
- global $yourls_user_passwords;
- foreach ( $yourls_user_passwords as $user => $pwdata ) {
- if ( !yourls_has_md5_password( $user ) && !yourls_has_phpass_password( $user ) ) {
- return true;
- }
- }
- return false;
+ global $yourls_user_passwords;
+ foreach ( $yourls_user_passwords as $user => $pwdata ) {
+ if ( !yourls_has_md5_password( $user ) && !yourls_has_phpass_password( $user ) ) {
+ return true;
+ }
+ }
+ return false;
}
/**
@@ -308,11 +308,11 @@ function yourls_has_cleartext_passwords() {
* @return bool true if password hashed, false otherwise
*/
function yourls_has_md5_password( $user ) {
- global $yourls_user_passwords;
- return( isset( $yourls_user_passwords[ $user ] )
- && substr( $yourls_user_passwords[ $user ], 0, 4 ) == 'md5:'
- && strlen( $yourls_user_passwords[ $user ] ) == 42 // http://www.google.com/search?q=the+answer+to+life+the+universe+and+everything
- );
+ global $yourls_user_passwords;
+ return( isset( $yourls_user_passwords[ $user ] )
+ && substr( $yourls_user_passwords[ $user ], 0, 4 ) == 'md5:'
+ && strlen( $yourls_user_passwords[ $user ] ) == 42 // http://www.google.com/search?q=the+answer+to+life+the+universe+and+everything
+ );
}
/**
@@ -327,10 +327,10 @@ function yourls_has_md5_password( $user ) {
* @return bool true if password hashed with password_hash, otherwise false
*/
function yourls_has_phpass_password( $user ) {
- global $yourls_user_passwords;
- return( isset( $yourls_user_passwords[ $user ] )
- && substr( $yourls_user_passwords[ $user ], 0, 7 ) == 'phpass:'
- );
+ global $yourls_user_passwords;
+ return( isset( $yourls_user_passwords[ $user ] )
+ && substr( $yourls_user_passwords[ $user ], 0, 7 ) == 'phpass:'
+ );
}
/**
@@ -339,14 +339,14 @@ function yourls_has_phpass_password( $user ) {
* @return bool true if authenticated, false otherwise
*/
function yourls_check_auth_cookie() {
- global $yourls_user_passwords;
- foreach( $yourls_user_passwords as $valid_user => $valid_password ) {
- if ( yourls_cookie_value( $valid_user ) === $_COOKIE[ yourls_cookie_name() ] ) {
- yourls_set_user( $valid_user );
- return true;
- }
- }
- return false;
+ global $yourls_user_passwords;
+ foreach( $yourls_user_passwords as $valid_user => $valid_password ) {
+ if ( yourls_cookie_value( $valid_user ) === $_COOKIE[ yourls_cookie_name() ] ) {
+ yourls_set_user( $valid_user );
+ return true;
+ }
+ }
+ return false;
}
/**
@@ -380,21 +380,21 @@ function yourls_check_signature_timestamp() {
return false;
}
- // Check signature & timestamp against all possible users
- global $yourls_user_passwords;
- foreach( $yourls_user_passwords as $valid_user => $valid_password ) {
- if (
+ // Check signature & timestamp against all possible users
+ global $yourls_user_passwords;
+ foreach( $yourls_user_passwords as $valid_user => $valid_password ) {
+ if (
hash( $hash_function, $_REQUEST['timestamp'].yourls_auth_signature( $valid_user ) ) === $_REQUEST['signature']
or
hash( $hash_function, yourls_auth_signature( $valid_user ).$_REQUEST['timestamp'] ) === $_REQUEST['signature']
- ) {
- yourls_set_user( $valid_user );
- return true;
- }
- }
+ ) {
+ yourls_set_user( $valid_user );
+ return true;
+ }
+ }
// Signature doesn't match known user
- return false;
+ return false;
}
/**
@@ -407,17 +407,17 @@ function yourls_check_signature() {
if( !isset( $_REQUEST['signature'] ) OR empty( $_REQUEST['signature'] ) )
return false;
- // Check signature against all possible users
+ // Check signature against all possible users
global $yourls_user_passwords;
- foreach( $yourls_user_passwords as $valid_user => $valid_password ) {
- if ( yourls_auth_signature( $valid_user ) === $_REQUEST['signature'] ) {
- yourls_set_user( $valid_user );
- return true;
- }
- }
+ foreach( $yourls_user_passwords as $valid_user => $valid_password ) {
+ if ( yourls_auth_signature( $valid_user ) === $_REQUEST['signature'] ) {
+ yourls_set_user( $valid_user );
+ return true;
+ }
+ }
// Signature doesn't match known user
- return false;
+ return false;
}
/**
@@ -427,10 +427,10 @@ function yourls_check_signature() {
* @return string Signature
*/
function yourls_auth_signature( $username = false ) {
- if( !$username && defined('YOURLS_USER') ) {
- $username = YOURLS_USER;
- }
- return ( $username ? substr( yourls_salt( $username ), 0, 10 ) : 'Cannot generate auth signature: no username' );
+ if( !$username && defined('YOURLS_USER') ) {
+ $username = YOURLS_USER;
+ }
+ return ( $username ? substr( yourls_salt( $username ), 0, 10 ) : 'Cannot generate auth signature: no username' );
}
/**
@@ -440,9 +440,9 @@ function yourls_auth_signature( $username = false ) {
* @return bool True if timestamp is valid
*/
function yourls_check_timestamp( $time ) {
- $now = time();
- // Allow timestamp to be a little in the future or the past -- see Issue 766
- return yourls_apply_filter( 'check_timestamp', abs( $now - (int)$time ) < yourls_get_nonce_life(), $time );
+ $now = time();
+ // Allow timestamp to be a little in the future or the past -- see Issue 766
+ return yourls_apply_filter( 'check_timestamp', abs( $now - (int)$time ) < yourls_get_nonce_life(), $time );
}
/**
@@ -454,30 +454,30 @@ function yourls_check_timestamp( $time ) {
function yourls_store_cookie( $user = '' ) {
// No user will delete the cookie with a cookie time from the past
- if( !$user ) {
- $time = time() - 3600;
- } else {
- $time = time() + yourls_get_cookie_life();
- }
+ if( !$user ) {
+ $time = time() - 3600;
+ } else {
+ $time = time() + yourls_get_cookie_life();
+ }
$path = yourls_apply_filter( 'setcookie_path', '/' );
- $domain = yourls_apply_filter( 'setcookie_domain', parse_url( yourls_get_yourls_site(), PHP_URL_HOST ) );
- $secure = yourls_apply_filter( 'setcookie_secure', yourls_is_ssl() );
- $httponly = yourls_apply_filter( 'setcookie_httponly', true );
+ $domain = yourls_apply_filter( 'setcookie_domain', parse_url( yourls_get_yourls_site(), PHP_URL_HOST ) );
+ $secure = yourls_apply_filter( 'setcookie_secure', yourls_is_ssl() );
+ $httponly = yourls_apply_filter( 'setcookie_httponly', true );
- // Some browsers refuse to store localhost cookie
- if ( $domain == 'localhost' )
- $domain = '';
+ // Some browsers refuse to store localhost cookie
+ if ( $domain == 'localhost' )
+ $domain = '';
- yourls_do_action( 'pre_setcookie', $user, $time, $path, $domain, $secure, $httponly );
+ yourls_do_action( 'pre_setcookie', $user, $time, $path, $domain, $secure, $httponly );
if ( !headers_sent( $filename, $linenum ) ) {
yourls_setcookie( yourls_cookie_name(), yourls_cookie_value( $user ), $time, $path, $domain, $secure, $httponly );
- } else {
- // For some reason cookies were not stored: action to be able to debug that
- yourls_do_action( 'setcookie_failed', $user );
+ } else {
+ // For some reason cookies were not stored: action to be able to debug that
+ yourls_do_action( 'setcookie_failed', $user );
yourls_debug_log( "Could not store cookie: headers already sent in $filename on line $linenum" );
- }
+ }
}
/**
@@ -517,8 +517,8 @@ function yourls_setcookie($name, $value, $expire, $path, $domain, $secure, $http
* @return void
*/
function yourls_set_user( $user ) {
- if( !defined( 'YOURLS_USER' ) )
- define( 'YOURLS_USER', $user );
+ if( !defined( 'YOURLS_USER' ) )
+ define( 'YOURLS_USER', $user );
}
/**
@@ -532,7 +532,7 @@ function yourls_set_user( $user ) {
* @return integer cookie life span, in seconds
*/
function yourls_get_cookie_life() {
- return yourls_apply_filter( 'get_cookie_life', YOURLS_COOKIE_LIFE );
+ return yourls_apply_filter( 'get_cookie_life', YOURLS_COOKIE_LIFE );
}
/**
@@ -547,7 +547,7 @@ function yourls_get_cookie_life() {
* @return integer nonce life span, in seconds
*/
function yourls_get_nonce_life() {
- return yourls_apply_filter( 'get_nonce_life', YOURLS_NONCE_LIFE );
+ return yourls_apply_filter( 'get_nonce_life', YOURLS_NONCE_LIFE );
}
/**
@@ -572,7 +572,7 @@ function yourls_cookie_name() {
* @return string cookie value
*/
function yourls_cookie_value( $user ) {
- return yourls_apply_filter( 'set_cookie_value', yourls_salt( $user ?? '' ), $user );
+ return yourls_apply_filter( 'set_cookie_value', yourls_salt( $user ?? '' ), $user );
}
/**
@@ -583,7 +583,7 @@ function yourls_cookie_value( $user ) {
* @return float
*/
function yourls_tick() {
- return ceil( time() / yourls_get_nonce_life() );
+ return ceil( time() / yourls_get_nonce_life() );
}
/**
@@ -596,8 +596,8 @@ function yourls_tick() {
* @return string hashed string
*/
function yourls_salt( $string ) {
- $salt = defined('YOURLS_COOKIEKEY') ? YOURLS_COOKIEKEY : md5(__FILE__) ;
- return yourls_apply_filter( 'yourls_salt', hash_hmac( yourls_hmac_algo(), $string, $salt), $string );
+ $salt = defined('YOURLS_COOKIEKEY') ? YOURLS_COOKIEKEY : md5(__FILE__) ;
+ return yourls_apply_filter( 'yourls_salt', hash_hmac( yourls_hmac_algo(), $string, $salt), $string );
}
/**
@@ -622,13 +622,13 @@ function yourls_hmac_algo() {
* @return string Nonce token
*/
function yourls_create_nonce($action, $user = false ) {
- if( false === $user ) {
+ if( false === $user ) {
$user = defined('YOURLS_USER') ? YOURLS_USER : '-1';
}
- $tick = yourls_tick();
- $nonce = substr( yourls_salt($tick . $action . $user), 0, 10 );
- // Allow plugins to alter the nonce
- return yourls_apply_filter( 'create_nonce', $nonce, $action, $user );
+ $tick = yourls_tick();
+ $nonce = substr( yourls_salt($tick . $action . $user), 0, 10 );
+ // Allow plugins to alter the nonce
+ return yourls_apply_filter( 'create_nonce', $nonce, $action, $user );
}
/**
@@ -641,10 +641,10 @@ function yourls_create_nonce($action, $user = false ) {
* @return string Nonce field
*/
function yourls_nonce_field($action, $name = 'nonce', $user = false, $echo = true ) {
- $field = ' ';
- if( $echo )
- echo $field."\n";
- return $field;
+ $field = ' ';
+ if( $echo )
+ echo $field."\n";
+ return $field;
}
/**
@@ -657,8 +657,8 @@ function yourls_nonce_field($action, $name = 'nonce', $user = false, $echo = tru
* @return string URL with nonce added
*/
function yourls_nonce_url($action, $url = false, $name = 'nonce', $user = false ) {
- $nonce = yourls_create_nonce( $action, $user );
- return yourls_add_query_arg( $name, $nonce, $url );
+ $nonce = yourls_create_nonce( $action, $user );
+ return yourls_add_query_arg( $name, $nonce, $url );
}
/**
@@ -674,31 +674,31 @@ function yourls_nonce_url($action, $url = false, $name = 'nonce', $user = false
* @return bool|void True if valid, dies otherwise
*/
function yourls_verify_nonce($action, $nonce = false, $user = false, $return = '' ) {
- // Get user
- if( false === $user ) {
+ // Get user
+ if( false === $user ) {
$user = defined('YOURLS_USER') ? YOURLS_USER : '-1';
}
- // Get nonce value from $_REQUEST if not specified
- if( false === $nonce && isset( $_REQUEST['nonce'] ) ) {
+ // Get nonce value from $_REQUEST if not specified
+ if( false === $nonce && isset( $_REQUEST['nonce'] ) ) {
$nonce = $_REQUEST['nonce'];
}
- // Allow plugins to short-circuit the rest of the function
- if (yourls_apply_filter( 'verify_nonce', false, $action, $nonce, $user, $return ) === true) {
- return true;
- }
+ // Allow plugins to short-circuit the rest of the function
+ if (yourls_apply_filter( 'verify_nonce', false, $action, $nonce, $user, $return ) === true) {
+ return true;
+ }
- // What nonce should be
- $valid = yourls_create_nonce( $action, $user );
+ // What nonce should be
+ $valid = yourls_create_nonce( $action, $user );
- if( $nonce === $valid ) {
- return true;
- } else {
- if( $return )
- die( $return );
- yourls_die( yourls__( 'Unauthorized action or expired link' ), yourls__( 'Error' ), 403 );
- }
+ if( $nonce === $valid ) {
+ return true;
+ } else {
+ if( $return )
+ die( $return );
+ yourls_die( yourls__( 'Unauthorized action or expired link' ), yourls__( 'Error' ), 403 );
+ }
}
/**
@@ -708,7 +708,7 @@ function yourls_verify_nonce($action, $nonce = false, $user = false, $return = '
* @return bool true if YOURLS_USER and YOURLS_PASSWORD are defined as environment variables
*/
function yourls_is_user_from_env() {
- return yourls_apply_filter('is_user_from_env', getenv('YOURLS_USER') && getenv('YOURLS_PASSWORD'));
+ return yourls_apply_filter('is_user_from_env', getenv('YOURLS_USER') && getenv('YOURLS_PASSWORD'));
}
diff --git a/includes/functions-compat.php b/includes/functions-compat.php
index 4bc1330..2dc17d3 100644
--- a/includes/functions-compat.php
+++ b/includes/functions-compat.php
@@ -11,9 +11,9 @@
*
*/
if( !function_exists( 'json_encode' ) ) {
- function json_encode( $array ) {
- return yourls_array_to_json( $array );
- }
+ function json_encode( $array ) {
+ return yourls_array_to_json( $array );
+ }
}
/**
@@ -26,60 +26,60 @@ function json_encode( $array ) {
*/
function yourls_array_to_json( $array ){
- if( !is_array( $array ) ){
- return false;
- }
+ if( !is_array( $array ) ){
+ return false;
+ }
- $associative = count( array_diff( array_keys($array), array_keys( array_keys( $array )) ));
- if( $associative ){
+ $associative = count( array_diff( array_keys($array), array_keys( array_keys( $array )) ));
+ if( $associative ){
- $construct = array();
- foreach( $array as $key => $value ){
+ $construct = array();
+ foreach( $array as $key => $value ){
- // We first copy each key/value pair into a staging array,
- // formatting each key and value properly as we go.
+ // We first copy each key/value pair into a staging array,
+ // formatting each key and value properly as we go.
- // Format the key:
- if( is_numeric( $key ) ){
- $key = "key_$key";
- }
- $key = '"'.addslashes( $key ).'"';
+ // Format the key:
+ if( is_numeric( $key ) ){
+ $key = "key_$key";
+ }
+ $key = '"'.addslashes( $key ).'"';
- // Format the value:
- if( is_array( $value )){
- $value = yourls_array_to_json( $value );
- } else if( !is_numeric( $value ) || is_string( $value ) ){
- $value = '"'.addslashes( $value ).'"';
- }
+ // Format the value:
+ if( is_array( $value )){
+ $value = yourls_array_to_json( $value );
+ } else if( !is_numeric( $value ) || is_string( $value ) ){
+ $value = '"'.addslashes( $value ).'"';
+ }
- // Add to staging array:
- $construct[] = "$key: $value";
- }
+ // Add to staging array:
+ $construct[] = "$key: $value";
+ }
- // Then we collapse the staging array into the JSON form:
- $result = "{ " . implode( ", ", $construct ) . " }";
+ // Then we collapse the staging array into the JSON form:
+ $result = "{ " . implode( ", ", $construct ) . " }";
- } else { // If the array is a vector (not associative):
+ } else { // If the array is a vector (not associative):
- $construct = array();
- foreach( $array as $value ){
+ $construct = array();
+ foreach( $array as $value ){
- // Format the value:
- if( is_array( $value )){
- $value = yourls_array_to_json( $value );
- } else if( !is_numeric( $value ) || is_string( $value ) ){
- $value = '"'.addslashes($value).'"';
- }
+ // Format the value:
+ if( is_array( $value )){
+ $value = yourls_array_to_json( $value );
+ } else if( !is_numeric( $value ) || is_string( $value ) ){
+ $value = '"'.addslashes($value).'"';
+ }
- // Add to staging array:
- $construct[] = $value;
- }
+ // Add to staging array:
+ $construct[] = $value;
+ }
- // Then we collapse the staging array into the JSON form:
- $result = "[ " . implode( ", ", $construct ) . " ]";
- }
+ // Then we collapse the staging array into the JSON form:
+ $result = "[ " . implode( ", ", $construct ) . " ]";
+ }
- return $result;
+ return $result;
}
@@ -88,23 +88,23 @@ function yourls_array_to_json( $array ){
*
*/
if ( !function_exists( 'bcdiv' ) ) {
- function bcdiv( $dividend, $divisor ) {
- $quotient = floor( $dividend/$divisor );
- return $quotient;
- }
- function bcmod( $dividend, $modulo ) {
- $remainder = $dividend%$modulo;
- return $remainder;
- }
- function bcmul( $left, $right ) {
- return $left * $right;
- }
- function bcadd( $left, $right ) {
- return $left + $right;
- }
- function bcpow( $base, $power ) {
- return pow( $base, $power );
- }
+ function bcdiv( $dividend, $divisor ) {
+ $quotient = floor( $dividend/$divisor );
+ return $quotient;
+ }
+ function bcmod( $dividend, $modulo ) {
+ $remainder = $dividend%$modulo;
+ return $remainder;
+ }
+ function bcmul( $left, $right ) {
+ return $left * $right;
+ }
+ function bcadd( $left, $right ) {
+ return $left + $right;
+ }
+ function bcpow( $base, $power ) {
+ return pow( $base, $power );
+ }
}
// @codeCoverageIgnoreEnd
diff --git a/includes/functions-debug.php b/includes/functions-debug.php
index 4e5a557..cac4f2d 100644
--- a/includes/functions-debug.php
+++ b/includes/functions-debug.php
@@ -6,8 +6,8 @@
/**
* Add a message to the debug log
*
- * When in debug mode ( YOURLS_DEBUG == true ) the debug log is echoed in yourls_html_footer()
- * Log messages are appended to $ydb->debug_log array, which is instanciated within class Database\YDB
+ * When in debug mode (YOURLS_DEBUG == true) the debug log is echoed in yourls_html_footer()
+ * Log messages are appended to $ydb->debug_log array, which is instantiated within class Database\YDB
*
* @since 1.7
* @param string $msg Message to add to the debug log
@@ -15,12 +15,7 @@
*/
function yourls_debug_log( $msg ) {
yourls_do_action( 'debug_log', $msg );
- // Get the DB object ($ydb), get its profiler (\Aura\Sql\Profiler\Profiler), its logger (\Aura\Sql\Profiler\MemoryLogger) and
- // pass it a unused argument (loglevel) and the message
- // Check if function exists to allow usage of the function in very early stages
- if(function_exists('yourls_debug_log')) {
- yourls_get_db()->getProfiler()->getLogger()->log( 'debug', $msg);
- }
+ yourls_get_db('read-debug_log')->getProfiler()->getLogger()->log('debug', $msg);
return $msg;
}
@@ -31,7 +26,7 @@ function yourls_debug_log( $msg ) {
* @return array
*/
function yourls_get_debug_log() {
- return yourls_get_db()->getProfiler()->getLogger()->getMessages();
+ return yourls_get_db('read-get_debug_log')->getProfiler()->getLogger()->getMessages();
}
/**
@@ -40,7 +35,7 @@ function yourls_get_debug_log() {
* @return int
*/
function yourls_get_num_queries() {
- return yourls_apply_filter( 'get_num_queries', yourls_get_db()->get_num_queries() );
+ return yourls_apply_filter( 'get_num_queries', yourls_get_db('read-get_num_queries')->get_num_queries() );
}
/**
@@ -52,7 +47,7 @@ function yourls_get_num_queries() {
*/
function yourls_debug_mode( $bool ) {
// log queries if true
- yourls_get_db()->getProfiler()->setActive( (bool)$bool );
+ yourls_get_db('read-debug_mode')->getProfiler()->setActive( (bool)$bool );
// report notices if true
$level = $bool ? -1 : ( E_ERROR | E_PARSE );
diff --git a/includes/functions-deprecated.php b/includes/functions-deprecated.php
index 3154c17..662ffb2 100644
--- a/includes/functions-deprecated.php
+++ b/includes/functions-deprecated.php
@@ -129,12 +129,12 @@ function yourls_get_search_text() {
*/
function yourls_current_time( $type, $gmt = 0 ) {
yourls_deprecated_function( __FUNCTION__, '1.7.10', 'yourls_get_timestamp' );
- switch ( $type ) {
- case 'mysql':
- return ( $gmt ) ? gmdate( 'Y-m-d H:i:s' ) : gmdate( 'Y-m-d H:i:s', yourls_get_timestamp( time() ));
- case 'timestamp':
- return ( $gmt ) ? time() : yourls_get_timestamp( time() );
- }
+ switch ( $type ) {
+ case 'mysql':
+ return ( $gmt ) ? gmdate( 'Y-m-d H:i:s' ) : gmdate( 'Y-m-d H:i:s', yourls_get_timestamp( time() ));
+ case 'timestamp':
+ return ( $gmt ) ? time() : yourls_get_timestamp( time() );
+ }
}
/**
@@ -169,8 +169,8 @@ function yourls_sanitize_string( $string, $restrict_to_shorturl_charset = false
*
*/
function yourls_favicon( $echo = true ) {
- yourls_deprecated_function( __FUNCTION__, '1.7.10', 'yourls_get_yourls_favicon_url' );
- return yourls_get_yourls_favicon_url( $echo );
+ yourls_deprecated_function( __FUNCTION__, '1.7.10', 'yourls_get_yourls_favicon_url' );
+ return yourls_get_yourls_favicon_url( $echo );
}
/**
@@ -180,8 +180,8 @@ function yourls_favicon( $echo = true ) {
*
*/
function yourls_get_link_stats( $url ) {
- yourls_deprecated_function( __FUNCTION__, '1.7.10', 'yourls_get_keyword_stats' );
- return yourls_get_keyword_stats( $url );
+ yourls_deprecated_function( __FUNCTION__, '1.7.10', 'yourls_get_keyword_stats' );
+ return yourls_get_keyword_stats( $url );
}
/**
@@ -192,8 +192,8 @@ function yourls_get_link_stats( $url ) {
*
*/
function yourls_url_exists( $url ) {
- yourls_deprecated_function( __FUNCTION__, '1.7.10', 'yourls_long_url_exists' );
- return yourls_long_url_exists( $url );
+ yourls_deprecated_function( __FUNCTION__, '1.7.10', 'yourls_long_url_exists' );
+ return yourls_long_url_exists( $url );
}
/**
@@ -201,8 +201,8 @@ function yourls_url_exists( $url ) {
*
*/
function yourls_plural( $word, $count=1 ) {
- yourls_deprecated_function( __FUNCTION__, '1.6', 'yourls_n' );
- return $word . ($count > 1 ? 's' : '');
+ yourls_deprecated_function( __FUNCTION__, '1.6', 'yourls_n' );
+ return $word . ($count > 1 ? 's' : '');
}
/**
@@ -210,10 +210,10 @@ function yourls_plural( $word, $count=1 ) {
*
*/
function yourls_get_duplicate_keywords( $longurl ) {
- yourls_deprecated_function( __FUNCTION__, '1.7', 'yourls_get_longurl_keywords' );
- if( !yourls_allow_duplicate_longurls() )
- return NULL;
- return yourls_apply_filter( 'get_duplicate_keywords', yourls_get_longurl_keywords ( $longurl ), $longurl );
+ yourls_deprecated_function( __FUNCTION__, '1.7', 'yourls_get_longurl_keywords' );
+ if( !yourls_allow_duplicate_longurls() )
+ return NULL;
+ return yourls_apply_filter( 'get_duplicate_keywords', yourls_get_longurl_keywords ( $longurl ), $longurl );
}
/**
@@ -223,8 +223,8 @@ function yourls_get_duplicate_keywords( $longurl ) {
*
*/
function yourls_intval( $int ) {
- yourls_deprecated_function( __FUNCTION__, '1.7', 'yourls_sanitize_int' );
- return yourls_escape( $int );
+ yourls_deprecated_function( __FUNCTION__, '1.7', 'yourls_sanitize_int' );
+ return yourls_escape( $int );
}
/**
@@ -232,8 +232,8 @@ function yourls_intval( $int ) {
*
*/
function yourls_get_remote_content( $url, $maxlen = 4096, $timeout = 5 ) {
- yourls_deprecated_function( __FUNCTION__, '1.7', 'yourls_http_get_body' );
- return yourls_http_get_body( $url );
+ yourls_deprecated_function( __FUNCTION__, '1.7', 'yourls_http_get_body' );
+ return yourls_http_get_body( $url );
}
/**
@@ -250,8 +250,8 @@ function yourls_get_remote_content( $url, $maxlen = 4096, $timeout = 5 ) {
* @return mixed
*/
function yourls_apply_filters( $hook, $value = '' ) {
- yourls_deprecated_function( __FUNCTION__, '1.7.1', 'yourls_apply_filter' );
- return yourls_apply_filter( $hook, $value );
+ yourls_deprecated_function( __FUNCTION__, '1.7.1', 'yourls_apply_filter' );
+ return yourls_apply_filter( $hook, $value );
}
/**
@@ -259,23 +259,22 @@ function yourls_apply_filters( $hook, $value = '' ) {
*
*/
function yourls_has_interface() {
- yourls_deprecated_function( __FUNCTION__, '1.7.1' );
- if( yourls_is_API() or yourls_is_GO() )
- return false;
- return true;
+ yourls_deprecated_function( __FUNCTION__, '1.7.1' );
+ if( yourls_is_API() or yourls_is_GO() )
+ return false;
+ return true;
}
/**
* Check if a proxy is defined for HTTP requests
*
- * @uses YOURLS_PROXY
* @since 1.7
* @deprecated 1.7.1
* @return bool true if a proxy is defined, false otherwise
*/
function yourls_http_proxy_is_defined() {
- yourls_deprecated_function( __FUNCTION__, '1.7.1', 'yourls_http_get_proxy' );
- return yourls_apply_filter( 'http_proxy_is_defined', defined( 'YOURLS_PROXY' ) );
+ yourls_deprecated_function( __FUNCTION__, '1.7.1', 'yourls_http_get_proxy' );
+ return yourls_apply_filter( 'http_proxy_is_defined', defined( 'YOURLS_PROXY' ) );
}
/**
@@ -293,8 +292,8 @@ function yourls_http_proxy_is_defined() {
* @return string Translated context string without pipe
*/
function yourls_ex( $text, $context, $domain = 'default' ) {
- yourls_deprecated_function( __FUNCTION__, '1.7.1', 'yourls_xe' );
- echo yourls_xe( $text, $context, $domain );
+ yourls_deprecated_function( __FUNCTION__, '1.7.1', 'yourls_xe' );
+ echo yourls_xe( $text, $context, $domain );
}
/**
@@ -308,20 +307,20 @@ function yourls_ex( $text, $context, $domain = 'default' ) {
* @return string|array escaped data
*/
function yourls_escape( $data ) {
- yourls_deprecated_function( __FUNCTION__, '1.7.3', 'PDO' );
- if( is_array( $data ) ) {
- foreach( $data as $k => $v ) {
- if( is_array( $v ) ) {
- $data[ $k ] = yourls_escape( $v );
- } else {
- $data[ $k ] = yourls_escape_real( $v );
- }
- }
- } else {
- $data = yourls_escape_real( $data );
- }
+ yourls_deprecated_function( __FUNCTION__, '1.7.3', 'PDO' );
+ if( is_array( $data ) ) {
+ foreach( $data as $k => $v ) {
+ if( is_array( $v ) ) {
+ $data[ $k ] = yourls_escape( $v );
+ } else {
+ $data[ $k ] = yourls_escape_real( $v );
+ }
+ }
+ } else {
+ $data = yourls_escape_real( $data );
+ }
- return $data;
+ return $data;
}
/**
@@ -338,13 +337,13 @@ function yourls_escape( $data ) {
* @return string escaped string
*/
function yourls_escape_real( $string ) {
- yourls_deprecated_function( __FUNCTION__, '1.7.3', 'PDO' );
- global $ydb;
- if( isset( $ydb ) && ( $ydb instanceof \YOURLS\Database\YDB ) )
- return $ydb->escape( $string );
+ yourls_deprecated_function( __FUNCTION__, '1.7.3', 'PDO' );
+ global $ydb;
+ if( isset( $ydb ) && ( $ydb instanceof \YOURLS\Database\YDB ) )
+ return $ydb->escape( $string );
- // YOURLS DB classes have been bypassed by a custom DB engine or a custom cache layer
- return yourls_apply_filter( 'custom_escape_real', addslashes( $string ), $string );
+ // YOURLS DB classes have been bypassed by a custom DB engine or a custom cache layer
+ return yourls_apply_filter( 'custom_escape_real', addslashes( $string ), $string );
}
// @codeCoverageIgnoreEnd
diff --git a/includes/functions-formatting.php b/includes/functions-formatting.php
index f7b034f..e0c7f49 100644
--- a/includes/functions-formatting.php
+++ b/includes/functions-formatting.php
@@ -12,18 +12,18 @@
* @return string Converted number
*/
function yourls_int2string($num, $chars = null) {
- if( $chars == null )
- $chars = yourls_get_shorturl_charset();
- $string = '';
- $len = strlen( $chars );
- while( $num >= $len ) {
- $mod = bcmod( (string)$num, (string)$len );
- $num = bcdiv( (string)$num, (string)$len );
- $string = $chars[ $mod ] . $string;
- }
- $string = $chars[ intval( $num ) ] . $string;
+ if( $chars == null )
+ $chars = yourls_get_shorturl_charset();
+ $string = '';
+ $len = strlen( $chars );
+ while( $num >= $len ) {
+ $mod = bcmod( (string)$num, (string)$len );
+ $num = bcdiv( (string)$num, (string)$len );
+ $string = $chars[ $mod ] . $string;
+ }
+ $string = $chars[ intval( $num ) ] . $string;
- return yourls_apply_filter( 'int2string', $string, $num, $chars );
+ return yourls_apply_filter( 'int2string', $string, $num, $chars );
}
/**
@@ -34,18 +34,18 @@ function yourls_int2string($num, $chars = null) {
* @return string Number (as a string)
*/
function yourls_string2int($string, $chars = null) {
- if( $chars == null )
- $chars = yourls_get_shorturl_charset();
- $integer = 0;
- $string = strrev( $string );
- $baselen = strlen( $chars );
- $inputlen = strlen( $string );
- for ($i = 0; $i < $inputlen; $i++) {
- $index = strpos( $chars, $string[$i] );
- $integer = bcadd( (string)$integer, bcmul( (string)$index, bcpow( (string)$baselen, (string)$i ) ) );
- }
+ if( $chars == null )
+ $chars = yourls_get_shorturl_charset();
+ $integer = 0;
+ $string = strrev( $string );
+ $baselen = strlen( $chars );
+ $inputlen = strlen( $string );
+ for ($i = 0; $i < $inputlen; $i++) {
+ $index = strpos( $chars, $string[$i] );
+ $integer = bcadd( (string)$integer, bcmul( (string)$index, bcpow( (string)$baselen, (string)$i ) ) );
+ }
- return yourls_apply_filter( 'string2int', $integer, $string, $chars );
+ return yourls_apply_filter( 'string2int', $integer, $string, $chars );
}
/**
@@ -58,10 +58,10 @@ function yourls_string2int($string, $chars = null) {
*/
function yourls_unique_element_id($prefix = 'yid', $initial_val = 1) {
static $id_counter = 1;
- if ($initial_val > 1) {
- $id_counter = (int) $initial_val;
- }
- return yourls_apply_filter( 'unique_element_id', $prefix . (string) $id_counter++ );
+ if ($initial_val > 1) {
+ $id_counter = (int) $initial_val;
+ }
+ return yourls_apply_filter( 'unique_element_id', $prefix . (string) $id_counter++ );
}
/**
@@ -86,7 +86,7 @@ function yourls_sanitize_keyword( $keyword, $restrict_to_shorturl_charset = fals
$valid = yourls_sanitize_url( $keyword );
}
- return yourls_apply_filter( 'sanitize_string', $valid, $keyword, $restrict_to_shorturl_charset );
+ return yourls_apply_filter( 'sanitize_string', $valid, $keyword, $restrict_to_shorturl_charset );
}
/**
@@ -99,15 +99,15 @@ function yourls_sanitize_keyword( $keyword, $restrict_to_shorturl_charset = fals
* @return string Safe title
*/
function yourls_sanitize_title( $unsafe_title, $fallback = '' ) {
- $title = $unsafe_title;
- $title = strip_tags( $title );
- $title = preg_replace( "/\s+/", ' ', trim( $title ) );
+ $title = $unsafe_title;
+ $title = strip_tags( $title );
+ $title = preg_replace( "/\s+/", ' ', trim( $title ) );
if ( '' === $title || false === $title ) {
$title = $fallback;
}
- return yourls_apply_filter( 'sanitize_title', $title, $unsafe_title, $fallback );
+ return yourls_apply_filter( 'sanitize_title', $title, $unsafe_title, $fallback );
}
/**
@@ -120,8 +120,8 @@ function yourls_sanitize_title( $unsafe_title, $fallback = '' ) {
* @return string Safe URL
*/
function yourls_sanitize_url( $unsafe_url, $protocols = array() ) {
- $url = yourls_esc_url( $unsafe_url, 'redirection', $protocols );
- return yourls_apply_filter( 'sanitize_url', $url, $unsafe_url );
+ $url = yourls_esc_url( $unsafe_url, 'redirection', $protocols );
+ return yourls_apply_filter( 'sanitize_url', $url, $unsafe_url );
}
/**
@@ -139,8 +139,8 @@ function yourls_sanitize_url( $unsafe_url, $protocols = array() ) {
* @return string Safe URL
*/
function yourls_sanitize_url_safe( $unsafe_url, $protocols = array() ) {
- $url = yourls_esc_url( $unsafe_url, 'safe', $protocols );
- return yourls_apply_filter( 'sanitize_url_safe', $url, $unsafe_url );
+ $url = yourls_esc_url( $unsafe_url, 'safe', $protocols );
+ return yourls_apply_filter( 'sanitize_url_safe', $url, $unsafe_url );
}
/**
@@ -153,18 +153,18 @@ function yourls_sanitize_url_safe( $unsafe_url, $protocols = array() ) {
* @return string The string with the replaced values.
*/
function yourls_deep_replace($search, $subject ){
- $found = true;
- while($found) {
- $found = false;
- foreach( (array) $search as $val ) {
- while( strpos( $subject, $val ) !== false ) {
- $found = true;
- $subject = str_replace( $val, '', $subject );
- }
- }
- }
+ $found = true;
+ while($found) {
+ $found = false;
+ foreach( (array) $search as $val ) {
+ while( strpos( $subject, $val ) !== false ) {
+ $found = true;
+ $subject = str_replace( $val, '', $subject );
+ }
+ }
+ }
- return $subject;
+ return $subject;
}
/**
@@ -174,7 +174,7 @@ function yourls_deep_replace($search, $subject ){
* @return string Integer as a string
*/
function yourls_sanitize_int($int ) {
- return ( substr( preg_replace( '/[^0-9]/', '', strval( $int ) ), 0, 20 ) );
+ return ( substr( preg_replace( '/[^0-9]/', '', strval( $int ) ), 0, 20 ) );
}
/**
@@ -185,7 +185,7 @@ function yourls_sanitize_int($int ) {
* @return string IP address
*/
function yourls_sanitize_ip($ip ) {
- return preg_replace( '/[^0-9a-fA-F:., ]/', '', $ip );
+ return preg_replace( '/[^0-9a-fA-F:., ]/', '', $ip );
}
/**
@@ -195,10 +195,10 @@ function yourls_sanitize_ip($ip ) {
* @return false|mixed Date in format m(m)/d(d)/yyyy or false if invalid
*/
function yourls_sanitize_date($date ) {
- if( !preg_match( '!^\d{1,2}/\d{1,2}/\d{4}$!' , $date ) ) {
- return false;
- }
- return $date;
+ if( !preg_match( '!^\d{1,2}/\d{1,2}/\d{4}$!' , $date ) ) {
+ return false;
+ }
+ return $date;
}
/**
@@ -208,9 +208,9 @@ function yourls_sanitize_date($date ) {
* @return false|string String in Y-m-d format for SQL search or false if malformed input
*/
function yourls_sanitize_date_for_sql($date) {
- if( !yourls_sanitize_date( $date ) )
- return false;
- return date( 'Y-m-d', strtotime( $date ) );
+ if( !yourls_sanitize_date( $date ) )
+ return false;
+ return date( 'Y-m-d', strtotime( $date ) );
}
/**
@@ -222,11 +222,11 @@ function yourls_sanitize_date_for_sql($date) {
* @return string Trimmed string
*/
function yourls_trim_long_string($string, $length = 60, $append = '[...]') {
- $newstring = $string;
+ $newstring = $string;
if ( mb_strlen( $newstring ) > $length ) {
$newstring = mb_substr( $newstring, 0, $length - mb_strlen( $append ), 'UTF-8' ) . $append;
}
- return yourls_apply_filter( 'trim_long_string', $newstring, $string, $length, $append );
+ return yourls_apply_filter( 'trim_long_string', $newstring, $string, $length, $append );
}
/**
@@ -234,7 +234,12 @@ function yourls_trim_long_string($string, $length = 60, $append = '[...]') {
*
* The regexp searches for the first digits, then a period, then more digits and periods, and discards
* all the rest.
- * For instance, 'mysql-5.5-beta' and '5.5-RC1' return '5.5'
+ * Examples:
+ * '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'
*
* @since 1.4.1
* @param string $version Version number
@@ -254,9 +259,42 @@ function yourls_sanitize_version( $version ) {
* @return string|null Sanitized file name (or null if it's just backslashes, ok...)
*/
function yourls_sanitize_filename($file) {
- $file = str_replace( '\\', '/', $file ); // sanitize for Win32 installs
- $file = preg_replace( '|/+|' ,'/', $file ); // remove any duplicate slash
- return $file;
+ $file = str_replace( '\\', '/', $file ); // sanitize for Win32 installs
+ $file = preg_replace( '|/+|' ,'/', $file ); // remove any duplicate slash
+ return $file;
+}
+
+/**
+ * Validate a JSONP callback name
+ *
+ * Check if the callback contains only safe characters: [a-zA-Z0-9_$.]
+ * Returns the original callback if valid, or false if invalid.
+ *
+ * Examples:
+ * - 'myCallback' => 'myCallback'
+ * - 'alert(1)' => false
+ * See tests/tests/format/JsonpCallbackTest.php for various cases covered
+ *
+ * @since 1.10.3
+ * @param string $callback Raw callback value
+ * @return string|false Original callback if valid, false otherwise
+ */
+function yourls_validate_jsonp_callback($callback ) {
+ $callback = (string) $callback;
+
+ // First, check for JavaScript unicode escape sequences like \u2028 or u2028
+ // They are sometimes used to smuggle line/paragraph separators.
+ if ( preg_match( '/\\\\?u[0-9a-fA-F]{4}/', $callback ) ) {
+ return yourls_apply_filter( 'validate_jsonp_callback_error', false, $callback );
+ }
+
+ // Check if callback contains only safe characters [a-zA-Z0-9_$.]
+ if ( !preg_match( '/^[a-zA-Z0-9_$.]+$/', $callback ) ) {
+ return yourls_apply_filter( 'validate_jsonp_callback_error', false, $callback );
+ }
+
+ // Callback is valid, return original value
+ return yourls_apply_filter( 'validate_jsonp_callback', $callback );
}
/**
@@ -266,22 +304,22 @@ function yourls_sanitize_filename($file) {
* @return bool Whether string seems valid UTF-8
*/
function yourls_seems_utf8($str) {
- $length = strlen( $str );
- for ( $i=0; $i < $length; $i++ ) {
- $c = ord( $str[ $i ] );
- if ( $c < 0x80 ) $n = 0; # 0bbbbbbb
- elseif (($c & 0xE0) == 0xC0) $n=1; # 110bbbbb
- elseif (($c & 0xF0) == 0xE0) $n=2; # 1110bbbb
- elseif (($c & 0xF8) == 0xF0) $n=3; # 11110bbb
- elseif (($c & 0xFC) == 0xF8) $n=4; # 111110bb
- elseif (($c & 0xFE) == 0xFC) $n=5; # 1111110b
- else return false; # Does not match any model
- for ($j=0; $j<$n; $j++) { # n bytes matching 10bbbbbb follow ?
- if ((++$i == $length) || ((ord($str[$i]) & 0xC0) != 0x80))
- return false;
- }
- }
- return true;
+ $length = strlen( $str );
+ for ( $i=0; $i < $length; $i++ ) {
+ $c = ord( $str[ $i ] );
+ if ( $c < 0x80 ) $n = 0; # 0bbbbbbb
+ elseif (($c & 0xE0) == 0xC0) $n=1; # 110bbbbb
+ elseif (($c & 0xF0) == 0xE0) $n=2; # 1110bbbb
+ elseif (($c & 0xF8) == 0xF0) $n=3; # 11110bbb
+ elseif (($c & 0xFC) == 0xF8) $n=4; # 111110bb
+ elseif (($c & 0xFE) == 0xFC) $n=5; # 1111110b
+ else return false; # Does not match any model
+ for ($j=0; $j<$n; $j++) { # n bytes matching 10bbbbbb follow ?
+ if ((++$i == $length) || ((ord($str[$i]) & 0xC0) != 0x80))
+ return false;
+ }
+ }
+ return true;
}
@@ -313,28 +351,28 @@ function yourls_supports_pcre_u() {
* @return string The checked text.
*/
function yourls_check_invalid_utf8( $string, $strip = false ) {
- $string = (string) $string;
+ $string = (string) $string;
- if ( 0 === strlen( $string ) ) {
- return '';
- }
+ if ( 0 === strlen( $string ) ) {
+ return '';
+ }
- // We can't demand utf8 in the PCRE installation, so just return the string in those cases
- if ( ! yourls_supports_pcre_u() ) {
- return $string;
- }
+ // We can't demand utf8 in the PCRE installation, so just return the string in those cases
+ if ( ! yourls_supports_pcre_u() ) {
+ return $string;
+ }
- // preg_match fails when it encounters invalid UTF8 in $string
- if ( 1 === @preg_match( '/^./us', $string ) ) {
- return $string;
- }
+ // preg_match fails when it encounters invalid UTF8 in $string
+ if ( 1 === @preg_match( '/^./us', $string ) ) {
+ return $string;
+ }
- // Attempt to strip the bad chars if requested (not recommended)
- if ( $strip && function_exists( 'iconv' ) ) {
- return iconv( 'utf-8', 'utf-8', $string );
- }
+ // Attempt to strip the bad chars if requested (not recommended)
+ if ( $strip && function_exists( 'iconv' ) ) {
+ return iconv( 'utf-8', 'utf-8', $string );
+ }
- return '';
+ return '';
}
/**
@@ -353,56 +391,56 @@ function yourls_check_invalid_utf8( $string, $strip = false ) {
* @return string The encoded text with HTML entities.
*/
function yourls_specialchars( $string, $quote_style = ENT_NOQUOTES, $double_encode = false ) {
- $string = (string) $string;
+ $string = (string) $string;
- if ( 0 === strlen( $string ) )
- return '';
+ if ( 0 === strlen( $string ) )
+ return '';
- // Don't bother if there are no specialchars - saves some processing
- if ( ! preg_match( '/[&<>"\']/', $string ) )
- return $string;
+ // Don't bother if there are no specialchars - saves some processing
+ if ( ! preg_match( '/[&<>"\']/', $string ) )
+ return $string;
- // Account for the previous behaviour of the function when the $quote_style is not an accepted value
- if ( empty( $quote_style ) )
- $quote_style = ENT_NOQUOTES;
- elseif ( ! in_array( $quote_style, array( 0, 2, 3, 'single', 'double' ), true ) )
- $quote_style = ENT_QUOTES;
+ // Account for the previous behaviour of the function when the $quote_style is not an accepted value
+ if ( empty( $quote_style ) )
+ $quote_style = ENT_NOQUOTES;
+ elseif ( ! in_array( $quote_style, array( 0, 2, 3, 'single', 'double' ), true ) )
+ $quote_style = ENT_QUOTES;
- $charset = 'UTF-8';
+ $charset = 'UTF-8';
- $_quote_style = $quote_style;
+ $_quote_style = $quote_style;
- if ( $quote_style === 'double' ) {
- $quote_style = ENT_COMPAT;
- $_quote_style = ENT_COMPAT;
- } elseif ( $quote_style === 'single' ) {
- $quote_style = ENT_NOQUOTES;
- }
+ if ( $quote_style === 'double' ) {
+ $quote_style = ENT_COMPAT;
+ $_quote_style = ENT_COMPAT;
+ } elseif ( $quote_style === 'single' ) {
+ $quote_style = ENT_NOQUOTES;
+ }
- // Handle double encoding ourselves
- if ( $double_encode ) {
- $string = @htmlspecialchars( $string, $quote_style, $charset );
- } else {
- // Decode & into &
- $string = yourls_specialchars_decode( $string, $_quote_style );
+ // Handle double encoding ourselves
+ if ( $double_encode ) {
+ $string = @htmlspecialchars( $string, $quote_style, $charset );
+ } else {
+ // Decode & into &
+ $string = yourls_specialchars_decode( $string, $_quote_style );
- // Guarantee every &entity; is valid or re-encode the &
- $string = yourls_kses_normalize_entities( $string );
+ // Guarantee every &entity; is valid or re-encode the &
+ $string = yourls_kses_normalize_entities( $string );
- // Now re-encode everything except &entity;
- $string = preg_split( '/(?x?[0-9a-z]+;)/i', $string, -1, PREG_SPLIT_DELIM_CAPTURE );
+ // Now re-encode everything except &entity;
+ $string = preg_split( '/(?x?[0-9a-z]+;)/i', $string, -1, PREG_SPLIT_DELIM_CAPTURE );
- for ( $i = 0; $i < count( $string ); $i += 2 )
- $string[$i] = @htmlspecialchars( $string[$i], $quote_style, $charset );
+ for ( $i = 0; $i < count( $string ); $i += 2 )
+ $string[$i] = @htmlspecialchars( $string[$i], $quote_style, $charset );
- $string = implode( '', $string );
- }
+ $string = implode( '', $string );
+ }
- // Backwards compatibility
- if ( 'single' === $_quote_style )
- $string = str_replace( "'", ''', $string );
+ // Backwards compatibility
+ if ( 'single' === $_quote_style )
+ $string = str_replace( "'", ''', $string );
- return $string;
+ return $string;
}
/**
@@ -420,53 +458,53 @@ function yourls_specialchars( $string, $quote_style = ENT_NOQUOTES, $double_enco
* @return string The decoded text without HTML entities.
*/
function yourls_specialchars_decode( $string, $quote_style = ENT_NOQUOTES ) {
- $string = (string) $string;
-
- if ( 0 === strlen( $string ) ) {
- return '';
- }
-
- // Don't bother if there are no entities - saves a lot of processing
- if ( strpos( $string, '&' ) === false ) {
- return $string;
- }
-
- // Match the previous behaviour of _wp_specialchars() when the $quote_style is not an accepted value
- if ( empty( $quote_style ) ) {
- $quote_style = ENT_NOQUOTES;
- } elseif ( !in_array( $quote_style, array( 0, 2, 3, 'single', 'double' ), true ) ) {
- $quote_style = ENT_QUOTES;
- }
-
- // More complete than get_html_translation_table( HTML_SPECIALCHARS )
- $single = array( ''' => '\'', ''' => '\'' );
- $single_preg = array( '/*39;/' => ''', '/*27;/i' => ''' );
- $double = array( '"' => '"', '"' => '"', '"' => '"' );
- $double_preg = array( '/*34;/' => '"', '/*22;/i' => '"' );
- $others = array( '<' => '<', '<' => '<', '>' => '>', '>' => '>', '&' => '&', '&' => '&', '&' => '&' );
- $others_preg = array( '/*60;/' => '<', '/*62;/' => '>', '/*38;/' => '&', '/*26;/i' => '&' );
+ $string = (string) $string;
+
+ if ( 0 === strlen( $string ) ) {
+ return '';
+ }
+
+ // Don't bother if there are no entities - saves a lot of processing
+ if ( strpos( $string, '&' ) === false ) {
+ return $string;
+ }
+
+ // Match the previous behaviour of _wp_specialchars() when the $quote_style is not an accepted value
+ if ( empty( $quote_style ) ) {
+ $quote_style = ENT_NOQUOTES;
+ } elseif ( !in_array( $quote_style, array( 0, 2, 3, 'single', 'double' ), true ) ) {
+ $quote_style = ENT_QUOTES;
+ }
+
+ // More complete than get_html_translation_table( HTML_SPECIALCHARS )
+ $single = array( ''' => '\'', ''' => '\'' );
+ $single_preg = array( '/*39;/' => ''', '/*27;/i' => ''' );
+ $double = array( '"' => '"', '"' => '"', '"' => '"' );
+ $double_preg = array( '/*34;/' => '"', '/*22;/i' => '"' );
+ $others = array( '<' => '<', '<' => '<', '>' => '>', '>' => '>', '&' => '&', '&' => '&', '&' => '&' );
+ $others_preg = array( '/*60;/' => '<', '/*62;/' => '>', '/*38;/' => '&', '/*26;/i' => '&' );
$translation = $translation_preg = [];
- if ( $quote_style === ENT_QUOTES ) {
- $translation = array_merge( $single, $double, $others );
- $translation_preg = array_merge( $single_preg, $double_preg, $others_preg );
- } elseif ( $quote_style === ENT_COMPAT || $quote_style === 'double' ) {
- $translation = array_merge( $double, $others );
- $translation_preg = array_merge( $double_preg, $others_preg );
- } elseif ( $quote_style === 'single' ) {
- $translation = array_merge( $single, $others );
- $translation_preg = array_merge( $single_preg, $others_preg );
- } elseif ( $quote_style === ENT_NOQUOTES ) {
- $translation = $others;
- $translation_preg = $others_preg;
- }
+ if ( $quote_style === ENT_QUOTES ) {
+ $translation = array_merge( $single, $double, $others );
+ $translation_preg = array_merge( $single_preg, $double_preg, $others_preg );
+ } elseif ( $quote_style === ENT_COMPAT || $quote_style === 'double' ) {
+ $translation = array_merge( $double, $others );
+ $translation_preg = array_merge( $double_preg, $others_preg );
+ } elseif ( $quote_style === 'single' ) {
+ $translation = array_merge( $single, $others );
+ $translation_preg = array_merge( $single_preg, $others_preg );
+ } elseif ( $quote_style === ENT_NOQUOTES ) {
+ $translation = $others;
+ $translation_preg = $others_preg;
+ }
- // Remove zero padding on numeric entities
- $string = preg_replace( array_keys( $translation_preg ), array_values( $translation_preg ), $string );
+ // Remove zero padding on numeric entities
+ $string = preg_replace( array_keys( $translation_preg ), array_values( $translation_preg ), $string );
- // Replace characters according to translation table
- return strtr( $string, $translation );
+ // Replace characters according to translation table
+ return strtr( $string, $translation );
}
@@ -479,9 +517,9 @@ function yourls_specialchars_decode( $string, $quote_style = ENT_NOQUOTES ) {
* @return string
*/
function yourls_esc_html( $text ) {
- $safe_text = yourls_check_invalid_utf8( $text );
- $safe_text = yourls_specialchars( $safe_text, ENT_QUOTES );
- return yourls_apply_filter( 'esc_html', $safe_text, $text );
+ $safe_text = yourls_check_invalid_utf8( $text );
+ $safe_text = yourls_specialchars( $safe_text, ENT_QUOTES );
+ return yourls_apply_filter( 'esc_html', $safe_text, $text );
}
/**
@@ -493,9 +531,9 @@ function yourls_esc_html( $text ) {
* @return string
*/
function yourls_esc_attr( $text ) {
- $safe_text = yourls_check_invalid_utf8( $text );
- $safe_text = yourls_specialchars( $safe_text, ENT_QUOTES );
- return yourls_apply_filter( 'esc_attr', $safe_text, $text );
+ $safe_text = yourls_check_invalid_utf8( $text );
+ $safe_text = yourls_specialchars( $safe_text, ENT_QUOTES );
+ return yourls_apply_filter( 'esc_attr', $safe_text, $text );
}
/**
@@ -518,38 +556,41 @@ function yourls_esc_url( $url, $context = 'display', $protocols = array() ) {
// trim first -- see #1931
$url = trim( $url );
- // make sure there's only one 'http://' at the beginning (prevents pasting a URL right after the default 'http://')
- $url = str_replace(
- array( 'http://http://', 'http://https://' ),
- array( 'http://', 'https://' ),
- $url
- );
+ // make sure there's only one 'http://' at the beginning (prevents pasting a URL right after the default 'http://')
+ $url = str_replace(
+ array( 'http://http://', 'http://https://' ),
+ array( 'http://', 'https://' ),
+ $url
+ );
- if ( '' == $url )
- return $url;
+ if ( '' == $url )
+ return $url;
- $original_url = $url;
+ $original_url = $url;
- // force scheme and domain to lowercase - see issues 591 and 1630
+ // force scheme and domain to lowercase - see issues 591 and 1630
$url = yourls_normalize_uri( $url );
- $url = preg_replace( '|[^a-z0-9-~+_.?#=!&;,/:%@$\|*\'()\[\]\\x80-\\xff]|i', '', $url );
- // Previous regexp in YOURLS was '|[^a-z0-9-~+_.?\[\]\^#=!&;,/:%@$\|*`\'<>"()\\x80-\\xff\{\}]|i'
- // TODO: check if that was it too destructive
+ $url = preg_replace( '|[^a-z0-9-~+_.?#=!&;,/:%@$\|*\'()\[\]\\\\\x80-\\xff]|i', '', $url );
+ // The replace above allows backslashes now, but we only should only allow them after a query string or a fragment identifier
+ $url = yourls_remove_backslashes_before_query_fragment($url);
+
+ // Previous regexp in YOURLS was '|[^a-z0-9-~+_.?\[\]\^#=!&;,/:%@$\|*`\'<>"()\\x80-\\xff\{\}]|i'
+ // TODO: check if that was it too destructive
// If $context is 'safe', an extra step is taken to make sure no CRLF injection is possible.
// To be used when $url can be forged by evil user (eg it's from a $_SERVER variable, a query string, etc..)
- if ( 'safe' == $context ) {
+ if ( 'safe' == $context ) {
$strip = array( '%0d', '%0a', '%0D', '%0A' );
$url = yourls_deep_replace( $strip, $url );
}
- // Replace ampersands and single quotes only when displaying.
- if ( 'display' == $context ) {
- $url = yourls_kses_normalize_entities( $url );
- $url = str_replace( '&', '&', $url );
- $url = str_replace( "'", ''', $url );
- }
+ // Replace ampersands and single quotes only when displaying.
+ if ( 'display' == $context ) {
+ $url = yourls_kses_normalize_entities( $url );
+ $url = str_replace( '&', '&', $url );
+ $url = str_replace( "'", ''', $url );
+ }
// If there's a protocol, make sure it's OK
if( yourls_get_protocol($url) !== '' ) {
@@ -565,9 +606,45 @@ function yourls_esc_url( $url, $context = 'display', $protocols = array() ) {
// I didn't use KSES function kses_bad_protocol() because it doesn't work the way I liked (returns //blah from illegal://blah)
}
- return yourls_apply_filter( 'esc_url', $url, $original_url, $context );
+ return yourls_apply_filter( 'esc_url', $url, $original_url, $context );
}
+/**
+ * Remove backslashes before query string or fragment identifier
+ *
+ * This function removes backslashes before the first ? or #, if any.
+ * If there's no ? or #, all backslashes are removed.
+ * See issue #3802 and PR #3998
+ *
+ * @since 1.10.3
+ * @param string $url URL
+ * @return string URL without backslashes before query string or fragment identifier
+ */
+function yourls_remove_backslashes_before_query_fragment(string $url): string {
+ $posQ = strpos($url, '?');
+ $posH = strpos($url, '#');
+
+ if ($posQ === false && $posH === false) {
+ // no ? or # -> remove all backslashes
+ return str_replace('\\', '', $url);
+ }
+
+ // chose the first of ? or #
+ if ($posQ === false) {
+ $pos = $posH;
+ } elseif ($posH === false) {
+ $pos = $posQ;
+ } else {
+ $pos = min($posQ, $posH);
+ }
+
+ $before = substr($url, 0, $pos);
+ $after = substr($url, $pos);
+
+ $before = str_replace('\\', '', $before);
+
+ return $before . $after;
+}
/**
* Normalize a URI : lowercase scheme and domain, convert IDN to UTF8
@@ -664,12 +741,12 @@ function yourls_normalize_uri( $url ) {
* @return string Escaped text.
*/
function yourls_esc_js( $text ) {
- $safe_text = yourls_check_invalid_utf8( $text );
- $safe_text = yourls_specialchars( $safe_text, ENT_COMPAT );
- $safe_text = preg_replace( '/(x)?0*(?(1)27|39);?/i', "'", stripslashes( $safe_text ) );
- $safe_text = str_replace( "\r", '', $safe_text );
- $safe_text = str_replace( "\n", '\\n', addslashes( $safe_text ) );
- return yourls_apply_filter( 'esc_js', $safe_text, $text );
+ $safe_text = yourls_check_invalid_utf8( $text );
+ $safe_text = yourls_specialchars( $safe_text, ENT_COMPAT );
+ $safe_text = preg_replace( '/(x)?0*(?(1)27|39);?/i', "'", stripslashes( $safe_text ) );
+ $safe_text = str_replace( "\r", '', $safe_text );
+ $safe_text = str_replace( "\n", '\\n', addslashes( $safe_text ) );
+ return yourls_apply_filter( 'esc_js', $safe_text, $text );
}
/**
@@ -681,8 +758,8 @@ function yourls_esc_js( $text ) {
* @return string
*/
function yourls_esc_textarea( $text ) {
- $safe_text = htmlspecialchars( $text, ENT_QUOTES );
- return yourls_apply_filter( 'esc_textarea', $safe_text, $text );
+ $safe_text = htmlspecialchars( $text, ENT_QUOTES );
+ return yourls_apply_filter( 'esc_textarea', $safe_text, $text );
}
/**
@@ -708,7 +785,7 @@ function yourls_backslashit($string) {
* @return bool
*/
function yourls_is_rawurlencoded( $string ) {
- return rawurldecode( $string ) != $string;
+ return rawurldecode( $string ) != $string;
}
/**
@@ -722,11 +799,11 @@ function yourls_is_rawurlencoded( $string ) {
* @return string
*/
function yourls_rawurldecode_while_encoded( $string ) {
- $string = rawurldecode( $string );
- if( yourls_is_rawurlencoded( $string ) ) {
- $string = yourls_rawurldecode_while_encoded( $string );
- }
- return $string;
+ $string = rawurldecode( $string );
+ if( yourls_is_rawurlencoded( $string ) ) {
+ $string = yourls_rawurldecode_while_encoded( $string );
+ }
+ return $string;
}
/**
diff --git a/includes/functions-html.php b/includes/functions-html.php
index e8b5bbd..aadf6f6 100644
--- a/includes/functions-html.php
+++ b/includes/functions-html.php
@@ -6,16 +6,16 @@
* @return void
*/
function yourls_html_logo() {
- yourls_do_action( 'pre_html_logo' );
- ?>
-
-
+
+
+ ?>
>
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
- ';
- echo join( "\n", yourls_get_debug_log() );
- echo ' ';
- } ?>
-
-
-
-
+
+
+ ';
+ echo join( "\n", yourls_get_debug_log() );
+ echo ' ';
+ } ?>
+
+