diff --git a/wp-includes/functions.php b/wp-includes/functions.php index 0fbb6d658d..3ddc0c808d 100644 --- a/wp-includes/functions.php +++ b/wp-includes/functions.php @@ -638,17 +638,13 @@ function pingback($content, $post_ID) { // original code by Mort (http://mort.mine.nu:8080) $log = debug_fopen('./pingback.log', 'a'); $post_links = array(); - debug_fwrite($log, 'BEGIN '.time()."\n"); + debug_fwrite($log, 'BEGIN '.date('YmdHis', time())."\n"); // Variables $ltrs = '\w'; $gunk = '/#~:.?+=&%@!\-'; $punc = '.:?\-'; $any = $ltrs.$gunk.$punc; - $pingback_str_dquote = 'rel="pingback"'; - $pingback_str_squote = 'rel=\'pingback\''; - $x_pingback_str = 'x-pingback: '; - $pingback_href_original_pos = 27; // Step 1 // Parsing the post, external links (if any) are stored in the $post_links array @@ -679,78 +675,11 @@ function pingback($content, $post_ID) { } foreach ($post_links as $pagelinkedto){ - debug_fwrite($log, 'Processing -- '.$pagelinkedto."\n\n"); - $bits = parse_url($pagelinkedto); - if (!isset($bits['host'])) { - debug_fwrite($log, 'Couldn\'t find a hostname for '.$pagelinkedto."\n\n"); - continue; - } - $host = $bits['host']; - $path = isset($bits['path']) ? $bits['path'] : ''; - if (isset($bits['query'])) { - $path .= '?'.$bits['query']; - } - if (!$path) { - $path = '/'; - } - $port = isset($bits['port']) ? $bits['port'] : 80; + debug_fwrite($log, "Processing -- $pagelinkedto\n"); + $pingback_server_url = discover_pingback_server_uri($pagelinkedto, 2048); - // Try to connect to the server at $host - $fp = fsockopen($host, $port, $errno, $errstr, 3); - if (!$fp) { - debug_fwrite($log, 'Couldn\'t open a connection to '.$host."\n\n"); - continue; - } - - // Send the GET request - $request = "GET $path HTTP/1.1\r\nHost: $host\r\nUser-Agent: WordPress/$wp_version PHP/" . phpversion() . "\r\n\r\n"; - ob_end_flush(); - fputs($fp, $request); - - // Start receiving headers and content - $contents = ''; - $headers = ''; - $gettingHeaders = true; - $found_pingback_server = 0; - while (!feof($fp)) { - $line = fgets($fp, 4096); - if (trim($line) == '') { - $gettingHeaders = false; - } - if (!$gettingHeaders) { - $contents .= trim($line)."\n"; - $pingback_link_offset_dquote = strpos($contents, $pingback_str_dquote); - $pingback_link_offset_squote = strpos($contents, $pingback_str_squote); - } else { - $headers .= trim($line)."\n"; - $x_pingback_header_offset = strpos(strtolower($headers), $x_pingback_str); - } - if ($x_pingback_header_offset) { - preg_match('#x-pingback: (.+)#is', $headers, $matches); - $pingback_server_url = trim($matches[1]); - debug_fwrite($log, "Pingback server found from X-Pingback header @ $pingback_server_url\n"); - $found_pingback_server = 1; - break; - } - if ($pingback_link_offset_dquote || $pingback_link_offset_squote) { - $quote = ($pingback_link_offset_dquote) ? '"' : '\''; - $pingback_link_offset = ($quote=='"') ? $pingback_link_offset_dquote : $pingback_link_offset_squote; - $pingback_href_pos = @strpos($contents, 'href=', $pingback_link_offset); - $pingback_href_start = $pingback_href_pos+6; - $pingback_href_end = @strpos($contents, $quote, $pingback_href_start); - $pingback_server_url_len = $pingback_href_end-$pingback_href_start; - $pingback_server_url = substr($contents, $pingback_href_start, $pingback_server_url_len); - debug_fwrite($log, "Pingback server found from Pingback tag @ $pingback_server_url\n"); - $found_pingback_server = 1; - break; - } - } - - if (!$found_pingback_server) { - debug_fwrite($log, "Pingback server not found\n\n*************************\n\n"); - @fclose($fp); - } else { + if($pingback_server_url) { // Now, the RPC call $method = 'pingback.ping'; @@ -778,6 +707,96 @@ function pingback($content, $post_ID) { debug_fclose($log); } +function discover_pingback_server_uri($url, $timeout_bytes = 2048) { + + $byte_count = 0; + $contents = ''; + $headers = ''; + $pingback_str_dquote = 'rel="pingback"'; + $pingback_str_squote = 'rel=\'pingback\''; + $x_pingback_str = 'x-pingback: '; + $pingback_href_original_pos = 27; + + extract(parse_url($url)); + + if (!isset($host)) { + // Not an URL. This should never happen. + return false; + } + + $path = (!isset($path)) ? '/' : $path; + $path .= (isset($query)) ? '?'.$query : ''; + $port = (isset($port)) ? $port : 80; + + // Try to connect to the server at $host + $fp = fsockopen($host, $port, $errno, $errstr, 3); + if (!$fp) { + // Couldn't open a connection to $host; + return false; + } + + // Send the GET request + $request = "GET $path HTTP/1.1\r\nHost: $host\r\nUser-Agent: WordPress/$wp_version PHP/" . phpversion() . "\r\n\r\n"; + ob_end_flush(); + fputs($fp, $request); + + // Let's check for an X-Pingback header first + while (!feof($fp)) { + $line = fgets($fp, 512); + if (trim($line) == '') { + break; + } + $headers .= trim($line)."\n"; + $x_pingback_header_offset = strpos(strtolower($headers), $x_pingback_str); + if ($x_pingback_header_offset) { + // We got it! + preg_match('#x-pingback: (.+)#is', $headers, $matches); + $pingback_server_url = trim($matches[1]); + return $pingback_server_url; + } + if(strpos(strtolower($headers), 'content-type: ')) { + preg_match('#content-type: (.+)#is', $headers, $matches); + $content_type = trim($matches[1]); + } + } + + if (preg_match('#(image|audio|video|model)/#is', $content_type)) { + // Not an (x)html, sgml, or xml page, no use going further + return false; + } + + while (!feof($fp)) { + $line = fgets($fp, 1024); + $contents .= trim($line); + $pingback_link_offset_dquote = strpos($contents, $pingback_str_dquote); + $pingback_link_offset_squote = strpos($contents, $pingback_str_squote); + if ($pingback_link_offset_dquote || $pingback_link_offset_squote) { + $quote = ($pingback_link_offset_dquote) ? '"' : '\''; + $pingback_link_offset = ($quote=='"') ? $pingback_link_offset_dquote : $pingback_link_offset_squote; + $pingback_href_pos = @strpos($contents, 'href=', $pingback_link_offset); + $pingback_href_start = $pingback_href_pos+6; + $pingback_href_end = @strpos($contents, $quote, $pingback_href_start); + $pingback_server_url_len = $pingback_href_end - $pingback_href_start; + $pingback_server_url = substr($contents, $pingback_href_start, $pingback_server_url_len); + // We may find rel="pingback" but an incomplete pingback URI + if ($pingback_server_url_len > 0) { + // We got it! + return $pingback_server_url; + } + } + $byte_count += strlen($line); + if ($byte_count > $timeout_bytes) { + // It's no use going further, there probably isn't any pingback + // server to find in this file. (Prevents loading large files.) + return false; + } + } + + // We didn't find anything. + return false; +} + + /* wp_set_comment_status: part of otaku42's comment moderation hack changes the status of a comment according to $comment_status.