Broken Link Checker - Version 1.10.3

Version Description

  • Security: Filter link URLs before displaying them on the "Broken Links" page.
    • Security: Prevent Editors and Administrators who don't have the "unfiltered_html" capability from creating "javascript:" URLs by editing existing links.
Download this release

Release Info

Developer whiteshadow
Plugin Icon 128x128 Broken Link Checker
Version 1.10.3
Comparing to
See all releases

Code changes from version 1.10.2 to 1.10.3

broken-link-checker.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Broken Link Checker
4
  Plugin URI: http://w-shadow.com/blog/2007/08/05/broken-link-checker-for-wordpress/
5
  Description: Checks your blog for broken links and missing images and notifies you on the dashboard if any are found.
6
- Version: 1.10.2
7
  Author: Janis Elsts
8
  Author URI: http://w-shadow.com/
9
  Text Domain: broken-link-checker
3
  Plugin Name: Broken Link Checker
4
  Plugin URI: http://w-shadow.com/blog/2007/08/05/broken-link-checker-for-wordpress/
5
  Description: Checks your blog for broken links and missing images and notifies you on the dashboard if any are found.
6
+ Version: 1.10.3
7
  Author: Janis Elsts
8
  Author URI: http://w-shadow.com/
9
  Text Domain: broken-link-checker
core/core.php CHANGED
@@ -3006,6 +3006,17 @@ class wsBrokenLinkChecker {
3006
  )));
3007
  }
3008
 
 
 
 
 
 
 
 
 
 
 
 
3009
  $new_text = (isset($_POST['new_text']) && is_string($_POST['new_text'])) ? stripslashes($_POST['new_text']) : null;
3010
  if ( $new_text === '' ) {
3011
  $new_text = null;
@@ -3042,6 +3053,7 @@ class wsBrokenLinkChecker {
3042
  'redirect_count' => $new_link->redirect_count,
3043
 
3044
  'url' => $new_link->url,
 
3045
  'final_url' => $new_link->final_url,
3046
  'link_text' => isset($new_text) ? $new_text : null,
3047
  'ui_link_text' => isset($new_text) ? $ui_link_text : null,
@@ -3143,6 +3155,7 @@ class wsBrokenLinkChecker {
3143
  $status = $link->analyse_status();
3144
  $response = array(
3145
  'url' => $link->url,
 
3146
  'new_link_id' => $result['new_link_id'],
3147
 
3148
  'status_text' => $status['text'],
3006
  )));
3007
  }
3008
 
3009
+ if ( !current_user_can('unfiltered_html') ) {
3010
+ //Disallow potentially dangerous URLs like "javascript:...".
3011
+ $protocols = wp_allowed_protocols();
3012
+ $good_protocol_url = wp_kses_bad_protocol($new_url, $protocols);
3013
+ if ( $new_url != $good_protocol_url ) {
3014
+ die( json_encode( array(
3015
+ 'error' => __("Oops, the new URL is invalid!", 'broken-link-checker')
3016
+ )));
3017
+ }
3018
+ }
3019
+
3020
  $new_text = (isset($_POST['new_text']) && is_string($_POST['new_text'])) ? stripslashes($_POST['new_text']) : null;
