/**
  * Class "constructor". Can't use an actual constructor due to how PHP4 handles object references.
  * 
  * Specifically, this class is a singleton. The function needs to pass $this to several other 
  * functions (to set up hooks), which will store the reference for later use. However, it appears 
  * that in PHP4 the actual value of $this is thrown away right after the constructor finishes, and
  * `new` returns a *copy* of $this. The result is that getInstance() won't be returning a ref.
  * to the same object as is used for hook callbacks. And that's horrible.   
  * 
  * Sets up hooks that monitor added/modified/deleted posts and registers
  * virtual modules for all post types.
  *
  * @return void
  */
 function init()
 {
     $this->plugin_conf = blc_get_configuration();
     if (isset($this->plugin_conf->options['enabled_post_statuses'])) {
         $this->enabled_post_statuses = $this->plugin_conf->options['enabled_post_statuses'];
     }
     //Register a virtual container module for each enabled post type
     $module_manager = blcModuleManager::getInstance();
     $post_types = get_post_types(array(), 'objects');
     $exceptions = array('revision', 'nav_menu_item', 'attachment');
     foreach ($post_types as $data) {
         $post_type = $data->name;
         if (in_array($post_type, $exceptions)) {
             continue;
         }
         $module_manager->register_virtual_module($post_type, array('Name' => $data->labels->name, 'ModuleCategory' => 'container', 'ModuleContext' => 'all', 'ModuleClassName' => 'blcAnyPostContainerManager'));
     }
     //These hooks update the synch & instance records when posts are added, deleted or modified.
     add_action('delete_post', array(&$this, 'post_deleted'));
     add_action('save_post', array(&$this, 'post_saved'));
     //We also treat post trashing/untrashing as delete/save.
     add_action('trash_post', array(&$this, 'post_deleted'));
     add_action('untrash_post', array(&$this, 'post_saved'));
     //Highlight and nofollow broken links in posts & pages
     if ($this->plugin_conf->options['mark_broken_links'] || $this->plugin_conf->options['nofollow_broken_links']) {
         add_filter('the_content', array(&$this, 'hook_the_content'));
         if ($this->plugin_conf->options['mark_broken_links'] && !empty($this->plugin_conf->options['broken_link_css'])) {
             add_action('wp_head', array(&$this, 'hook_wp_head'));
         }
     }
 }
