PluginProbe
HTTP 410 (Gone) responses / 0.5
HTTP 410 (Gone) responses v0.5
1.2.1 trunk 0.1 0.2 0.3 0.4 0.5 0.6 0.6.1 0.7 0.7.1 0.7.2 0.8.1 0.8.2 1.0.2 1.0.3 1.1.0
wp-410 / wp-410.php

wp-410.php in HTTP 410 (Gone) responses 0.5, at wp-410.php

226 lines 8.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 Plugin Name: 410 for Wordpress
4 Plugin URI: http://rayofsolaris.net/code/410-for-wordpress
5 Description: Sends HTTP 410 (Gone) responses to requests for pages that no longer exist on your blog.
6 Version: 0.5
7 Author: Samir Shah
8 Author URI: http://rayofsolaris.net/
9 License: GPL2
10 */
11
12 if( ! defined( 'ABSPATH' ) )
13 exit;
14
15 class WP_410 {
16 const db_version = 2; // DB version, since 0.2
17 private $permalinks;
18
19 function __construct() {
20 $struct = get_option('permalink_structure');
21 $this->permalinks = !empty( $struct );
22
23 add_action( 'init', array( $this, 'upgrade_check' ) );
24
25 if( is_admin() )
26 add_action( 'admin_menu', array( $this, 'settings_menu' ) );
27
28 add_action('delete_post', array( $this, 'note_deleted_post' ) );
29 add_action('wp_insert_post', array( $this, 'note_inserted_post' ) );
30 add_action('template_redirect', array( $this, 'check_for_410' ) );
31 }
32
33 function upgrade_check() {
34 $options_version = get_option( 'wp_410_options_version', 0 );
35
36 if( $options_version == self::db_version ) // nothing to do
37 return;
38
39 $old_links = get_option( 'wp_410_links_list', array() );
40 $new_links = array();
41
42 if( 0 == $options_version ) {
43 // upgrade from 0.1 to 0.2, saving links in regex form
44 foreach( $old_links as $link )
45 $new_links[ rawurldecode( $link ) ] = self::build_regex( rawurldecode( $link ) ); // new links have key = display link and value = regex
46
47 }
48 elseif( 1 == $options_version ) {
49 // regex format changed, add case-insensitive parameter to end and fix urlencoding
50 foreach( $old_links as $key => $regex )
51 $new_links[ rawurldecode( $key ) ] = rawurldecode( $regex ) . 'i';
52 }
53
54 update_option( 'wp_410_links_list', $new_links );
55 update_option( 'wp_410_options_version', self::db_version );
56 }
57
58 function settings_menu() {
59 add_submenu_page('plugins.php', '410 for WordPress', '410 for WordPress', 'manage_options', 'wp_410_settings', array( $this, 'settings_page') );
60 }
61
62 function settings_page() {
63 $old_links = get_option( 'wp_410_links_list', array() );
64
65 if ( isset( $_POST['submit'] ) ) {
66 $failed_to_add = array();
67 if( !empty( $_POST['old_links_to_add'] ) ) {
68 $added_links = preg_split( '/(\r?\n)+/', $_POST['old_links_to_add'], -1, PREG_SPLIT_NO_EMPTY );
69
70 foreach( $added_links as $k => $link ) {
71 $parts = parse_url( $link );
72 if( !$parts || empty( $parts['scheme'] ) || empty( $parts['host'] ) ) // invalid URL
73 $failed_to_add[] = '<code>' . htmlspecialchars( $link ) . '</code>';
74 else
75 $old_links[$link] = self::build_regex( $link ); // key is display link, value is regex
76 }
77 }
78
79 if( !empty( $_POST['old_links_to_remove'] ) )
80 foreach( $_POST['old_links_to_remove'] as $key )
81 unset( $old_links[$key] );
82
83 ksort( $old_links );
84
85 update_option( 'wp_410_links_list', $old_links );
86 echo '<div class="updated fade"><p>Options updated.</p></div>';
87
88 if( $failed_to_add )
89 echo '<div class="error"><p>The following entries could not be recognised as valid URLs, and were not added to the list.<br />- ' . implode( '<br />- ', $failed_to_add ) .'</p></div>';
90 }
91 ?>
92 <style>
93 .indent {padding-left: 2em}
94 .wp_gone_deleted label {text-decoration: line-through}
95 </style>
96 <div class="wrap">
97 <h2>410 for WordPress</h2>
98 <p>This plugin will issue a HTTP 410 response to articles that no longer exist on your blog. When an article is deleted, it records this and issues a 410 response when pages unique to that article are requested. This HTTP code informs robots visiting your site that the requested page has been permanently removed, and that they should stop trying to access it.</p>
99 <p>Note: this plugin will only return a 410 response if Wordpress has not found something valid to display for the requested URL.</p>
100 <form action="" method="post" id="wp-gone-captcha-settings">
101 <table class="form-table"><tbody>
102 <tr><th>Obsolete URLs</th><td>
103 <?php
104 if( empty( $old_links ) ) {
105 echo '<p>There are currently no obsolete URLs in this list. You can add some manually below.</p>';
106 }
107 else {
108 echo '<p>The following URLs are currently considered obsolete. To remove items from the list, check the corresponding box.</p>';
109 echo '<ul id="wp_gone_old_links" class="indent">';
110 foreach( array_keys( $old_links ) as $k )
111 echo "<li><input type='checkbox' name='old_links_to_remove[]' value='" . htmlspecialchars( $k ) . "' id='old_link_$k' /> <label for='old_link_$k'><code>" . htmlspecialchars( rawurldecode( $k ) ). "</code></label></li>";
112 echo '</ul>';
113 }
114 ?>
115 <p><small>If you create or update an article whose URL matches one of those above, that URL will automatically be removed from this list.</small></p>
116 </td></tr>
117 <tr><th>Manually add URLs</th><td>
118 <p>You can manually add items to the list by entering them below. Please enter one <strong>fully qualified</strong> URL per line.</p>
119 <p>Use <code>*</code> as a wildcard character. So <code>http://www.example.com/*/music/</code> will match all URLs ending in <code>/music/</code>.</p>
120 <textarea name="old_links_to_add" rows="8" cols="80"></textarea>
121 </td></tr>
122 <tr><th>410 reponse message</th><td>
123 <p>By default, the plugin issues the following plain-text message as part of the 410 response: <code>Sorry, the page you requested has been permanently removed.</code></p>
124 <?php
125 if( locate_template( '410.php' ) )
126 echo '<p><strong>A template file <code>410.php</code> has been detected in your theme folder. This file will be used to display 410 responses.</strong> To revert back to the default message, remove the file from your template folder.</p>';
127 else
128 echo '<p>If you would like to use your own template instead, simply place a file called <code>410.php</code> in your theme folder, containing your template.</p>';
129 ?>
130 </td></tr>
131 </tbody></table>
132 <p class="submit"><input class="button-primary" type="submit" name="submit" value="Update settings" /></p>
133 </form>
134 </div>
135 <script>
136 jQuery(document).ready(function(){
137 jQuery('#wp_gone_old_links input').change( function(){
138 this.parentNode.className = jQuery(this).is(":checked") ? 'wp_gone_deleted' : '';
139 });
140 });
141 </script>
142 <?php
143 }
144
145 function note_deleted_post( $id ) {
146 // NOTE: function wp_delete_post calls the delete_post action twice, so we store deleted IDs in an array to avoid repeating
147 // but still allow repeated use of the function for batch deletes
148 static $noted = array();
149 $id = (int) $id;
150
151 if( in_array( $id, $noted ) )
152 return;
153 $noted[] = $id;
154
155 $post = get_post( $id );
156
157 if( 'revision' == $post->post_type )
158 return;
159
160 $link = rawurldecode( get_permalink( $id ) );
161 if( $this->permalinks )
162 $link .= '*'; // catch everything like /page/ and /feed/
163
164 $list = get_option( 'wp_410_links_list', array() );
165
166 $list[$link] = self::build_regex( $link );
167
168 update_option( 'wp_410_links_list', $list );
169 }
170
171 function note_inserted_post( $id ) {
172 $post = get_post( $id );
173
174 if( 'revision' == $post->post_type || 'draft' == $post->post_status )
175 return;
176
177 // Check our list of URLs against the new/updated post's permalink, and if they match, scratch it from our list
178 $links = array();
179
180 $links[] = rawurldecode( get_permalink( $id ) );
181 $links[] = get_post_comments_feed_link( $id ); // back compat
182
183 if( $this->permalinks )
184 $links[0] .= '*';
185
186 $list = get_option( 'wp_410_links_list', array() );
187
188 foreach( $links as $link )
189 unset( $list[$link] );
190
191 update_option( 'wp_410_links_list', $list );
192 }
193
194 function check_for_410() {
195 // Don't mess if Wordpress has found something to display
196 if( !is_404() )
197 return;
198
199 $links = get_option( 'wp_410_links_list', array() );
200 $req = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
201 $req = rawurldecode( $req );
202
203 foreach( $links as $regex ) {
204 if( @preg_match( $regex, $req ) ) {
205 status_header( 410 );
206 do_action( 'wp_410_response' ); // you can use this to customise the response message
207
208 if( ! locate_template( '410.php', true ) )
209 echo 'Sorry, the page you requested has been permanently removed.';
210
211 exit;
212 }
213 }
214 }
215
216 static function build_regex( $link ) {
217 $parts = preg_split( '/(\*)/', $link, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY );
218 foreach( $parts as &$part ) if( '*' != $part )
219 $part = preg_quote( $part, '|' );
220 $parts = str_replace( '*', '.*', $parts );
221 return '|^' . implode( '', $parts ) . '$|i';
222 }
223 }
224
225 new WP_410();
226