3021
  if ( $new_text === '' ) {
3022
  $new_text = null;
3053
  'redirect_count' => $new_link->redirect_count,
3054
 
3055
  'url' => $new_link->url,
3056
+ 'escaped_url' => esc_url_raw($new_link->url),
3057
  'final_url' => $new_link->final_url,
3058
  'link_text' => isset($new_text) ? $new_text : null,
3059
  'ui_link_text' => isset($new_text) ? $ui_link_text : null,
3155
  $status = $link->analyse_status();
3156
  $response = array(
3157
  'url' => $link->url,
3158
+ 'escaped_url' => esc_url_raw($link->url),
3159
  'new_link_id' => $result['new_link_id'],
3160
 
3161
  'status_text' => $status['text'],
includes/admin/links-page-js.php CHANGED
@@ -359,7 +359,8 @@ jQuery(function($){
359
 
360
  //Populate editor fields.
361
  var urlElement = master.find('a.blc-link-url');
362
- var urlInput = editRow.find('.blc-link-url-field').val(urlElement.attr('href'));
 
363
 
364
  var titleInput = editRow.find('.blc-link-text-field');
365
  var linkText = master.data('link-text'),
@@ -390,7 +391,7 @@ jQuery(function($){
390
  if (canEditUrl && blc_suggestions_enabled && (master.hasClass('link-status-error') || master.hasClass('link-status-warning'))) {
391
  editRow.find('.blc-url-replacement-suggestions').show();
392
  var suggestionList = editRow.find('.blc-suggestion-list');
393
- findReplacementSuggestions(urlElement.attr('href'), suggestionList);
394
  }
395
 
396
  editRow.find('.blc-update-link-button').prop('disabled', !(canEditUrl || canEditText));
@@ -544,7 +545,15 @@ jQuery(function($){
544
  //Everything went well. Update the link row with the new values.
545
 
546
  //Replace the displayed link URL with the new one.
547
- master.find('a.blc-link-url').attr('href', response.url).text(response.url);
 
 
 
 
 
 
 
 
548
 
549
  //Save the new ID
550
  replaceLinkId(linkId, response.new_link_id);
359
 
360
  //Populate editor fields.
361
  var urlElement = master.find('a.blc-link-url');
362
+ var linkUrl = urlElement.data('editable-url') || urlElement.attr('href');
363
+ var urlInput = editRow.find('.blc-link-url-field').val(linkUrl);
364
 
365
  var titleInput = editRow.find('.blc-link-text-field');
366
  var linkText = master.data('link-text'),
391
  if (canEditUrl && blc_suggestions_enabled && (master.hasClass('link-status-error') || master.hasClass('link-status-warning'))) {
392
  editRow.find('.blc-url-replacement-suggestions').show();
393
  var suggestionList = editRow.find('.blc-suggestion-list');
394
+ findReplacementSuggestions(linkUrl, suggestionList);
395
  }
396
 
397
  editRow.find('.blc-update-link-button').prop('disabled', !(canEditUrl || canEditText));
545
  //Everything went well. Update the link row with the new values.
546
 
547
  //Replace the displayed link URL with the new one.
548
+ var urlElement = master.find('a.blc-link-url');
549
+ urlElement
550
+ .attr('href', response.url)
551
+ .text(response.url)
552
+ .data('editable-url', response.url)
553
+ .prop('title', response.url);
554
+ if ( typeof response['escaped_url'] != 'undefined' ) {
555
+ urlElement.attr('href', response.escaped_url)
556
+ }
557
 
558
  //Save the new ID
559
  replaceLinkId(linkId, response.new_link_id);
includes/admin/table-printer.php CHANGED
@@ -669,8 +669,12 @@ class blcTablePrinter {
669
  */
670
  function column_new_url($link){
671
  ?>
672
- <a href="<?php print esc_attr($link->url); ?>" target='_blank' class='blc-link-url' title="<?php echo esc_attr($link->url); ?>">
673
- <?php print $link->url; ?></a>
 
 
 
 
674
  <?php
675
  //Output inline action links for the link/URL
676
  $actions = array();
669
  */
670
  function column_new_url($link){
671
  ?>
672
+ <a href="<?php print esc_attr(esc_url_raw($link->url)); ?>"
673
+ target='_blank'
674
+ class='blc-link-url'
675
+ title="<?php echo esc_attr($link->url); ?>"
676
+ data-editable-url="<?php echo esc_attr($link->url); ?>">
677
+ <?php print esc_html($link->url); ?></a>
678
  <?php
679
  //Output inline action links for the link/URL
680
  $actions = array();
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_i
4
  Tags: links, broken, maintenance, blogroll, custom fields, admin, comments, posts
5
  Requires at least: 3.2
6
  Tested up to: 4.0.1
7
- Stable tag: 1.10.2
8
 
9
  This plugin will check your posts, comments and other content for broken links and missing images, and notify you if any are found.
10
 
@@ -98,6 +98,10 @@ To upgrade your installation
98
 
99
  == Changelog ==
100
 
 
 
 
 
101
  = 1.10.2 =
102
  * Fixed an XSS vulnerability on the link checker settings page.
103
  * Fixed old YouTube embed code parsing - now it should pick up self-closing embed tags without an `<object>` wrapper.
4
  Tags: links, broken, maintenance, blogroll, custom fields, admin, comments, posts
5
  Requires at least: 3.2
6
  Tested up to: 4.0.1
7
+ Stable tag: 1.10.3
8
 
9
  This plugin will check your posts, comments and other content for broken links and missing images, and notify you if any are found.
10
 
98
 
99
  == Changelog ==
100
 
101
+ = 1.10.3 =
102
+ * Security: Filter link URLs before displaying them on the "Broken Links" page.
103
+ * Security: Prevent Editors and Administrators who don't have the "unfiltered_html" capability from creating "javascript:" URLs by editing existing links.
104
+
105
  = 1.10.2 =
106
  * Fixed an XSS vulnerability on the link checker settings page.
107
  * Fixed old YouTube embed code parsing - now it should pick up self-closing embed tags without an `<object>` wrapper.