Version Description
Download this release
Release Info
Developer | whiteshadow |
Plugin | Broken Link Checker |
Version | 0.1 |
Comparing to | |
See all releases |
Version 0.1
- broken-link-checker.php +341 -0
- readme.txt +36 -0
- wsblc_ajax.php +257 -0
broken-link-checker.php
ADDED
@@ -0,0 +1,341 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
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 posts for broken links in background and notifies you on the dashboard if any are found.
|
6 |
+
Version: 0.1
|
7 |
+
Author: Janis Elsts
|
8 |
+
Author URI: http://w-shadow.com/blog/
|
9 |
+
*/
|
10 |
+
|
11 |
+
/*
|
12 |
+
Copyright 2007 Janis Elsts (email : whiteshadow@w-shadow.com)
|
13 |
+
*/
|
14 |
+
|
15 |
+
if (!class_exists('ws_broken_link_checker')) {
|
16 |
+
|
17 |
+
class ws_broken_link_checker {
|
18 |
+
var $options;
|
19 |
+
var $options_name='wsblc_options';
|
20 |
+
var $postdata_name;
|
21 |
+
var $linkdata_name;
|
22 |
+
var $version='0.1';
|
23 |
+
var $myfile='';
|
24 |
+
var $myfolder='';
|
25 |
+
var $mybasename='';
|
26 |
+
|
27 |
+
|
28 |
+
function ws_broken_link_checker() {
|
29 |
+
global $wpdb;
|
30 |
+
|
31 |
+
$this->postdata_name=$wpdb->prefix . "blc_postdata";
|
32 |
+
$this->linkdata_name=$wpdb->prefix . "blc_linkdata";
|
33 |
+
$this->options=get_option($this->options_name);
|
34 |
+
|
35 |
+
$my_file = str_replace('\\', '/',__FILE__);
|
36 |
+
$my_file = preg_replace('/^.*wp-content[\\\\\/]plugins[\\\\\/]/', '', $my_file);
|
37 |
+
add_action('activate_'.$my_file, array(&$this,'activation'));
|
38 |
+
$this->myfile=$my_file;
|
39 |
+
$this->myfolder=basename(dirname(__FILE__));
|
40 |
+
$this->mybasename=plugin_basename(__FILE__);
|
41 |
+
|
42 |
+
add_action('admin_menu', array(&$this,'options_menu'));
|
43 |
+
|
44 |
+
add_action('delete_post', array(&$this,'post_deleted'));
|
45 |
+
add_action('save_post', array(&$this,'post_saved'));
|
46 |
+
add_action('admin_footer', array(&$this,'admin_footer'));
|
47 |
+
add_action('admin_print_scripts', array(&$this,'admin_print_scripts'));
|
48 |
+
add_action('activity_box_end', array(&$this,'activity_box'));
|
49 |
+
}
|
50 |
+
|
51 |
+
function admin_footer(){
|
52 |
+
?>
|
53 |
+
<!-- wsblc admin footer -->
|
54 |
+
<div id='wsblc_updater_div'></div>
|
55 |
+
<script type='text/javascript'>
|
56 |
+
new Ajax.PeriodicalUpdater('wsblc_updater_div', '<?php
|
57 |
+
echo get_option( "siteurl" ).'/wp-content/plugins/'.$this->myfolder.'/wsblc_ajax.php?action=run_check' ; ?>',
|
58 |
+
{
|
59 |
+
method: 'get',
|
60 |
+
frequency: <?php echo ($this->options['max_work_session']-1); ?>,
|
61 |
+
decay: 1.3
|
62 |
+
});
|
63 |
+
</script>
|
64 |
+
<!-- /wsblc admin footer -->
|
65 |
+
<?php
|
66 |
+
}
|
67 |
+
|
68 |
+
function activity_box(){
|
69 |
+
?>
|
70 |
+
<!-- wsblc activity box -->
|
71 |
+
<div id='wsblc_activity_box'></div>
|
72 |
+
<script type='text/javascript'>
|
73 |
+
new Ajax.Updater('wsblc_activity_box', '<?php
|
74 |
+
echo get_option( "siteurl" ).'/wp-content/plugins/'.$this->myfolder.'/wsblc_ajax.php?action=dashboard_status' ; ?>');
|
75 |
+
</script>
|
76 |
+
<!-- /wsblc activity box -->
|
77 |
+
<?php
|
78 |
+
}
|
79 |
+
|
80 |
+
function admin_print_scripts(){
|
81 |
+
// use JavaScript Prototype library for AJAX
|
82 |
+
wp_print_scripts( array( 'prototype' ) );
|
83 |
+
}
|
84 |
+
|
85 |
+
function post_deleted($post_id){
|
86 |
+
global $wpdb;
|
87 |
+
$sql="DELETE FROM ".$this->linksdata_name." WHERE post_id=$post_id";
|
88 |
+
$wpdb->query($sql);
|
89 |
+
$sql="DELETE FROM ".$this->postdata_name." WHERE post_id=$post_id";
|
90 |
+
$wpdb->query($sql);
|
91 |
+
}
|
92 |
+
|
93 |
+
function post_saved($post_id){
|
94 |
+
global $wpdb;
|
95 |
+
|
96 |
+
$found=$wpdb->get_var("SELECT post_id FROM $this->postdata_name WHERE post_id=$post_id LIMIT 1");
|
97 |
+
if($found===NULL){
|
98 |
+
//this post hasn't been saved previously, save the additional data now
|
99 |
+
$wpdb->query("INSERT INTO $this->postdata_name (post_id, last_check) VALUES($post_id, '00-00-0000 00:00:00')");
|
100 |
+
} else {
|
101 |
+
//mark the post as not checked
|
102 |
+
$wpdb->query("UPDATE $this->postdata_name SET last_check='00-00-0000 00:00:00' WHERE post_id=$post_id");
|
103 |
+
//delete the previously extracted links - they are possibly no longer in the post
|
104 |
+
$wpdb->query("DELETE FROM $this->linkdata_name WHERE post_id=$post_id");
|
105 |
+
}
|
106 |
+
}
|
107 |
+
|
108 |
+
|
109 |
+
function sync_posts_to_db(){
|
110 |
+
global $wpdb;
|
111 |
+
|
112 |
+
$sql="INSERT INTO ".$this->postdata_name."( post_id, last_check )
|
113 |
+
SELECT id, '00-00-0000 00:00:00'
|
114 |
+
FROM $wpdb->posts b
|
115 |
+
WHERE NOT EXISTS (
|
116 |
+
SELECT post_id
|
117 |
+
FROM ".$this->postdata_name." a
|
118 |
+
WHERE a.post_id = b.id
|
119 |
+
)";
|
120 |
+
$wpdb->query($sql);
|
121 |
+
}
|
122 |
+
|
123 |
+
function activation(){
|
124 |
+
global $wpdb;
|
125 |
+
|
126 |
+
if(!is_array($this->options)){
|
127 |
+
|
128 |
+
//set default options
|
129 |
+
$this->options=array(
|
130 |
+
'version' => $this->version,
|
131 |
+
'max_work_session' => 27,
|
132 |
+
'check_treshold' => 72
|
133 |
+
);
|
134 |
+
|
135 |
+
update_option($this->options_name, $this->options);
|
136 |
+
};
|
137 |
+
|
138 |
+
if($wpdb->get_var("show tables like '".($this->postdata_name)."'") != $this->postdata_name) {
|
139 |
+
$sql="CREATE TABLE ".$this->postdata_name." (
|
140 |
+
post_id BIGINT( 20 ) NOT NULL ,
|
141 |
+
last_check DATETIME NOT NULL ,
|
142 |
+
UNIQUE KEY post_id (post_id)
|
143 |
+
);";
|
144 |
+
|
145 |
+
require_once(ABSPATH . 'wp-admin/upgrade-functions.php');
|
146 |
+
dbDelta($sql);
|
147 |
+
}
|
148 |
+
|
149 |
+
if($wpdb->get_var("show tables like '".($this->linkdata_name)."'") != $this->linkdata_name) {
|
150 |
+
$sql="CREATE TABLE ".$this->linkdata_name." (
|
151 |
+
id BIGINT( 20 ) UNSIGNED NOT NULL AUTO_INCREMENT ,
|
152 |
+
post_id BIGINT( 20 ) NOT NULL ,
|
153 |
+
url TEXT NOT NULL ,
|
154 |
+
link_text VARCHAR( 50 ) NOT NULL ,
|
155 |
+
broken TINYINT( 1 ) UNSIGNED DEFAULT '0' NOT NULL,
|
156 |
+
last_check DATETIME NOT NULL ,
|
157 |
+
hidden TINYINT( 1 ) UNSIGNED DEFAULT '0' NOT NULL,
|
158 |
+
PRIMARY KEY id (id)
|
159 |
+
);";
|
160 |
+
|
161 |
+
require_once(ABSPATH . 'wp-admin/upgrade-functions.php');
|
162 |
+
dbDelta($sql);
|
163 |
+
}
|
164 |
+
|
165 |
+
$this->sync_posts_to_db();
|
166 |
+
}
|
167 |
+
|
168 |
+
function options_menu(){
|
169 |
+
add_options_page('Link Checker Settings', 'Link Checker', 'manage_options',
|
170 |
+
__FILE__,array(&$this, 'options_page'));
|
171 |
+
add_management_page('View Broken Links', 'Broken Links', 'manage_options',
|
172 |
+
__FILE__,array(&$this, 'broken_links_page'));
|
173 |
+
}
|
174 |
+
|
175 |
+
function mytruncate($str, $max_length=50){
|
176 |
+
if(strlen($str)<=$max_length) return $str;
|
177 |
+
return (substr($str, 0, $max_length-3).'...');
|
178 |
+
}
|
179 |
+
|
180 |
+
function options_page(){
|
181 |
+
|
182 |
+
$this->options = get_option('wsblc_options');
|
183 |
+
$reminder = '';
|
184 |
+
if (isset($_GET['updated']) && ($_GET['updated'] == 'true')) {
|
185 |
+
if(isset($_POST['Submit'])) {
|
186 |
+
|
187 |
+
$new_session_length=intval($_POST['max_work_session']);
|
188 |
+
if( $new_session_length >0 ){
|
189 |
+
$this->options['max_work_session']=$new_session_length;
|
190 |
+
}
|
191 |
+
|
192 |
+
$new_check_treshold=intval($_POST['check_treshold']);
|
193 |
+
if( $new_check_treshold > 0 ){
|
194 |
+
$this->options['check_treshold']=$new_check_treshold;
|
195 |
+
}
|
196 |
+
|
197 |
+
update_option($this->options_name,$this->options);
|
198 |
+
}
|
199 |
+
|
200 |
+
}
|
201 |
+
echo $reminder;
|
202 |
+
?>
|
203 |
+
<div class="wrap"><h2>Broken Link Checker Options</h2>
|
204 |
+
<form name="link_checker_options" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>?page=<?php echo plugin_basename(__FILE__); ?>&updated=true">
|
205 |
+
<p class="submit"><input type="submit" name="Submit" value="Update Options »" /></p>
|
206 |
+
|
207 |
+
<table class="optiontable">
|
208 |
+
|
209 |
+
<tr valign="top">
|
210 |
+
<th scope="row">Status:</th>
|
211 |
+
<td>
|
212 |
+
|
213 |
+
|
214 |
+
<div id='wsblc_full_status'>
|
215 |
+
<br/><br/>
|
216 |
+
</div>
|
217 |
+
<script type='text/javascript'>
|
218 |
+
new Ajax.PeriodicalUpdater('wsblc_full_status', '<?php
|
219 |
+
echo get_option( "siteurl" ).'/wp-content/plugins/'.$this->myfolder.'/wsblc_ajax.php?action=full_status' ; ?>',
|
220 |
+
{
|
221 |
+
method: 'get',
|
222 |
+
frequency: 10,
|
223 |
+
decay: 2
|
224 |
+
});
|
225 |
+
</script>
|
226 |
+
</td>
|
227 |
+
</tr>
|
228 |
+
|
229 |
+
<tr valign="top">
|
230 |
+
<th scope="row">Check Every Post:</th>
|
231 |
+
<td>
|
232 |
+
|
233 |
+
Every <input type="text" name="check_treshold" id="check_treshold"
|
234 |
+
value="<?php echo $this->options['check_treshold']; ?>" size='5' maxlength='3'/>
|
235 |
+
hours
|
236 |
+
<br/>
|
237 |
+
Links in old posts will be re-checked this often. New posts will be usually checked ASAP.
|
238 |
+
|
239 |
+
</td>
|
240 |
+
</tr>
|
241 |
+
|
242 |
+
<tr valign="top">
|
243 |
+
<th scope="row">Work Session Length:</th>
|
244 |
+
<td>
|
245 |
+
|
246 |
+
<input type="text" name="max_work_session" id="max_work_session"
|
247 |
+
value="<?php echo $this->options['max_work_session']; ?>" size='5' maxlength='3'/>
|
248 |
+
seconds
|
249 |
+
<br/>
|
250 |
+
The link checker does its work in short "sessions" while any page of the WP admin panel is open.
|
251 |
+
Typically you won't need to change this value.
|
252 |
+
|
253 |
+
</td>
|
254 |
+
</tr>
|
255 |
+
|
256 |
+
</table>
|
257 |
+
|
258 |
+
<p class="submit"><input type="submit" name="Submit" value="Update Options »" /></p>
|
259 |
+
</form>
|
260 |
+
</div>
|
261 |
+
<?php
|
262 |
+
}
|
263 |
+
|
264 |
+
function broken_links_page(){
|
265 |
+
global $wpdb;
|
266 |
+
$sql="SELECT count(*) FROM $this->linkdata_name WHERE broken=1 AND hidden=0";
|
267 |
+
$broken_links=$wpdb->get_var($sql);
|
268 |
+
|
269 |
+
?>
|
270 |
+
<div class="wrap">
|
271 |
+
<h2><?php
|
272 |
+
echo ($broken_links>0)?"$broken_links Broken Links":"No broken links found";
|
273 |
+
?></h2>
|
274 |
+
<br style="clear:both;" />
|
275 |
+
<?php
|
276 |
+
$sql="SELECT b.post_title, a.* FROM $this->linkdata_name a, $wpdb->posts b
|
277 |
+
WHERE a.post_id=b.id AND a.broken=1 AND a.hidden=0 ORDER BY a.last_check DESC";
|
278 |
+
$links=$wpdb->get_results($sql, OBJECT);
|
279 |
+
if($links && (count($links)>0)){
|
280 |
+
?>
|
281 |
+
<table class="widefat">
|
282 |
+
<thead>
|
283 |
+
<tr>
|
284 |
+
|
285 |
+
<th scope="col"><div style="text-align: center">#</div></th>
|
286 |
+
|
287 |
+
<th scope="col">Post</th>
|
288 |
+
<th scope="col">Link Text</th>
|
289 |
+
<th scope="col">URL</th>
|
290 |
+
|
291 |
+
<th scope="col"></th>
|
292 |
+
<th scope="col"></th>
|
293 |
+
<th scope="col"></th>
|
294 |
+
|
295 |
+
</tr>
|
296 |
+
</thead>
|
297 |
+
<tbody id="the-list">
|
298 |
+
<?php
|
299 |
+
|
300 |
+
$rownumber=0;
|
301 |
+
foreach ($links as $link) {
|
302 |
+
$rownumber++;
|
303 |
+
echo "<tr id='link-$link->id' class='alternate'>
|
304 |
+
<th scope='row' style='text-align: center'>$rownumber</th>
|
305 |
+
<td>$link->post_title</td>
|
306 |
+
|
307 |
+
<td>$link->link_text</td>
|
308 |
+
<td><a href='$link->url'>".$this->mytruncate($link->url)."</a></td>
|
309 |
+
<td><a href='".get_option('siteurl')."?p=$link->post_id' class='edit'>View</a></td>
|
310 |
+
|
311 |
+
<td><a href='post.php?action=edit&post=$link->post_id' class='edit'>Edit Post</a></td>
|
312 |
+
<td><a href='javascript:void(0);' class='delete'
|
313 |
+
onclick='discardLinkMessage($link->id);return false;' );' title='Discard This Message'>Discard</a></td>
|
314 |
+
</tr>";
|
315 |
+
|
316 |
+
}
|
317 |
+
|
318 |
+
echo '</tbody></table>';
|
319 |
+
};
|
320 |
+
?>
|
321 |
+
|
322 |
+
<script type='text/javascript'>
|
323 |
+
function discardLinkMessage(link_id){
|
324 |
+
new Ajax.Request('<?php
|
325 |
+
echo get_option( "siteurl" ).'/wp-content/plugins/'.$this->myfolder.'/wsblc_ajax.php?';
|
326 |
+
?>action=discard_link&id='+link_id,
|
327 |
+
{ method:'get' });
|
328 |
+
$('link-'+link_id).hide();
|
329 |
+
}
|
330 |
+
</script>
|
331 |
+
</div>
|
332 |
+
<?php
|
333 |
+
}
|
334 |
+
|
335 |
+
}//class ends here
|
336 |
+
|
337 |
+
} // if class_exists...
|
338 |
+
|
339 |
+
$ws_link_checker = new ws_broken_link_checker();
|
340 |
+
|
341 |
+
?>
|
readme.txt
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
=== Broken Link Checker ===
|
2 |
+
Contributors: whiteshadow
|
3 |
+
Tags: links, broken, maintenance
|
4 |
+
Requires at least: 2.0.2
|
5 |
+
Tested up to: 2.3
|
6 |
+
Stable tag: 0.1
|
7 |
+
|
8 |
+
This plugin will check your posts for broken links in background and notify you on the dashboard if any are found. It runs while any page of WP admin panel is open.
|
9 |
+
|
10 |
+
== Description ==
|
11 |
+
|
12 |
+
Sometimes, links get broken. A page is deleted, a subdirectory forgotten, a site moved to a different domain. Most likely some of your blog posts contain links. It is almost inevitable that over time some of them will start giving the 404 Not Found error. Obviously you don't want your readers to be annoyed by clicking a link that leads nowhere. You can check the links yourself but that might be quite a task if you have a lot of posts. You could use your webserver's stats but that only works for local links. So I've made a plugin for WordPress that will check your posts (and pages) in the background, looking for broken links, and let you know if any are found.
|
13 |
+
|
14 |
+
The broken links, if any are found, will show up in a new tab of WP admin panel - Manage -> Broken Links. There are several buttons for each broken link - "View" and "Edit Post" do exactly what they say and "Discard" will remove the message about a broken link, but not the link itself (so it will show up again later unless you fix it).
|
15 |
+
|
16 |
+
You can modify the few available options at Options -> Link Checker. You can see the current checking status there, too - e.g. how many posts need to be checked and how many links are in the queue.
|
17 |
+
|
18 |
+
The plugin runs while you have any page of the WordPress admin panel open.
|
19 |
+
|
20 |
+
|
21 |
+
== Installation ==
|
22 |
+
|
23 |
+
To do a new installation of the plugin, please follow these steps
|
24 |
+
|
25 |
+
1. Download the broken-link-checker.zip file to your local machine.
|
26 |
+
1. Unzip the file
|
27 |
+
1. Upload `broken-link-checker` folder to the `/wp-content/plugins/` directory
|
28 |
+
1. Activate the plugin through the 'Plugins' menu in WordPress
|
29 |
+
|
30 |
+
That's it.
|
31 |
+
|
32 |
+
To upgrade your installation
|
33 |
+
|
34 |
+
1. De-activate the plugin
|
35 |
+
1. Get and upload the new files (do steps 1. - 3. from "new installation" instructions)
|
36 |
+
1. Reactivate the plugin. Your settings should have been retained from the previous version.
|
wsblc_ajax.php
ADDED
@@ -0,0 +1,257 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The AJAX-y part of the link checker.
|
4 |
+
*/
|
5 |
+
require_once("../../../wp-config.php");
|
6 |
+
require_once("../../../wp-includes/wp-db.php");
|
7 |
+
|
8 |
+
error_reporting(E_ALL);
|
9 |
+
|
10 |
+
$execution_start_time=microtime(true);
|
11 |
+
|
12 |
+
function execution_time(){
|
13 |
+
global $execution_start_time;
|
14 |
+
return microtime(true)-$execution_start_time;
|
15 |
+
}
|
16 |
+
|
17 |
+
@set_time_limit(0);
|
18 |
+
@ignore_user_abort(true);
|
19 |
+
|
20 |
+
$url_pattern='/(<a[\s]+[^>]*href\s*=\s*[\"\']?)([^\'\" >]+)([\'\"]+[^<>]*>)((?sU).*)(<\/a>)/i';
|
21 |
+
|
22 |
+
$postdata_name=$wpdb->prefix . "blc_postdata";
|
23 |
+
$linkdata_name=$wpdb->prefix . "blc_linkdata";
|
24 |
+
|
25 |
+
$options=get_option('wsblc_options');
|
26 |
+
$siteurl=get_option('siteurl');
|
27 |
+
$max_execution_time=isset($options['max_work_session'])?intval($options['max_work_session']):27;
|
28 |
+
|
29 |
+
$check_treshold=date('Y-m-d H:i:s', strtotime('-'.$options['check_treshold'].' hours'));
|
30 |
+
|
31 |
+
$action=isset($_GET['action'])?$_GET['action']:'run_check';
|
32 |
+
|
33 |
+
if($action=='dashboard_status'){
|
34 |
+
/* displays a notification if broken links have been found */
|
35 |
+
$sql="SELECT count(*) FROM $linkdata_name WHERE broken=1 AND hidden=0";
|
36 |
+
$broken_links=$wpdb->get_var($sql);
|
37 |
+
if($broken_links>0){
|
38 |
+
echo "<div>
|
39 |
+
<h3>Broken Links</h3>
|
40 |
+
<p><a href='".get_option('siteurl')."/wp-admin/edit.php?page=".
|
41 |
+
$ws_link_checker->mybasename."' title='View broken links'>Found $broken_links broken links</a></p>
|
42 |
+
</div>";
|
43 |
+
};
|
44 |
+
|
45 |
+
} else if($action=='full_status'){
|
46 |
+
/* give some stats about the current situation */
|
47 |
+
$sql="SELECT count(*) FROM $postdata_name WHERE last_check<'$check_treshold'";
|
48 |
+
$posts_unchecked=$wpdb->get_var($sql);
|
49 |
+
|
50 |
+
$sql="SELECT count(*) FROM $linkdata_name WHERE last_check<'$check_treshold' AND hidden=0";
|
51 |
+
$links_unchecked=$wpdb->get_var($sql);
|
52 |
+
|
53 |
+
$sql="SELECT count(*) FROM $linkdata_name WHERE broken=1 AND hidden=0";
|
54 |
+
$broken_links=$wpdb->get_var($sql);
|
55 |
+
|
56 |
+
if($broken_links>0){
|
57 |
+
echo "<a href='".get_option('siteurl')."/wp-admin/edit.php?page=".
|
58 |
+
$ws_link_checker->mybasename."' title='View broken links'><strong>Found $broken_links broken links</strong></a>";
|
59 |
+
} else {
|
60 |
+
echo "No broken links found.";
|
61 |
+
}
|
62 |
+
|
63 |
+
echo "<br/>";
|
64 |
+
|
65 |
+
if($posts_unchecked || $links_unchecked) {
|
66 |
+
echo "$posts_unchecked posts and $links_unchecked links in the work queue.";
|
67 |
+
} else {
|
68 |
+
echo "The work queue is empty.";
|
69 |
+
}
|
70 |
+
|
71 |
+
|
72 |
+
} else if($action=='run_check'){
|
73 |
+
/* check for posts that haven't been checked for a long time & parse them for links, put the links in queue */
|
74 |
+
echo "<!-- run_check -->";
|
75 |
+
|
76 |
+
$sql="SELECT b.* FROM $postdata_name a, $wpdb->posts b
|
77 |
+
WHERE a.last_check<'$check_treshold' AND a.post_id=b.id ORDER BY a.last_check ASC LIMIT 20";
|
78 |
+
|
79 |
+
$rows=$wpdb->get_results($sql, OBJECT);
|
80 |
+
if($rows && (count($rows)>0)){
|
81 |
+
//some rows found
|
82 |
+
echo "<!-- parsing pages (rand : ".rand(1,1000).") -->";
|
83 |
+
foreach ($rows as $post) {
|
84 |
+
$wpdb->query("DELETE FROM $linkdata_name WHERE post_id=$post->ID");
|
85 |
+
gather_and_save_links($post->post_content, $post->ID);
|
86 |
+
$wpdb->query("UPDATE $postdata_name SET last_check=NOW() WHERE post_id=$post->ID");
|
87 |
+
}
|
88 |
+
};
|
89 |
+
|
90 |
+
if(execution_time()>$max_execution_time){
|
91 |
+
die('<!-- general timeout -->');
|
92 |
+
}
|
93 |
+
|
94 |
+
/* check the queue and process any links unchecked */
|
95 |
+
$sql="SELECT * FROM $linkdata_name WHERE last_check<'$check_treshold' AND hidden=0 LIMIT 100";
|
96 |
+
$links=$wpdb->get_results($sql, OBJECT);
|
97 |
+
if($links && (count($links)>0)){
|
98 |
+
//some unchecked links found
|
99 |
+
echo "<!-- checking links (rand : ".rand(1,1000).") -->";
|
100 |
+
foreach ($links as $link) {
|
101 |
+
if(page_exists_simple($link->url)){
|
102 |
+
//link OK, remove from queue
|
103 |
+
$wpdb->query("DELETE FROM $linkdata_name WHERE id=$link->id");
|
104 |
+
} else {
|
105 |
+
$wpdb->query("UPDATE $linkdata_name SET broken=1, last_check=NOW() WHERE id=$link->id");
|
106 |
+
};
|
107 |
+
|
108 |
+
|
109 |
+
if(execution_time()>$max_execution_time){
|
110 |
+
die('<!-- url loop timeout -->');
|
111 |
+
}
|
112 |
+
}
|
113 |
+
};
|
114 |
+
|
115 |
+
die('<!-- /run_check -->');
|
116 |
+
|
117 |
+
} else if ($action=='discard_link'){
|
118 |
+
$id=intval($_GET['id']);
|
119 |
+
$wpdb->query("DELETE FROM $linkdata_name WHERE id=$id LIMIT 1");
|
120 |
+
};
|
121 |
+
|
122 |
+
|
123 |
+
function parse_link($matches, $post_id){
|
124 |
+
global $wpdb, $siteurl, $linkdata_name;
|
125 |
+
|
126 |
+
$url=$matches[2];
|
127 |
+
|
128 |
+
$parts=@parse_url($url);
|
129 |
+
|
130 |
+
if(!$parts) return false;
|
131 |
+
|
132 |
+
$url=preg_replace(
|
133 |
+
array('/([\?&]PHPSESSID=\w+)$/i','/(#[^\/]*)$/i', '/&/','/^(javascript:.*)/i','/([\?&]sid=\w+)$/i'),
|
134 |
+
array('','','&','',''),
|
135 |
+
$url);
|
136 |
+
|
137 |
+
$url=trim($url);
|
138 |
+
if($url=='') return false;
|
139 |
+
|
140 |
+
// turn relative URLs into absolute URLs
|
141 |
+
$url = relative2absolute($siteurl, $url);
|
142 |
+
|
143 |
+
if(strlen($url)>5){
|
144 |
+
$wpdb->query(
|
145 |
+
"INSERT INTO $linkdata_name(post_id, url, link_text)
|
146 |
+
VALUES($post_id, '".$wpdb->escape($url)."', '".$wpdb->escape(strip_tags($matches[4]))."')"
|
147 |
+
);
|
148 |
+
};
|
149 |
+
|
150 |
+
return true;
|
151 |
+
}
|
152 |
+
|
153 |
+
function gather_and_save_links($content, $post_id){
|
154 |
+
$url_pattern='/(<a[\s]+[^>]*href\s*=\s*[\"\']?)([^\'\" >]+)([\'\"]+[^<>]*>)((?sU).*)(<\/a>)/i';
|
155 |
+
|
156 |
+
if(preg_match_all($url_pattern, $content, $matches, PREG_SET_ORDER)){
|
157 |
+
foreach($matches as $link){
|
158 |
+
parse_link($link, $post_id);
|
159 |
+
}
|
160 |
+
};
|
161 |
+
|
162 |
+
return $content;
|
163 |
+
}
|
164 |
+
|
165 |
+
function page_exists_simple($url){
|
166 |
+
$parts=parse_url($url);
|
167 |
+
if(!$parts) return false;
|
168 |
+
|
169 |
+
if(!isset($parts['scheme'])) $url='http://'.$url;
|
170 |
+
|
171 |
+
$ch = curl_init();
|
172 |
+
curl_setopt($ch, CURLOPT_URL, $url);
|
173 |
+
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)');
|
174 |
+
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
|
175 |
+
|
176 |
+
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
|
177 |
+
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
|
178 |
+
curl_setopt($ch, CURLOPT_TIMEOUT, 20);
|
179 |
+
|
180 |
+
//curl_setopt($ch, CURLOPT_FAILONERROR, true);
|
181 |
+
curl_setopt($ch, CURLOPT_HEADER, true);
|
182 |
+
|
183 |
+
if($parts['scheme']=='https'){
|
184 |
+
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
|
185 |
+
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
186 |
+
} else {
|
187 |
+
curl_setopt($ch, CURLOPT_NOBODY, true);
|
188 |
+
}
|
189 |
+
|
190 |
+
$response = curl_exec($ch);
|
191 |
+
curl_close($ch);
|
192 |
+
|
193 |
+
if(preg_match('/HTTP\/1\.\d+\s+(\d+)/', $response, $matches)){
|
194 |
+
$code=intval($matches[1]);
|
195 |
+
} else {
|
196 |
+
return false;
|
197 |
+
};
|
198 |
+
|
199 |
+
return (($code>=200) && ($code<400));
|
200 |
+
}
|
201 |
+
|
202 |
+
function relative2absolute($absolute, $relative) {
|
203 |
+
$p = @parse_url($relative);
|
204 |
+
if(!$p) {
|
205 |
+
//WTF? $relative is a seriously malformed URL
|
206 |
+
return false;
|
207 |
+
}
|
208 |
+
if(isset($p["scheme"])) return $relative;
|
209 |
+
|
210 |
+
$parts=(parse_url($absolute));
|
211 |
+
|
212 |
+
if(substr($relative,0,1)=='/') {
|
213 |
+
$cparts = (explode("/", $relative));
|
214 |
+
array_shift($cparts);
|
215 |
+
} else {
|
216 |
+
if(isset($parts['path'])){
|
217 |
+
$aparts=explode('/',$parts['path']);
|
218 |
+
array_pop($aparts);
|
219 |
+
$aparts=array_filter($aparts);
|
220 |
+
} else {
|
221 |
+
$aparts=array();
|
222 |
+
}
|
223 |
+
|
224 |
+
$rparts = (explode("/", $relative));
|
225 |
+
|
226 |
+
$cparts = array_merge($aparts, $rparts);
|
227 |
+
foreach($cparts as $i => $part) {
|
228 |
+
if($part == '.') {
|
229 |
+
unset($cparts[$i]);
|
230 |
+
} else if($part == '..') {
|
231 |
+
unset($cparts[$i]);
|
232 |
+
unset($cparts[$i-1]);
|
233 |
+
}
|
234 |
+
}
|
235 |
+
}
|
236 |
+
$path = implode("/", $cparts);
|
237 |
+
|
238 |
+
$url = '';
|
239 |
+
if($parts['scheme']) {
|
240 |
+
$url = "$parts[scheme]://";
|
241 |
+
}
|
242 |
+
if(isset($parts['user'])) {
|
243 |
+
$url .= $parts['user'];
|
244 |
+
if(isset($parts['pass'])) {
|
245 |
+
$url .= ":".$parts['pass'];
|
246 |
+
}
|
247 |
+
$url .= "@";
|
248 |
+
}
|
249 |
+
if(isset($parts['host'])) {
|
250 |
+
$url .= $parts['host']."/";
|
251 |
+
}
|
252 |
+
$url .= $path;
|
253 |
+
|
254 |
+
return $url;
|
255 |
+
}
|
256 |
+
|
257 |
+
?>
|