Broken Link Checker - Version 1.10.6

Version Description

  • Fixed a serious CSRF/XSS vulnerability.
  • Switched to YouTube API v3. The old API version will be shut down on April 20, so the plugin needs to be updated to continue checking links to YouTube videos.
  • Fixed long URLs overflowing into adjacent table columns.
  • Fixed a few minor PHP strict-mode notices.
  • Added database character set to the "Show debug info" table.
Download this release

Release Info

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

Code changes from version 1.10.5 to 1.10.6

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.5
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.6
7
  Author: Janis Elsts
8
  Author URI: http://w-shadow.com/
9
  Text Domain: broken-link-checker
core/core.php CHANGED
@@ -1315,7 +1315,7 @@ class wsBrokenLinkChecker {
1315
 
1316
  printf(
1317
  ' | <a class="blc-toggle-link toggle-module-settings" id="toggle-module-settings-%s" href="#">%s</a>',
1318
- $module_id,
1319
  __('Configure', 'broken-link-checker')
1320
  );
1321
 
@@ -2248,13 +2248,13 @@ class wsBrokenLinkChecker {
2248
  'The "Warnings" page lists problems that are probably temporary or suspected to be false positives.<br> Warnings that persist for a long time will usually be reclassified as broken links.',
2249
  'broken-link-checker'
2250
  ),
2251
- add_query_arg($notice_name, '0'),
2252
  _x(
2253
  'Hide notice',
2254
  'admin notice under Tools - Broken links - Warnings',
2255
  'broken-link-checker'
2256
  ),
2257
- admin_url('options-general.php?page=link-checker-settings#blc_warning_settings'),
2258
  _x(
2259
  'Change warning settings',
2260
  'a link from the admin notice under Tools - Broken links - Warnings',
@@ -2783,7 +2783,7 @@ class wsBrokenLinkChecker {
2783
  "<a href='%s' title='" . __('View broken links', 'broken-link-checker') . "'><strong>".
2784
  _n('Found %d broken link', 'Found %d broken links', $status['broken_links'], 'broken-link-checker') .
2785
  "</strong></a>",
2786
- admin_url('tools.php?page=view-broken-links'),
2787
  $status['broken_links']
2788
  );
2789
  } else {
@@ -3428,7 +3428,15 @@ class wsBrokenLinkChecker {
3428
  'state' => 'ok',
3429
  'value' => sprintf(__('%s seconds'), ini_get('max_execution_time')),
3430
  );
3431
-
 
 
 
 
 
 
 
 
3432
  //Resynch flag.
3433
  $debug['Resynch. flag'] = array(
3434
  'state' => 'ok',
1315
 
1316
  printf(
1317
  ' | <a class="blc-toggle-link toggle-module-settings" id="toggle-module-settings-%s" href="#">%s</a>',
1318
+ esc_attr($module_id),
1319
  __('Configure', 'broken-link-checker')
1320
  );
1321
 
2248
  'The "Warnings" page lists problems that are probably temporary or suspected to be false positives.<br> Warnings that persist for a long time will usually be reclassified as broken links.',
2249
  'broken-link-checker'
2250
  ),
2251
+ esc_attr(add_query_arg($notice_name, '0')),
2252
  _x(
2253
  'Hide notice',
2254
  'admin notice under Tools - Broken links - Warnings',
2255
  'broken-link-checker'
2256
  ),
2257
+ esc_attr(admin_url('options-general.php?page=link-checker-settings#blc_warning_settings')),
2258
  _x(
2259
  'Change warning settings',
2260
  'a link from the admin notice under Tools - Broken links - Warnings',
2783
  "<a href='%s' title='" . __('View broken links', 'broken-link-checker') . "'><strong>".
2784
  _n('Found %d broken link', 'Found %d broken links', $status['broken_links'], 'broken-link-checker') .
2785
  "</strong></a>",
2786
+ esc_attr(admin_url('tools.php?page=view-broken-links')),
2787
  $status['broken_links']
2788
  );
2789
  } else {
3428
  'state' => 'ok',
3429
  'value' => sprintf(__('%s seconds'), ini_get('max_execution_time')),
3430
  );
3431
+
3432
+ //Database character set. Usually it's UTF-8. Setting it to something else can cause problems
3433
+ //unless the site owner really knows what they're doing.
3434
+ $charset = $wpdb->get_charset_collate();
3435
+ $debug[ __('Database character set', 'broken-link-checker') ] = array(
3436
+ 'state' => 'ok',
3437
+ 'value' => !empty($charset) ? $charset : '-',
3438
+ );
3439
+
3440
  //Resynch flag.
3441
  $debug['Resynch. flag'] = array(
3442
  'state' => 'ok',
css/links-page.css CHANGED
@@ -229,6 +229,7 @@ td.column-new-url { /* The URL never wraps */
229
  white-space: nowrap;
230
  text-overflow: ellipsis;
231
  -o-text-overflow: ellipsis;
 
232
  }
233
 
234
  td.column-new-url .row-actions { /* However, the action links below the URL can wrap. */
229
  white-space: nowrap;
230
  text-overflow: ellipsis;
231
  -o-text-overflow: ellipsis;
232
+ overflow-x: hidden;
233
  }
234
 
235
  td.column-new-url .row-actions { /* However, the action links below the URL can wrap. */
includes/any-post.php CHANGED
@@ -432,14 +432,14 @@ class blcAnyPostContainer extends blcContainer {
432
  $actions['trash'] = sprintf(
433
  "<span class='trash'><a class='submitdelete' title='%s' href='%s'>%s</a>",
434
  esc_attr(__('Move this item to the Trash')),
435
- get_delete_post_link($this->container_id, '', false),
436
  __('Trash')
437
  );
438
  } else {
439
  $actions['delete'] = sprintf(
440
  "<span><a class='submitdelete' title='%s' href='%s'>%s</a>",
441
  esc_attr(__('Delete this item permanently')),
442
- get_delete_post_link($this->container_id, '', true),
443
  __('Delete')
444
  );
445
  }
432
  $actions['trash'] = sprintf(
433
  "<span class='trash'><a class='submitdelete' title='%s' href='%s'>%s</a>",
434
  esc_attr(__('Move this item to the Trash')),
435
+ esc_attr(get_delete_post_link($this->container_id, '', false)),
436
  __('Trash')
437
  );
438
  } else {
439
  $actions['delete'] = sprintf(
440
  "<span><a class='submitdelete' title='%s' href='%s'>%s</a>",
441
  esc_attr(__('Delete this item permanently')),
442
+ esc_attr(get_delete_post_link($this->container_id, '', true)),
443
  __('Delete')
444
  );
445
  }
includes/links.php CHANGED
@@ -1012,7 +1012,7 @@ class blcLink {
1012
 
1013
  if ( $this->broken || $this->warning ){
1014
  $code = BLC_LINK_STATUS_WARNING;
1015
- $text = __('Unknown Error', 'link status', 'broken-link-checker');
1016
 
1017
  if ( $this->timeout ){
1018
 
1012
 
1013
  if ( $this->broken || $this->warning ){
1014
  $code = BLC_LINK_STATUS_WARNING;
1015
+ $text = __('Unknown Error', 'broken-link-checker');
1016
 
1017
  if ( $this->timeout ){
1018
 
modules/checkers/http.php CHANGED
@@ -362,7 +362,7 @@ class blcCurlHttp extends blcHttpCheckerBase {
362
 
363
  if ( !$nobody && ($content !== false) && $result['broken'] ) {
364
  $log .= "Response HTML\n" . str_repeat('=', 16) . "\n";
365
- $log .= htmlentities($content);
366
  }
367
 
368
  if ( !empty($result['broken']) && !empty($result['timeout']) ) {
362
 
363
  if ( !$nobody && ($content !== false) && $result['broken'] ) {
364
  $log .= "Response HTML\n" . str_repeat('=', 16) . "\n";
365
+ $log .= htmlentities(substr($content, 0, 2048));
366
  }
367
 
368
  if ( !empty($result['broken']) && !empty($result['timeout']) ) {
modules/extras/youtube-embed.php CHANGED
@@ -28,7 +28,8 @@ class blcYouTubeEmbed extends blcEmbedParserBase {
28
 
29
  function link_url_from_src($src){
30
  //Extract video ID from the SRC. The ID is always 11 characters.
31
- $video_id = substr( end(explode('/', $src)), 0, 11 );
 
32
 
33
  //Reconstruct the video permalink based on the ID
34
  $url = 'http://www.youtube.com/watch?v='.$video_id;
28
 
29
  function link_url_from_src($src){
30
  //Extract video ID from the SRC. The ID is always 11 characters.
31
+ $parts = explode('/', $src);
32
+ $video_id = substr( end($parts), 0, 11 );
33
 
34
  //Reconstruct the video permalink based on the ID
35
  $url = 'http://www.youtube.com/watch?v='.$video_id;
modules/extras/youtube-iframe.php CHANGED
@@ -91,7 +91,8 @@ class blcYouTubeIframe extends blcEmbedParserBase {
91
 
92
  } else {
93
  //Extract video ID from the SRC. The ID is always 11 characters.
94
- $video_id = substr( end(explode('/', $parts['path'])), 0, 11 );
 
95
 
96
  //Reconstruct the video permalink based on the ID
97
  $url = 'http://www.youtube.com/watch?v='.$video_id;
91
 
92
  } else {
93
  //Extract video ID from the SRC. The ID is always 11 characters.
94
+ $exploded = explode('/', $parts['path']);
95
+ $video_id = substr( end($exploded), 0, 11 );
96
 
97
  //Reconstruct the video permalink based on the ID
98
  $url = 'http://www.youtube.com/watch?v='.$video_id;
modules/extras/youtube.php CHANGED
@@ -3,7 +3,7 @@
3
  /*
4
  Plugin Name: YouTube API
5
  Description: Check links to YouTube videos and playlists using the YouTube API.
6
- Version: 1.1
7
  Author: Janis Elsts
8
 
9
  ModuleID: youtube-checker
@@ -17,7 +17,7 @@ ModuleCheckerUrlPattern: @^https?://(?:([\w\d]+\.)*youtube\.[^/]+/watch\?.*v=[^/
17
  */
18
 
19
  class blcYouTubeChecker extends blcChecker {
20
- var $youtube_developer_key = 'AI39si4OM05fWUMbt1g8hBdYPRTGpNbOWVD0-7sKwShqZTOpKigo7Moj1YGk7dMk95-VWB1Iue2aiTNJb655L32-QGM2xq_yVQ';
21
  var $api_grace_period = 0.3; //How long to wait between YouTube API requests.
22
  var $last_api_request = 0; //Timestamp of the last request.
23
 
@@ -68,9 +68,9 @@ class blcYouTubeChecker extends blcChecker {
68
 
69
  //Fetch video or playlist from the YouTube API
70
  if ( !empty($video_id) ) {
71
- $api_url = $this->get_video_feed_url($video_id);
72
  } else {
73
- $api_url = $this->get_playlist_feed_url($playlist_id);
74
  }
75
 
76
  $conf = blc_get_configuration();
@@ -119,85 +119,38 @@ class blcYouTubeChecker extends blcChecker {
119
  * @return array New result array.
120
  */
121
  protected function check_video($response, $result) {
122
- switch($result['http_code']){
123
- case 404 : //Not found
124
- $result['log'] .= __('Video Not Found', 'broken-link-checker');
125
- $result['broken'] = true;
126
- $result['http_code'] = 0;
127
- $result['status_text'] = __('Video Not Found', 'broken-link-checker');
128
- $result['status_code'] = BLC_LINK_STATUS_ERROR;
129
- break;
130
-
131
- case 403 : //Forbidden. Usually means that the video has been removed. Body contains details.
132
- $result['log'] .= $response['body'];
133
- $result['broken'] = true;
134
- $result['http_code'] = 0;
135
- $result['status_text'] = __('Video Removed', 'broken-link-checker');
136
- $result['status_code'] = BLC_LINK_STATUS_ERROR;
137
- break;
138
-
139
- case 400 : //Bad request. Usually means that the video ID is incorrect. Body contains details.
140
- $result['log'] .= $response['body'];
141
- $result['broken'] = true;
142
- $result['http_code'] = 0;
143
- $result['status_text'] = __('Invalid Video ID', 'broken-link-checker');
144
- $result['status_code'] = BLC_LINK_STATUS_WARNING;
145
- break;
146
-
147
- case 200 : //Video exists, but may be restricted. Check for <yt:state> tags.
148
- //See http://code.google.com/apis/youtube/2.0/reference.html#youtube_data_api_tag_yt:state
149
-
150
- //Can we count on an XML parser being installed? No, probably not.
151
- //Back to our makeshift tag "parser" we go.
152
- $state = blcUtility::extract_tags($response['body'], 'yt:state', false);
153
- if ( empty($state) ){
154
- //Phew, no restrictions.
155
- $result['log'] .= __("Video OK", 'broken-link-checker');
156
- $result['status_text'] = __('OK', 'link status', 'broken-link-checker');
157
- $result['status_code'] = BLC_LINK_STATUS_OK;
158
- $result['http_code'] = 0;
159
- } else {
160
-
161
- //Get the state name and code and append them to the log
162
- $state = reset($state);
163
- $state_name = $state['attributes']['name'];
164
- $state_reason = isset($state['attributes']['reasonCode'])?$state['attributes']['reasonCode']:'';
165
-
166
- $result['state_name'] = $state_name;
167
- $result['state_reason'] = $state_reason;
168
-
169
- $result['log'] .= sprintf(
170
- __('Video status : %s%s', 'broken-link-checker'),
171
- $state_name,
172
- $state_reason ? ' ['.$state_reason.']':''
173
- );
174
-
175
- if ( $this->is_state_ok($state_name, $state_reason) ) {
176
- $result['broken'] = false;
177
- $result['status_text'] = __('OK', 'link status', 'broken-link-checker');
178
- $result['status_code'] = BLC_LINK_STATUS_OK;
179
- $result['http_code'] = 0;
180
- } else {
181
- $result['broken'] = true;
182
- $result['status_text'] = __('Video Restricted', 'broken-link-checker');
183
- $result['status_code'] = BLC_LINK_STATUS_WARNING;
184
- $result['http_code'] = 0;
185
- }
186
- }
187
 
188
- //Add the video title to the log, purely for information.
189
- //http://code.google.com/apis/youtube/2.0/reference.html#youtube_data_api_tag_media:title
190
- $title = blcUtility::extract_tags($response['body'], 'media:title', false);
191
- if ( !empty($title) ){
192
- $result['log'] .= "\n\nTitle : \"" . $title[0]['contents'] . '"';
193
- }
194
 
195
- break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
 
197
- default:
198
- $result['log'] .= $result['http_code'] . $response['response']['message'];
199
- $result['log'] .= "\n" . __('Unknown YouTube API response received.');
200
- break;
 
 
201
  }
202
 
203
  return $result;
@@ -211,140 +164,122 @@ class blcYouTubeChecker extends blcChecker {
211
  * @return array
212
  */
213
  protected function check_playlist($response, $result) {
214
-
215
- switch($result['http_code']){
216
- case 404 : //Not found
217
- $result['log'] .= __('Playlist Not Found', 'broken-link-checker');
218
- $result['broken'] = true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
219
  $result['http_code'] = 0;
220
- $result['status_text'] = __('Playlist Not Found', 'broken-link-checker');
221
- $result['status_code'] = BLC_LINK_STATUS_ERROR;
222
- break;
223
-
224
- case 403 : //Forbidden. We're unlikely to see this code for playlists, but lets allow it.
225
- $result['log'] .= $response['body'];
226
  $result['broken'] = true;
227
- $result['status_text'] = __('Playlist Restricted', 'broken-link-checker');
228
- $result['status_code'] = BLC_LINK_STATUS_ERROR;
229
- break;
 
 
 
 
 
 
 
230
 
231
- case 400 : //Bad request. Probably indicates a client error (invalid API request). Body contains details.
232
- $result['log'] .= $response['body'];
233
- $result['broken'] = true;
234
- $result['status_text'] = __('Invalid Playlist', 'broken-link-checker');
235
- $result['status_code'] = BLC_LINK_STATUS_WARNING;
236
- break;
237
-
238
- case 200 :
239
- //The playlist exists, but some of the videos may be restricted.
240
- //Check for <yt:state> tags.
241
- $video_states = blcUtility::extract_tags($response['body'], 'yt:state', false);
242
- if ( empty($video_states) ){
243
-
244
- //No restrictions. Does the playlist have any entries?
245
- $entries = blcUtility::extract_tags($response['body'], 'entry', false);
246
- if ( !empty($entries) ) {
247
- //All is well.
248
- $result['log'] .= __("Playlist OK", 'broken-link-checker');
249
- $result['status_text'] = __('OK', 'link status', 'broken-link-checker');
250
- $result['status_code'] = BLC_LINK_STATUS_OK;
251
- $result['http_code'] = 0;
252
- } else {
253
- //An empty playlist. It is possible that all of the videos
254
- //have been deleted. Treat it as a warning.
255
- $result['log'] .= __("This playlist has no entries or all entries have been deleted.", 'broken-link-checker');
256
- $result['status_text'] = __('Empty Playlist', 'link status', 'broken-link-checker');
257
- $result['status_code'] = BLC_LINK_STATUS_WARNING;
258
- $result['http_code'] = 0;
259
  $result['broken'] = true;
260
- }
261
-
262
- } else {
263
-
264
- //Treat the playlist as broken if at least one video is inaccessible.
265
- foreach($video_states as $state) {
266
- $state_name = $state['attributes']['name'];
267
- $state_reason = isset($state['attributes']['reasonCode'])?$state['attributes']['reasonCode']:'';
268
-
269
- if ( ! $this->is_state_ok($state_name, $state_reason) ) {
270
- $result['log'] .= sprintf(
271
- __('Video status : %s%s', 'broken-link-checker'),
272
- $state_name,
273
- $state_reason ? ' ['.$state_reason.']':''
274
- );
275
-
276
- $result['state_name'] = $state_name;
277
- $result['state_reason'] = $state_reason;
278
-
279
- $result['broken'] = true;
280
- $result['status_text'] = __('Video Restricted', 'broken-link-checker');
281
- $result['status_code'] = BLC_LINK_STATUS_WARNING;
282
- $result['http_code'] = 0;
283
-
284
- break;
285
- }
286
- }
287
-
288
- if ( ! $result['broken'] ) {
289
- $result['status_text'] = __('OK', 'link status', 'broken-link-checker');
290
- $result['status_code'] = BLC_LINK_STATUS_OK;
291
  $result['http_code'] = 0;
 
292
  }
293
  }
294
 
295
- //Add the playlist title to the log, purely for information.
296
- $title = blcUtility::extract_tags($response['body'], 'title', false);
297
- if ( !empty($title) ){
298
- $result['log'] .= "\n\nPlaylist title : \"" . $title[0]['contents'] . '"';
 
 
299
  }
 
300
 
301
- break;
 
 
 
302
 
303
- default:
304
- $result['log'] .= $result['http_code'] . $response['response']['message'];
305
- $result['log'] .= "\n" . __('Unknown YouTube API response received.');
306
- break;
 
 
307
  }
308
 
309
  return $result;
310
  }
311
 
312
- protected function get_video_feed_url($video_id) {
313
- return 'http://gdata.youtube.com/feeds/api/videos/' . $video_id . '?key=' . urlencode($this->youtube_developer_key);
 
 
 
 
 
 
314
  }
315
 
316
- protected function get_playlist_feed_url($playlist_id) {
317
  if ( strpos($playlist_id, 'PL') === 0 ) {
318
  $playlist_id = substr($playlist_id, 2);
319
  }
320
- $query = http_build_query(
321
- array(
322
- 'key' => $this->youtube_developer_key,
323
- 'v' => 2,
324
- 'safeSearch' => 'none'
325
- ),
326
- '', '&'
327
  );
328
-
329
- return 'http://gdata.youtube.com/feeds/api/playlists/' . $playlist_id . '?' . $query;
330
  }
331
 
332
- /**
333
- * Check if a video is restricted due to some minor problem (e.g. it's still processing)
334
- * or if we should treat it as broken.
335
- *
336
- * @param string $state_name
337
- * @param string $state_reason
338
- * @return bool
339
- */
340
- protected function is_state_ok($state_name, $state_reason) {
341
- //A couple of restricted states are not that bad
342
- $state_ok = ($state_name == 'processing') || //Video still processing; temporary.
343
- (
344
- $state_name == 'restricted' &&
345
- $state_reason == 'limitedSyndication' //Only available in browser
346
- );
347
- return $state_ok;
 
 
 
 
 
 
348
  }
349
 
350
  }
3
  /*
4
  Plugin Name: YouTube API
5
  Description: Check links to YouTube videos and playlists using the YouTube API.
6
+ Version: 3
7
  Author: Janis Elsts
8
 
9
  ModuleID: youtube-checker
17
  */
18
 
19
  class blcYouTubeChecker extends blcChecker {
20
+ var $youtube_developer_key = 'AIzaSyAyye_rE5jYd7VpwvcLNItXQCo5zxVvMFY';
21
  var $api_grace_period = 0.3; //How long to wait between YouTube API requests.
22
  var $last_api_request = 0; //Timestamp of the last request.
23
 
68
 
69
  //Fetch video or playlist from the YouTube API
70
  if ( !empty($video_id) ) {
71
+ $api_url = $this->get_video_resource_url($video_id);
72
  } else {
73
+ $api_url = $this->get_playlist_resource_url($playlist_id);
74
  }
75
 
76
  $conf = blc_get_configuration();
119
  * @return array New result array.
120
  */
121
  protected function check_video($response, $result) {
122
+ $api = json_decode($response['body'], true);
123
+ $videoFound = ($result['http_code'] == 200) && isset($api['items'], $api['items'][0]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
 
125
+ if ( isset($api['error']) && ($result['http_code'] != 404) ) { //404's are handled later.
126
+ $result['status_code'] = BLC_LINK_STATUS_WARNING;
127
+ $result['warning'] = true;
 
 
 
128
 
129
+ if ( isset($api['error']['message']) ) {
130
+ $result['status_text'] = $api['error']['message'];
131
+ } else {
132
+ $result['status_text'] = __('Unknown Error', 'broken-link-checker');
133
+ }
134
+ $result['log'] .= $this->format_api_error($response, $api);
135
+
136
+ } else if ( $videoFound ) {
137
+ $result['log'] .= __("Video OK", 'broken-link-checker');
138
+ $result['status_text'] = _x('OK', 'link status', 'broken-link-checker');
139
+ $result['status_code'] = BLC_LINK_STATUS_OK;
140
+ $result['http_code'] = 0;
141
+
142
+ //Add the video title to the log, purely for information.
143
+ if ( isset($api['items'][0]['snippet']['title']) ) {
144
+ $title = $api['items'][0]['snippet']['title'];
145
+ $result['log'] .= "\n\nTitle : \"" . htmlentities($title) . '"';
146
+ }
147
 
148
+ } else {
149
+ $result['log'] .= __('Video Not Found', 'broken-link-checker');
150
+ $result['broken'] = true;
151
+ $result['http_code'] = 0;
152
+ $result['status_text'] = __('Video Not Found', 'broken-link-checker');
153
+ $result['status_code'] = BLC_LINK_STATUS_ERROR;
154
  }
155
 
156
  return $result;
164
  * @return array
165
  */
166
  protected function check_playlist($response, $result) {
167
+ $api = json_decode($response['body'], true);
168
+
169
+ if ( $result['http_code'] == 404 ) {
170
+ //Not found.
171
+ $result['log'] .= __('Playlist Not Found', 'broken-link-checker');
172
+ $result['broken'] = true;
173
+ $result['http_code'] = 0;
174
+ $result['status_text'] = __('Playlist Not Found', 'broken-link-checker');
175
+ $result['status_code'] = BLC_LINK_STATUS_ERROR;
176
+
177
+ } else if ( $result['http_code'] == 403 ) {
178
+ //Forbidden. We're unlikely to see this code for playlists, but lets allow it.
179
+ $result['log'] .= htmlentities($response['body']);
180
+ $result['broken'] = true;
181
+ $result['status_text'] = __('Playlist Restricted', 'broken-link-checker');
182
+ $result['status_code'] = BLC_LINK_STATUS_ERROR;
183
+
184
+ } else if ( ($result['http_code'] == 200) && isset($api['items']) && is_array($api['items']) ) {
185
+ //The playlist exists.
186
+ if ( empty($api['items']) ) {
187
+ //An empty playlist. It is possible that all of the videos have been deleted.
188
+ $result['log'] .= __("This playlist has no entries or all entries have been deleted.", 'broken-link-checker');
189
+ $result['status_text'] = _x('Empty Playlist', 'link status', 'broken-link-checker');
190
+ $result['status_code'] = BLC_LINK_STATUS_WARNING;
191
  $result['http_code'] = 0;
 
 
 
 
 
 
192
  $result['broken'] = true;
193
+ } else {
194
+ //Treat the playlist as broken if at least one video is inaccessible.
195
+ foreach($api['items'] as $video) {
196
+ $is_private = isset($video['status']['privacyStatus']) && ($video['status']['privacyStatus'] == 'private');
197
+ if ( $is_private ) {
198
+ $result['log'] .= sprintf(
199
+ __('Video status : %s%s', 'broken-link-checker'),
200
+ $video['status']['privacyStatus'],
201
+ ''
202
+ );
203
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
  $result['broken'] = true;
205
+ $result['status_text'] = __('Video Restricted', 'broken-link-checker');
206
+ $result['status_code'] = BLC_LINK_STATUS_WARNING;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
207
  $result['http_code'] = 0;
208
+ break;
209
  }
210
  }
211
 
212
+ if ( !$result['broken'] ) {
213
+ //All is well.
214
+ $result['log'] .= __("Playlist OK", 'broken-link-checker');
215
+ $result['status_text'] = _x('OK', 'link status', 'broken-link-checker');
216
+ $result['status_code'] = BLC_LINK_STATUS_OK;
217
+ $result['http_code'] = 0;
218
  }
219
+ }
220
 
221
+ } else {
222
+ //Some other error.
223
+ $result['status_code'] = BLC_LINK_STATUS_WARNING;
224
+ $result['warning'] = true;
225
 
226
+ if ( isset($api['error']['message']) ) {
227
+ $result['status_text'] = $api['error']['message'];
228
+ } else {
229
+ $result['status_text'] = __('Unknown Error', 'broken-link-checker');
230
+ }
231
+ $result['log'] .= $this->format_api_error($response, $api);
232
  }
233
 
234
  return $result;
235
  }
236
 
237
+ protected function get_video_resource_url($video_id) {
238
+ $params = array(
239
+ 'part' => 'status,snippet',
240
+ 'id' => $video_id,
241
+ 'key' => $this->youtube_developer_key,
242
+ );
243
+ $params = array_map('urlencode', $params);
244
+ return 'https://www.googleapis.com/youtube/v3/videos?' . build_query($params);
245
  }
246
 
247
+ protected function get_playlist_resource_url($playlist_id) {
248
  if ( strpos($playlist_id, 'PL') === 0 ) {
249
  $playlist_id = substr($playlist_id, 2);
250
  }
251
+ $params = array(
252
+ 'key' => $this->youtube_developer_key,
253
+ 'playlistId' => $playlist_id,
254
+ 'part' => 'snippet,status',
255
+ 'maxResults' => 10, //Playlists can be big. Lets just check the first few videos.
 
 
256
  );
257
+ $query = build_query(array_map('urlencode', $params));
258
+ return 'https://www.googleapis.com/youtube/v3/playlistItems?' . $query;
259
  }
260
 
261
+ protected function format_api_error($response, $api) {
262
+ $log = $response['response']['code'] . ' ' . $response['response']['message'];
263
+ $log .= "\n" . __('Unknown YouTube API response received.');
264
+
265
+ //Log error details.
266
+ if ( isset($api['error']['errors']) && is_array($api['error']['errors']) ) {
267
+ foreach($api['error']['errors'] as $error) {
268
+ $log .= "\n---\n";
269
+
270
+ if (is_array($error)) {
271
+ foreach($error as $key => $value) {
272
+ $log .= sprintf(
273
+ "%s: %s\n",
274
+ htmlentities($key),
275
+ htmlentities($value)
276
+ );
277
+ }
278
+ }
279
+ }
280
+ }
281
+
282
+ return $log;
283
  }
284
 
285
  }
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.2-beta
7
- Stable tag: 1.10.5
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,13 @@ To upgrade your installation
98
 
99
  == Changelog ==
100
 
 
 
 
 
 
 
 
101
  = 1.10.5 =
102
  * Security: Fixed an XSS vulnerability that could be used by Editors and Administrators to inject arbitrary HTML/JS code in the "Tools -> Broken Links" page.
103
  * Other minor security fixes.
4
  Tags: links, broken, maintenance, blogroll, custom fields, admin, comments, posts
5
  Requires at least: 3.2
6
  Tested up to: 4.2-beta
7
+ Stable tag: 1.10.6
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.6 =
102
+ * Fixed a serious CSRF/XSS vulnerability.
103
+ * Switched to YouTube API v3. The old API version will be shut down on April 20, so the plugin needs to be updated to continue checking links to YouTube videos.
104
+ * Fixed long URLs overflowing into adjacent table columns.
105
+ * Fixed a few minor PHP strict-mode notices.
106
+ * Added database character set to the "Show debug info" table.
107
+
108
  = 1.10.5 =
109
  * Security: Fixed an XSS vulnerability that could be used by Editors and Administrators to inject arbitrary HTML/JS code in the "Tools -> Broken Links" page.
110
  * Other minor security fixes.