/**
* Display a notice asking the user to take the Broken Link Checker user survey.
*
* @return void
*/
function blc_display_survey_notice()
{
    //Only people who can actually use the plugin will see the notice
    if (!current_user_can('manage_links')) {
        return;
    }
    if (!empty($_GET['dismiss-blc-survey'])) {
        //The user has chosen to hide the survey notice
        $blc_config = blc_get_configuration();
        $blc_config->options['hide_surveyio_notice'] = true;
        $blc_config->save_options();
        return;
    }
    $survey_url = 'http://survey.io/survey/7fbf0';
    $msg = sprintf('<strong>Help improve Broken Link Checker - <a href="%s" target="_blank" title="This link will open in a new window" id="blc-take-survey-link">take a user feedback survey!</a></strong>
		 <br><a href="%s">Hide this notice</a>', $survey_url, esc_attr(add_query_arg('dismiss-blc-survey', 1)));
    echo '<div id="update-nag" class="blc-survey-notice" style="text-align: left; padding-left: 10px;">' . $msg . '</div>';
    //Auto-hide the notice after the user clicks the survey link
    ?>
	<script type="text/javascript">
	jQuery(function($){
		$('#blc-take-survey-link').click(function(){
			$('.blc-survey-notice').hide('fast');
			$.get('<?php 
    echo esc_js(add_query_arg('dismiss-blc-survey', 1, admin_url()));
    ?>
');
		});
	});
	</script>
	<?php 
}
 /**
  * Create and/or upgrade the plugin's database tables.
  *
  * @return bool
  */
 public static function upgrade_database()
 {
     global $wpdb, $blclog;
     $conf = blc_get_configuration();
     $current = $conf->options['current_db_version'];
     if ($current != 0 && $current < 4) {
         //The 4th DB version makes a lot of backwards-incompatible changes to the main
         //BLC tables, so instead of upgrading we just throw them away and recreate.
         if (!blcDatabaseUpgrader::drop_tables()) {
             return false;
         }
         $current = 0;
     }
     //Create/update the plugin's tables
     if (!blcDatabaseUpgrader::make_schema_current()) {
         return false;
     }
     if ($current != 0) {
         if ($current < 5) {
             blcDatabaseUpgrader::upgrade_095();
         }
     }
     $conf->options['current_db_version'] = BLC_DATABASE_VERSION;
     $conf->save_options();
     $blclog->info('Database successfully upgraded.');
     return true;
 }
Exemple #4
0
 /**
  * Notify the link checker that there are unsynched items 
  * that might contain links (e.g. a new or edited post).
  *
  * @return void
  */
 function blc_got_unsynched_items()
 {
     $conf = blc_get_configuration();
     if (!$conf->options['need_resynch']) {
         $conf->options['need_resynch'] = true;
         $conf->save_options();
     }
 }
 /**
  * Class "constructor".
  * 
  * @param array $default_active_modules An array of module ids specifying which modules are active by default.
  * @return void
  */
 function init($default_active_modules = null)
 {
     $this->module_dir = realpath(dirname(__FILE__) . '/../modules');
     $this->plugin_conf = blc_get_configuration();
     $this->default_active_modules = $default_active_modules;
     $this->loaded = array();
     $this->instances = array();
     add_filter('extra_plugin_headers', array(&$this, 'inject_module_headers'));
 }
 function save_settings()
 {
     $information = array();
     $information['result'] = 'NOTCHANGE';
     $new_check_threshold = intval($_POST['check_threshold']);
     if ($new_check_threshold > 0) {
         $conf = blc_get_configuration();
         $conf->options['check_threshold'] = $new_check_threshold;
         if ($conf->save_options()) {
             $information['result'] = 'SUCCESS';
         }
     }
     return $information;
 }
 /**
  * Check a FileServe link.
  *
  * See the FileServe API documentation for details:
  * http://app.fileserve.com/api/download/
  *
  * @param string $url File URL.
  * @return array
  */
 function check($url)
 {
     $result = array('final_url' => $url, 'redirect_count' => 0, 'timeout' => false, 'broken' => false, 'log' => sprintf("<em>(%s)</em>\n\n", __('Using FileServe API', 'broken-link-checker')), 'result_hash' => '', 'status_code' => '', 'status_text' => '');
     //We know the URL will match because ModuleCheckerUrlPattern matched.
     preg_match('@^http://(?:www\\.)?fileserve\\.com/file/([\\w\\d]+?)(?:/|$|[?#])@i', $url, $matches);
     $file_id = $matches[1];
     $conf = blc_get_configuration();
     $args = array('timeout' => $conf->options['timeout'], 'body' => array('shorten' => $file_id));
     $start = microtime_float();
     $response = wp_remote_post($this->fileserve_api_url, $args);
     $result['request_duration'] = microtime_float() - $start;
     $error_code = 0;
     if (is_wp_error($response)) {
         $result['log'] .= "Error : " . $response->get_error_message();
         $result['broken'] = true;
         $result['http_code'] = 0;
     } else {
         $result['http_code'] = intval($response['response']['code']);
         if ($result['http_code'] == 200) {
             //In this case, the HTTP code returned by is not meaningful in itself,
             //so we won't store it or display it to the user.
             $result['http_code'] = 0;
             $json = json_decode($response['body'], false);
             if (isset($json->error_code)) {
                 $error_code = intval($json->error_code);
             }
             $failure_codes = array(310 => 'Invalid request', 403 => 'Not premium', 404 => 'Invalid link', 601 => 'Limited free download', 602 => 'Number of concurrent download exceeded', 603 => 'Too many invalid capcha', 605 => 'Expired premium', 606 => 'Invalid file ID', 607 => 'File not available', 608 => 'File not available');
             if (array_key_exists($error_code, $failure_codes)) {
                 $result['broken'] = true;
                 $result['status_code'] = BLC_LINK_STATUS_ERROR;
                 $result['status_text'] = __('Not Found', 'broken-link-checker');
                 $result['log'] .= sprintf(__('FileServe : %d %s', 'broken-link-checker') . "\n", $error_code, $failure_codes[$error_code]);
             } else {
                 $result['status_code'] = BLC_LINK_STATUS_OK;
                 $result['status_text'] = _x('OK', 'link status', 'broken-link-checker');
             }
             //$result['log'] .= "API response :\n" . htmlspecialchars(print_r((array)$json, true));
             $result['log'] .= "API response :\n<code>" . htmlspecialchars($response['body']) . "</code>\n";
         } else {
             //Unexpected error.
             $result['log'] .= $response['body'];
             $result['broken'] = true;
         }
     }
     //Generate the result hash (used for detecting false positives)
     $result['result_hash'] = implode('|', array('fileserve', $result['http_code'], $result['broken'] ? 'broken' : '0', $result['timeout'] ? 'timeout' : '0', $error_code));
     return $result;
 }
 function __construct()
 {
     //Init. the available native filters.
     $this->native_filters = array('all' => array('params' => array('where_expr' => '1'), 'name' => __('All', 'broken-link-checker'), 'heading' => __('Detected Links', 'broken-link-checker'), 'heading_zero' => __('No links found (yet)', 'broken-link-checker'), 'native' => true), 'broken' => array('params' => array('where_expr' => '( broken = 1 )', 's_include_dismissed' => false), 'name' => __('Broken', 'broken-link-checker'), 'heading' => __('Broken Links', 'broken-link-checker'), 'heading_zero' => __('No broken links found', 'broken-link-checker'), 'native' => true), 'warnings' => array('params' => array('where_expr' => '( warning = 1 )', 's_include_dismissed' => false), 'name' => _x('Warnings', 'filter name', 'broken-link-checker'), 'heading' => __('Warnings', 'filter heading', 'broken-link-checker'), 'heading_zero' => __('No warnings found', 'broken-link-checker'), 'native' => true), 'redirects' => array('params' => array('where_expr' => '( redirect_count > 0 )', 's_include_dismissed' => false), 'name' => __('Redirects', 'broken-link-checker'), 'heading' => __('Redirected Links', 'broken-link-checker'), 'heading_zero' => __('No redirects found', 'broken-link-checker'), 'native' => true), 'dismissed' => array('params' => array('where_expr' => '( dismissed = 1 )'), 'name' => __('Dismissed', 'broken-link-checker'), 'heading' => __('Dismissed Links', 'broken-link-checker'), 'heading_zero' => __('No dismissed links found', 'broken-link-checker'), 'native' => true));
     //The user can turn off warnings. In that case, all errors will show up in the "broken" filter instead.
     $conf = blc_get_configuration();
     if (!$conf->get('warnings_enabled')) {
         unset($this->native_filters['warnings']);
     }
     //Create the special "search" filter
     $this->search_filter = array('name' => __('Search', 'broken-link-checker'), 'heading' => __('Search Results', 'broken-link-checker'), 'heading_zero' => __('No links found for your query', 'broken-link-checker'), 'params' => array(), 'use_url_params' => true, 'hidden' => true);
     //These search arguments may be passed via the URL if the filter's 'use_url_params' field is set to True.
     //They map to the fields of the search form on the Tools -> Broken Links page. Only these arguments
     //can be used in user-defined filters.
     $this->valid_url_params = array('s_link_text', 's_link_url', 's_parser_type', 's_container_type', 's_link_type', 's_http_code', 's_filter');
 }
 function save_settings()
 {
     $information = array();
     $information['result'] = 'NOTCHANGE';
     $new_check_threshold = intval($_POST['check_threshold']);
     if (update_option('mainwp_child_blc_max_number_of_links', intval($_POST['max_number_of_links']))) {
         $information['result'] = 'SUCCESS';
     }
     if ($new_check_threshold > 0) {
         $conf = blc_get_configuration();
         $conf->options['check_threshold'] = $new_check_threshold;
         if ($conf->save_options()) {
             $information['result'] = 'SUCCESS';
         }
     }
     return $information;
 }
 /**
  * blcHTMLLink::unlink_callback()
  *
  * @access private
  * 
  * @param array $link
  * @param array $params
  * @return string
  */
 function unlink_callback($link, $params)
 {
     //Skip links that don't match the specified URL
     if ($link['href'] != $params['old_url']) {
         return $link['#raw'];
     }
     $config = blc_get_configuration();
     if ($config->options['mark_removed_links']) {
         //Leave only the anchor text + the removed_link CSS class
         return sprintf('<span class="removed_link" title="%s">%s</span>', esc_attr($link['href']), $link['#link_text']);
     } else {
         //Just the anchor text
         return $link['#link_text'];
     }
 }
 /**
  * Decide whether the result of the latest check means that the link is really broken
  * or should just be reported as a warning.
  *
  * @param array $check_results
  * @return array
  */
 private function decide_warning_state($check_results)
 {
     if (!$check_results['broken'] && !$check_results['warning']) {
         //Nothing to do, this is a working link.
         return $check_results;
     }
     $configuration = blc_get_configuration();
     if (!$configuration->get('warnings_enabled', true)) {
         //The user wants all failures to be reported as "broken", regardless of severity.
         if ($check_results['warning']) {
             $check_results['broken'] = true;
             $check_results['warning'] = false;
         }
         return $check_results;
     }
     $warning_reason = null;
     $failure_count = $this->check_count;
     $failure_duration = $this->first_failure != 0 ? time() - $this->first_failure : 0;
     //These could be configurable, but lets put that off until someone actually asks for it.
     $duration_threshold = 24 * 3600;
     $count_threshold = 3;
     //We can't just use ($check_results['status_code'] == 'warning' because some "warning" problems are not
     //temporary. For example, region-restricted YouTube videos use the "warning" status code.
     $maybe_temporary_error = false;
     //Some basic heuristics to determine if this failure might be temporary.
     //----------------------------------------------------------------------
     if ($check_results['timeout']) {
         $maybe_temporary_error = true;
         $warning_reason = 'Timeouts are sometimes caused by high server load or other temporary issues.';
     }
     $error_code = isset($check_results['error_code']) ? $check_results['error_code'] : '';
     if ($error_code === 'connection_failed') {
         $maybe_temporary_error = true;
         $warning_reason = 'Connection failures are sometimes caused by high server load or other temporary issues.';
     }
     $http_code = intval($check_results['http_code']);
     $temporary_http_errors = array(408, 420, 429, 502, 503, 504, 509, 520, 522, 524);
     if (in_array($http_code, $temporary_http_errors)) {
         $maybe_temporary_error = true;
         if (in_array($http_code, array(502, 503, 504, 509))) {
             $warning_reason = sprintf('HTTP error %d usually means that the site is down due to high server load or a configuration problem. ' . 'This error is often temporary and will go away after while.', $http_code);
         } else {
             $warning_reason = 'This HTTP error is often temporary.';
         }
     }
     //----------------------------------------------------------------------
     //Attempt to detect false positives.
     $suspected_false_positive = false;
     //A "403 Forbidden" error on an internal link usually means something on the site is blocking automated
     //requests. Possible culprits include hotlink protection rules in .htaccess, badly configured IDS, and so on.
     $is_internal_link = $this->is_internal_to_domain();
     if ($is_internal_link && $http_code == 403) {
         $suspected_false_positive = true;
         $warning_reason = 'This might be a false positive. Make sure the link is not password-protected, ' . 'and that your server is not set up to block automated requests.';
     }
     //Some hosting providers turn off loopback connections. This causes all internal links to be reported as broken.
     if ($is_internal_link && in_array($error_code, array('connection_failed', 'couldnt_resolve_host'))) {
         $suspected_false_positive = true;
         $warning_reason = 'This is probably a false positive. ';
         if ($error_code === 'connection_failed') {
             $warning_reason .= 'The plugin could not connect to your site. That usually means that your ' . 'hosting provider has disabled loopback connections.';
         } elseif ($error_code === 'couldnt_resolve_host') {
             $warning_reason .= 'The plugin could not connect to your site because DNS resolution failed. ' . 'This could mean DNS is configured incorrectly on your server.';
         }
     }
     //----------------------------------------------------------------------
     //Temporary problems and suspected false positives start out as warnings. False positives stay that way
     //indefinitely because they are usually caused by bugs and server configuration issues, not temporary downtime.
     if ($maybe_temporary_error && $failure_count < $count_threshold || $suspected_false_positive) {
         $check_results['warning'] = true;
         $check_results['broken'] = false;
     }
     //Upgrade temporary warnings to "broken" after X consecutive failures or Y hours, whichever comes first.
     $threshold_reached = $failure_count >= $count_threshold || $failure_duration >= $duration_threshold;
     if ($check_results['warning']) {
         if ($maybe_temporary_error && $threshold_reached && !$suspected_false_positive) {
             $check_results['warning'] = false;
             $check_results['broken'] = true;
         }
     }
     if (!empty($warning_reason) && $check_results['warning']) {
         $formatted_reason = "\n==========\n" . 'Severity: Warning' . "\n" . 'Reason: ' . trim($warning_reason) . "\n==========\n";
         $check_results['log'] .= $formatted_reason;
     }
     return $check_results;
 }
 /**
  * Perform a HEAD request to the specified URL.
  * 
  * Note : 
  * 
  * Since the MediaFire checker works by parsing the "Location" header, redirect following
  * _must_ be disabled. This can become a problem on servers where WP is forced to fall back
  * on using WP_Http_Fopen which ignores the 'redirection' flag. WP_Http_Fsockopen would work, 
  * but it has the lowest priority of all transports. 
  * 
  * Alas, there is no way to reliably influence which transport is chosen - the WP_Http::_getTransport
  * function caches the available choices, so plugins can disable individual transports only during
  * its first run. Therefore, we must pick the best transport manually.
  * 
  * @param string $url
  * @return array|WP_Error
  */
 function head($url)
 {
     //Only consider transports that allow redirection to be disabled.
     $args = array();
     if (class_exists('WP_Http_ExtHttp') && true === WP_Http_ExtHttp::test($args)) {
         $transport = new WP_Http_ExtHttp();
     } else {
         if (class_exists('WP_Http_Curl') && true === WP_Http_Curl::test($args)) {
             $transport = new WP_Http_Curl();
         } else {
             if (class_exists('WP_Http_Curl') && true === WP_Http_Fsockopen::test($args)) {
                 $transport = new WP_Http_Fsockopen();
             } else {
                 return new WP_Error('no_suitable_transport', "No suitable HTTP transport found. Please upgrade to a more recent version of PHP or install the CURL extension.");
             }
         }
     }
     $conf = blc_get_configuration();
     $args = array('timeout' => $conf->options['timeout'], 'redirection' => 0, 'method' => 'HEAD');
     return $transport->request($url, $args);
 }
Exemple #13
0
 /**
  * A hook for the 'wp_head' action. Outputs the user-defined broken link CSS.
  *
  * @return void
  */
 function hook_wp_head()
 {
     $conf = blc_get_configuration();
     echo '<style type="text/css">', $conf->options['broken_link_css'], '</style>';
 }
Exemple #14
0
        /**
         * Show an admin notice that explains what the "Warnings" section under "Tools -> Broken Links" does.
         * The user can hide the notice.
         */
        public function show_warnings_section_notice()
        {
            $is_warnings_section = isset($_GET['filter_id']) && $_GET['filter_id'] === 'warnings' && isset($_GET['page']) && $_GET['page'] === 'view-broken-links';
            if (!($is_warnings_section && current_user_can('edit_others_posts'))) {
                return;
            }
            //Let the user hide the notice.
            $conf = blc_get_configuration();
            $notice_name = 'show_warnings_section_hint';
            if (isset($_GET[$notice_name]) && is_numeric($_GET[$notice_name])) {
                $conf->set($notice_name, (bool) $_GET[$notice_name]);
                $conf->save_options();
            }
            if (!$conf->get($notice_name, true)) {
                return;
            }
            printf('<div class="updated">
					<p>%1$s</p>
					<p>
						<a href="%2$s">%3$s</a> |
						<a href="%4$s">%5$s</a>
					<p>
				</div>', __('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.', 'broken-link-checker'), esc_attr(add_query_arg($notice_name, '0')), _x('Hide notice', 'admin notice under Tools - Broken links - Warnings', 'broken-link-checker'), esc_attr(admin_url('options-general.php?page=link-checker-settings#blc_warning_settings')), _x('Change warning settings', 'a link from the admin notice under Tools - Broken links - Warnings', 'broken-link-checker'));
        }
Exemple #15
0
 /**
  * Check the status of one or more MegaUpload files.
  * 
  * The MegaUpload API that is used in this function isn't documented anywhere.
  * The input and output data formats were reverse-engineered by sniffing the
  * HTTP requests made by the "Mega Manager" tool. 
  * 
  * @param array|string $file_ids
  * @return array|WP_Error
  */
 function check_files($file_ids)
 {
     if (is_string($file_ids)) {
         $file_ids = array($file_ids);
     }
     //The API expects input in this format : id0=file1id&id1=file2id&...
     $request_ids = array();
     $counter = 0;
     foreach ($file_ids as $file_id) {
         $id = 'id' . $counter;
         $request_ids[$id] = $file_id;
         $counter++;
     }
     $conf = blc_get_configuration();
     $args = array('timeout' => $conf->options['timeout'], 'body' => $request_ids);
     //Submit the request
     $rez = wp_remote_post('http://www.megaupload.com/mgr_linkcheck.php', $args);
     if (is_wp_error($rez)) {
         return $rez;
     }
     if ($rez['response']['code'] == 200 && !empty($rez['body'])) {
         $api_results = $this->parse_api_response($rez['body']);
         $results = array();
         //Resort the results by real file IDs
         foreach ($api_results as $id => $file_info) {
             if (!array_key_exists($id, $request_ids)) {
                 continue;
             }
             $results[$request_ids[$id]] = $file_info;
         }
         return $results;
     } else {
         return new WP_Error('megaupload_api_error', "MegaUpload API Error", $rez);
     }
 }
Exemple #16
0
 /**
  * Check a RapidShare file.
  * 
  * @param string $url File URL.
  * @return array
  */
 function check($url)
 {
     $result = array('final_url' => $url, 'redirect_count' => 0, 'timeout' => false, 'broken' => false, 'log' => sprintf("<em>(%s)</em>\n\n", __('Using RapidShare API', 'broken-link-checker')), 'result_hash' => '', 'status_code' => '', 'status_text' => '');
     //We know the URL will match because ModuleCheckerUrlPattern matched.
     preg_match('@^https?://(?:[\\w\\d]+\\.)*rapidshare\\.\\w+/files/(\\d+)/([^&?#/]+?)(?:$|[&?#/])@i', $url, $matches);
     $file_id = $matches[1];
     $file_name = $matches[2];
     /*
     We use the checkfiles function to check file status. The RapidShare API docs can be found here :
     http://images.rapidshare.com/apidoc.txt
     	 	
     	 	The relevant function is documented thusly :  
     	 	
     sub=checkfiles
     
     Description:
     		Gets status details about a list of given files. (files parameter limited to 3000 bytes.
     		filenames parameter limited to 30000 bytes.)
     
     Parameters:
     		files=comma separated list of file ids
     		filenames=comma separated list of the respective filename. Example: files=50444381,50444382 filenames=test1.rar,test2.rar
     
     Reply fields:
     		1:File ID
     		2:Filename
     		3:Size (in bytes. If size is 0, this file does not exist.)
     		4:Server ID
     		5:Status integer, which can have the following numeric values:
     			0=File not found
     			1=File OK
     			3=Server down
     			4=File marked as illegal
     		6:Short host (Use the short host to get the best download mirror: http://rs$serverid$shorthost.rapidshare.com/files/$fileid/$filename)
     		7:MD5 (hexadecimal)
     
     Reply format:	integer,string,integer,integer,integer,string,string
     */
     $api_url = sprintf('http://api.rapidshare.com/cgi-bin/rsapi.cgi?sub=checkfiles&files=%d&filenames=%s', $file_id, $file_name);
     $conf = blc_get_configuration();
     $args = array('timeout' => $conf->options['timeout']);
     $start = microtime_float();
     $response = wp_remote_get($api_url, $args);
     $result['request_duration'] = microtime_float() - $start;
     $file_status = 0;
     $file_status_text = '';
     //Is the response valid?
     if (is_wp_error($response)) {
         $result['log'] .= "Error : " . $response->get_error_message();
         $result['broken'] = true;
         $result['http_code'] = 0;
     } else {
         $result['http_code'] = intval($response['response']['code']);
         if ($result['http_code'] == 200) {
             //Parse the API response
             $data = explode(',', $response['body']);
             //Check file status
             if (isset($data[4])) {
                 $file_status = intval($data[4]);
                 $file_status_text = '';
                 if ($file_status >= 0 && $file_status <= 6) {
                     //Lets not confuse the user by showing the HTTP code we got from the API.
                     //It's always "200" - whether the file exists or not.
                     $result['http_code'] = 0;
                 }
                 switch ($file_status) {
                     case 0:
                         $file_status_text = 'File not found';
                         $result['broken'] = true;
                         $result['status_code'] = BLC_LINK_STATUS_ERROR;
                         $result['status_text'] = __('Not Found', 'broken-link-checker');
                         break;
                     case 1:
                         $file_status_text = 'File OK (Anonymous downloading)';
                         $result['status_code'] = BLC_LINK_STATUS_OK;
                         $result['status_text'] = _x('OK', 'link status', 'broken-link-checker');
                         break;
                     case 2:
                         $file_status_text = 'File OK (TrafficShare direct download without any logging)';
                         $result['status_code'] = BLC_LINK_STATUS_OK;
                         $result['status_text'] = _x('OK', 'link status', 'broken-link-checker');
                         break;
                     case 3:
                         $file_status_text = 'Server down';
                         $result['broken'] = true;
                         $result['status_code'] = BLC_LINK_STATUS_WARNING;
                         $result['status_text'] = __('RS Server Down', 'broken-link-checker');
                         break;
                     case 4:
                         $file_status_text = 'File marked as illegal';
                         $result['broken'] = true;
                         $result['status_code'] = BLC_LINK_STATUS_ERROR;
                         $result['status_text'] = __('File Blocked', 'broken-link-checker');
                         break;
                     case 5:
                         $file_status_text = 'Anonymous file locked because it has more than 10 downloads';
                         $result['broken'] = true;
                         $result['status_code'] = BLC_LINK_STATUS_WARNING;
                         $result['status_text'] = __('File Locked', 'broken-link-checker');
                         break;
                     case 6:
                         $file_status_text = 'File OK (TrafficShare direct download with enabled logging)';
                         $result['status_code'] = BLC_LINK_STATUS_OK;
                         $result['status_text'] = _x('OK', 'link status', 'broken-link-checker');
                         break;
                 }
                 $result['log'] .= sprintf(__('RapidShare : %s', 'broken-link-checker'), $file_status_text);
             } else {
                 $result['log'] .= sprintf(__('RapidShare API error: %s', 'broken-link-checker'), $response['body']);
             }
         } else {
             //Unexpected error.
             $result['log'] .= $response['body'];
             $result['broken'] = true;
         }
     }
     //Generate the result hash (used for detecting false positives)
     $result['result_hash'] = implode('|', array('rapidshare', $result['http_code'], $result['broken'] ? 'broken' : '0', $result['timeout'] ? 'timeout' : '0', $file_status));
     return $result;
 }
 /**
  * Mark custom fields as unsynched when they're modified or deleted.
  *
  * @param array|int $meta_id
  * @param int $object_id
  * @param string $meta_key
  * @param string $meta_value
  * @return void
  */
 function meta_modified($meta_id, $object_id = 0, $meta_key = '', $meta_value = '')
 {
     global $wpdb;
     //If object_id isn't specified then the hook was probably called from the
     //stupidly inconsistent delete_meta() function in /wp-admin/includes/post.php.
     if (empty($object_id)) {
         //We must manually retrieve object_id and meta_key from the DB.
         if (is_array($meta_id)) {
             $meta_id = array_shift($meta_id);
         }
         $meta = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->postmeta} WHERE meta_id = %d", $meta_id), ARRAY_A);
         if (empty($meta)) {
             return;
         }
         $object_id = $meta['post_id'];
         $meta_key = $meta['meta_key'];
     }
     //Metadata changes only matter to us if the modified key
     //is one that the user wants checked.
     $conf =& blc_get_configuration();
     if (!is_array($conf->options['custom_fields'])) {
         return;
     }
     if (!in_array($meta_key, $conf->options['custom_fields'])) {
         return;
     }
     $container =& blcContainerHelper::get_container(array($this->container_type, intval($object_id)));
     $container->mark_as_unsynched();
 }
/**
 * Display installation errors (if any) on the Dashboard.
 *
 * @return void
 */
function blc_print_installation_errors()
{
    $conf = blc_get_configuration();
    if (!$conf->options['installation_failed']) {
        return;
    }
    $logger = new blcOptionLogger('blc_installation_log');
    $log = $logger->get_messages();
    $message = array('<strong>' . __('Broken Link Checker installation failed', 'broken-link-checker') . '</strong>', '', '<em>Installation log follows :</em>');
    foreach ($log as $entry) {
        array_push($message, $entry);
    }
    $message = implode("<br>\n", $message);
    echo "<div class='error'><p>{$message}</p></div>";
}
        /**
         * @param blcLink $link
         */
        function column_new_url($link)
        {
            ?>
        <a href="<?php 
            print esc_url($link->url);
            ?>
"
		   target='_blank'
		   class='blc-link-url'
		   title="<?php 
            echo esc_attr($link->url);
            ?>
"
		   data-editable-url="<?php 
            echo esc_attr($link->url);
            ?>
">
        	<?php 
            print esc_html($link->url);
            ?>
</a>
        <?php 
            //Output inline action links for the link/URL
            $actions = array();
            $actions['edit'] = "<a href='javascript:void(0)' class='blc-edit-button' title='" . esc_attr(__('Edit this link', 'broken-link-checker')) . "'>" . __('Edit URL', 'broken-link-checker') . "</a>";
            $actions['delete'] = "<a class='submitdelete blc-unlink-button' title='" . esc_attr(__('Remove this link from all posts', 'broken-link-checker')) . "' " . "href='javascript:void(0);'>" . __('Unlink', 'broken-link-checker') . "</a>";
            if ($link->broken || $link->warning) {
                $actions['blc-discard-action'] = sprintf('<a href="#" title="%s" class="blc-discard-button">%s</a>', esc_attr(__('Remove this link from the list of broken links and mark it as valid', 'broken-link-checker')), __('Not broken', 'broken-link-checker'));
            }
            if (!$link->dismissed && ($link->broken || $link->warning || $link->redirect_count > 0)) {
                $actions['blc-dismiss-action'] = sprintf('<a href="#" title="%s" class="blc-dismiss-button">%s</a>', esc_attr(__('Hide this link and do not report it again unless its status changes', 'broken-link-checker')), __('Dismiss', 'broken-link-checker'));
            } else {
                if ($link->dismissed) {
                    $actions['blc-undismiss-action'] = sprintf('<a href="#" title="%s" class="blc-undismiss-button">%s</a>', esc_attr(__('Undismiss this link', 'broken-link-checker')), __('Undismiss', 'broken-link-checker'));
                }
            }
            $actions['blc-recheck-action'] = sprintf('<a href="#" class="blc-recheck-button">%s</a>', __('Recheck', 'broken-link-checker'));
            if ($link->redirect_count > 0 && !empty($link->final_url) && $link->url != $link->final_url) {
                //TODO: Check if at least one instance has an editable URL. Otherwise this won't work.
                $actions['blc-deredirect-action'] = sprintf('<a href="#" class="blc-deredirect-button" title="%s">%s</a>', __('Replace this redirect with a direct link', 'broken-link-checker'), _x('Fix redirect', 'link action; replace one redirect with a direct link', 'broken-link-checker'));
            }
            //Only show the enabled actions.
            $conf = blc_get_configuration();
            foreach ($conf->get('show_link_actions', $actions) as $name => $enabled) {
                if (!$enabled) {
                    unset($actions[$name]);
                }
            }
            //Wrap actions with <span></span> and separate them with | characters.
            //Basically, this emulates the HTML structure that WP uses for post actions under Posts -> All Posts.
            $spans = array();
            $is_first_action = true;
            foreach ($actions as $name => $html) {
                $spans[] = sprintf('<span class="%s">%s%s</span>', esc_attr($name), $is_first_action ? '' : ' | ', $html);
                $is_first_action = false;
            }
            echo '<div class="row-actions">';
            echo implode('', $spans);
            echo '</div>';
            ?>
		<div class="blc-url-editor-buttons">
			<input type="button" class="button-secondary cancel alignleft blc-cancel-button" value="<?php 
            echo esc_attr(__('Cancel', 'broken-link-checker'));
            ?>
" />
			<input type="button" class="button-primary save alignright blc-update-url-button" value="<?php 
            echo esc_attr(__('Update URL', 'broken-link-checker'));
            ?>
" />
			<img class="waiting" style="display:none;" src="<?php 
            echo esc_url(admin_url('images/wpspin_light.gif'));
            ?>
" alt="" />
		</div>
		<?php 
        }
Exemple #20
0
 function check($url)
 {
     //Throttle API requests to avoid getting blocked due to quota violation.
     $delta = microtime_float() - $this->last_api_request;
     if ($delta < $this->api_grace_period) {
         usleep(($this->api_grace_period - $delta) * 1000000);
     }
     $result = array('final_url' => $url, 'redirect_count' => 0, 'timeout' => false, 'broken' => false, 'log' => "<em>(Using YouTube API)</em>\n\n", 'result_hash' => '');
     $components = @parse_url($url);
     if (isset($components['query'])) {
         parse_str($components['query'], $query);
     } else {
         $query = array();
     }
     //Extract the video or playlist ID from the URL
     $video_id = $playlist_id = null;
     if (strtolower($components['host']) === 'youtu.be') {
         $video_id = trim($components['path'], '/');
     } else {
         if (strpos($components['path'], 'watch') !== false && isset($query['v'])) {
             $video_id = $query['v'];
         } else {
             if ($components['path'] == '/playlist') {
                 $playlist_id = $query['list'];
             } else {
                 if ($components['path'] == '/view_play_list') {
                     $playlist_id = $query['p'];
                 }
             }
         }
     }
     if (empty($playlist_id) && empty($video_id)) {
         $result['status_text'] = 'Unsupported URL Syntax';
         $result['status_code'] = BLC_LINK_STATUS_UNKNOWN;
         return $result;
     }
     //Fetch video or playlist from the YouTube API
     if (!empty($video_id)) {
         $api_url = $this->get_video_resource_url($video_id);
     } else {
         $api_url = $this->get_playlist_resource_url($playlist_id);
     }
     $conf = blc_get_configuration();
     $args = array('timeout' => $conf->options['timeout']);
     $start = microtime_float();
     $response = wp_remote_get($api_url, $args);
     $result['request_duration'] = microtime_float() - $start;
     $this->last_api_request = $start;
     //Got anything?
     if (is_wp_error($response)) {
         $result['log'] .= "Error.\n" . $response->get_error_message();
         //WP doesn't make it easy to distinguish between different internal errors.
         $result['broken'] = true;
         $result['http_code'] = 0;
     } else {
         $result['http_code'] = intval($response['response']['code']);
         if (!empty($video_id)) {
             $result = $this->check_video($response, $result);
         } else {
             $result = $this->check_playlist($response, $result);
         }
     }
     //The hash should contain info about all pieces of data that pertain to determining if the
     //link is working.
     $result['result_hash'] = implode('|', array('youtube', $result['http_code'], $result['broken'] ? 'broken' : '0', $result['timeout'] ? 'timeout' : '0', isset($result['state_name']) ? $result['state_name'] : '-', isset($result['state_reason']) ? $result['state_reason'] : '-'));
     return $result;
 }
 function check($url)
 {
     $result = array('final_url' => $url, 'redirect_count' => 0, 'timeout' => false, 'broken' => false, 'log' => "<em>(Using YouTube API)</em>\n\n", 'result_hash' => '');
     //Extract the video ID from the URL
     $components = @parse_url($url);
     parse_str($components['query'], $query);
     $video_id = $query['v'];
     //Fetch video data from the YouTube API
     $api_url = 'http://gdata.youtube.com/feeds/api/videos/' . $video_id;
     $conf =& blc_get_configuration();
     $args = array('timeout' => $conf->options['timeout']);
     $start = microtime_float();
     $response = wp_remote_get($api_url, $args);
     $result['request_duration'] = microtime_float() - $start;
     //Placeholders for video restriction data
     $state_name = $state_reason = '';
     //Got anything?
     if (is_wp_error($response)) {
         $result['log'] .= "Error.\n" . $response->get_error_message();
         //WP doesn't make it easy to distinguish between different internal errors.
         $result['broken'] = true;
         $result['http_code'] = 0;
     } else {
         $result['http_code'] = intval($response['response']['code']);
         switch ($result['http_code']) {
             case 404:
                 //Not found
                 $result['log'] .= __('Video Not Found', 'broken-link-checker');
                 $result['broken'] = true;
                 $result['http_code'] = 0;
                 $result['status_text'] = __('Video Not Found', 'broken-link-checker');
                 $result['status_code'] = BLC_LINK_STATUS_ERROR;
                 break;
             case 403:
                 //Forbidden. Usually means that the video has been removed. Body contains details.
                 $result['log'] .= $response['body'];
                 $result['broken'] = true;
                 $result['http_code'] = 0;
                 $result['status_text'] = __('Video Removed', 'broken-link-checker');
                 $result['status_code'] = BLC_LINK_STATUS_ERROR;
                 break;
             case 400:
                 //Bad request. Usually means that the video ID is incorrect. Body contains details.
                 $result['log'] .= $response['body'];
                 $result['broken'] = true;
                 $result['http_code'] = 0;
                 $result['status_text'] = __('Invalid Video ID', 'broken-link-checker');
                 $result['status_code'] = BLC_LINK_STATUS_WARNING;
                 break;
             case 200:
                 //Video exists, but may be restricted. Check for <yt:state> tags.
                 //See http://code.google.com/apis/youtube/2.0/reference.html#youtube_data_api_tag_yt:state
                 //Can we count on an XML parser being installed? No, probably not.
                 //Back to our makeshift tag "parser" we go.
                 $state = blcUtility::extract_tags($response['body'], 'yt:state', false);
                 if (empty($state)) {
                     //Phew, no restrictions.
                     $result['log'] .= __("Video OK", 'broken-link-checker');
                     $result['status_text'] = __('OK', 'link status', 'broken-link-checker');
                     $result['status_code'] = BLC_LINK_STATUS_OK;
                     $result['http_code'] = 0;
                 } else {
                     //Get the state name and code and append them to the log
                     $state = reset($state);
                     $state_name = $state['attributes']['name'];
                     $state_reason = isset($state['attributes']['reasonCode']) ? $state['attributes']['reasonCode'] : '';
                     $result['result_hash'] = 'youtube_api|' . $state_name . '|' . $state_reason;
                     $result['log'] .= sprintf(__('Video status : %s%s', 'broken-link-checker'), $state_name, $state_reason ? ' [' . $state_reason . ']' : '');
                     //A couple of restricted states are not that bad
                     $state_ok = $state_name == 'processing' || $state_name == 'restricted' && $state_reason == 'limitedSyndication';
                     if ($state_ok) {
                         $result['broken'] = false;
                         $result['status_text'] = __('OK', 'link status', 'broken-link-checker');
                         $result['status_code'] = BLC_LINK_STATUS_OK;
                         $result['http_code'] = 0;
                     } else {
                         $result['broken'] = true;
                         $result['status_text'] = __('Video Restricted', 'broken-link-checker');
                         $result['status_code'] = BLC_LINK_STATUS_WARNING;
                         $result['http_code'] = 0;
                     }
                 }
                 //Add the video title to the log, purely for information.
                 //http://code.google.com/apis/youtube/2.0/reference.html#youtube_data_api_tag_media:title
                 $title = blcUtility::extract_tags($response['body'], 'media:title', false);
                 if (!empty($title)) {
                     $result['log'] .= "\n\nTitle : \"" . $title[0]['contents'] . '"';
                 }
                 break;
             default:
                 $result['log'] .= $result['http_code'] . $response['response']['message'];
                 $result['log'] .= "\n" . __('Unknown YouTube API response received.');
                 break;
         }
     }
     //The hash should contain info about all pieces of data that pertain to determining if the
     //link is working.
     $result['result_hash'] = implode('|', array('youtube', $result['http_code'], $result['broken'] ? 'broken' : '0', $result['timeout'] ? 'timeout' : '0', $state_name, $state_reason));
     return $result;
 }
Exemple #22
0
<?php

$configuration = blc_get_configuration();
if (!function_exists('fetch_feed')) {
    include_once ABSPATH . WPINC . '/feed.php';
}
$show_plugin_feed = $show_ame_ad = false;
if (!$configuration->get('user_has_donated', false)) {
    if (blcUtility::constrained_hash(get_site_url() . 'y', 0, 100) < 40 && function_exists('fetch_feed')) {
        $show_plugin_feed = true;
    } else {
        $show_ame_ad = true;
    }
}
?>

<!-- "More plugins" RSS feed -->
<?php 
if ($show_plugin_feed) {
    $feed_url = 'http://w-shadow.com/files/blc-plugin-links.rss';
    $num_items = 3;
    $feed = fetch_feed($feed_url);
    if (!is_wp_error($feed)) {
        ?>
<div id="advertising" class="postbox">
	<h3 class="hndle"><?php 
        _e('More plugins by Janis Elsts', 'broken-link-checker');
        ?>
</h3>
	<div class="inside">
		<ul>
Exemple #23
0
 /**
  * Perform a HEAD request to the specified URL.
  * 
  * Note : 
  * 
  * Since the MediaFire checker works by parsing the "Location" header, redirect following
  * _must_ be disabled. This can become a problem on servers where WP is forced to fall back
  * on using WP_Http_Fopen which ignores the 'redirection' flag. WP_Http_Fsockopen would work, 
  * but it has the lowest priority of all transports. 
  * 
  * Alas, there is no way to reliably influence which transport is chosen - the WP_Http::_getTransport
  * function caches the available choices, so plugins can disable individual transports only during
  * its first run. Therefore, we must pick the best transport manually.
  * 
  * @param string $url
  * @return array|WP_Error
  */
 function head($url)
 {
     $conf = blc_get_configuration();
     $args = array('timeout' => $conf->options['timeout'], 'redirection' => 0, '_redirection' => 0);
     return wp_remote_head($url, $args);
 }
Exemple #24
0
 function check($url)
 {
     $url = $this->clean_url($url);
     //Note : Snoopy doesn't work too well with HTTPS URLs.
     $result = array('broken' => false, 'timeout' => false);
     $log = '';
     //Get the timeout setting from the BLC configuration.
     $conf = blc_get_configuration();
     $timeout = $conf->options['timeout'];
     $start_time = microtime_float();
     //Fetch the URL with Snoopy
     $snoopy = new Snoopy();
     $snoopy->read_timeout = $timeout;
     //read timeout in seconds
     $snoopy->agent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)";
     //masquerade as IE 7
     $snoopy->referer = home_url();
     //valid referer helps circumvent some hotlink protection schemes
     $snoopy->maxlength = 1024 * 5;
     //load up to 5 kilobytes
     $snoopy->fetch($this->urlencodefix($url));
     $result['request_duration'] = microtime_float() - $start_time;
     $result['http_code'] = $snoopy->status;
     //HTTP status code
     //Snoopy returns -100 on timeout
     if ($result['http_code'] == -100) {
         $result['http_code'] = 0;
         $result['timeout'] = true;
     }
     //Build the log
     $log .= '=== ';
     if ($result['http_code']) {
         $log .= sprintf(__('HTTP code : %d', 'broken-link-checker'), $result['http_code']);
     } else {
         $log .= __('(No response)', 'broken-link-checker');
     }
     $log .= " ===\n\n";
     if ($snoopy->error) {
         $log .= $snoopy->error . "\n";
     }
     if ($snoopy->timed_out) {
         $log .= __("Request timed out.", 'broken-link-checker') . "\n";
         $result['timeout'] = true;
     }
     if (is_array($snoopy->headers)) {
         $log .= implode("", $snoopy->headers) . "\n";
     }
     //those headers already contain newlines
     //Redirected?
     if ($snoopy->lastredirectaddr) {
         $result['final_url'] = $snoopy->lastredirectaddr;
         $result['redirect_count'] = $snoopy->_redirectdepth;
     } else {
         $result['final_url'] = $url;
     }
     //Determine if the link counts as "broken"
     $result['broken'] = $this->is_error_code($result['http_code']) || $result['timeout'];
     $log .= "<em>(" . __('Using Snoopy', 'broken-link-checker') . ")</em>";
     $result['log'] = $log;
     //The hash should contain info about all pieces of data that pertain to determining if the
     //link is working.
     $result['result_hash'] = implode('|', array($result['http_code'], $result['broken'] ? 'broken' : '0', $result['timeout'] ? 'timeout' : '0', md5($result['final_url'])));
     return $result;
 }