Changeset 3481394
- Timestamp:
- 03/12/2026 05:59:22 PM (2 weeks ago)
- Location:
- broken-link-notifier
- Files:
-
- 56 added
- 6 edited
-
tags/1.3.7.2 (added)
-
tags/1.3.7.2/broken-link-notifier.php (added)
-
tags/1.3.7.2/includes (added)
-
tags/1.3.7.2/includes/cache.php (added)
-
tags/1.3.7.2/includes/css (added)
-
tags/1.3.7.2/includes/css/results-front.css (added)
-
tags/1.3.7.2/includes/css/results-front.min.css (added)
-
tags/1.3.7.2/includes/discord.php (added)
-
tags/1.3.7.2/includes/example-hook.php (added)
-
tags/1.3.7.2/includes/export.php (added)
-
tags/1.3.7.2/includes/helpers.php (added)
-
tags/1.3.7.2/includes/img (added)
-
tags/1.3.7.2/includes/img/admin-help-docs.png (added)
-
tags/1.3.7.2/includes/img/clear-cache-everywhere.png (added)
-
tags/1.3.7.2/includes/img/dev-debug-tools.png (added)
-
tags/1.3.7.2/includes/img/devconsole.gif (added)
-
tags/1.3.7.2/includes/img/discord.png (added)
-
tags/1.3.7.2/includes/img/eri-file-library.png (added)
-
tags/1.3.7.2/includes/img/gf-discord.png (added)
-
tags/1.3.7.2/includes/img/gf-msteams.png (added)
-
tags/1.3.7.2/includes/img/gf-tools.png (added)
-
tags/1.3.7.2/includes/img/gravity-zwr.png (added)
-
tags/1.3.7.2/includes/img/logo-teal.png (added)
-
tags/1.3.7.2/includes/img/logo-transparent.png (added)
-
tags/1.3.7.2/includes/img/screen_options.png (added)
-
tags/1.3.7.2/includes/index.php (added)
-
tags/1.3.7.2/includes/integrations.php (added)
-
tags/1.3.7.2/includes/js (added)
-
tags/1.3.7.2/includes/js/index.php (added)
-
tags/1.3.7.2/includes/js/omits.js (added)
-
tags/1.3.7.2/includes/js/results-back.js (added)
-
tags/1.3.7.2/includes/js/results-front.js (added)
-
tags/1.3.7.2/includes/js/results-front.min.js (added)
-
tags/1.3.7.2/includes/js/scan-multi.js (added)
-
tags/1.3.7.2/includes/js/scan-single.js (added)
-
tags/1.3.7.2/includes/js/settings.js (added)
-
tags/1.3.7.2/includes/loader.php (added)
-
tags/1.3.7.2/includes/menu.php (added)
-
tags/1.3.7.2/includes/msteams.php (added)
-
tags/1.3.7.2/includes/omits.php (added)
-
tags/1.3.7.2/includes/page-export.php (added)
-
tags/1.3.7.2/includes/page-help.php (added)
-
tags/1.3.7.2/includes/page-link-search.php (added)
-
tags/1.3.7.2/includes/page-results.php (added)
-
tags/1.3.7.2/includes/page-scan-multi.php (added)
-
tags/1.3.7.2/includes/page-scan-single.php (added)
-
tags/1.3.7.2/includes/page-settings.php (added)
-
tags/1.3.7.2/includes/page.php (added)
-
tags/1.3.7.2/includes/results.php (added)
-
tags/1.3.7.2/includes/scan-multi.php (added)
-
tags/1.3.7.2/includes/scan.php (added)
-
tags/1.3.7.2/includes/test_files (added)
-
tags/1.3.7.2/includes/test_files/Jubiläum-A-und-B.pdf (added)
-
tags/1.3.7.2/index.php (added)
-
tags/1.3.7.2/readme.txt (added)
-
tags/1.3.7.2/uninstall.php (added)
-
trunk/broken-link-notifier.php (modified) (1 diff)
-
trunk/includes/js/results-back.js (modified) (3 diffs)
-
trunk/includes/js/results-front.js (modified) (1 diff)
-
trunk/includes/js/results-front.min.js (modified) (1 diff)
-
trunk/includes/results.php (modified) (13 diffs)
-
trunk/readme.txt (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
broken-link-notifier/trunk/broken-link-notifier.php
r3481332 r3481394 4 4 * Plugin URI: https://pluginrx.com/plugin/broken-link-notifier/ 5 5 * Description: Get notified when someone loads a page with a broken link 6 * Version: 1.3.7. 16 * Version: 1.3.7.2 7 7 * Requires at least: 5.9 8 8 * Tested up to: 6.9 -
broken-link-notifier/trunk/includes/js/results-back.js
r3475895 r3481394 183 183 action: 'blnotifier_replace_link', 184 184 nonce: nonceReplace, 185 linkID: linkID, 185 186 oldLink: oldLink, 186 187 newLink: newLink, … … 241 242 let button = $( this ); 242 243 let link = button.data( 'link' ); 244 let linkID = $( this ).closest( 'tr' ).data( 'link-id' ); 243 245 244 246 $.ajax( { … … 249 251 action: 'blnotifier_delete_result', 250 252 nonce: nonceDelete, 251 link: link 253 link: link, 254 linkID: linkID 252 255 }, 253 256 success: function ( response ) { -
broken-link-notifier/trunk/includes/js/results-front.js
r3143920 r3481394 133 133 // Failure 134 134 } else if ( response.type == 'error' ) { 135 console.log( 'Scan failed. Please contact plugin developer.' ); 135 var errorMsg = response.msg ? response.msg : 'Unknown error occurred.'; 136 console.error( 'Scan failed: ' + errorMsg ); 136 137 } 137 138 } -
broken-link-notifier/trunk/includes/js/results-front.min.js
r3283556 r3481394 1 jQuery(o=>{const n=blnotifier_front_end.elements,e=window.location.search,i=new URLSearchParams(e);if(i.has("blink")){console.log("Looking for highlights; checking for broken links paused.");const e=i.get("blink");o.each(n,function(n,i){o(n).not("#wpadminbar "+n).each(function(n){const t=o(this).attr(i);if(void 0!==t&&t.includes(e))if(o(this).addClass("glowText"),o(this).is(":hidden")){var r="It looks like one or more of the links are hidden. To find them, try searching for it in your browser's Developer console.";console.log(r),alert(r)}else console.log("The element should glow yellow if it is visible on the page. If you do not see it on the page, then it is hidden somewhere. Check any JavaScript elements, too. You can try searching for it in your browser's Developer console.")})})}else{blnotifier_front_end.show_in_console&&console.log("%c Fetching links using the Broken Link Notifier Plugin... ","background: #2570AC; color: white");var t=[],r=[],s=[];o.each(n,function(n,e){o(n).each(function(n){const i=o(this).attr(e),l=o(this).parents("#wpadminbar").length,c=o(this).parents("header").length,a=o(this).parents("footer").length;void 0===i||l||(blnotifier_front_end.scan_header&&c?t.push(i):blnotifier_front_end.scan_footer&&a?s.push(i):c||a||r.push(i))})}),blnotifier_front_end.show_in_console&&(blnotifier_front_end.scan_header&&(console.log("%c Header links found: ","background: #222; color: #bada55"),console.log(t)),console.log("%c Content links found: ","background: #222; color: #bada55"),console.log(r),blnotifier_front_end.scan_header&&(console.log("%c Footer links found: ","background: #222; color: #bada55"),console.log(s)),console.log("%c Scanning for broken links... please wait. This may take a few minutes if there are a lot of links.","background: #2570AC; color: white"));var l=blnotifier_front_end.nonce;o.ajax({type:"post",dataType:"json",url:blnotifier_front_end.ajaxurl,data:{action:"blnotifier_blinks",nonce:l,scan_header:blnotifier_front_end.scan_header,scan_footer:blnotifier_front_end.scan_footer,source_url:window.location.href,header_links:t,content_links:r,footer_links:s},success:function(e){ "success"==e.type?(blnotifier_front_end.show_in_console&&(console.log("%c Broken Link Scan Results: ","background: #2570AC; color: white"),e.notify?console.error(e.notify):console.info("No broken links found. :)"),console.log(`%c ${e.timing} `,"background: #2570AC; color: white")),i.has("blinks")&&"true"==i.get("blinks")&&o.each(e.notify,function(e,i){o.each(i,function(e,i){o.each(n,function(n,e){o(n).each(function(n){var t=o(this).attr(e);i.link==t&&o(this).addClass("glowText")})})})})):"error"==e.type&&console.log("Scan failed. Please contact plugin developer.")}})}});1 jQuery(o=>{const n=blnotifier_front_end.elements,e=window.location.search,i=new URLSearchParams(e);if(i.has("blink")){console.log("Looking for highlights; checking for broken links paused.");const e=i.get("blink");o.each(n,function(n,i){o(n).not("#wpadminbar "+n).each(function(n){const t=o(this).attr(i);if(void 0!==t&&t.includes(e))if(o(this).addClass("glowText"),o(this).is(":hidden")){var r="It looks like one or more of the links are hidden. To find them, try searching for it in your browser's Developer console.";console.log(r),alert(r)}else console.log("The element should glow yellow if it is visible on the page. If you do not see it on the page, then it is hidden somewhere. Check any JavaScript elements, too. You can try searching for it in your browser's Developer console.")})})}else{blnotifier_front_end.show_in_console&&console.log("%c Fetching links using the Broken Link Notifier Plugin... ","background: #2570AC; color: white");var t=[],r=[],s=[];o.each(n,function(n,e){o(n).each(function(n){const i=o(this).attr(e),l=o(this).parents("#wpadminbar").length,c=o(this).parents("header").length,a=o(this).parents("footer").length;void 0===i||l||(blnotifier_front_end.scan_header&&c?t.push(i):blnotifier_front_end.scan_footer&&a?s.push(i):c||a||r.push(i))})}),blnotifier_front_end.show_in_console&&(blnotifier_front_end.scan_header&&(console.log("%c Header links found: ","background: #222; color: #bada55"),console.log(t)),console.log("%c Content links found: ","background: #222; color: #bada55"),console.log(r),blnotifier_front_end.scan_header&&(console.log("%c Footer links found: ","background: #222; color: #bada55"),console.log(s)),console.log("%c Scanning for broken links... please wait. This may take a few minutes if there are a lot of links.","background: #2570AC; color: white"));var l=blnotifier_front_end.nonce;o.ajax({type:"post",dataType:"json",url:blnotifier_front_end.ajaxurl,data:{action:"blnotifier_blinks",nonce:l,scan_header:blnotifier_front_end.scan_header,scan_footer:blnotifier_front_end.scan_footer,source_url:window.location.href,header_links:t,content_links:r,footer_links:s},success:function(e){if("success"==e.type)blnotifier_front_end.show_in_console&&(console.log("%c Broken Link Scan Results: ","background: #2570AC; color: white"),e.notify?console.error(e.notify):console.info("No broken links found. :)"),console.log(`%c ${e.timing} `,"background: #2570AC; color: white")),i.has("blinks")&&"true"==i.get("blinks")&&o.each(e.notify,function(e,i){o.each(i,function(e,i){o.each(n,function(n,e){o(n).each(function(n){var t=o(this).attr(e);i.link==t&&o(this).addClass("glowText")})})})});else if("error"==e.type){var t=e.msg?e.msg:"Unknown error occurred.";console.error("Scan failed: "+t)}}})}}); -
broken-link-notifier/trunk/includes/results.php
r3481332 r3481394 377 377 /** 378 378 * Remove a broken or warning link 379 * 380 * @param string $link 379 * 380 * @param string $link 381 * @param int|bool $id Optional link ID for direct deletion 381 382 * @return boolean 382 383 */ 383 public function remove( $link ) {384 public function remove( $link, $id = false ) { 384 385 global $wpdb; 385 386 $table_name = $wpdb->prefix . $this->table_name; 386 $link = sanitize_text_field( $link ); 387 388 // 1. New Normalized Hash 389 $url_parts = explode( '?', $link ); 390 $url_parts[ 0 ] = untrailingslashit( $url_parts[ 0 ] ); 391 $new_hash = md5( strtolower( implode( '?', $url_parts ) ) ); 392 393 // 2. Old Logic Hash (Legacy) 394 $old_hash = md5( strtolower( untrailingslashit( $link ) ) ); 395 396 // Try to delete by either hash 397 $deleted = $wpdb->query( 398 $wpdb->prepare( 399 "DELETE FROM $table_name WHERE link_hash = %s OR link_hash = %s", 400 $new_hash, 401 $old_hash 402 ) 403 ); 387 $deleted = 0; 388 389 // 1. Try deleting by ID first if provided 390 if ( $id ) { 391 $deleted = $wpdb->delete( 392 $table_name, 393 [ 'id' => absint( $id ) ], 394 [ '%d' ] 395 ); 396 } 397 398 // 2. Fallback to hash lookup if ID didn't work or wasn't provided 399 if ( ! $deleted ) { 400 $link = sanitize_text_field( $link ); 401 402 // New Normalized Hash 403 $url_parts = explode( '?', $link ); 404 $url_parts[0] = untrailingslashit( $url_parts[0] ); 405 $new_hash = md5( strtolower( implode( '?', $url_parts ) ) ); 406 407 // Old Logic Hash (Legacy) 408 $old_hash = md5( strtolower( untrailingslashit( $link ) ) ); 409 410 $deleted = $wpdb->query( 411 $wpdb->prepare( 412 "DELETE FROM $table_name WHERE link_hash = %s OR link_hash = %s", 413 $new_hash, 414 $old_hash 415 ) 416 ); 417 } 404 418 405 419 return ( false !== $deleted && $deleted > 0 ); … … 583 597 // Public endpoint: allow guests, but validate capability for logged-in users. 584 598 if ( is_user_logged_in() && ! current_user_can( 'read' ) ) { 585 wp_send_json_error( 'Permission denied' ); 599 $result = [ 600 'type' => 'error', 601 'msg' => 'Permission denied' 602 ]; 603 self::send_ajax_or_redirect( $result ); 586 604 } 587 605 … … 592 610 $footer_links = isset( $_REQUEST[ 'footer_links' ] ) ? wp_unslash( $_REQUEST[ 'footer_links' ] ) : []; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized 593 611 612 // Permissions 613 $user_can_manage = (new BLNOTIFIER_HELPERS)->user_can_manage_broken_links(); 614 594 615 // Enforce max links per page 595 616 $max_links = absint( get_option( 'blnotifier_max_links_per_page', 200 ) ); 596 617 $total_links = count( $header_links ) + count( $content_links ) + count( $footer_links ); 597 618 if ( $total_links > $max_links ) { 619 $error_msg = sprintf( __( 'Too many links in one scan. Max allowed: %d.', 'broken-link-notifier' ), $max_links ); 620 621 // If the user is an admin/manager, append the instruction 622 if ( $user_can_manage ) { 623 $error_msg .= ' ' . __( 'You can increase this limit in the plugin settings.', 'broken-link-notifier' ); 624 } 625 598 626 $result = [ 599 627 'type' => 'error', 600 'msg' => sprintf( 'Too many links in one scan. Max allowed: %d', $max_links )628 'msg' => $error_msg 601 629 ]; 630 602 631 self::send_ajax_or_redirect( $result ); 603 632 } 604 633 605 634 // Rate limit per IP only for non-link-managers 606 if ( ! (new BLNOTIFIER_HELPERS)->user_can_manage_broken_links()) {635 if ( !$user_can_manage ) { 607 636 $ip = $_SERVER[ 'REMOTE_ADDR' ]; 608 637 $transient_key = 'bln_rate_' . md5( $ip ); … … 622 651 // Only allow webpages, not file:///, etc. 623 652 if ( !str_starts_with( $source_url, 'http' ) ) { 624 wp_send_json_error( 'Invalid source: ' . $source_url ); 653 $result = [ 654 'type' => 'error', 655 'msg' => 'Invalid source: ' . $source_url 656 ]; 657 self::send_ajax_or_redirect( $result ); 625 658 } 626 659 … … 628 661 $site_url = site_url(); 629 662 if ( ! str_starts_with( $source_url, $site_url ) ) { 630 wp_send_json_error( 'External source URLs are not permitted.' ); 663 $result = [ 664 'type' => 'error', 665 'msg' => 'External source URLs are not permitted.' 666 ]; 667 self::send_ajax_or_redirect( $result ); 631 668 } 632 669 … … 642 679 // If it's not a post/page and it's not the homepage, it's likely a 404 or invalid 643 680 if ( ! $post_id && $source_url !== trailingslashit( $site_url ) && $source_url !== $site_url ) { 644 wp_send_json_error( 'Source URL does not exist on this site.' ); 681 $result = [ 682 'type' => 'error', 683 'msg' => 'Source URL does not exist on this site.' 684 ]; 685 self::send_ajax_or_redirect( $result ); 645 686 } 646 687 … … 804 845 // If the source no longer exists, auto remove it 805 846 if ( !$source_id || !get_post( $source_id ) ) { 806 $remove = $this->remove( $HELPERS->str_replace_on_link( $link ) );847 $remove = $this->remove( $HELPERS->str_replace_on_link( $link ), $link_id ); 807 848 $status = [ 808 849 'type' => 'n/a', … … 819 860 } else { 820 861 $result[ 'type' ] = 'error'; 821 $result[ 'msg' ] = __( 'Could not auto-remove link. ', 'broken-link-notifier' );862 $result[ 'msg' ] = __( 'Could not auto-remove link. Link not found in DB.', 'broken-link-notifier' ); 822 863 } 823 864 … … 830 871 // If it's good now, remove the old post 831 872 if ( $status[ 'type' ] == 'good' || $status[ 'type' ] == 'omitted' ) { 832 $remove = $this->remove( $HELPERS->str_replace_on_link( $link ) );873 $remove = $this->remove( $HELPERS->str_replace_on_link( $link ), $link_id ); 833 874 if ( $remove ) { 834 875 $result[ 'type' ] = 'success'; … … 846 887 // If it's still not good, but doesn't have the same code or type, update it 847 888 } elseif ( $code !== $status[ 'code' ] || $type !== $status[ 'type' ] ) { 848 $remove = $this->remove( $HELPERS->str_replace_on_link( $link ) );889 $remove = $this->remove( $HELPERS->str_replace_on_link( $link ), $link_id ); 849 890 if ( $remove ) { 850 891 $result[ 'type' ] = 'success'; … … 904 945 905 946 // Get the vars 947 $link_id = isset( $_REQUEST[ 'linkID' ] ) ? absint( wp_unslash( $_REQUEST[ 'linkID' ] ) ) : false; 906 948 $oldLink = isset( $_REQUEST[ 'oldLink' ] ) ? sanitize_text_field( wp_unslash( $_REQUEST[ 'oldLink' ] ) ) : false; 907 949 $newLink = isset( $_REQUEST[ 'newLink' ] ) ? sanitize_text_field( wp_unslash( $_REQUEST[ 'newLink' ] ) ) : false; … … 927 969 928 970 // Let's also delete the result 929 $this->remove( $HELPERS->str_replace_on_link( $oldLink ) );971 $this->remove( $HELPERS->str_replace_on_link( $oldLink ), $link_id ); 930 972 931 973 // Respond … … 959 1001 // Remove the link 960 1002 $link = isset( $_REQUEST[ 'link' ] ) ? sanitize_text_field( wp_unslash( $_REQUEST[ 'link' ] ) ) : false; 1003 $link_id = isset( $_REQUEST[ 'linkID' ] ) ? absint( wp_unslash( $_REQUEST[ 'linkID' ] ) ) : false; 1004 961 1005 if ( $link ) { 962 $this->remove( $HELPERS->str_replace_on_link( $link ) );1006 $this->remove( $HELPERS->str_replace_on_link( $link ), $link_id ); 963 1007 wp_send_json_success(); 964 1008 } -
broken-link-notifier/trunk/readme.txt
r3481332 r3481394 5 5 Tested up to: 6.9 6 6 Requires PHP: 7.4 7 Stable tag: 1.3.7. 17 Stable tag: 1.3.7.2 8 8 License: GPLv2 or later 9 9 License URI: http://www.gnu.org/licenses/gpl-2.0.txt … … 127 127 128 128 == Changelog == 129 = 1.3.7.2 = 130 * Tweak: Remove links on rescan by ID instead of link hash lookup 131 * Tweak: Added actual error message to front-end scan if there is an error so we can figure out what the actual problem is 132 129 133 = 1.3.7.1 = 130 134 * Tweak: Skipping internal pagination and reply links
Note: See TracChangeset
for help on using the changeset viewer.